From 3212754e62a73f75dd055d5c9e8eb1e43a5dec29 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 26 Feb 2020 07:50:11 -0700 Subject: [PATCH 01/64] [Maps] add Top term aggregation (#57875) * [Maps] add Top term aggregation * update pew-pew source to handle terms agg * make helper function for pulling values from bucket * update terms source * better join labels * categoricla meta * remove unused constant * remove unused changes * remove unused constant METRIC_SCHEMA_CONFIG * update jest expect * fix auto complete suggestions for top term * get category autocomplete working with style props from joins * pluck categorical style meta with real field name * mock MetricsEditor to fix jest test * review feedback * es_agg_utils.js to es_agg_utils.ts * typing updates * use composit agg to avoid search.buckets limit * i18n update and functional test fix * stop paging through results when request is aborted * remove unused file * do not use composite agg when no terms sub-aggregations * clean up * pass indexPattern to getValueAggsDsl * review feedback * more review feedback * ts-ignore for untyped imports in tests * more review feedback * add bucket.hasOwnProperty check Co-authored-by: Elastic Machine --- .../legacy/plugins/maps/common/constants.ts | 4 +- .../maps/public/actions/map_actions.js | 22 +- .../maps/public/components/metric_editor.js | 13 +- .../maps/public/components/metric_select.js | 20 +- .../maps/public/components/metrics_editor.js | 4 +- .../resources/metrics_expression.js | 8 +- .../resources/metrics_expression.test.js | 6 + .../connected_components/map/mb/view.js | 15 +- .../maps/public/elasticsearch_geo_utils.js | 18 ++ .../maps/public/layers/fields/es_agg_field.js | 33 ++- .../public/layers/fields/es_agg_field.test.js | 14 +- .../public/layers/sources/es_agg_source.js | 38 ++-- .../es_geo_grid_source/convert_to_geojson.js | 89 ++++---- .../convert_to_geojson.test.ts | 159 ++++++++++++++ .../es_geo_grid_source/es_geo_grid_source.js | 201 ++++++++++++++---- .../es_geo_grid_source/geo_tile_utils.js | 3 +- .../es_geo_grid_source/geo_tile_utils.test.js | 2 + .../es_pew_pew_source/convert_to_lines.js | 19 +- .../convert_to_lines.test.ts | 68 ++++++ .../es_pew_pew_source/es_pew_pew_source.js | 8 +- .../es_search_source/es_search_source.js | 26 +-- .../maps/public/layers/sources/es_source.js | 11 +- .../public/layers/sources/es_term_source.js | 91 +++----- .../layers/sources/es_term_source.test.js | 91 +------- .../properties/dynamic_size_property.js | 12 +- .../properties/dynamic_style_property.js | 27 ++- .../layers/styles/vector/vector_style.js | 10 +- .../tooltips/es_aggmetric_tooltip_property.js | 6 +- .../public/layers/util/es_agg_utils.test.ts | 37 ++++ .../maps/public/layers/util/es_agg_utils.ts | 51 +++++ .../public/layers/util/is_metric_countable.js | 4 +- .../maps/public/layers/vector_layer.js | 15 +- .../maps/public/selectors/map_selectors.js | 15 ++ .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 35 files changed, 726 insertions(+), 416 deletions(-) create mode 100644 x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.test.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/convert_to_lines.test.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/util/es_agg_utils.test.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/util/es_agg_utils.ts diff --git a/x-pack/legacy/plugins/maps/common/constants.ts b/x-pack/legacy/plugins/maps/common/constants.ts index ab9a696fa3a17..542abfb004d0d 100644 --- a/x-pack/legacy/plugins/maps/common/constants.ts +++ b/x-pack/legacy/plugins/maps/common/constants.ts @@ -117,16 +117,16 @@ export const DRAW_TYPE = { POLYGON: 'POLYGON', }; -export const METRIC_TYPE = { +export const AGG_TYPE = { AVG: 'avg', COUNT: 'count', MAX: 'max', MIN: 'min', SUM: 'sum', + TERMS: 'terms', UNIQUE_COUNT: 'cardinality', }; -export const COUNT_AGG_TYPE = METRIC_TYPE.COUNT; export const COUNT_PROP_LABEL = i18n.translate('xpack.maps.aggs.defaultCountLabel', { defaultMessage: 'count', }); diff --git a/x-pack/legacy/plugins/maps/public/actions/map_actions.js b/x-pack/legacy/plugins/maps/public/actions/map_actions.js index 2c6c60db9a012..cfca044ea759a 100644 --- a/x-pack/legacy/plugins/maps/public/actions/map_actions.js +++ b/x-pack/legacy/plugins/maps/public/actions/map_actions.js @@ -18,6 +18,7 @@ import { getTransientLayerId, getOpenTooltips, getQuery, + getDataRequestDescriptor, } from '../selectors/map_selectors'; import { FLYOUT_STATE } from '../reducers/ui'; import { @@ -76,7 +77,7 @@ export const HIDE_LAYER_CONTROL = 'HIDE_LAYER_CONTROL'; export const HIDE_VIEW_CONTROL = 'HIDE_VIEW_CONTROL'; export const SET_WAITING_FOR_READY_HIDDEN_LAYERS = 'SET_WAITING_FOR_READY_HIDDEN_LAYERS'; -function getLayerLoadingCallbacks(dispatch, layerId) { +function getLayerLoadingCallbacks(dispatch, getState, layerId) { return { startLoading: (dataId, requestToken, meta) => dispatch(startDataLoad(layerId, dataId, requestToken, meta)), @@ -87,6 +88,13 @@ function getLayerLoadingCallbacks(dispatch, layerId) { updateSourceData: newData => { dispatch(updateSourceDataRequest(layerId, newData)); }, + isRequestStillActive: (dataId, requestToken) => { + const dataRequest = getDataRequestDescriptor(getState(), layerId, dataId); + if (!dataRequest) { + return false; + } + return dataRequest.dataRequestToken === requestToken; + }, registerCancelCallback: (requestToken, callback) => dispatch(registerCancelCallback(requestToken, callback)), }; @@ -98,11 +106,11 @@ function getLayerById(layerId, state) { }); } -async function syncDataForAllLayers(getState, dispatch, dataFilters) { +async function syncDataForAllLayers(dispatch, getState, dataFilters) { const state = getState(); const layerList = getLayerList(state); const syncs = layerList.map(layer => { - const loadingFunctions = getLayerLoadingCallbacks(dispatch, layer.getId()); + const loadingFunctions = getLayerLoadingCallbacks(dispatch, getState, layer.getId()); return layer.syncData({ ...loadingFunctions, dataFilters }); }); await Promise.all(syncs); @@ -412,7 +420,7 @@ export function mapExtentChanged(newMapConstants) { }, }); const newDataFilters = { ...dataFilters, ...newMapConstants }; - await syncDataForAllLayers(getState, dispatch, newDataFilters); + await syncDataForAllLayers(dispatch, getState, newDataFilters); }; } @@ -653,7 +661,7 @@ export function syncDataForLayer(layerId) { const targetLayer = getLayerById(layerId, getState()); if (targetLayer) { const dataFilters = getDataFilters(getState()); - const loadingFunctions = getLayerLoadingCallbacks(dispatch, layerId); + const loadingFunctions = getLayerLoadingCallbacks(dispatch, getState, layerId); await targetLayer.syncData({ ...loadingFunctions, dataFilters, @@ -773,7 +781,7 @@ export function setQuery({ query, timeFilters, filters = [], refresh = false }) }); const dataFilters = getDataFilters(getState()); - await syncDataForAllLayers(getState, dispatch, dataFilters); + await syncDataForAllLayers(dispatch, getState, dataFilters); }; } @@ -792,7 +800,7 @@ export function triggerRefreshTimer() { }); const dataFilters = getDataFilters(getState()); - await syncDataForAllLayers(getState, dispatch, dataFilters); + await syncDataForAllLayers(dispatch, getState, dataFilters); }; } 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 e60c2ac0dd7ab..530f402592b2b 100644 --- a/x-pack/legacy/plugins/maps/public/components/metric_editor.js +++ b/x-pack/legacy/plugins/maps/public/components/metric_editor.js @@ -12,17 +12,16 @@ 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'; +import { AGG_TYPE } from '../../common/constants'; +import { getTermsFields } from '../index_pattern_util'; function filterFieldsForAgg(fields, aggType) { if (!fields) { return []; } - if (aggType === METRIC_TYPE.UNIQUE_COUNT) { - return fields.filter(field => { - return field.aggregatable; - }); + if (aggType === AGG_TYPE.UNIQUE_COUNT || aggType === AGG_TYPE.TERMS) { + return getTermsFields(fields); } return fields.filter(field => { @@ -38,7 +37,7 @@ export function MetricEditor({ fields, metricsFilter, metric, onChange, removeBu }; // unset field when new agg type does not support currently selected field. - if (metric.field && metricAggregationType !== METRIC_TYPE.COUNT) { + if (metric.field && metricAggregationType !== AGG_TYPE.COUNT) { const fieldsForNewAggType = filterFieldsForAgg(fields, metricAggregationType); const found = fieldsForNewAggType.find(field => { return field.name === metric.field; @@ -64,7 +63,7 @@ export function MetricEditor({ fields, metricsFilter, metric, onChange, removeBu }; let fieldSelect; - if (metric.type && metric.type !== METRIC_TYPE.COUNT) { + if (metric.type && metric.type !== AGG_TYPE.COUNT) { fieldSelect = ( { - if (type === METRIC_TYPE.COUNT) { + if (type === AGG_TYPE.COUNT) { return true; } @@ -70,7 +70,7 @@ export class MetricsExpression extends Component { }) .map(({ type, field }) => { // do not use metric label so field and aggregation are not obscured. - if (type === METRIC_TYPE.COUNT) { + if (type === AGG_TYPE.COUNT) { return 'count'; } @@ -130,5 +130,5 @@ MetricsExpression.propTypes = { }; MetricsExpression.defaultProps = { - metrics: [{ type: METRIC_TYPE.COUNT }], + metrics: [{ type: AGG_TYPE.COUNT }], }; diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/metrics_expression.test.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/metrics_expression.test.js index e0e1556ecde06..e4e3776c8e92c 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/metrics_expression.test.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/metrics_expression.test.js @@ -4,6 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ +jest.mock('../../../../components/metrics_editor', () => ({ + MetricsEditor: () => { + return
mockMetricsEditor
; + }, +})); + import React from 'react'; import { shallow } from 'enzyme'; import { MetricsExpression } from './metrics_expression'; diff --git a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js index 1e44c7225a564..fdc8ad2176d08 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js @@ -23,6 +23,7 @@ import sprites1 from '@elastic/maki/dist/sprite@1.png'; import sprites2 from '@elastic/maki/dist/sprite@2.png'; import { DrawControl } from './draw_control'; import { TooltipControl } from './tooltip_control'; +import { clampToLatBounds, clampToLonBounds } from '../../../elasticsearch_geo_utils'; mapboxgl.workerUrl = mbWorkerUrl; mapboxgl.setRTLTextPlugin(mbRtlPlugin); @@ -234,12 +235,12 @@ export class MBMapContainer extends React.Component { //clamping ot -89/89 latitudes since Mapboxgl does not seem to handle bounds that contain the poles (logs errors to the console when using -90/90) const lnLatBounds = new mapboxgl.LngLatBounds( new mapboxgl.LngLat( - clamp(goto.bounds.min_lon, -180, 180), - clamp(goto.bounds.min_lat, -89, 89) + clampToLonBounds(goto.bounds.min_lon), + clampToLatBounds(goto.bounds.min_lat) ), new mapboxgl.LngLat( - clamp(goto.bounds.max_lon, -180, 180), - clamp(goto.bounds.max_lat, -89, 89) + clampToLonBounds(goto.bounds.max_lon), + clampToLatBounds(goto.bounds.max_lat) ) ); //maxZoom ensure we're not zooming in too far on single points or small shapes @@ -306,9 +307,3 @@ export class MBMapContainer extends React.Component { ); } } - -function clamp(val, min, max) { - if (val > max) val = max; - else if (val < min) val = min; - return val; -} diff --git a/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.js b/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.js index ec0ae4161b3f2..9b33d3036785c 100644 --- a/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.js +++ b/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.js @@ -433,3 +433,21 @@ export function convertMapExtentToPolygon({ maxLat, maxLon, minLat, minLon }) { return formatEnvelopeAsPolygon({ maxLat, maxLon, minLat, minLon }); } + +export function clampToLatBounds(lat) { + return clamp(lat, -89, 89); +} + +export function clampToLonBounds(lon) { + return clamp(lon, -180, 180); +} + +export function clamp(val, min, max) { + if (val > max) { + return max; + } else if (val < min) { + return min; + } else { + return val; + } +} diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js b/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js index 65109cb99809f..28c199b64d3ef 100644 --- a/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js +++ b/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js @@ -5,9 +5,10 @@ */ import { AbstractField } from './field'; -import { COUNT_AGG_TYPE } from '../../../common/constants'; +import { AGG_TYPE } from '../../../common/constants'; import { isMetricCountable } from '../util/is_metric_countable'; import { ESAggMetricTooltipProperty } from '../tooltips/es_aggmetric_tooltip_property'; +import { getField, addFieldToDSL } from '../util/es_agg_utils'; export class ESAggMetricField extends AbstractField { static type = 'ES_AGG'; @@ -34,12 +35,11 @@ export class ESAggMetricField extends AbstractField { } isValid() { - return this.getAggType() === COUNT_AGG_TYPE ? true : !!this._esDocField; + return this.getAggType() === AGG_TYPE.COUNT ? true : !!this._esDocField; } async getDataType() { - // aggregations only provide numerical data - return 'number'; + return this.getAggType() === AGG_TYPE.TERMS ? 'string' : 'number'; } getESDocFieldName() { @@ -47,9 +47,9 @@ export class ESAggMetricField extends AbstractField { } getRequestDescription() { - return this.getAggType() !== COUNT_AGG_TYPE + return this.getAggType() !== AGG_TYPE.COUNT ? `${this.getAggType()} ${this.getESDocFieldName()}` - : COUNT_AGG_TYPE; + : AGG_TYPE.COUNT; } async createTooltipProperty(value) { @@ -63,18 +63,13 @@ export class ESAggMetricField extends AbstractField { ); } - makeMetricAggConfig() { - const metricAggConfig = { - id: this.getName(), - enabled: true, - type: this.getAggType(), - schema: 'metric', - params: {}, + getValueAggDsl(indexPattern) { + const field = getField(indexPattern, this.getESDocFieldName()); + const aggType = this.getAggType(); + const aggBody = aggType === AGG_TYPE.TERMS ? { size: 1, shard_size: 1 } : {}; + return { + [aggType]: addFieldToDSL(aggBody, field), }; - if (this.getAggType() !== COUNT_AGG_TYPE) { - metricAggConfig.params = { field: this.getESDocFieldName() }; - } - return metricAggConfig; } supportsFieldMeta() { @@ -85,4 +80,8 @@ export class ESAggMetricField extends AbstractField { async getOrdinalFieldMetaRequest(config) { return this._esDocField.getOrdinalFieldMetaRequest(config); } + + async getCategoricalFieldMetaRequest() { + return this._esDocField.getCategoricalFieldMetaRequest(); + } } diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.test.js b/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.test.js index 2f18987513d92..aeeffd63607ee 100644 --- a/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.test.js @@ -5,24 +5,24 @@ */ import { ESAggMetricField } from './es_agg_field'; -import { METRIC_TYPE } from '../../../common/constants'; +import { AGG_TYPE } from '../../../common/constants'; describe('supportsFieldMeta', () => { test('Non-counting aggregations should support field meta', () => { - const avgMetric = new ESAggMetricField({ aggType: METRIC_TYPE.AVG }); + const avgMetric = new ESAggMetricField({ aggType: AGG_TYPE.AVG }); expect(avgMetric.supportsFieldMeta()).toBe(true); - const maxMetric = new ESAggMetricField({ aggType: METRIC_TYPE.MAX }); + const maxMetric = new ESAggMetricField({ aggType: AGG_TYPE.MAX }); expect(maxMetric.supportsFieldMeta()).toBe(true); - const minMetric = new ESAggMetricField({ aggType: METRIC_TYPE.MIN }); + const minMetric = new ESAggMetricField({ aggType: AGG_TYPE.MIN }); expect(minMetric.supportsFieldMeta()).toBe(true); }); test('Counting aggregations should not support field meta', () => { - const countMetric = new ESAggMetricField({ aggType: METRIC_TYPE.COUNT }); + const countMetric = new ESAggMetricField({ aggType: AGG_TYPE.COUNT }); expect(countMetric.supportsFieldMeta()).toBe(false); - const sumMetric = new ESAggMetricField({ aggType: METRIC_TYPE.SUM }); + const sumMetric = new ESAggMetricField({ aggType: AGG_TYPE.SUM }); expect(sumMetric.supportsFieldMeta()).toBe(false); - const uniqueCountMetric = new ESAggMetricField({ aggType: METRIC_TYPE.UNIQUE_COUNT }); + const uniqueCountMetric = new ESAggMetricField({ aggType: AGG_TYPE.UNIQUE_COUNT }); expect(uniqueCountMetric.supportsFieldMeta()).toBe(false); }); }); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js index 967a3c41aec26..bee35216f59da 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js @@ -8,8 +8,7 @@ import { AbstractESSource } from './es_source'; import { ESAggMetricField } from '../fields/es_agg_field'; import { ESDocField } from '../fields/es_doc_field'; import { - METRIC_TYPE, - COUNT_AGG_TYPE, + AGG_TYPE, COUNT_PROP_LABEL, COUNT_PROP_NAME, FIELD_ORIGIN, @@ -18,23 +17,6 @@ import { export const AGG_DELIMITER = '_of_'; export class AbstractESAggSource extends AbstractESSource { - static METRIC_SCHEMA_CONFIG = { - group: 'metrics', - name: 'metric', - title: 'Value', - min: 1, - max: Infinity, - aggFilter: [ - METRIC_TYPE.AVG, - METRIC_TYPE.COUNT, - METRIC_TYPE.MAX, - METRIC_TYPE.MIN, - METRIC_TYPE.SUM, - METRIC_TYPE.UNIQUE_COUNT, - ], - defaults: [{ schema: 'metric', type: METRIC_TYPE.COUNT }], - }; - constructor(descriptor, inspectorAdapters) { super(descriptor, inspectorAdapters); this._metricFields = this._descriptor.metrics @@ -81,7 +63,7 @@ export class AbstractESAggSource extends AbstractESSource { if (metrics.length === 0) { metrics.push( new ESAggMetricField({ - aggType: COUNT_AGG_TYPE, + aggType: AGG_TYPE.COUNT, source: this, origin: this.getOriginForField(), }) @@ -91,15 +73,23 @@ export class AbstractESAggSource extends AbstractESSource { } formatMetricKey(aggType, fieldName) { - return aggType !== COUNT_AGG_TYPE ? `${aggType}${AGG_DELIMITER}${fieldName}` : COUNT_PROP_NAME; + return aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${fieldName}` : COUNT_PROP_NAME; } formatMetricLabel(aggType, fieldName) { - return aggType !== COUNT_AGG_TYPE ? `${aggType} of ${fieldName}` : COUNT_PROP_LABEL; + return aggType !== AGG_TYPE.COUNT ? `${aggType} of ${fieldName}` : COUNT_PROP_LABEL; } - createMetricAggConfigs() { - return this.getMetricFields().map(esAggMetric => esAggMetric.makeMetricAggConfig()); + getValueAggsDsl(indexPattern) { + const valueAggsDsl = {}; + this.getMetricFields() + .filter(esAggMetric => { + return esAggMetric.getAggType() !== AGG_TYPE.COUNT; + }) + .forEach(esAggMetric => { + valueAggsDsl[esAggMetric.getName()] = esAggMetric.getValueAggDsl(indexPattern); + }); + return valueAggsDsl; } async getNumberFields() { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.js index 4e15d1c927c36..bb9bf1b508f94 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.js @@ -4,68 +4,63 @@ * you may not use this file except in compliance with the Elastic License. */ +import _ from 'lodash'; import { RENDER_AS } from './render_as'; import { getTileBoundingBox } from './geo_tile_utils'; -import { EMPTY_FEATURE_COLLECTION } from '../../../../common/constants'; +import { extractPropertiesFromBucket } from '../../util/es_agg_utils'; +import { clamp } from '../../../elasticsearch_geo_utils'; -export function convertToGeoJson({ table, renderAs }) { - if (!table || !table.rows) { - return EMPTY_FEATURE_COLLECTION; - } +const GRID_BUCKET_KEYS_TO_IGNORE = ['key', 'gridCentroid']; - const geoGridColumn = table.columns.find( - column => column.aggConfig.type.dslName === 'geotile_grid' +export function convertCompositeRespToGeoJson(esResponse, renderAs) { + return convertToGeoJson( + esResponse, + renderAs, + esResponse => { + return _.get(esResponse, 'aggregations.compositeSplit.buckets', []); + }, + gridBucket => { + return gridBucket.key.gridSplit; + } ); - if (!geoGridColumn) { - return EMPTY_FEATURE_COLLECTION; - } +} - const metricColumns = table.columns.filter(column => { - return ( - column.aggConfig.type.type === 'metrics' && column.aggConfig.type.dslName !== 'geo_centroid' - ); - }); - const geocentroidColumn = table.columns.find( - column => column.aggConfig.type.dslName === 'geo_centroid' +export function convertRegularRespToGeoJson(esResponse, renderAs) { + return convertToGeoJson( + esResponse, + renderAs, + esResponse => { + return _.get(esResponse, 'aggregations.gridSplit.buckets', []); + }, + gridBucket => { + return gridBucket.key; + } ); - if (!geocentroidColumn) { - return EMPTY_FEATURE_COLLECTION; - } +} +function convertToGeoJson(esResponse, renderAs, pluckGridBuckets, pluckGridKey) { const features = []; - table.rows.forEach(row => { - const gridKey = row[geoGridColumn.id]; - if (!gridKey) { - return; - } - - const properties = {}; - metricColumns.forEach(metricColumn => { - properties[metricColumn.aggConfig.id] = row[metricColumn.id]; - }); + const gridBuckets = pluckGridBuckets(esResponse); + for (let i = 0; i < gridBuckets.length; i++) { + const gridBucket = gridBuckets[i]; + const gridKey = pluckGridKey(gridBucket); features.push({ type: 'Feature', geometry: rowToGeometry({ - row, gridKey, - geocentroidColumn, + gridCentroid: gridBucket.gridCentroid, renderAs, }), id: gridKey, - properties, + properties: extractPropertiesFromBucket(gridBucket, GRID_BUCKET_KEYS_TO_IGNORE), }); - }); + } - return { - featureCollection: { - type: 'FeatureCollection', - features: features, - }, - }; + return features; } -function rowToGeometry({ row, gridKey, geocentroidColumn, renderAs }) { +function rowToGeometry({ gridKey, gridCentroid, renderAs }) { const { top, bottom, right, left } = getTileBoundingBox(gridKey); if (renderAs === RENDER_AS.GRID) { @@ -83,10 +78,10 @@ function rowToGeometry({ row, gridKey, geocentroidColumn, renderAs }) { }; } - // see https://github.com/elastic/elasticsearch/issues/24694 for why clampGrid is used + // see https://github.com/elastic/elasticsearch/issues/24694 for why clamp is used const pointCoordinates = [ - clampGrid(row[geocentroidColumn.id].lon, left, right), - clampGrid(row[geocentroidColumn.id].lat, bottom, top), + clamp(gridCentroid.location.lon, left, right), + clamp(gridCentroid.location.lat, bottom, top), ]; return { @@ -94,9 +89,3 @@ function rowToGeometry({ row, gridKey, geocentroidColumn, renderAs }) { coordinates: pointCoordinates, }; } - -function clampGrid(val, min, max) { - if (val > max) val = max; - else if (val < min) val = min; - return val; -} diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.test.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.test.ts new file mode 100644 index 0000000000000..ba79464a01a9b --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/convert_to_geojson.test.ts @@ -0,0 +1,159 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +jest.mock('../../../kibana_services', () => {}); + +// @ts-ignore +import { convertCompositeRespToGeoJson, convertRegularRespToGeoJson } from './convert_to_geojson'; +// @ts-ignore +import { RENDER_AS } from './render_as'; + +describe('convertCompositeRespToGeoJson', () => { + const esResponse = { + aggregations: { + compositeSplit: { + after_key: { + gridSplit: '10/327/460', + }, + buckets: [ + { + key: { gridSplit: '4/4/6' }, + doc_count: 65, + avg_of_bytes: { value: 5359.2307692307695 }, + 'terms_of_machine.os.keyword': { + buckets: [ + { + key: 'win xp', + doc_count: 16, + }, + ], + }, + gridCentroid: { + location: { lat: 36.62813963153614, lon: -81.94552666092149 }, + count: 65, + }, + }, + ], + }, + }, + }; + + it('Should convert elasticsearch aggregation response into feature collection of points', () => { + const features = convertCompositeRespToGeoJson(esResponse, RENDER_AS.POINT); + expect(features.length).toBe(1); + expect(features[0]).toEqual({ + geometry: { + coordinates: [-81.94552666092149, 36.62813963153614], + type: 'Point', + }, + id: '4/4/6', + properties: { + avg_of_bytes: 5359.2307692307695, + doc_count: 65, + 'terms_of_machine.os.keyword': 'win xp', + }, + type: 'Feature', + }); + }); + + it('Should convert elasticsearch aggregation response into feature collection of Polygons', () => { + const features = convertCompositeRespToGeoJson(esResponse, RENDER_AS.GRID); + expect(features.length).toBe(1); + expect(features[0]).toEqual({ + geometry: { + coordinates: [ + [ + [-67.5, 40.9799], + [-90, 40.9799], + [-90, 21.94305], + [-67.5, 21.94305], + [-67.5, 40.9799], + ], + ], + type: 'Polygon', + }, + id: '4/4/6', + properties: { + avg_of_bytes: 5359.2307692307695, + doc_count: 65, + 'terms_of_machine.os.keyword': 'win xp', + }, + type: 'Feature', + }); + }); +}); + +describe('convertRegularRespToGeoJson', () => { + const esResponse = { + aggregations: { + gridSplit: { + buckets: [ + { + key: '4/4/6', + doc_count: 65, + avg_of_bytes: { value: 5359.2307692307695 }, + 'terms_of_machine.os.keyword': { + buckets: [ + { + key: 'win xp', + doc_count: 16, + }, + ], + }, + gridCentroid: { + location: { lat: 36.62813963153614, lon: -81.94552666092149 }, + count: 65, + }, + }, + ], + }, + }, + }; + + it('Should convert elasticsearch aggregation response into feature collection of points', () => { + const features = convertRegularRespToGeoJson(esResponse, RENDER_AS.POINT); + expect(features.length).toBe(1); + expect(features[0]).toEqual({ + geometry: { + coordinates: [-81.94552666092149, 36.62813963153614], + type: 'Point', + }, + id: '4/4/6', + properties: { + avg_of_bytes: 5359.2307692307695, + doc_count: 65, + 'terms_of_machine.os.keyword': 'win xp', + }, + type: 'Feature', + }); + }); + + it('Should convert elasticsearch aggregation response into feature collection of Polygons', () => { + const features = convertRegularRespToGeoJson(esResponse, RENDER_AS.GRID); + expect(features.length).toBe(1); + expect(features[0]).toEqual({ + geometry: { + coordinates: [ + [ + [-67.5, 40.9799], + [-90, 40.9799], + [-90, 21.94305], + [-67.5, 21.94305], + [-67.5, 40.9799], + ], + ], + type: 'Polygon', + }, + id: '4/4/6', + properties: { + avg_of_bytes: 5359.2307692307695, + doc_count: 65, + 'terms_of_machine.os.keyword': 'win xp', + }, + type: 'Feature', + }); + }); +}); 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 0912e5a9f1283..a0ddf584bcebc 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 @@ -10,9 +10,7 @@ import uuid from 'uuid/v4'; import { VECTOR_SHAPE_TYPES } from '../vector_feature_types'; import { HeatmapLayer } from '../../heatmap_layer'; import { VectorLayer } from '../../vector_layer'; -import { AggConfigs, Schemas } from 'ui/agg_types'; -import { tabifyAggResponse } from '../../../../../../../../src/legacy/core_plugins/data/public'; -import { convertToGeoJson } from './convert_to_geojson'; +import { convertCompositeRespToGeoJson, convertRegularRespToGeoJson } from './convert_to_geojson'; import { VectorStyle } from '../../styles/vector/vector_style'; import { getDefaultDynamicProperties, @@ -24,6 +22,8 @@ import { CreateSourceEditor } from './create_source_editor'; import { UpdateSourceEditor } from './update_source_editor'; import { GRID_RESOLUTION } from '../../grid_resolution'; import { + AGG_TYPE, + DEFAULT_MAX_BUCKETS_LIMIT, SOURCE_DATA_ID_ORIGIN, ES_GEO_GRID, COUNT_PROP_NAME, @@ -34,21 +34,10 @@ import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { AbstractESAggSource } from '../es_agg_source'; import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property'; import { StaticStyleProperty } from '../../styles/vector/properties/static_style_property'; +import { DataRequestAbortError } from '../../util/data_request'; const MAX_GEOTILE_LEVEL = 29; -const aggSchemas = new Schemas([ - AbstractESAggSource.METRIC_SCHEMA_CONFIG, - { - group: 'buckets', - name: 'segment', - title: 'Geo Grid', - aggFilter: 'geotile_grid', - min: 1, - max: 1, - }, -]); - export class ESGeoGridSource extends AbstractESAggSource { static type = ES_GEO_GRID; static title = i18n.translate('xpack.maps.source.esGridTitle', { @@ -175,15 +164,120 @@ export class ESGeoGridSource extends AbstractESAggSource { ); } - async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback) { - const indexPattern = await this.getIndexPattern(); - const searchSource = await this._makeSearchSource(searchFilters, 0); - const aggConfigs = new AggConfigs( - indexPattern, - this._makeAggConfigs(searchFilters.geogridPrecision), - aggSchemas.all - ); - searchSource.setField('aggs', aggConfigs.toDsl()); + async _compositeAggRequest({ + searchSource, + indexPattern, + precision, + layerName, + registerCancelCallback, + bucketsPerGrid, + isRequestStillActive, + }) { + const gridsPerRequest = Math.floor(DEFAULT_MAX_BUCKETS_LIMIT / bucketsPerGrid); + const aggs = { + compositeSplit: { + composite: { + size: gridsPerRequest, + sources: [ + { + gridSplit: { + geotile_grid: { + field: this._descriptor.geoField, + precision, + }, + }, + }, + ], + }, + aggs: { + gridCentroid: { + geo_centroid: { + field: this._descriptor.geoField, + }, + }, + ...this.getValueAggsDsl(indexPattern), + }, + }, + }; + + const features = []; + let requestCount = 0; + let afterKey = null; + while (true) { + if (!isRequestStillActive()) { + // Stop paging through results if request is obsolete + throw new DataRequestAbortError(); + } + + requestCount++; + + // circuit breaker to ensure reasonable number of requests + if (requestCount > 5) { + throw new Error( + i18n.translate('xpack.maps.source.esGrid.compositePaginationErrorMessage', { + defaultMessage: `{layerName} is causing too many requests. Reduce "Grid resolution" and/or reduce the number of top term "Metrics".`, + values: { layerName }, + }) + ); + } + + if (afterKey) { + aggs.compositeSplit.composite.after = afterKey; + } + searchSource.setField('aggs', aggs); + const requestId = afterKey ? `${this.getId()} afterKey ${afterKey.geoSplit}` : this.getId(); + const esResponse = await this._runEsQuery({ + requestId, + requestName: `${layerName} (${requestCount})`, + searchSource, + registerCancelCallback, + requestDescription: i18n.translate( + 'xpack.maps.source.esGrid.compositeInspectorDescription', + { + defaultMessage: 'Elasticsearch geo grid aggregation request: {requestId}', + values: { requestId }, + } + ), + }); + + features.push(...convertCompositeRespToGeoJson(esResponse, this._descriptor.requestType)); + + afterKey = esResponse.aggregations.compositeSplit.after_key; + if (esResponse.aggregations.compositeSplit.buckets.length < gridsPerRequest) { + // Finished because request did not get full resultset back + break; + } + } + + return features; + } + + // Do not use composite aggregation when there are no terms sub-aggregations + // see https://github.com/elastic/kibana/pull/57875#issuecomment-590515482 for explanation on using separate code paths + async _nonCompositeAggRequest({ + searchSource, + indexPattern, + precision, + layerName, + registerCancelCallback, + }) { + searchSource.setField('aggs', { + gridSplit: { + geotile_grid: { + field: this._descriptor.geoField, + precision, + }, + aggs: { + gridCentroid: { + geo_centroid: { + field: this._descriptor.geoField, + }, + }, + ...this.getValueAggsDsl(indexPattern), + }, + }, + }); + const esResponse = await this._runEsQuery({ requestId: this.getId(), requestName: layerName, @@ -194,14 +288,45 @@ export class ESGeoGridSource extends AbstractESAggSource { }), }); - const tabifiedResp = tabifyAggResponse(aggConfigs, esResponse); - const { featureCollection } = convertToGeoJson({ - table: tabifiedResp, - renderAs: this._descriptor.requestType, + return convertRegularRespToGeoJson(esResponse, this._descriptor.requestType); + } + + async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback, isRequestStillActive) { + const indexPattern = await this.getIndexPattern(); + const searchSource = await this._makeSearchSource(searchFilters, 0); + + let bucketsPerGrid = 1; + this.getMetricFields().forEach(metricField => { + if (metricField.getAggType() === AGG_TYPE.TERMS) { + // each terms aggregation increases the overall number of buckets per grid + bucketsPerGrid++; + } }); + const features = + bucketsPerGrid === 1 + ? await this._nonCompositeAggRequest({ + searchSource, + indexPattern, + precision: searchFilters.geogridPrecision, + layerName, + registerCancelCallback, + }) + : await this._compositeAggRequest({ + searchSource, + indexPattern, + precision: searchFilters.geogridPrecision, + layerName, + registerCancelCallback, + bucketsPerGrid, + isRequestStillActive, + }); + return { - data: featureCollection, + data: { + type: 'FeatureCollection', + features: features, + }, meta: { areResultsTrimmed: false, }, @@ -212,24 +337,6 @@ export class ESGeoGridSource extends AbstractESAggSource { return true; } - _makeAggConfigs(precision) { - const metricAggConfigs = this.createMetricAggConfigs(); - return [ - ...metricAggConfigs, - { - id: 'grid', - enabled: true, - type: 'geotile_grid', - schema: 'segment', - params: { - field: this._descriptor.geoField, - useGeocentroid: true, - precision: precision, - }, - }, - ]; - } - _createHeatmapLayerDescriptor(options) { return HeatmapLayer.createDescriptor({ sourceDescriptor: this._descriptor, diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/geo_tile_utils.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/geo_tile_utils.js index da0bc1685f223..251e33b9579cb 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/geo_tile_utils.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/geo_tile_utils.js @@ -6,6 +6,7 @@ import _ from 'lodash'; import { DECIMAL_DEGREES_PRECISION } from '../../../../common/constants'; +import { clampToLatBounds } from '../../../elasticsearch_geo_utils'; const ZOOM_TILE_KEY_INDEX = 0; const X_TILE_KEY_INDEX = 1; @@ -87,7 +88,7 @@ function sec(value) { } function latitudeToTile(lat, tileCount) { - const radians = (lat * Math.PI) / 180; + const radians = (clampToLatBounds(lat) * Math.PI) / 180; const y = ((1 - Math.log(Math.tan(radians) + sec(radians)) / Math.PI) / 2) * tileCount; return Math.floor(y); } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/geo_tile_utils.test.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/geo_tile_utils.test.js index ae2623e168766..88a6ce048a178 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/geo_tile_utils.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/geo_tile_utils.test.js @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +jest.mock('../../../kibana_services', () => {}); + import { parseTileKey, getTileBoundingBox, expandToTileBoundaries } from './geo_tile_utils'; it('Should parse tile key', () => { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/convert_to_lines.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/convert_to_lines.js index 2057949c30c88..96a7f50cdf523 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/convert_to_lines.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/convert_to_lines.js @@ -5,9 +5,11 @@ */ import _ from 'lodash'; +import { extractPropertiesFromBucket } from '../../util/es_agg_utils'; const LAT_INDEX = 0; const LON_INDEX = 1; +const PEW_PEW_BUCKET_KEYS_TO_IGNORE = ['key', 'sourceCentroid']; function parsePointFromKey(key) { const split = key.split(','); @@ -25,25 +27,16 @@ export function convertToLines(esResponse) { const dest = parsePointFromKey(destBucket.key); const sourceBuckets = _.get(destBucket, 'sourceGrid.buckets', []); for (let j = 0; j < sourceBuckets.length; j++) { - const { key, sourceCentroid, ...rest } = sourceBuckets[j]; - - // flatten metrics - Object.keys(rest).forEach(key => { - if (_.has(rest[key], 'value')) { - rest[key] = rest[key].value; - } - }); - + const sourceBucket = sourceBuckets[j]; + const sourceCentroid = sourceBucket.sourceCentroid; lineFeatures.push({ type: 'Feature', geometry: { type: 'LineString', coordinates: [[sourceCentroid.location.lon, sourceCentroid.location.lat], dest], }, - id: `${dest.join()},${key}`, - properties: { - ...rest, - }, + id: `${dest.join()},${sourceBucket.key}`, + properties: extractPropertiesFromBucket(sourceBucket, PEW_PEW_BUCKET_KEYS_TO_IGNORE), }); } } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/convert_to_lines.test.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/convert_to_lines.test.ts new file mode 100644 index 0000000000000..5fbd5a3ad20c0 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/convert_to_lines.test.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// @ts-ignore +import { convertToLines } from './convert_to_lines'; + +const esResponse = { + aggregations: { + destSplit: { + buckets: [ + { + key: '43.68389896117151, 10.39269994944334', + doc_count: 2, + sourceGrid: { + buckets: [ + { + key: '4/9/3', + doc_count: 1, + terms_of_Carrier: { + buckets: [ + { + key: 'ES-Air', + doc_count: 1, + }, + ], + }, + sourceCentroid: { + location: { + lat: 68.15180202014744, + lon: 33.46390150487423, + }, + count: 1, + }, + avg_of_FlightDelayMin: { + value: 3, + }, + }, + ], + }, + }, + ], + }, + }, +}; + +it('Should convert elasticsearch aggregation response into feature collection of lines', () => { + const geoJson = convertToLines(esResponse); + expect(geoJson.featureCollection.features.length).toBe(1); + expect(geoJson.featureCollection.features[0]).toEqual({ + geometry: { + coordinates: [ + [33.46390150487423, 68.15180202014744], + [10.39269994944334, 43.68389896117151], + ], + type: 'LineString', + }, + id: '10.39269994944334,43.68389896117151,4/9/3', + properties: { + avg_of_FlightDelayMin: 3, + doc_count: 1, + terms_of_Carrier: 'ES-Air', + }, + type: 'Feature', + }); +}); 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 176ab62baf98c..53536b11aaca6 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 @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { SOURCE_DATA_ID_ORIGIN, ES_PEW_PEW, COUNT_PROP_NAME } from '../../../../common/constants'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { convertToLines } from './convert_to_lines'; -import { AggConfigs, Schemas } from 'ui/agg_types'; import { AbstractESAggSource } from '../es_agg_source'; import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property'; import { COLOR_GRADIENTS } from '../../styles/color_utils'; @@ -28,8 +27,6 @@ import { indexPatterns } from '../../../../../../../../src/plugins/data/public'; const MAX_GEOTILE_LEVEL = 29; -const aggSchemas = new Schemas([AbstractESAggSource.METRIC_SCHEMA_CONFIG]); - export class ESPewPewSource extends AbstractESAggSource { static type = ES_PEW_PEW; static title = i18n.translate('xpack.maps.source.pewPewTitle', { @@ -170,9 +167,6 @@ export class ESPewPewSource extends AbstractESAggSource { async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback) { const indexPattern = await this.getIndexPattern(); - const metricAggConfigs = this.createMetricAggConfigs(); - const aggConfigs = new AggConfigs(indexPattern, metricAggConfigs, aggSchemas.all); - const searchSource = await this._makeSearchSource(searchFilters, 0); searchSource.setField('aggs', { destSplit: { @@ -199,7 +193,7 @@ export class ESPewPewSource extends AbstractESAggSource { field: this._descriptor.sourceGeoField, }, }, - ...aggConfigs.toDsl(), + ...this.getValueAggsDsl(indexPattern), }, }, }, 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 288dd117da137..3533282436139 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 @@ -28,31 +28,7 @@ import { loadIndexSettings } from './load_index_settings'; import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants'; import { ESDocField } from '../../fields/es_doc_field'; - -function getField(indexPattern, fieldName) { - const field = indexPattern.fields.getByName(fieldName); - if (!field) { - throw new Error( - i18n.translate('xpack.maps.source.esSearch.fieldNotFoundMsg', { - defaultMessage: `Unable to find '{fieldName}' in index-pattern '{indexPatternTitle}'.`, - values: { fieldName, indexPatternTitle: indexPattern.title }, - }) - ); - } - return field; -} - -function addFieldToDSL(dsl, field) { - return !field.scripted - ? { ...dsl, field: field.name } - : { - ...dsl, - script: { - source: field.script, - lang: field.lang, - }, - }; -} +import { getField, addFieldToDSL } from '../../util/es_agg_utils'; function getDocValueAndSourceFields(indexPattern, fieldNames) { const docValueFields = []; 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 d78d3038f870d..782f2845ceeff 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 @@ -18,7 +18,7 @@ import { AggConfigs } from 'ui/agg_types'; import { i18n } from '@kbn/i18n'; import uuid from 'uuid/v4'; import { copyPersistentState } from '../../reducers/util'; -import { ES_GEO_FIELD_TYPE, METRIC_TYPE } from '../../../common/constants'; +import { ES_GEO_FIELD_TYPE, AGG_TYPE } from '../../../common/constants'; import { DataRequestAbortError } from '../util/data_request'; import { expandToTileBoundaries } from './es_geo_grid_source/geo_tile_utils'; @@ -270,7 +270,7 @@ export class AbstractESSource extends AbstractVectorSource { // Do not use field formatters for counting metrics if ( metricField && - (metricField.type === METRIC_TYPE.COUNT || metricField.type === METRIC_TYPE.UNIQUE_COUNT) + (metricField.type === AGG_TYPE.COUNT || metricField.type === AGG_TYPE.UNIQUE_COUNT) ) { return null; } @@ -347,13 +347,16 @@ export class AbstractESSource extends AbstractVectorSource { } getValueSuggestions = async (fieldName, query) => { - if (!fieldName) { + // fieldName could be an aggregation so it needs to be unpacked to expose raw field. + const metricField = this.getMetricFields().find(field => field.getName() === fieldName); + const realFieldName = metricField ? metricField.getESDocFieldName() : fieldName; + if (!realFieldName) { return []; } try { const indexPattern = await this.getIndexPattern(); - const field = indexPattern.fields.getByName(fieldName); + const field = indexPattern.fields.getByName(realFieldName); return await autocompleteService.getValueSuggestions({ indexPattern, field, 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 7d7a2e159d128..9cc2919404a94 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 @@ -6,46 +6,25 @@ import _ from 'lodash'; -import { AggConfigs, Schemas } from 'ui/agg_types'; import { i18n } from '@kbn/i18n'; -import { - COUNT_PROP_LABEL, - DEFAULT_MAX_BUCKETS_LIMIT, - FIELD_ORIGIN, - METRIC_TYPE, -} from '../../../common/constants'; +import { DEFAULT_MAX_BUCKETS_LIMIT, FIELD_ORIGIN, AGG_TYPE } from '../../../common/constants'; import { ESDocField } from '../fields/es_doc_field'; import { AbstractESAggSource, AGG_DELIMITER } from './es_agg_source'; +import { getField, addFieldToDSL, extractPropertiesFromBucket } from '../util/es_agg_utils'; const TERMS_AGG_NAME = 'join'; const FIELD_NAME_PREFIX = '__kbnjoin__'; const GROUP_BY_DELIMITER = '_groupby_'; +const TERMS_BUCKET_KEYS_TO_IGNORE = ['key', 'doc_count']; -const aggSchemas = new Schemas([ - AbstractESAggSource.METRIC_SCHEMA_CONFIG, - { - group: 'buckets', - name: 'segment', - title: 'Terms', - aggFilter: 'terms', - min: 1, - max: 1, - }, -]); - -export function extractPropertiesMap(rawEsData, propertyNames, countPropertyName) { +export function extractPropertiesMap(rawEsData, countPropertyName) { const propertiesMap = new Map(); _.get(rawEsData, ['aggregations', TERMS_AGG_NAME, 'buckets'], []).forEach(termBucket => { - const properties = {}; + const properties = extractPropertiesFromBucket(termBucket, TERMS_BUCKET_KEYS_TO_IGNORE); if (countPropertyName) { properties[countPropertyName] = termBucket.doc_count; } - propertyNames.forEach(propertyName => { - if (_.has(termBucket, [propertyName, 'value'])) { - properties[propertyName] = _.get(termBucket, [propertyName, 'value']); - } - }); propertiesMap.set(termBucket.key.toString(), properties); }); return propertiesMap; @@ -90,15 +69,27 @@ export class ESTermSource extends AbstractESAggSource { formatMetricKey(aggType, fieldName) { const metricKey = - aggType !== METRIC_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${fieldName}` : aggType; + aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${fieldName}` : aggType; return `${FIELD_NAME_PREFIX}${metricKey}${GROUP_BY_DELIMITER}${ this._descriptor.indexPatternTitle }.${this._termField.getName()}`; } formatMetricLabel(type, fieldName) { - const metricLabel = type !== METRIC_TYPE.COUNT ? `${type} ${fieldName}` : COUNT_PROP_LABEL; - return `${metricLabel} of ${this._descriptor.indexPatternTitle}:${this._termField.getName()}`; + switch (type) { + case AGG_TYPE.COUNT: + return i18n.translate('xpack.maps.source.esJoin.countLabel', { + defaultMessage: `Count of {indexPatternTitle}`, + values: { indexPatternTitle: this._descriptor.indexPatternTitle }, + }); + case AGG_TYPE.TERMS: + return i18n.translate('xpack.maps.source.esJoin.topTermLabel', { + defaultMessage: `Top {fieldName}`, + values: { fieldName }, + }); + default: + return `${type} ${fieldName}`; + } } async getPropertiesMap(searchFilters, leftSourceName, leftFieldName, registerCancelCallback) { @@ -108,9 +99,14 @@ export class ESTermSource extends AbstractESAggSource { const indexPattern = await this.getIndexPattern(); const searchSource = await this._makeSearchSource(searchFilters, 0); - const configStates = this._makeAggConfigs(); - const aggConfigs = new AggConfigs(indexPattern, configStates, aggSchemas.all); - searchSource.setField('aggs', aggConfigs.toDsl()); + const termsField = getField(indexPattern, this._termField.getName()); + const termsAgg = { size: DEFAULT_MAX_BUCKETS_LIMIT }; + searchSource.setField('aggs', { + [TERMS_AGG_NAME]: { + terms: addFieldToDSL(termsAgg, termsField), + aggs: { ...this.getValueAggsDsl(indexPattern) }, + }, + }); const rawEsData = await this._runEsQuery({ requestId: this.getId(), @@ -120,19 +116,9 @@ export class ESTermSource extends AbstractESAggSource { requestDescription: this._getRequestDescription(leftSourceName, leftFieldName), }); - const metricPropertyNames = configStates - .filter(configState => { - return configState.schema === 'metric' && configState.type !== METRIC_TYPE.COUNT; - }) - .map(configState => { - return configState.id; - }); - const countConfigState = configStates.find(configState => { - return configState.type === METRIC_TYPE.COUNT; - }); - const countPropertyName = _.get(countConfigState, 'id'); + const countPropertyName = this.formatMetricKey(AGG_TYPE.COUNT); return { - propertiesMap: extractPropertiesMap(rawEsData, metricPropertyNames, countPropertyName), + propertiesMap: extractPropertiesMap(rawEsData, countPropertyName), }; } @@ -164,23 +150,6 @@ export class ESTermSource extends AbstractESAggSource { }); } - _makeAggConfigs() { - const metricAggConfigs = this.createMetricAggConfigs(); - return [ - ...metricAggConfigs, - { - id: TERMS_AGG_NAME, - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: this._termField.getName(), - size: DEFAULT_MAX_BUCKETS_LIMIT, - }, - }, - ]; - } - async getDisplayName() { //no need to localize. this is never rendered. return `es_table ${this._descriptor.indexPatternId}`; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js index ffaaf2d705b5c..39cc301d458cb 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js @@ -8,9 +8,6 @@ import { ESTermSource, extractPropertiesMap } from './es_term_source'; jest.mock('ui/new_platform'); jest.mock('../vector_layer', () => {}); -jest.mock('ui/agg_types', () => ({ - Schemas: function() {}, -})); jest.mock('ui/timefilter', () => {}); const indexPatternTitle = 'myIndex'; @@ -44,7 +41,7 @@ describe('getMetricFields', () => { expect(metrics[0].getAggType()).toEqual('count'); expect(metrics[0].getName()).toEqual('__kbnjoin__count_groupby_myIndex.myTermField'); - expect(await metrics[0].getLabel()).toEqual('count of myIndex:myTermField'); + expect(await metrics[0].getLabel()).toEqual('Count of myIndex'); }); it('should remove incomplete metric configurations', async () => { @@ -65,84 +62,13 @@ describe('getMetricFields', () => { expect(metrics[1].getAggType()).toEqual('count'); expect(metrics[1].getName()).toEqual('__kbnjoin__count_groupby_myIndex.myTermField'); - expect(await metrics[1].getLabel()).toEqual('count of myIndex:myTermField'); - }); -}); - -describe('_makeAggConfigs', () => { - describe('no metrics', () => { - let aggConfigs; - beforeAll(() => { - const source = new ESTermSource({ - indexPatternTitle: indexPatternTitle, - term: termFieldName, - }); - aggConfigs = source._makeAggConfigs(); - }); - - it('should make default "count" metric agg config', () => { - expect(aggConfigs.length).toBe(2); - expect(aggConfigs[0]).toEqual({ - id: '__kbnjoin__count_groupby_myIndex.myTermField', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }); - }); - - it('should make "terms" buckets agg config', () => { - expect(aggConfigs.length).toBe(2); - expect(aggConfigs[1]).toEqual({ - id: 'join', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: termFieldName, - size: 10000, - }, - }); - }); - }); - - describe('metrics', () => { - let aggConfigs; - beforeAll(() => { - const source = new ESTermSource({ - indexPatternTitle: indexPatternTitle, - term: 'myTermField', - metrics: metricExamples, - }); - aggConfigs = source._makeAggConfigs(); - }); - - it('should ignore invalid metrics configs', () => { - expect(aggConfigs.length).toBe(3); - }); - - it('should make agg config for each valid metric', () => { - expect(aggConfigs[0]).toEqual({ - id: '__kbnjoin__sum_of_myFieldGettingSummed_groupby_myIndex.myTermField', - enabled: true, - type: 'sum', - schema: 'metric', - params: { - field: sumFieldName, - }, - }); - expect(aggConfigs[1]).toEqual({ - id: '__kbnjoin__count_groupby_myIndex.myTermField', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }); - }); + expect(await metrics[1].getLabel()).toEqual('Count of myIndex'); }); }); describe('extractPropertiesMap', () => { + const minPropName = + '__kbnjoin__min_of_avlAirTemp_groupby_kibana_sample_data_ky_avl.kytcCountyNmbr'; const responseWithNumberTypes = { aggregations: { join: { @@ -150,14 +76,14 @@ describe('extractPropertiesMap', () => { { key: 109, doc_count: 1130, - '__kbnjoin__min_of_avlAirTemp_groupby_kibana_sample_data_ky_avl.kytcCountyNmbr': { + [minPropName]: { value: 36, }, }, { key: 62, doc_count: 448, - '__kbnjoin__min_of_avlAirTemp_groupby_kibana_sample_data_ky_avl.kytcCountyNmbr': { + [minPropName]: { value: 0, }, }, @@ -166,11 +92,10 @@ describe('extractPropertiesMap', () => { }, }; const countPropName = '__kbnjoin__count_groupby_kibana_sample_data_ky_avl.kytcCountyNmbr'; - const minPropName = - '__kbnjoin__min_of_avlAirTemp_groupby_kibana_sample_data_ky_avl.kytcCountyNmbr'; + let propertiesMap; beforeAll(() => { - propertiesMap = extractPropertiesMap(responseWithNumberTypes, [minPropName], countPropName); + propertiesMap = extractPropertiesMap(responseWithNumberTypes, countPropName); }); it('should create key for each join term', () => { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js index e137e15730827..dfc5c530cc90f 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js @@ -43,16 +43,8 @@ function getSymbolSizeIcons() { } export class DynamicSizeProperty extends DynamicStyleProperty { - constructor( - options, - styleName, - field, - getFieldMeta, - getFieldFormatter, - getValueSuggestions, - isSymbolizedAsIcon - ) { - super(options, styleName, field, getFieldMeta, getFieldFormatter, getValueSuggestions); + constructor(options, styleName, field, getFieldMeta, getFieldFormatter, isSymbolizedAsIcon) { + super(options, styleName, field, getFieldMeta, getFieldFormatter); this._isSymbolizedAsIcon = isSymbolizedAsIcon; } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js index ef19e9b23b10d..af78c4c0e461e 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js @@ -13,21 +13,22 @@ import React from 'react'; import { OrdinalLegend } from './components/ordinal_legend'; import { CategoricalLegend } from './components/categorical_legend'; import { OrdinalFieldMetaOptionsPopover } from '../components/ordinal_field_meta_options_popover'; +import { ESAggMetricField } from '../../../fields/es_agg_field'; export class DynamicStyleProperty extends AbstractStyleProperty { static type = STYLE_TYPE.DYNAMIC; - constructor(options, styleName, field, getFieldMeta, getFieldFormatter, source) { + constructor(options, styleName, field, getFieldMeta, getFieldFormatter) { super(options, styleName); this._field = field; this._getFieldMeta = getFieldMeta; this._getFieldFormatter = getFieldFormatter; - this._source = source; } getValueSuggestions = query => { const fieldName = this.getFieldName(); - return this._source && fieldName ? this._source.getValueSuggestions(fieldName, query) : []; + const fieldSource = this.getFieldSource(); + return fieldSource && fieldName ? fieldSource.getValueSuggestions(fieldName, query) : []; }; getFieldMeta() { @@ -38,6 +39,10 @@ export class DynamicStyleProperty extends AbstractStyleProperty { return this._field; } + getFieldSource() { + return this._field ? this._field.getSource() : null; + } + getFieldName() { return this._field ? this._field.getName() : ''; } @@ -180,9 +185,10 @@ export class DynamicStyleProperty extends AbstractStyleProperty { } _pluckOrdinalStyleMetaFromFieldMetaData(fieldMetaData) { - const realFieldName = this._field.getESDocFieldName - ? this._field.getESDocFieldName() - : this._field.getName(); + const realFieldName = + this._field instanceof ESAggMetricField + ? this._field.getESDocFieldName() + : this._field.getName(); const stats = fieldMetaData[realFieldName]; if (!stats) { return null; @@ -203,12 +209,15 @@ export class DynamicStyleProperty extends AbstractStyleProperty { } _pluckCategoricalStyleMetaFromFieldMetaData(fieldMetaData) { - const name = this.getField().getName(); - if (!fieldMetaData[name] || !fieldMetaData[name].buckets) { + const realFieldName = + this._field instanceof ESAggMetricField + ? this._field.getESDocFieldName() + : this._field.getName(); + if (!fieldMetaData[realFieldName] || !fieldMetaData[realFieldName].buckets) { return null; } - const ordered = fieldMetaData[name].buckets.map(bucket => { + const ordered = fieldMetaData[realFieldName].buckets.map(bucket => { return { key: bucket.key, count: bucket.doc_count, diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js index 62651fdd702d6..053aa114d94ae 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js @@ -625,7 +625,6 @@ export class VectorStyle extends AbstractStyle { field, this._getFieldMeta, this._getFieldFormatter, - this._source, isSymbolizedAsIcon ); } else { @@ -645,8 +644,7 @@ export class VectorStyle extends AbstractStyle { styleName, field, this._getFieldMeta, - this._getFieldFormatter, - this._source + this._getFieldFormatter ); } else { throw new Error(`${descriptor} not implemented`); @@ -678,8 +676,7 @@ export class VectorStyle extends AbstractStyle { VECTOR_STYLES.LABEL_TEXT, field, this._getFieldMeta, - this._getFieldFormatter, - this._source + this._getFieldFormatter ); } else { throw new Error(`${descriptor} not implemented`); @@ -698,8 +695,7 @@ export class VectorStyle extends AbstractStyle { VECTOR_STYLES.ICON, field, this._getFieldMeta, - this._getFieldFormatter, - this._source + this._getFieldFormatter ); } else { throw new Error(`${descriptor} not implemented`); 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 7cfb60910c155..229c84fe234bd 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 @@ -5,7 +5,7 @@ */ import { ESTooltipProperty } from './es_tooltip_property'; -import { METRIC_TYPE } from '../../../common/constants'; +import { AGG_TYPE } from '../../../common/constants'; export class ESAggMetricTooltipProperty extends ESTooltipProperty { constructor(propertyKey, propertyName, rawValue, indexPattern, metricField) { @@ -22,8 +22,8 @@ export class ESAggMetricTooltipProperty extends ESTooltipProperty { return '-'; } if ( - this._metricField.getAggType() === METRIC_TYPE.COUNT || - this._metricField.getAggType() === METRIC_TYPE.UNIQUE_COUNT + this._metricField.getAggType() === AGG_TYPE.COUNT || + this._metricField.getAggType() === AGG_TYPE.UNIQUE_COUNT ) { return this._rawValue; } diff --git a/x-pack/legacy/plugins/maps/public/layers/util/es_agg_utils.test.ts b/x-pack/legacy/plugins/maps/public/layers/util/es_agg_utils.test.ts new file mode 100644 index 0000000000000..201d6907981a2 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/util/es_agg_utils.test.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { extractPropertiesFromBucket } from './es_agg_utils'; + +describe('extractPropertiesFromBucket', () => { + test('Should ignore specified keys', () => { + const properties = extractPropertiesFromBucket({ key: '4/4/6' }, ['key']); + expect(properties).toEqual({}); + }); + + test('Should extract metric aggregation values', () => { + const properties = extractPropertiesFromBucket({ avg_of_bytes: { value: 5359 } }); + expect(properties).toEqual({ + avg_of_bytes: 5359, + }); + }); + + test('Should extract bucket aggregation values', () => { + const properties = extractPropertiesFromBucket({ + 'terms_of_machine.os.keyword': { + buckets: [ + { + key: 'win xp', + doc_count: 16, + }, + ], + }, + }); + expect(properties).toEqual({ + 'terms_of_machine.os.keyword': 'win xp', + }); + }); +}); diff --git a/x-pack/legacy/plugins/maps/public/layers/util/es_agg_utils.ts b/x-pack/legacy/plugins/maps/public/layers/util/es_agg_utils.ts new file mode 100644 index 0000000000000..7af176acfaf46 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/util/es_agg_utils.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { i18n } from '@kbn/i18n'; +import _ from 'lodash'; +import { IndexPattern, IFieldType } from '../../../../../../../src/plugins/data/public'; + +export function getField(indexPattern: IndexPattern, fieldName: string) { + const field = indexPattern.fields.getByName(fieldName); + if (!field) { + throw new Error( + i18n.translate('xpack.maps.source.esSearch.fieldNotFoundMsg', { + defaultMessage: `Unable to find '{fieldName}' in index-pattern '{indexPatternTitle}'.`, + values: { fieldName, indexPatternTitle: indexPattern.title }, + }) + ); + } + return field; +} + +export function addFieldToDSL(dsl: object, field: IFieldType) { + return !field.scripted + ? { ...dsl, field: field.name } + : { + ...dsl, + script: { + source: field.script, + lang: field.lang, + }, + }; +} + +export function extractPropertiesFromBucket(bucket: any, ignoreKeys: string[] = []) { + const properties: Record = {}; + for (const key in bucket) { + if (ignoreKeys.includes(key) || !bucket.hasOwnProperty(key)) { + continue; + } + + if (_.has(bucket[key], 'value')) { + properties[key] = bucket[key].value; + } else if (_.has(bucket[key], 'buckets')) { + properties[key] = _.get(bucket[key], 'buckets[0].key'); + } else { + properties[key] = bucket[key]; + } + } + return properties; +} diff --git a/x-pack/legacy/plugins/maps/public/layers/util/is_metric_countable.js b/x-pack/legacy/plugins/maps/public/layers/util/is_metric_countable.js index 54d8794b1e3cf..69ccb8890d10c 100644 --- a/x-pack/legacy/plugins/maps/public/layers/util/is_metric_countable.js +++ b/x-pack/legacy/plugins/maps/public/layers/util/is_metric_countable.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { METRIC_TYPE } from '../../../common/constants'; +import { AGG_TYPE } from '../../../common/constants'; export function isMetricCountable(aggType) { - return [METRIC_TYPE.COUNT, METRIC_TYPE.SUM, METRIC_TYPE.UNIQUE_COUNT].includes(aggType); + return [AGG_TYPE.COUNT, AGG_TYPE.SUM, AGG_TYPE.UNIQUE_COUNT].includes(aggType); } diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index 1698d52ea4406..e1a30c8aef1d3 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -365,8 +365,10 @@ export class VectorLayer extends AbstractLayer { onLoadError, registerCancelCallback, dataFilters, + isRequestStillActive, }) { - const requestToken = Symbol(`layer-${this.getId()}-${SOURCE_DATA_ID_ORIGIN}`); + const dataRequestId = SOURCE_DATA_ID_ORIGIN; + const requestToken = Symbol(`layer-${this.getId()}-${dataRequestId}`); const searchFilters = this._getSearchFilters(dataFilters); const prevDataRequest = this.getSourceDataRequest(); const canSkipFetch = await canSkipSourceUpdate({ @@ -382,22 +384,25 @@ export class VectorLayer extends AbstractLayer { } try { - startLoading(SOURCE_DATA_ID_ORIGIN, requestToken, searchFilters); + startLoading(dataRequestId, requestToken, searchFilters); const layerName = await this.getDisplayName(); const { data: sourceFeatureCollection, meta } = await this._source.getGeoJsonWithMeta( layerName, searchFilters, - registerCancelCallback.bind(null, requestToken) + registerCancelCallback.bind(null, requestToken), + () => { + return isRequestStillActive(dataRequestId, requestToken); + } ); const layerFeatureCollection = assignFeatureIds(sourceFeatureCollection); - stopLoading(SOURCE_DATA_ID_ORIGIN, requestToken, layerFeatureCollection, meta); + stopLoading(dataRequestId, requestToken, layerFeatureCollection, meta); return { refreshed: true, featureCollection: layerFeatureCollection, }; } catch (error) { if (!(error instanceof DataRequestAbortError)) { - onLoadError(SOURCE_DATA_ID_ORIGIN, requestToken, error.message); + onLoadError(dataRequestId, requestToken, error.message); } return { refreshed: false, diff --git a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js index d1048a759beca..4074344916390 100644 --- a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js +++ b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js @@ -125,6 +125,21 @@ export const getRefreshConfig = ({ map }) => { export const getRefreshTimerLastTriggeredAt = ({ map }) => map.mapState.refreshTimerLastTriggeredAt; +function getLayerDescriptor(state = {}, layerId) { + const layerListRaw = getLayerListRaw(state); + return layerListRaw.find(layer => layer.id === layerId); +} + +export function getDataRequestDescriptor(state = {}, layerId, dataId) { + const layerDescriptor = getLayerDescriptor(state, layerId); + if (!layerDescriptor || !layerDescriptor.__dataRequests) { + return; + } + return _.get(layerDescriptor, '__dataRequests', []).find(dataRequest => { + return dataRequest.dataId === dataId; + }); +} + export const getDataFilters = createSelector( getMapExtent, getMapBuffer, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 4a627d48c3cf0..3c7d0ce47acb7 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7263,7 +7263,6 @@ "xpack.maps.source.esGrid.finestDropdownOption": "最も細かい", "xpack.maps.source.esGrid.geospatialFieldLabel": "地理空間フィールド", "xpack.maps.source.esGrid.indexPatternLabel": "インデックスパターン", - "xpack.maps.source.esGrid.inspectorDescription": "Elasticsearch ジオグリッド集約リクエスト", "xpack.maps.source.esGrid.metricsLabel": "メトリック", "xpack.maps.source.esGrid.noIndexPatternErrorMessage": "インデックスパターン {id} が見つかりません", "xpack.maps.source.esGrid.resolutionParamErrorMessage": "グリッド解像度パラメーターが認識されません: {resolution}", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e0ef4a7a1ebdb..b262be626aa53 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7263,7 +7263,6 @@ "xpack.maps.source.esGrid.finestDropdownOption": "最精致化", "xpack.maps.source.esGrid.geospatialFieldLabel": "地理空间字段", "xpack.maps.source.esGrid.indexPatternLabel": "索引模式", - "xpack.maps.source.esGrid.inspectorDescription": "Elasticsearch 地理网格聚合请求", "xpack.maps.source.esGrid.metricsLabel": "指标", "xpack.maps.source.esGrid.noIndexPatternErrorMessage": "找不到索引模式 {id}", "xpack.maps.source.esGrid.resolutionParamErrorMessage": "无法识别网格分辨率参数:{resolution}", From 47aa5b46df1dcafe0cf26043e00cb113da6bad79 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 26 Feb 2020 15:59:22 +0100 Subject: [PATCH 02/64] Saved query management: Discard pending listing requests (#58433) * discard pending listing requests * consolidate requests --- .../saved_query/saved_query_service.test.ts | 27 +++++++++++++++---- .../query/saved_query/saved_query_service.ts | 13 +++++---- .../data/public/query/saved_query/types.ts | 2 +- .../saved_query_management_component.tsx | 20 +++++++++++--- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/plugins/data/public/query/saved_query/saved_query_service.test.ts b/src/plugins/data/public/query/saved_query/saved_query_service.test.ts index a6b8de32a00bd..c983cc4ea8fc5 100644 --- a/src/plugins/data/public/query/saved_query/saved_query_service.test.ts +++ b/src/plugins/data/public/query/saved_query/saved_query_service.test.ts @@ -169,15 +169,27 @@ describe('saved query service', () => { it('should find and return saved queries without search text or pagination parameters', async () => { mockSavedObjectsClient.find.mockReturnValue({ savedObjects: [{ id: 'foo', attributes: savedQueryAttributes }], + total: 5, }); const response = await findSavedQueries(); - expect(response).toEqual([{ id: 'foo', attributes: savedQueryAttributes }]); + expect(response.queries).toEqual([{ id: 'foo', attributes: savedQueryAttributes }]); + }); + + it('should return the total count along with the requested queries', async () => { + mockSavedObjectsClient.find.mockReturnValue({ + savedObjects: [{ id: 'foo', attributes: savedQueryAttributes }], + total: 5, + }); + + const response = await findSavedQueries(); + expect(response.total).toEqual(5); }); it('should find and return saved queries with search text matching the title field', async () => { mockSavedObjectsClient.find.mockReturnValue({ savedObjects: [{ id: 'foo', attributes: savedQueryAttributes }], + total: 5, }); const response = await findSavedQueries('foo'); expect(mockSavedObjectsClient.find).toHaveBeenCalledWith({ @@ -188,7 +200,7 @@ describe('saved query service', () => { sortField: '_score', type: 'query', }); - expect(response).toEqual([{ id: 'foo', attributes: savedQueryAttributes }]); + expect(response.queries).toEqual([{ id: 'foo', attributes: savedQueryAttributes }]); }); it('should find and return parsed filters and timefilters items', async () => { const serializedSavedQueryAttributesWithFilters = { @@ -198,16 +210,20 @@ describe('saved query service', () => { }; mockSavedObjectsClient.find.mockReturnValue({ savedObjects: [{ id: 'foo', attributes: serializedSavedQueryAttributesWithFilters }], + total: 5, }); const response = await findSavedQueries('bar'); - expect(response).toEqual([{ id: 'foo', attributes: savedQueryAttributesWithFilters }]); + expect(response.queries).toEqual([ + { id: 'foo', attributes: savedQueryAttributesWithFilters }, + ]); }); it('should return an array of saved queries', async () => { mockSavedObjectsClient.find.mockReturnValue({ savedObjects: [{ id: 'foo', attributes: savedQueryAttributes }], + total: 5, }); const response = await findSavedQueries(); - expect(response).toEqual( + expect(response.queries).toEqual( expect.objectContaining([ { attributes: { @@ -226,6 +242,7 @@ describe('saved query service', () => { { id: 'foo', attributes: savedQueryAttributes }, { id: 'bar', attributes: savedQueryAttributesBar }, ], + total: 5, }); const response = await findSavedQueries(undefined, 2, 1); expect(mockSavedObjectsClient.find).toHaveBeenCalledWith({ @@ -236,7 +253,7 @@ describe('saved query service', () => { sortField: '_score', type: 'query', }); - expect(response).toEqual( + expect(response.queries).toEqual( expect.objectContaining([ { attributes: { diff --git a/src/plugins/data/public/query/saved_query/saved_query_service.ts b/src/plugins/data/public/query/saved_query/saved_query_service.ts index 80dec1c9373ea..4d3a8f441ce5e 100644 --- a/src/plugins/data/public/query/saved_query/saved_query_service.ts +++ b/src/plugins/data/public/query/saved_query/saved_query_service.ts @@ -95,7 +95,7 @@ export const createSavedQueryService = ( searchText: string = '', perPage: number = 50, activePage: number = 1 - ): Promise => { + ): Promise<{ total: number; queries: SavedQuery[] }> => { const response = await savedObjectsClient.find({ type: 'query', search: searchText, @@ -105,10 +105,13 @@ export const createSavedQueryService = ( page: activePage, }); - return response.savedObjects.map( - (savedObject: { id: string; attributes: SerializedSavedQueryAttributes }) => - parseSavedQueryObject(savedObject) - ); + return { + total: response.total, + queries: response.savedObjects.map( + (savedObject: { id: string; attributes: SerializedSavedQueryAttributes }) => + parseSavedQueryObject(savedObject) + ), + }; }; const getSavedQuery = async (id: string): Promise => { diff --git a/src/plugins/data/public/query/saved_query/types.ts b/src/plugins/data/public/query/saved_query/types.ts index d05eada7b29e6..6ac5e51d5c312 100644 --- a/src/plugins/data/public/query/saved_query/types.ts +++ b/src/plugins/data/public/query/saved_query/types.ts @@ -46,7 +46,7 @@ export interface SavedQueryService { searchText?: string, perPage?: number, activePage?: number - ) => Promise; + ) => Promise<{ total: number; queries: SavedQuery[] }>; getSavedQuery: (id: string) => Promise; deleteSavedQuery: (id: string) => Promise<{}>; getSavedQueryCount: () => Promise; diff --git a/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx b/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx index 2a11531ee336d..9347ef5974261 100644 --- a/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx +++ b/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx @@ -33,7 +33,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import React, { FunctionComponent, useEffect, useState, Fragment } from 'react'; +import React, { FunctionComponent, useEffect, useState, Fragment, useRef } from 'react'; import { sortBy } from 'lodash'; import { SavedQuery, SavedQueryService } from '../..'; import { SavedQueryListItem } from './saved_query_list_item'; @@ -62,14 +62,25 @@ export const SavedQueryManagementComponent: FunctionComponent = ({ const [savedQueries, setSavedQueries] = useState([] as SavedQuery[]); const [count, setTotalCount] = useState(0); const [activePage, setActivePage] = useState(0); + const cancelPendingListingRequest = useRef<() => void>(() => {}); useEffect(() => { const fetchCountAndSavedQueries = async () => { - const savedQueryCount = await savedQueryService.getSavedQueryCount(); - setTotalCount(savedQueryCount); + cancelPendingListingRequest.current(); + let requestGotCancelled = false; + cancelPendingListingRequest.current = () => { + requestGotCancelled = true; + }; + + const { + total: savedQueryCount, + queries: savedQueryItems, + } = await savedQueryService.findSavedQueries('', perPage, activePage + 1); + + if (requestGotCancelled) return; - const savedQueryItems = await savedQueryService.findSavedQueries('', perPage, activePage + 1); const sortedSavedQueryItems = sortBy(savedQueryItems, 'attributes.title'); + setTotalCount(savedQueryCount); setSavedQueries(sortedSavedQueryItems); }; if (isOpen) { @@ -103,6 +114,7 @@ export const SavedQueryManagementComponent: FunctionComponent = ({ ); const onDeleteSavedQuery = async (savedQuery: SavedQuery) => { + cancelPendingListingRequest.current(); setSavedQueries( savedQueries.filter(currentSavedQuery => currentSavedQuery.id !== savedQuery.id) ); From 8524303b6e5cac434353d57700a31e907ab93f5a Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Wed, 26 Feb 2020 16:22:35 +0100 Subject: [PATCH 03/64] Allow savedObjects types registration from NP (#57430) * expose `registerType` API * expose `getTypeRegistry` API * change SavedObjectMigrationFn signature to add context * fix exported types * update generated doc * update migration documentation * fix legacy service test * fix typings * update service setup description * add saved_objects server folder convention * fix unit test * documentation NITs * add typeRegistry to SavedObjectClientWrapperOptions --- ...-plugin-server.isavedobjecttyperegistry.md | 13 ++ .../core/server/kibana-plugin-server.md | 7 +- ...-server.savedobjectmigrationcontext.log.md | 13 ++ ...ugin-server.savedobjectmigrationcontext.md | 20 ++ ...na-plugin-server.savedobjectmigrationfn.md | 21 +- ...server.savedobjectsclientwrapperoptions.md | 1 + ...bjectsclientwrapperoptions.typeregistry.md | 11 ++ ...-plugin-server.savedobjectsservicesetup.md | 24 ++- ...r.savedobjectsservicesetup.registertype.md | 60 ++++++ ...avedobjectsservicestart.gettyperegistry.md | 13 ++ ...-plugin-server.savedobjectsservicestart.md | 1 + ...ver.savedobjecttyperegistry.getalltypes.md | 17 ++ ...server.savedobjecttyperegistry.getindex.md | 24 +++ ...-server.savedobjecttyperegistry.gettype.md | 24 +++ ...server.savedobjecttyperegistry.ishidden.md | 24 +++ ...dobjecttyperegistry.isnamespaceagnostic.md | 24 +++ ...a-plugin-server.savedobjecttyperegistry.md | 25 +++ ...er.savedobjecttyperegistry.registertype.md | 24 +++ src/core/CONVENTIONS.md | 43 +++++ src/core/MIGRATION.md | 3 + src/core/MIGRATION_EXAMPLES.md | 181 ++++++++++++++++++ src/core/server/index.ts | 2 + src/core/server/legacy/legacy_service.ts | 3 +- src/core/server/mocks.ts | 8 +- src/core/server/plugins/plugin_context.ts | 2 + .../__snapshots__/utils.test.ts.snap | 6 +- src/core/server/saved_objects/index.ts | 6 +- .../migrations/core/document_migrator.test.ts | 2 +- .../migrations/core/document_migrator.ts | 3 +- .../server/saved_objects/migrations/index.ts | 6 +- .../server/saved_objects/migrations/types.ts | 33 +++- .../saved_objects_service.mock.ts | 5 +- .../saved_objects_service.test.ts | 13 +- .../saved_objects/saved_objects_service.ts | 95 ++++++--- .../saved_objects_type_registry.mock.ts | 5 +- .../saved_objects_type_registry.ts | 13 +- .../lib/scoped_client_provider.test.js | 12 ++ .../service/lib/scoped_client_provider.ts | 15 +- src/core/server/saved_objects/types.ts | 21 +- src/core/server/saved_objects/utils.test.ts | 47 ++++- src/core/server/saved_objects/utils.ts | 20 +- src/core/server/server.api.md | 20 +- src/legacy/server/kbn_server.d.ts | 1 - .../saved_objects/saved_objects_mixin.js | 2 +- .../saved_objects/saved_objects_mixin.test.js | 7 +- 45 files changed, 841 insertions(+), 79 deletions(-) create mode 100644 docs/development/core/server/kibana-plugin-server.isavedobjecttyperegistry.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectmigrationcontext.log.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectmigrationcontext.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.typeregistry.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.gettyperegistry.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.getalltypes.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.getindex.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.gettype.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.ishidden.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.isnamespaceagnostic.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.registertype.md diff --git a/docs/development/core/server/kibana-plugin-server.isavedobjecttyperegistry.md b/docs/development/core/server/kibana-plugin-server.isavedobjecttyperegistry.md new file mode 100644 index 0000000000000..bbcba50c81027 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.isavedobjecttyperegistry.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ISavedObjectTypeRegistry](./kibana-plugin-server.isavedobjecttyperegistry.md) + +## ISavedObjectTypeRegistry type + +See [SavedObjectTypeRegistry](./kibana-plugin-server.savedobjecttyperegistry.md) for documentation. + +Signature: + +```typescript +export declare type ISavedObjectTypeRegistry = Pick; +``` diff --git a/docs/development/core/server/kibana-plugin-server.md b/docs/development/core/server/kibana-plugin-server.md index 9ec443d6482e8..15a1fd0506256 100644 --- a/docs/development/core/server/kibana-plugin-server.md +++ b/docs/development/core/server/kibana-plugin-server.md @@ -27,6 +27,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) | | | [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) | | | [SavedObjectsSerializer](./kibana-plugin-server.savedobjectsserializer.md) | A serializer that can be used to manually convert [raw](./kibana-plugin-server.savedobjectsrawdoc.md) or [sanitized](./kibana-plugin-server.savedobjectsanitizeddoc.md) documents to the other kind. | +| [SavedObjectTypeRegistry](./kibana-plugin-server.savedobjecttyperegistry.md) | Registry holding information about all the registered [saved object types](./kibana-plugin-server.savedobjectstype.md). | | [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). | ## Enumerations @@ -108,6 +109,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [RouteValidatorOptions](./kibana-plugin-server.routevalidatoroptions.md) | Additional options for the RouteValidator class to modify its default behaviour. | | [SavedObject](./kibana-plugin-server.savedobject.md) | | | [SavedObjectAttributes](./kibana-plugin-server.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. | +| [SavedObjectMigrationContext](./kibana-plugin-server.savedobjectmigrationcontext.md) | Migration context provided when invoking a [migration handler](./kibana-plugin-server.savedobjectmigrationfn.md) | | [SavedObjectMigrationMap](./kibana-plugin-server.savedobjectmigrationmap.md) | A map of [migration functions](./kibana-plugin-server.savedobjectmigrationfn.md) to be used for a given type. The map's keys must be valid semver versions.For a given document, only migrations with a higher version number than that of the document will be applied. Migrations are executed in order, starting from the lowest version and ending with the highest one. | | [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) | A reference to another saved object. | | [SavedObjectsBaseOptions](./kibana-plugin-server.savedobjectsbaseoptions.md) | | @@ -143,7 +145,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) | A raw document as represented directly in the saved object index. | | [SavedObjectsRepositoryFactory](./kibana-plugin-server.savedobjectsrepositoryfactory.md) | Factory provided when invoking a [client factory provider](./kibana-plugin-server.savedobjectsclientfactoryprovider.md) See [SavedObjectsServiceSetup.setClientFactoryProvider](./kibana-plugin-server.savedobjectsservicesetup.setclientfactoryprovider.md) | | [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) | Options to control the "resolve import" operation. | -| [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) | Saved Objects is Kibana's data persistence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods for creating and registering Saved Object client wrappers. | +| [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) | Saved Objects is Kibana's data persistence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods for registering Saved Object types, creating and registering Saved Object client wrappers and factories. | | [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceStart API provides a scoped Saved Objects client for interacting with Saved Objects. | | [SavedObjectsType](./kibana-plugin-server.savedobjectstype.md) | | | [SavedObjectsTypeMappingDefinition](./kibana-plugin-server.savedobjectstypemappingdefinition.md) | Describe a saved object type mapping. | @@ -195,6 +197,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ICustomClusterClient](./kibana-plugin-server.icustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-server.clusterclient.md). | | [IsAuthenticated](./kibana-plugin-server.isauthenticated.md) | Returns authentication status for a request. | | [ISavedObjectsRepository](./kibana-plugin-server.isavedobjectsrepository.md) | See [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) | +| [ISavedObjectTypeRegistry](./kibana-plugin-server.isavedobjecttyperegistry.md) | See [SavedObjectTypeRegistry](./kibana-plugin-server.savedobjecttyperegistry.md) for documentation. | | [IScopedClusterClient](./kibana-plugin-server.iscopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). | | [KibanaRequestRouteOptions](./kibana-plugin-server.kibanarequestrouteoptions.md) | Route options: If 'GET' or 'OPTIONS' method, body options won't be returned. | | [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) | Creates an object containing request response payload, HTTP headers, error details, and other data transmitted to the client. | @@ -226,7 +229,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [RouteValidatorFullConfig](./kibana-plugin-server.routevalidatorfullconfig.md) | Route validations config and options merged into one object | | [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) | Type definition for a Saved Object attribute value | | [SavedObjectAttributeSingle](./kibana-plugin-server.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) | -| [SavedObjectMigrationFn](./kibana-plugin-server.savedobjectmigrationfn.md) | A migration function defined for a [saved objects type](./kibana-plugin-server.savedobjectstype.md) used to migrate it's | +| [SavedObjectMigrationFn](./kibana-plugin-server.savedobjectmigrationfn.md) | A migration function for a [saved object type](./kibana-plugin-server.savedobjectstype.md) used to migrate it to a given version | | [SavedObjectSanitizedDoc](./kibana-plugin-server.savedobjectsanitizeddoc.md) | | | [SavedObjectsClientContract](./kibana-plugin-server.savedobjectsclientcontract.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state.\#\# SavedObjectsClient errorsSince the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to to application code. Ideally, all errors will be either:1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md)Type 1 errors are inevitable, but since all expected/handle-able errors should be Type 2 the isXYZError() helpers exposed at SavedObjectsErrorHelpers should be used to understand and manage error responses from the SavedObjectsClient.Type 2 errors are decorated versions of the source error, so if the elasticsearch client threw an error it will be decorated based on its type. That means that rather than looking for error.body.error.type or doing substring checks on error.body.error.reason, just use the helpers to understand the meaning of the error:\`\`\`js if (SavedObjectsErrorHelpers.isNotFoundError(error)) { // handle 404 }if (SavedObjectsErrorHelpers.isNotAuthorizedError(error)) { // 401 handling should be automatic, but in case you wanted to know }// always rethrow the error unless you handle it throw error; \`\`\`\#\#\# 404s from missing indexFrom the perspective of application code and APIs the SavedObjectsClient is a black box that persists objects. One of the internal details that users have no control over is that we use an elasticsearch index for persistance and that index might be missing.At the time of writing we are in the process of transitioning away from the operating assumption that the SavedObjects index is always available. Part of this transition is handling errors resulting from an index missing. These used to trigger a 500 error in most cases, and in others cause 404s with different error messages.From my (Spencer) perspective, a 404 from the SavedObjectsApi is a 404; The object the request/call was targeting could not be found. This is why \#14141 takes special care to ensure that 404 errors are generic and don't distinguish between index missing or document missing.\#\#\# 503s from missing indexUnlike all other methods, create requests are supposed to succeed even when the Kibana index does not exist because it will be automatically created by elasticsearch. When that is not the case it is because Elasticsearch's action.auto_create_index setting prevents it from being created automatically so we throw a special 503 with the intention of informing the user that their Elasticsearch settings need to be updated.See [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) See [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) | | [SavedObjectsClientFactory](./kibana-plugin-server.savedobjectsclientfactory.md) | Describes the factory used to create instances of the Saved Objects Client. | diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectmigrationcontext.log.md b/docs/development/core/server/kibana-plugin-server.savedobjectmigrationcontext.log.md new file mode 100644 index 0000000000000..4e4eaa3ca91e6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectmigrationcontext.log.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectMigrationContext](./kibana-plugin-server.savedobjectmigrationcontext.md) > [log](./kibana-plugin-server.savedobjectmigrationcontext.log.md) + +## SavedObjectMigrationContext.log property + +logger instance to be used by the migration handler + +Signature: + +```typescript +log: SavedObjectsMigrationLogger; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectmigrationcontext.md b/docs/development/core/server/kibana-plugin-server.savedobjectmigrationcontext.md new file mode 100644 index 0000000000000..77698b37cd3c9 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectmigrationcontext.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectMigrationContext](./kibana-plugin-server.savedobjectmigrationcontext.md) + +## SavedObjectMigrationContext interface + +Migration context provided when invoking a [migration handler](./kibana-plugin-server.savedobjectmigrationfn.md) + +Signature: + +```typescript +export interface SavedObjectMigrationContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [log](./kibana-plugin-server.savedobjectmigrationcontext.log.md) | SavedObjectsMigrationLogger | logger instance to be used by the migration handler | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectmigrationfn.md b/docs/development/core/server/kibana-plugin-server.savedobjectmigrationfn.md index 629d748083737..838fa55a7f089 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectmigrationfn.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectmigrationfn.md @@ -4,10 +4,27 @@ ## SavedObjectMigrationFn type -A migration function defined for a [saved objects type](./kibana-plugin-server.savedobjectstype.md) used to migrate it's +A migration function for a [saved object type](./kibana-plugin-server.savedobjectstype.md) used to migrate it to a given version Signature: ```typescript -export declare type SavedObjectMigrationFn = (doc: SavedObjectUnsanitizedDoc, log: SavedObjectsMigrationLogger) => SavedObjectUnsanitizedDoc; +export declare type SavedObjectMigrationFn = (doc: SavedObjectUnsanitizedDoc, context: SavedObjectMigrationContext) => SavedObjectUnsanitizedDoc; ``` + +## Example + + +```typescript +const migrateProperty: SavedObjectMigrationFn = (doc, { log }) => { + if(doc.attributes.someProp === null) { + log.warn('Skipping migration'); + } else { + doc.attributes.someProp = migrateProperty(doc.attributes.someProp); + } + + return doc; +} + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.md index dfff863898a2b..67746126e79b4 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.md @@ -18,4 +18,5 @@ export interface SavedObjectsClientWrapperOptions | --- | --- | --- | | [client](./kibana-plugin-server.savedobjectsclientwrapperoptions.client.md) | SavedObjectsClientContract | | | [request](./kibana-plugin-server.savedobjectsclientwrapperoptions.request.md) | KibanaRequest | | +| [typeRegistry](./kibana-plugin-server.savedobjectsclientwrapperoptions.typeregistry.md) | ISavedObjectTypeRegistry | | diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.typeregistry.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.typeregistry.md new file mode 100644 index 0000000000000..afd6898699384 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.typeregistry.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientWrapperOptions](./kibana-plugin-server.savedobjectsclientwrapperoptions.md) > [typeRegistry](./kibana-plugin-server.savedobjectsclientwrapperoptions.typeregistry.md) + +## SavedObjectsClientWrapperOptions.typeRegistry property + +Signature: + +```typescript +typeRegistry: ISavedObjectTypeRegistry; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md index 9981bfee0cb7d..b6f2e7320c48a 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md @@ -4,7 +4,7 @@ ## SavedObjectsServiceSetup interface -Saved Objects is Kibana's data persistence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods for creating and registering Saved Object client wrappers. +Saved Objects is Kibana's data persistence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods for registering Saved Object types, creating and registering Saved Object client wrappers and factories. Signature: @@ -14,11 +14,9 @@ export interface SavedObjectsServiceSetup ## Remarks -Note: The Saved Object setup API's should only be used for creating and registering client wrappers. Constructing a Saved Objects client or repository for use within your own plugin won't have any of the registered wrappers applied and is considered an anti-pattern. Use the Saved Objects client from the [SavedObjectsServiceStart\#getScopedClient](./kibana-plugin-server.savedobjectsservicestart.md) method or the [route handler context](./kibana-plugin-server.requesthandlercontext.md) instead. +When plugins access the Saved Objects client, a new client is created using the factory provided to `setClientFactory` and wrapped by all wrappers registered through `addClientWrapper`. -When plugins access the Saved Objects client, a new client is created using the factory provided to `setClientFactory` and wrapped by all wrappers registered through `addClientWrapper`. To create a factory or wrapper, plugins will have to construct a Saved Objects client. First create a repository by calling `scopedRepository` or `internalRepository` and then use this repository as the argument to the [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) constructor. - -## Example +## Example 1 ```ts @@ -34,10 +32,26 @@ export class Plugin() { ``` +## Example 2 + + +```ts +import { SavedObjectsClient, CoreSetup } from 'src/core/server'; +import { mySoType } from './saved_objects' + +export class Plugin() { + setup: (core: CoreSetup) => { + core.savedObjects.registerType(mySoType); + } +} + +``` + ## Properties | Property | Type | Description | | --- | --- | --- | | [addClientWrapper](./kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md) | (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void | Add a [client wrapper factory](./kibana-plugin-server.savedobjectsclientwrapperfactory.md) with the given priority. | +| [registerType](./kibana-plugin-server.savedobjectsservicesetup.registertype.md) | (type: SavedObjectsType) => void | Register a [savedObjects type](./kibana-plugin-server.savedobjectstype.md) definition.See the [mappings format](./kibana-plugin-server.savedobjectstypemappingdefinition.md) and [migration format](./kibana-plugin-server.savedobjectmigrationmap.md) for more details about these. | | [setClientFactoryProvider](./kibana-plugin-server.savedobjectsservicesetup.setclientfactoryprovider.md) | (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void | Set the default [factory provider](./kibana-plugin-server.savedobjectsclientfactoryprovider.md) for creating Saved Objects clients. Only one provider can be set, subsequent calls to this method will fail. | diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md new file mode 100644 index 0000000000000..89102d292d634 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md @@ -0,0 +1,60 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) > [registerType](./kibana-plugin-server.savedobjectsservicesetup.registertype.md) + +## SavedObjectsServiceSetup.registerType property + +Register a [savedObjects type](./kibana-plugin-server.savedobjectstype.md) definition. + +See the [mappings format](./kibana-plugin-server.savedobjectstypemappingdefinition.md) and [migration format](./kibana-plugin-server.savedobjectmigrationmap.md) for more details about these. + +Signature: + +```typescript +registerType: (type: SavedObjectsType) => void; +``` + +## Remarks + +The type definition is an aggregation of the legacy savedObjects `schema`, `mappings` and `migration` concepts. This API is the single entry point to register saved object types in the new platform. + +## Example + + +```ts +// src/plugins/my_plugin/server/saved_objects/my_type.ts +import { SavedObjectsType } from 'src/core/server'; +import * as migrations from './migrations'; + +export const myType: SavedObjectsType = { + name: 'MyType', + hidden: false, + namespaceAgnostic: true, + mappings: { + properties: { + textField: { + type: 'text', + }, + boolField: { + type: 'boolean', + }, + }, + }, + migrations: { + '2.0.0': migrations.migrateToV2, + '2.1.0': migrations.migrateToV2_1 + }, +}; + +// src/plugins/my_plugin/server/plugin.ts +import { SavedObjectsClient, CoreSetup } from 'src/core/server'; +import { myType } from './saved_objects'; + +export class Plugin() { + setup: (core: CoreSetup) => { + core.savedObjects.registerType(myType); + } +} + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.gettyperegistry.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.gettyperegistry.md new file mode 100644 index 0000000000000..82e67bb307588 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.gettyperegistry.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) > [getTypeRegistry](./kibana-plugin-server.savedobjectsservicestart.gettyperegistry.md) + +## SavedObjectsServiceStart.getTypeRegistry property + +Returns the [registry](./kibana-plugin-server.isavedobjecttyperegistry.md) containing all registered [saved object types](./kibana-plugin-server.savedobjectstype.md) + +Signature: + +```typescript +getTypeRegistry: () => ISavedObjectTypeRegistry; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.md index ad34d76bb33f4..293255bb33c2a 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.md @@ -20,4 +20,5 @@ export interface SavedObjectsServiceStart | [createScopedRepository](./kibana-plugin-server.savedobjectsservicestart.createscopedrepository.md) | (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. | | [createSerializer](./kibana-plugin-server.savedobjectsservicestart.createserializer.md) | () => SavedObjectsSerializer | Creates a [serializer](./kibana-plugin-server.savedobjectsserializer.md) that is aware of all registered types. | | [getScopedClient](./kibana-plugin-server.savedobjectsservicestart.getscopedclient.md) | (req: KibanaRequest, options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract | Creates a [Saved Objects client](./kibana-plugin-server.savedobjectsclientcontract.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. If other plugins have registered Saved Objects client wrappers, these will be applied to extend the functionality of the client.A client that is already scoped to the incoming request is also exposed from the route handler context see [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md). | +| [getTypeRegistry](./kibana-plugin-server.savedobjectsservicestart.gettyperegistry.md) | () => ISavedObjectTypeRegistry | Returns the [registry](./kibana-plugin-server.isavedobjecttyperegistry.md) containing all registered [saved object types](./kibana-plugin-server.savedobjectstype.md) | diff --git a/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.getalltypes.md b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.getalltypes.md new file mode 100644 index 0000000000000..d71b392c40840 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.getalltypes.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectTypeRegistry](./kibana-plugin-server.savedobjecttyperegistry.md) > [getAllTypes](./kibana-plugin-server.savedobjecttyperegistry.getalltypes.md) + +## SavedObjectTypeRegistry.getAllTypes() method + +Return all [types](./kibana-plugin-server.savedobjectstype.md) currently registered. + +Signature: + +```typescript +getAllTypes(): SavedObjectsType[]; +``` +Returns: + +`SavedObjectsType[]` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.getindex.md b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.getindex.md new file mode 100644 index 0000000000000..3479600456c47 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.getindex.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectTypeRegistry](./kibana-plugin-server.savedobjecttyperegistry.md) > [getIndex](./kibana-plugin-server.savedobjecttyperegistry.getindex.md) + +## SavedObjectTypeRegistry.getIndex() method + +Returns the `indexPattern` property for given type, or `undefined` if the type is not registered. + +Signature: + +```typescript +getIndex(type: string): string | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | + +Returns: + +`string | undefined` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.gettype.md b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.gettype.md new file mode 100644 index 0000000000000..b32301a253731 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.gettype.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectTypeRegistry](./kibana-plugin-server.savedobjecttyperegistry.md) > [getType](./kibana-plugin-server.savedobjecttyperegistry.gettype.md) + +## SavedObjectTypeRegistry.getType() method + +Return the [type](./kibana-plugin-server.savedobjectstype.md) definition for given type name. + +Signature: + +```typescript +getType(type: string): SavedObjectsType | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | + +Returns: + +`SavedObjectsType | undefined` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.ishidden.md b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.ishidden.md new file mode 100644 index 0000000000000..956ba2cbc1dbd --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.ishidden.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectTypeRegistry](./kibana-plugin-server.savedobjecttyperegistry.md) > [isHidden](./kibana-plugin-server.savedobjecttyperegistry.ishidden.md) + +## SavedObjectTypeRegistry.isHidden() method + +Returns the `hidden` property for given type, or `false` if the type is not registered. + +Signature: + +```typescript +isHidden(type: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.isnamespaceagnostic.md b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.isnamespaceagnostic.md new file mode 100644 index 0000000000000..e6e578d893648 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.isnamespaceagnostic.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectTypeRegistry](./kibana-plugin-server.savedobjecttyperegistry.md) > [isNamespaceAgnostic](./kibana-plugin-server.savedobjecttyperegistry.isnamespaceagnostic.md) + +## SavedObjectTypeRegistry.isNamespaceAgnostic() method + +Returns the `namespaceAgnostic` property for given type, or `false` if the type is not registered. + +Signature: + +```typescript +isNamespaceAgnostic(type: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.md b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.md new file mode 100644 index 0000000000000..3daad35808624 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectTypeRegistry](./kibana-plugin-server.savedobjecttyperegistry.md) + +## SavedObjectTypeRegistry class + +Registry holding information about all the registered [saved object types](./kibana-plugin-server.savedobjectstype.md). + +Signature: + +```typescript +export declare class SavedObjectTypeRegistry +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [getAllTypes()](./kibana-plugin-server.savedobjecttyperegistry.getalltypes.md) | | Return all [types](./kibana-plugin-server.savedobjectstype.md) currently registered. | +| [getIndex(type)](./kibana-plugin-server.savedobjecttyperegistry.getindex.md) | | Returns the indexPattern property for given type, or undefined if the type is not registered. | +| [getType(type)](./kibana-plugin-server.savedobjecttyperegistry.gettype.md) | | Return the [type](./kibana-plugin-server.savedobjectstype.md) definition for given type name. | +| [isHidden(type)](./kibana-plugin-server.savedobjecttyperegistry.ishidden.md) | | Returns the hidden property for given type, or false if the type is not registered. | +| [isNamespaceAgnostic(type)](./kibana-plugin-server.savedobjecttyperegistry.isnamespaceagnostic.md) | | Returns the namespaceAgnostic property for given type, or false if the type is not registered. | +| [registerType(type)](./kibana-plugin-server.savedobjecttyperegistry.registertype.md) | | Register a [type](./kibana-plugin-server.savedobjectstype.md) inside the registry. A type can only be registered once. subsequent calls with the same type name will throw an error. | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.registertype.md b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.registertype.md new file mode 100644 index 0000000000000..4e6d62ccd28d0 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjecttyperegistry.registertype.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectTypeRegistry](./kibana-plugin-server.savedobjecttyperegistry.md) > [registerType](./kibana-plugin-server.savedobjecttyperegistry.registertype.md) + +## SavedObjectTypeRegistry.registerType() method + +Register a [type](./kibana-plugin-server.savedobjectstype.md) inside the registry. A type can only be registered once. subsequent calls with the same type name will throw an error. + +Signature: + +```typescript +registerType(type: SavedObjectsType): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | SavedObjectsType | | + +Returns: + +`void` + diff --git a/src/core/CONVENTIONS.md b/src/core/CONVENTIONS.md index dd83ab2daca82..2769079757bc3 100644 --- a/src/core/CONVENTIONS.md +++ b/src/core/CONVENTIONS.md @@ -7,6 +7,7 @@ - [Applications](#applications) - [Services](#services) - [Usage Collection](#usage-collection) + - [Saved Objects Types](#saved-objects-types) ## Plugin Structure @@ -31,6 +32,9 @@ my_plugin/ │ └── index.ts ├── collectors │ └── register.ts + ├── saved_objects + │ ├── index.ts + │ └── my_type.ts    ├── services    │   ├── my_service    │   │ └── index.ts @@ -259,6 +263,45 @@ export function registerMyPluginUsageCollector(usageCollection?: UsageCollection } ``` +### Saved Objects Types + +Saved object type definitions should be defined in their own `server/saved_objects` directory. + +The folder should contain a file per type, named after the snake_case name of the type, and an `index.ts` file exporting all the types. + +```typescript +// src/plugins/my-plugin/server/saved_objects/my_type.ts +import { SavedObjectsType } from 'src/core/server'; + +export const myType: SavedObjectsType = { + name: 'my-type', + hidden: false, + namespaceAgnostic: true, + mappings: { + properties: { + someField: { + type: 'text', + }, + anotherField: { + type: 'text', + }, + }, + }, + migrations: { + '1.0.0': migrateFirstTypeToV1, + '2.0.0': migrateFirstTypeToV2, + }, +}; +``` + +```typescript +// src/plugins/my-plugin/server/saved_objects/index.ts + +export { myType } from './my_type'; +``` + +Migration example from the legacy format is available in `src/core/MIGRATION_EXAMPLES.md#saved-objects-types` + ### Naming conventions Export start and setup contracts as `MyPluginStart` and `MyPluginSetup`. diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index d33fd9bcce7a0..6ee432635a947 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -1207,6 +1207,9 @@ In server code, `core` can be accessed from either `server.newPlatform` or `kbnS | `request.getSavedObjectsClient` | [`context.core.savedObjects.client`](/docs/development/core/server/kibana-plugin-server.requesthandlercontext.core.md) | | | `request.getUiSettingsService` | [`context.uiSettings.client`](/docs/development/core/server/kibana-plugin-server.iuisettingsclient.md) | | | `kibana.Plugin.deprecations` | [Handle plugin configuration deprecations](#handle-plugin-config-deprecations) and [`PluginConfigDescriptor.deprecations`](docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.md) | Deprecations from New Platform are not applied to legacy configuration | +| `kibana.Plugin.savedObjectSchemas` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | +| `kibana.Plugin.mappings` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | +| `kibana.Plugin.migrations` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | _See also: [Server's CoreSetup API Docs](/docs/development/core/server/kibana-plugin-server.coresetup.md)_ diff --git a/src/core/MIGRATION_EXAMPLES.md b/src/core/MIGRATION_EXAMPLES.md index 5517dfa7f9a23..def83ba177fc9 100644 --- a/src/core/MIGRATION_EXAMPLES.md +++ b/src/core/MIGRATION_EXAMPLES.md @@ -19,6 +19,7 @@ APIs to their New Platform equivalents. - [Updating an application navlink](#updating-application-navlink) - [Chromeless Applications](#chromeless-applications) - [Render HTML Content](#render-html-content) + - [Saved Objects types](#saved-objects-types) ## Configuration @@ -737,3 +738,183 @@ router.get( } ); ``` + +## Saved Objects types + +In the legacy platform, saved object types were registered using static definitions in the `uiExports` part of +the plugin manifest. + +In the new platform, all these registration are to be performed programmatically during your plugin's `setup` phase, +using the core `savedObjects`'s `registerType` setup API. + +The most notable difference is that in the new platform, the type registration is performed in a single call to +`registerType`, passing a new `SavedObjectsType` structure that is a superset of the legacy `schema`, `migrations` +and `mappings`. + +### Concrete example + +Let say we have the following in a legacy plugin: + +```js +// src/legacy/core_plugins/my_plugin/index.js +import mappings from './mappings.json'; +import { migrations } from './migrations'; + +new kibana.Plugin({ + init(server){ + // [...] + }, + uiExports: { + mappings, + migrations, + savedObjectSchemas: { + 'first-type': { + isNamespaceAgnostic: true, + }, + 'second-type': { + isHidden: true, + }, + }, + }, +}) +``` + +```json +// src/legacy/core_plugins/my_plugin/mappings.json +{ + "first-type": { + "properties": { + "someField": { + "type": "text" + }, + "anotherField": { + "type": "text" + } + } + }, + "second-type": { + "properties": { + "textField": { + "type": "text" + }, + "boolField": { + "type": "boolean" + } + } + } +} +``` + +```js +// src/legacy/core_plugins/my_plugin/migrations.js +export const migrations = { + 'first-type': { + '1.0.0': migrateFirstTypeToV1, + '2.0.0': migrateFirstTypeToV2, + }, + 'second-type': { + '1.5.0': migrateSecondTypeToV15, + } +} +``` + +To migrate this, we will have to regroup the declaration per-type. That would become: + +First type: + +```typescript +// src/plugins/my_plugin/server/saved_objects/first_type.ts +import { SavedObjectsType } from 'src/core/server'; + +export const firstType: SavedObjectsType = { + name: 'first-type', + hidden: false, + namespaceAgnostic: true, + mappings: { + properties: { + someField: { + type: 'text', + }, + anotherField: { + type: 'text', + }, + }, + }, + migrations: { + '1.0.0': migrateFirstTypeToV1, + '2.0.0': migrateFirstTypeToV2, + }, +}; +``` + +Second type: + +```typescript +// src/plugins/my_plugin/server/saved_objects/second_type.ts +import { SavedObjectsType } from 'src/core/server'; + +export const secondType: SavedObjectsType = { + name: 'second-type', + hidden: true, + namespaceAgnostic: false, + mappings: { + properties: { + textField: { + type: 'text', + }, + boolField: { + type: 'boolean', + }, + }, + }, + migrations: { + '1.5.0': migrateSecondTypeToV15, + }, +}; +``` + +Registration in the plugin's setup phase: + +```typescript +// src/plugins/my_plugin/server/plugin.ts +import { firstType, secondType } from './saved_objects'; + +export class MyPlugin implements Plugin { + setup({ savedObjects }) { + savedObjects.registerType(firstType); + savedObjects.registerType(secondType); + } +} +``` + +### Changes in structure compared to legacy + +The NP `registerType` expected input is very close to the legacy format. However, there are some minor changes: + +- The `schema.isNamespaceAgnostic` property has been renamed: `SavedObjectsType.namespaceAgnostic` + +- The `schema.indexPattern` was accepting either a `string` or a `(config: LegacyConfig) => string`. `SavedObjectsType.indexPattern` only accepts a string, as you can access the configuration during your plugin's setup phase. + +- The migration function signature has changed: +In legacy, it was `(doc: SavedObjectUnsanitizedDoc, log: SavedObjectsMigrationLogger) => SavedObjectUnsanitizedDoc;` +In new platform, it is now `(doc: SavedObjectUnsanitizedDoc, context: SavedObjectMigrationContext) => SavedObjectUnsanitizedDoc;` + +With context being: + +```typescript +export interface SavedObjectMigrationContext { + log: SavedObjectsMigrationLogger; +} +``` + +The changes is very minor though. The legacy migration: + +```js +const migration = (doc, log) => {...} +``` + +Would be converted to: + +```typescript +const migration: SavedObjectMigrationFn = (doc, { log }) => {...} +``` \ No newline at end of file diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 52827b72ee0cc..e45d4f28edcc3 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -201,6 +201,7 @@ export { SavedObjectsImportRetry, SavedObjectsImportUnknownError, SavedObjectsImportUnsupportedTypeError, + SavedObjectMigrationContext, SavedObjectsMigrationLogger, SavedObjectsRawDoc, SavedObjectSanitizedDoc, @@ -224,6 +225,7 @@ export { SavedObjectsTypeMappingDefinition, SavedObjectsMappingProperties, SavedObjectTypeRegistry, + ISavedObjectTypeRegistry, SavedObjectsType, SavedObjectMigrationMap, SavedObjectMigrationFn, diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index b2501496d87ef..44f77b5ad215e 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -263,6 +263,7 @@ export class LegacyService implements CoreService { createScopedRepository: startDeps.core.savedObjects.createScopedRepository, createInternalRepository: startDeps.core.savedObjects.createInternalRepository, createSerializer: startDeps.core.savedObjects.createSerializer, + getTypeRegistry: startDeps.core.savedObjects.getTypeRegistry, }, uiSettings: { asScopedToClient: startDeps.core.uiSettings.asScopedToClient }, }; @@ -298,6 +299,7 @@ export class LegacyService implements CoreService { savedObjects: { setClientFactoryProvider: setupDeps.core.savedObjects.setClientFactoryProvider, addClientWrapper: setupDeps.core.savedObjects.addClientWrapper, + registerType: setupDeps.core.savedObjects.registerType, }, uiSettings: { register: setupDeps.core.uiSettings.register, @@ -329,7 +331,6 @@ export class LegacyService implements CoreService { __internals: { hapiServer: setupDeps.core.http.server, kibanaMigrator: startDeps.core.savedObjects.migrator, - typeRegistry: startDeps.core.savedObjects.typeRegistry, uiPlugins: setupDeps.core.plugins.uiPlugins, elasticsearch: setupDeps.core.elasticsearch, rendering: setupDeps.core.rendering, diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index d6554babab53e..b8380a3045962 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -114,18 +114,12 @@ function createCoreSetupMock() { register: uiSettingsServiceMock.createSetupContract().register, }; - const savedObjectsService = savedObjectsServiceMock.createSetupContract(); - const savedObjectMock: jest.Mocked = { - addClientWrapper: savedObjectsService.addClientWrapper, - setClientFactoryProvider: savedObjectsService.setClientFactoryProvider, - }; - const mock: CoreSetupMockType = { capabilities: capabilitiesServiceMock.createSetupContract(), context: contextServiceMock.createSetupContract(), elasticsearch: elasticsearchServiceMock.createSetup(), http: httpMock, - savedObjects: savedObjectMock, + savedObjects: savedObjectsServiceMock.createInternalSetupContract(), uiSettings: uiSettingsMock, uuid: uuidServiceMock.createSetupContract(), getStartServices: jest diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index a7b555a9eba01..a8a16713f69a4 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -169,6 +169,7 @@ export function createPluginSetupContext( savedObjects: { setClientFactoryProvider: deps.savedObjects.setClientFactoryProvider, addClientWrapper: deps.savedObjects.addClientWrapper, + registerType: deps.savedObjects.registerType, }, uiSettings: { register: deps.uiSettings.register, @@ -206,6 +207,7 @@ export function createPluginStartContext( createInternalRepository: deps.savedObjects.createInternalRepository, createScopedRepository: deps.savedObjects.createScopedRepository, createSerializer: deps.savedObjects.createSerializer, + getTypeRegistry: deps.savedObjects.getTypeRegistry, }, uiSettings: { asScopedToClient: deps.uiSettings.asScopedToClient, diff --git a/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap b/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap index 7846e7f1a802a..89ff2b542c60f 100644 --- a/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap +++ b/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap @@ -64,8 +64,8 @@ Array [ }, }, "migrations": Object { - "1.0.0": [MockFunction], - "2.0.4": [MockFunction], + "1.0.0": [Function], + "2.0.4": [Function], }, "name": "typeA", "namespaceAgnostic": true, @@ -100,7 +100,7 @@ Array [ }, }, "migrations": Object { - "1.5.3": [MockFunction], + "1.5.3": [Function], }, "name": "typeC", "namespaceAgnostic": false, diff --git a/src/core/server/saved_objects/index.ts b/src/core/server/saved_objects/index.ts index 5be4458bdf2af..9bfe658028258 100644 --- a/src/core/server/saved_objects/index.ts +++ b/src/core/server/saved_objects/index.ts @@ -64,7 +64,11 @@ export { SavedObjectsTypeMappingDefinitions, } from './mappings'; -export { SavedObjectMigrationMap, SavedObjectMigrationFn } from './migrations'; +export { + SavedObjectMigrationMap, + SavedObjectMigrationFn, + SavedObjectMigrationContext, +} from './migrations'; export { SavedObjectsType } from './types'; diff --git a/src/core/server/saved_objects/migrations/core/document_migrator.test.ts b/src/core/server/saved_objects/migrations/core/document_migrator.test.ts index 0e3a4780e12b6..ef3f546b5e574 100644 --- a/src/core/server/saved_objects/migrations/core/document_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/core/document_migrator.test.ts @@ -585,7 +585,7 @@ describe('DocumentMigrator', () => { typeRegistry: createRegistry({ name: 'dog', migrations: { - '1.2.3': (doc, log) => { + '1.2.3': (doc, { log }) => { log.info(logTestMsg); log.warning(logTestMsg); return doc; diff --git a/src/core/server/saved_objects/migrations/core/document_migrator.ts b/src/core/server/saved_objects/migrations/core/document_migrator.ts index b5019b2874bec..0284f513a361c 100644 --- a/src/core/server/saved_objects/migrations/core/document_migrator.ts +++ b/src/core/server/saved_objects/migrations/core/document_migrator.ts @@ -309,7 +309,8 @@ function wrapWithTry( ) { return function tryTransformDoc(doc: SavedObjectUnsanitizedDoc) { try { - const result = migrationFn(doc, new MigrationLogger(log)); + const context = { log: new MigrationLogger(log) }; + const result = migrationFn(doc, context); // A basic sanity check to help migration authors detect basic errors // (e.g. forgetting to return the transformed doc) diff --git a/src/core/server/saved_objects/migrations/index.ts b/src/core/server/saved_objects/migrations/index.ts index e96986bd702e6..dc966f0797822 100644 --- a/src/core/server/saved_objects/migrations/index.ts +++ b/src/core/server/saved_objects/migrations/index.ts @@ -18,4 +18,8 @@ */ export { KibanaMigrator, IKibanaMigrator } from './kibana'; -export { SavedObjectMigrationFn, SavedObjectMigrationMap } from './types'; +export { + SavedObjectMigrationFn, + SavedObjectMigrationMap, + SavedObjectMigrationContext, +} from './types'; diff --git a/src/core/server/saved_objects/migrations/types.ts b/src/core/server/saved_objects/migrations/types.ts index 01741dd2ded1a..6bc085dde872e 100644 --- a/src/core/server/saved_objects/migrations/types.ts +++ b/src/core/server/saved_objects/migrations/types.ts @@ -21,14 +21,41 @@ import { SavedObjectUnsanitizedDoc } from '../serialization'; import { SavedObjectsMigrationLogger } from './core/migration_logger'; /** - * A migration function defined for a {@link SavedObjectsType | saved objects type} - * used to migrate it's {@link SavedObjectUnsanitizedDoc | documents} + * A migration function for a {@link SavedObjectsType | saved object type} + * used to migrate it to a given version + * + * @example + * ```typescript + * const migrateProperty: SavedObjectMigrationFn = (doc, { log }) => { + * if(doc.attributes.someProp === null) { + * log.warn('Skipping migration'); + * } else { + * doc.attributes.someProp = migrateProperty(doc.attributes.someProp); + * } + * + * return doc; + * } + * ``` + * + * @public */ export type SavedObjectMigrationFn = ( doc: SavedObjectUnsanitizedDoc, - log: SavedObjectsMigrationLogger + context: SavedObjectMigrationContext ) => SavedObjectUnsanitizedDoc; +/** + * Migration context provided when invoking a {@link SavedObjectMigrationFn | migration handler} + * + * @public + */ +export interface SavedObjectMigrationContext { + /** + * logger instance to be used by the migration handler + */ + log: SavedObjectsMigrationLogger; +} + /** * A map of {@link SavedObjectMigrationFn | migration functions} to be used for a given type. * The map's keys must be valid semver versions. diff --git a/src/core/server/saved_objects/saved_objects_service.mock.ts b/src/core/server/saved_objects/saved_objects_service.mock.ts index 70f3d5a5b18e4..cbdff16324536 100644 --- a/src/core/server/saved_objects/saved_objects_service.mock.ts +++ b/src/core/server/saved_objects/saved_objects_service.mock.ts @@ -38,11 +38,13 @@ const createStartContractMock = () => { createInternalRepository: jest.fn(), createScopedRepository: jest.fn(), createSerializer: jest.fn(), + getTypeRegistry: jest.fn(), }; startContrat.getScopedClient.mockReturnValue(savedObjectsClientMock.create()); startContrat.createInternalRepository.mockReturnValue(savedObjectsRepositoryMock.create()); startContrat.createScopedRepository.mockReturnValue(savedObjectsRepositoryMock.create()); + startContrat.getTypeRegistry.mockReturnValue(typeRegistryMock.create()); return startContrat; }; @@ -52,7 +54,6 @@ const createInternalStartContractMock = () => { ...createStartContractMock(), clientProvider: savedObjectsClientProviderMock.create(), migrator: mockKibanaMigrator.create(), - typeRegistry: typeRegistryMock.create(), }; return internalStartContract; @@ -62,6 +63,7 @@ const createSetupContractMock = () => { const setupContract: jest.Mocked = { setClientFactoryProvider: jest.fn(), addClientWrapper: jest.fn(), + registerType: jest.fn(), }; return setupContract; @@ -70,7 +72,6 @@ const createSetupContractMock = () => { const createInternalSetupContractMock = () => { const internalSetupContract: jest.Mocked = { ...createSetupContractMock(), - registerType: jest.fn(), }; return internalSetupContract; }; diff --git a/src/core/server/saved_objects/saved_objects_service.test.ts b/src/core/server/saved_objects/saved_objects_service.test.ts index 0c7bedecf39f5..a1e2c1e8dbf26 100644 --- a/src/core/server/saved_objects/saved_objects_service.test.ts +++ b/src/core/server/saved_objects/saved_objects_service.test.ts @@ -130,7 +130,7 @@ describe('SavedObjectsService', () => { }); }); - describe('registerType', () => { + describe('#registerType', () => { it('registers the type to the internal typeRegistry', async () => { const coreContext = createCoreContext(); const soService = new SavedObjectsService(coreContext); @@ -231,5 +231,16 @@ describe('SavedObjectsService', () => { expect(startContract.migrator).toBe(migratorInstanceMock); expect(migratorInstanceMock.runMigrations).toHaveBeenCalledTimes(1); }); + + describe('#getTypeRegistry', () => { + it('returns the internal type registry of the service', async () => { + const coreContext = createCoreContext({ skipMigration: false }); + const soService = new SavedObjectsService(coreContext); + await soService.setup(createSetupDeps()); + const { getTypeRegistry } = await soService.start({}); + + expect(getTypeRegistry()).toBe(typeRegistryInstanceMock); + }); + }); }); }); diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index fa2b67a3e43b2..da8f7ab96d689 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -53,26 +53,13 @@ import { registerRoutes } from './routes'; /** * Saved Objects is Kibana's data persistence mechanism allowing plugins to - * use Elasticsearch for storing and querying state. The - * SavedObjectsServiceSetup API exposes methods for creating and registering - * Saved Object client wrappers. + * use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods + * for registering Saved Object types, creating and registering Saved Object client wrappers and factories. * * @remarks - * Note: The Saved Object setup API's should only be used for creating and - * registering client wrappers. Constructing a Saved Objects client or - * repository for use within your own plugin won't have any of the registered - * wrappers applied and is considered an anti-pattern. Use the Saved Objects - * client from the - * {@link SavedObjectsServiceStart | SavedObjectsServiceStart#getScopedClient } - * method or the {@link RequestHandlerContext | route handler context} instead. - * * When plugins access the Saved Objects client, a new client is created using * the factory provided to `setClientFactory` and wrapped by all wrappers - * registered through `addClientWrapper`. To create a factory or wrapper, - * plugins will have to construct a Saved Objects client. First create a - * repository by calling `scopedRepository` or `internalRepository` and then - * use this repository as the argument to the {@link SavedObjectsClient} - * constructor. + * registered through `addClientWrapper`. * * @example * ```ts @@ -87,6 +74,18 @@ import { registerRoutes } from './routes'; * } * ``` * + * @example + * ```ts + * import { SavedObjectsClient, CoreSetup } from 'src/core/server'; + * import { mySoType } from './saved_objects' + * + * export class Plugin() { + * setup: (core: CoreSetup) => { + * core.savedObjects.registerType(mySoType); + * } + * } + * ``` + * * @public */ export interface SavedObjectsServiceSetup { @@ -104,14 +103,60 @@ export interface SavedObjectsServiceSetup { id: string, factory: SavedObjectsClientWrapperFactory ) => void; + + /** + * Register a {@link SavedObjectsType | savedObjects type} definition. + * + * See the {@link SavedObjectsTypeMappingDefinition | mappings format} and + * {@link SavedObjectMigrationMap | migration format} for more details about these. + * + * @example + * ```ts + * // src/plugins/my_plugin/server/saved_objects/my_type.ts + * import { SavedObjectsType } from 'src/core/server'; + * import * as migrations from './migrations'; + * + * export const myType: SavedObjectsType = { + * name: 'MyType', + * hidden: false, + * namespaceAgnostic: true, + * mappings: { + * properties: { + * textField: { + * type: 'text', + * }, + * boolField: { + * type: 'boolean', + * }, + * }, + * }, + * migrations: { + * '2.0.0': migrations.migrateToV2, + * '2.1.0': migrations.migrateToV2_1 + * }, + * }; + * + * // src/plugins/my_plugin/server/plugin.ts + * import { SavedObjectsClient, CoreSetup } from 'src/core/server'; + * import { myType } from './saved_objects'; + * + * export class Plugin() { + * setup: (core: CoreSetup) => { + * core.savedObjects.registerType(myType); + * } + * } + * ``` + * + * @remarks The type definition is an aggregation of the legacy savedObjects `schema`, `mappings` and `migration` concepts. + * This API is the single entry point to register saved object types in the new platform. + */ + registerType: (type: SavedObjectsType) => void; } /** * @internal */ -export interface InternalSavedObjectsServiceSetup extends SavedObjectsServiceSetup { - registerType: (type: SavedObjectsType) => void; -} +export type InternalSavedObjectsServiceSetup = SavedObjectsServiceSetup; /** * Saved Objects is Kibana's data persisentence mechanism allowing plugins to @@ -159,6 +204,11 @@ export interface SavedObjectsServiceStart { * Creates a {@link SavedObjectsSerializer | serializer} that is aware of all registered types. */ createSerializer: () => SavedObjectsSerializer; + /** + * Returns the {@link ISavedObjectTypeRegistry | registry} containing all registered + * {@link SavedObjectsType | saved object types} + */ + getTypeRegistry: () => ISavedObjectTypeRegistry; } export interface InternalSavedObjectsServiceStart extends SavedObjectsServiceStart { @@ -170,10 +220,6 @@ export interface InternalSavedObjectsServiceStart extends SavedObjectsServiceSta * @deprecated Exposed only for injecting into Legacy */ clientProvider: ISavedObjectsClientProvider; - /** - * @deprecated Exposed only for injecting into Legacy - */ - typeRegistry: ISavedObjectTypeRegistry; } /** @@ -359,6 +405,7 @@ export class SavedObjectsService const repository = repositoryFactory.createScopedRepository(request); return new SavedObjectsClient(repository); }, + typeRegistry: this.typeRegistry, }); if (this.clientFactoryProvider) { const clientFactory = this.clientFactoryProvider(repositoryFactory); @@ -371,11 +418,11 @@ export class SavedObjectsService return { migrator, clientProvider, - typeRegistry: this.typeRegistry, getScopedClient: clientProvider.getClient.bind(clientProvider), createScopedRepository: repositoryFactory.createScopedRepository, createInternalRepository: repositoryFactory.createInternalRepository, createSerializer: () => new SavedObjectsSerializer(this.typeRegistry), + getTypeRegistry: () => this.typeRegistry, }; } diff --git a/src/core/server/saved_objects/saved_objects_type_registry.mock.ts b/src/core/server/saved_objects/saved_objects_type_registry.mock.ts index 6e11920db6b7d..435e352335ecf 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.mock.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.mock.ts @@ -17,9 +17,10 @@ * under the License. */ -import { ISavedObjectTypeRegistry } from './saved_objects_type_registry'; +import { ISavedObjectTypeRegistry, SavedObjectTypeRegistry } from './saved_objects_type_registry'; -const createRegistryMock = (): jest.Mocked => { +const createRegistryMock = (): jest.Mocked> => { const mock = { registerType: jest.fn(), getType: jest.fn(), diff --git a/src/core/server/saved_objects/saved_objects_type_registry.ts b/src/core/server/saved_objects/saved_objects_type_registry.ts index 3f26d696831fd..b73c80ad9dff7 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.ts @@ -23,14 +23,17 @@ import { SavedObjectsType } from './types'; /** * See {@link SavedObjectTypeRegistry} for documentation. * - * @internal - * */ -export type ISavedObjectTypeRegistry = PublicMethodsOf; + * @public + */ +export type ISavedObjectTypeRegistry = Pick< + SavedObjectTypeRegistry, + 'getType' | 'getAllTypes' | 'getIndex' | 'isNamespaceAgnostic' | 'isHidden' +>; /** - * Registry holding information about all the registered {@link SavedObjectsType | savedObject types}. + * Registry holding information about all the registered {@link SavedObjectsType | saved object types}. * - * @internal + * @public */ export class SavedObjectTypeRegistry { private readonly types = new Map(); diff --git a/src/core/server/saved_objects/service/lib/scoped_client_provider.test.js b/src/core/server/saved_objects/service/lib/scoped_client_provider.test.js index eb210b6843de0..aa9448e61009d 100644 --- a/src/core/server/saved_objects/service/lib/scoped_client_provider.test.js +++ b/src/core/server/saved_objects/service/lib/scoped_client_provider.test.js @@ -18,6 +18,7 @@ */ import { SavedObjectsClientProvider } from './scoped_client_provider'; +import { typeRegistryMock } from '../../saved_objects_type_registry.mock'; test(`uses default client factory when one isn't set`, () => { const returnValue = Symbol(); @@ -26,6 +27,7 @@ test(`uses default client factory when one isn't set`, () => { const clientProvider = new SavedObjectsClientProvider({ defaultClientFactory: defaultClientFactoryMock, + typeRegistry: typeRegistryMock.create(), }); const result = clientProvider.getClient(request); @@ -44,6 +46,7 @@ test(`uses custom client factory when one is set`, () => { const clientProvider = new SavedObjectsClientProvider({ defaultClientFactory: defaultClientFactoryMock, + typeRegistry: typeRegistryMock.create(), }); clientProvider.setClientFactory(customClientFactoryMock); const result = clientProvider.getClient(request); @@ -68,6 +71,7 @@ test(`throws error when registering a wrapper with a duplicate id`, () => { const defaultClientFactoryMock = jest.fn(); const clientProvider = new SavedObjectsClientProvider({ defaultClientFactory: defaultClientFactoryMock, + typeRegistry: typeRegistryMock.create(), }); const firstClientWrapperFactoryMock = jest.fn(); const secondClientWrapperFactoryMock = jest.fn(); @@ -80,9 +84,11 @@ test(`throws error when registering a wrapper with a duplicate id`, () => { test(`invokes and uses wrappers in specified order`, () => { const defaultClient = Symbol(); + const typeRegistry = typeRegistryMock.create(); const defaultClientFactoryMock = jest.fn().mockReturnValue(defaultClient); const clientProvider = new SavedObjectsClientProvider({ defaultClientFactory: defaultClientFactoryMock, + typeRegistry, }); const firstWrappedClient = Symbol('first client'); const firstClientWrapperFactoryMock = jest.fn().mockReturnValue(firstWrappedClient); @@ -98,18 +104,22 @@ test(`invokes and uses wrappers in specified order`, () => { expect(firstClientWrapperFactoryMock).toHaveBeenCalledWith({ request, client: secondWrapperClient, + typeRegistry, }); expect(secondClientWrapperFactoryMock).toHaveBeenCalledWith({ request, client: defaultClient, + typeRegistry, }); }); test(`does not invoke or use excluded wrappers`, () => { const defaultClient = Symbol(); + const typeRegistry = typeRegistryMock.create(); const defaultClientFactoryMock = jest.fn().mockReturnValue(defaultClient); const clientProvider = new SavedObjectsClientProvider({ defaultClientFactory: defaultClientFactoryMock, + typeRegistry, }); const firstWrappedClient = Symbol('first client'); const firstClientWrapperFactoryMock = jest.fn().mockReturnValue(firstWrappedClient); @@ -128,6 +138,7 @@ test(`does not invoke or use excluded wrappers`, () => { expect(firstClientWrapperFactoryMock).toHaveBeenCalledWith({ request, client: defaultClient, + typeRegistry, }); expect(secondClientWrapperFactoryMock).not.toHaveBeenCalled(); }); @@ -137,6 +148,7 @@ test(`allows all wrappers to be excluded`, () => { const defaultClientFactoryMock = jest.fn().mockReturnValue(defaultClient); const clientProvider = new SavedObjectsClientProvider({ defaultClientFactory: defaultClientFactoryMock, + typeRegistry: typeRegistryMock.create(), }); const firstWrappedClient = Symbol('first client'); const firstClientWrapperFactoryMock = jest.fn().mockReturnValue(firstWrappedClient); diff --git a/src/core/server/saved_objects/service/lib/scoped_client_provider.ts b/src/core/server/saved_objects/service/lib/scoped_client_provider.ts index 8aadc4f57317c..24813cd8d9ab8 100644 --- a/src/core/server/saved_objects/service/lib/scoped_client_provider.ts +++ b/src/core/server/saved_objects/service/lib/scoped_client_provider.ts @@ -19,6 +19,7 @@ import { PriorityCollection } from './priority_collection'; import { SavedObjectsClientContract } from '../../types'; import { SavedObjectsRepositoryFactory } from '../../saved_objects_service'; +import { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry'; import { KibanaRequest } from '../../../http'; /** @@ -27,6 +28,7 @@ import { KibanaRequest } from '../../../http'; */ export interface SavedObjectsClientWrapperOptions { client: SavedObjectsClientContract; + typeRegistry: ISavedObjectTypeRegistry; request: KibanaRequest; } @@ -84,9 +86,17 @@ export class SavedObjectsClientProvider { }>(); private _clientFactory: SavedObjectsClientFactory; private readonly _originalClientFactory: SavedObjectsClientFactory; - - constructor({ defaultClientFactory }: { defaultClientFactory: SavedObjectsClientFactory }) { + private readonly _typeRegistry: ISavedObjectTypeRegistry; + + constructor({ + defaultClientFactory, + typeRegistry, + }: { + defaultClientFactory: SavedObjectsClientFactory; + typeRegistry: ISavedObjectTypeRegistry; + }) { this._originalClientFactory = this._clientFactory = defaultClientFactory; + this._typeRegistry = typeRegistry; } addClientWrapperFactory( @@ -129,6 +139,7 @@ export class SavedObjectsClientProvider { return factory({ request, client: clientToWrap, + typeRegistry: this._typeRegistry, }); }, client); } diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index 9c204784b0aeb..495d896ad12cd 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -34,6 +34,8 @@ export { } from './import/types'; import { LegacyConfig } from '../legacy'; +import { SavedObjectUnsanitizedDoc } from './serialization'; +import { SavedObjectsMigrationLogger } from './migrations/core/migration_logger'; export { SavedObjectAttributes, SavedObjectAttribute, @@ -273,9 +275,26 @@ export interface SavedObjectsLegacyMapping { * @deprecated */ export interface SavedObjectsLegacyMigrationDefinitions { - [type: string]: SavedObjectMigrationMap; + [type: string]: SavedObjectLegacyMigrationMap; } +/** + * @internal + * @deprecated + */ +export interface SavedObjectLegacyMigrationMap { + [version: string]: SavedObjectLegacyMigrationFn; +} + +/** + * @internal + * @deprecated + */ +export type SavedObjectLegacyMigrationFn = ( + doc: SavedObjectUnsanitizedDoc, + log: SavedObjectsMigrationLogger +) => SavedObjectUnsanitizedDoc; + /** * @internal * @deprecated diff --git a/src/core/server/saved_objects/utils.test.ts b/src/core/server/saved_objects/utils.test.ts index 1e2b9f6a0f694..0a56535ac8509 100644 --- a/src/core/server/saved_objects/utils.test.ts +++ b/src/core/server/saved_objects/utils.test.ts @@ -20,7 +20,8 @@ import { legacyServiceMock } from '../legacy/legacy_service.mock'; import { convertLegacyTypes, convertTypesToLegacySchema } from './utils'; import { SavedObjectsLegacyUiExports, SavedObjectsType } from './types'; -import { LegacyConfig } from 'kibana/server'; +import { LegacyConfig, SavedObjectMigrationContext } from 'kibana/server'; +import { SavedObjectUnsanitizedDoc } from './serialization'; describe('convertLegacyTypes', () => { let legacyConfig: ReturnType; @@ -190,8 +191,48 @@ describe('convertLegacyTypes', () => { const converted = convertLegacyTypes(uiExports, legacyConfig); expect(converted.length).toEqual(2); - expect(converted[0].migrations).toEqual(migrationsA); - expect(converted[1].migrations).toEqual(migrationsB); + expect(Object.keys(converted[0]!.migrations!)).toEqual(Object.keys(migrationsA)); + expect(Object.keys(converted[1]!.migrations!)).toEqual(Object.keys(migrationsB)); + }); + + it('converts the migration to the new format', () => { + const legacyMigration = jest.fn(); + const migrationsA = { + '1.0.0': legacyMigration, + }; + + const uiExports: SavedObjectsLegacyUiExports = { + savedObjectMappings: [ + { + pluginId: 'pluginA', + properties: { + typeA: { + properties: { + fieldA: { type: 'text' }, + }, + }, + }, + }, + ], + savedObjectMigrations: { + typeA: migrationsA, + }, + savedObjectSchemas: {}, + savedObjectValidations: {}, + savedObjectsManagement: {}, + }; + + const converted = convertLegacyTypes(uiExports, legacyConfig); + expect(Object.keys(converted[0]!.migrations!)).toEqual(['1.0.0']); + + const migration = converted[0]!.migrations!['1.0.0']!; + + const doc = {} as SavedObjectUnsanitizedDoc; + const context = { log: {} } as SavedObjectMigrationContext; + migration(doc, context); + + expect(legacyMigration).toHaveBeenCalledTimes(1); + expect(legacyMigration).toHaveBeenCalledWith(doc, context.log); }); it('merges everything when all are present', () => { diff --git a/src/core/server/saved_objects/utils.ts b/src/core/server/saved_objects/utils.ts index 5c4d0ccb84b25..bb2c42c6a362c 100644 --- a/src/core/server/saved_objects/utils.ts +++ b/src/core/server/saved_objects/utils.ts @@ -18,7 +18,12 @@ */ import { LegacyConfig } from '../legacy'; -import { SavedObjectsType, SavedObjectsLegacyUiExports } from './types'; +import { SavedObjectMigrationMap } from './migrations'; +import { + SavedObjectsType, + SavedObjectsLegacyUiExports, + SavedObjectLegacyMigrationMap, +} from './types'; import { SavedObjectsSchemaDefinition } from './schema'; /** @@ -49,7 +54,7 @@ export const convertLegacyTypes = ( ? schema.indexPattern(legacyConfig) : schema?.indexPattern, convertToAliasScript: schema?.convertToAliasScript, - migrations: migrations ?? {}, + migrations: convertLegacyMigrations(migrations ?? {}), }; }), ]; @@ -74,3 +79,14 @@ export const convertTypesToLegacySchema = ( }; }, {} as SavedObjectsSchemaDefinition); }; + +const convertLegacyMigrations = ( + legacyMigrations: SavedObjectLegacyMigrationMap +): SavedObjectMigrationMap => { + return Object.entries(legacyMigrations).reduce((migrated, [version, migrationFn]) => { + return { + ...migrated, + [version]: (doc, context) => migrationFn(doc, context.log), + }; + }, {} as SavedObjectMigrationMap); +}; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index f717f30fdb0cf..8f4feb7169651 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -929,6 +929,9 @@ export type IsAuthenticated = (request: KibanaRequest | LegacyRequest) => boolea // @public export type ISavedObjectsRepository = Pick; +// @public +export type ISavedObjectTypeRegistry = Pick; + // @public export type IScopedClusterClient = Pick; @@ -1489,12 +1492,15 @@ export interface SavedObjectAttributes { // @public export type SavedObjectAttributeSingle = string | number | boolean | null | undefined | SavedObjectAttributes; +// @public +export interface SavedObjectMigrationContext { + log: SavedObjectsMigrationLogger; +} + // Warning: (ae-forgotten-export) The symbol "SavedObjectUnsanitizedDoc" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "SavedObjectMigrationFn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "SavedObjectUnsanitizedDoc" // // @public -export type SavedObjectMigrationFn = (doc: SavedObjectUnsanitizedDoc, log: SavedObjectsMigrationLogger) => SavedObjectUnsanitizedDoc; +export type SavedObjectMigrationFn = (doc: SavedObjectUnsanitizedDoc, context: SavedObjectMigrationContext) => SavedObjectUnsanitizedDoc; // @public export interface SavedObjectMigrationMap { @@ -1619,6 +1625,8 @@ export interface SavedObjectsClientWrapperOptions { client: SavedObjectsClientContract; // (undocumented) request: KibanaRequest; + // (undocumented) + typeRegistry: ISavedObjectTypeRegistry; } // @public @@ -2013,8 +2021,6 @@ export class SavedObjectsSchema { // @public export class SavedObjectsSerializer { - // Warning: (ae-forgotten-export) The symbol "ISavedObjectTypeRegistry" needs to be exported by the entry point index.d.ts - // // @internal constructor(registry: ISavedObjectTypeRegistry); generateRawId(namespace: string | undefined, type: string, id?: string): string; @@ -2026,6 +2032,7 @@ export class SavedObjectsSerializer { // @public export interface SavedObjectsServiceSetup { addClientWrapper: (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void; + registerType: (type: SavedObjectsType) => void; setClientFactoryProvider: (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void; } @@ -2035,6 +2042,7 @@ export interface SavedObjectsServiceStart { createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; createSerializer: () => SavedObjectsSerializer; getScopedClient: (req: KibanaRequest, options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; + getTypeRegistry: () => ISavedObjectTypeRegistry; } // @public (undocumented) @@ -2069,7 +2077,7 @@ export interface SavedObjectsUpdateResponse extends Omit { }, }, }; + + const coreStart = coreMock.createStart(); + coreStart.savedObjects.getTypeRegistry.mockReturnValue(typeRegistry); + mockKbnServer = { newPlatform: { __internals: { kibanaMigrator: migrator, savedObjectsClientProvider: clientProvider, - typeRegistry, }, setup: { core: coreMock.createSetup(), }, start: { - core: coreMock.createStart(), + core: coreStart, }, }, server: mockServer, From 457783e8395b622de80f7c176c95172d5ce21c3b Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 26 Feb 2020 08:25:03 -0700 Subject: [PATCH 04/64] [kbn/ui-shared-deps] load base css file (#58520) Co-authored-by: Elastic Machine --- packages/kbn-ui-shared-deps/index.d.ts | 5 +++++ packages/kbn-ui-shared-deps/index.js | 1 + packages/kbn-ui-shared-deps/scripts/build.js | 7 +++++-- src/legacy/ui/ui_render/ui_render_mixin.js | 1 + tasks/config/karma.js | 1 + 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/kbn-ui-shared-deps/index.d.ts b/packages/kbn-ui-shared-deps/index.d.ts index 132445bbde745..7ee96050a1248 100644 --- a/packages/kbn-ui-shared-deps/index.d.ts +++ b/packages/kbn-ui-shared-deps/index.d.ts @@ -27,6 +27,11 @@ export const distDir: string; */ export const distFilename: string; +/** + * Filename of the unthemed css file in the distributable directory + */ +export const baseCssDistFilename: string; + /** * Filename of the dark-theme css file in the distributable directory */ diff --git a/packages/kbn-ui-shared-deps/index.js b/packages/kbn-ui-shared-deps/index.js index c7c004bd55794..d1bb93ddecd0a 100644 --- a/packages/kbn-ui-shared-deps/index.js +++ b/packages/kbn-ui-shared-deps/index.js @@ -21,6 +21,7 @@ const Path = require('path'); exports.distDir = Path.resolve(__dirname, 'target'); exports.distFilename = 'kbn-ui-shared-deps.js'; +exports.baseCssDistFilename = 'kbn-ui-shared-deps.css'; exports.lightCssDistFilename = 'kbn-ui-shared-deps.light.css'; exports.darkCssDistFilename = 'kbn-ui-shared-deps.dark.css'; exports.externals = { diff --git a/packages/kbn-ui-shared-deps/scripts/build.js b/packages/kbn-ui-shared-deps/scripts/build.js index 8b7c22dac24ff..e45b3dbed1748 100644 --- a/packages/kbn-ui-shared-deps/scripts/build.js +++ b/packages/kbn-ui-shared-deps/scripts/build.js @@ -64,8 +64,11 @@ run( }); compiler.hooks.watchRun.tap('report on start', () => { - process.stdout.cursorTo(0, 0); - process.stdout.clearScreenDown(); + if (process.stdout.isTTY) { + process.stdout.cursorTo(0, 0); + process.stdout.clearScreenDown(); + } + log.info('Running webpack compilation...'); }); diff --git a/src/legacy/ui/ui_render/ui_render_mixin.js b/src/legacy/ui/ui_render/ui_render_mixin.js index 21c10bb20962f..0a1b95c23450b 100644 --- a/src/legacy/ui/ui_render/ui_render_mixin.js +++ b/src/legacy/ui/ui_render/ui_render_mixin.js @@ -112,6 +112,7 @@ export function uiRenderMixin(kbnServer, server, config) { ); const styleSheetPaths = [ ...dllStyleChunks, + `${basePath}/bundles/kbn-ui-shared-deps/${UiSharedDeps.baseCssDistFilename}`, ...(darkMode ? [ `${basePath}/bundles/kbn-ui-shared-deps/${UiSharedDeps.darkCssDistFilename}`, diff --git a/tasks/config/karma.js b/tasks/config/karma.js index 9992dafed41c5..24e97aa081e51 100644 --- a/tasks/config/karma.js +++ b/tasks/config/karma.js @@ -64,6 +64,7 @@ module.exports = function(grunt) { ? `http://localhost:5610/bundles/tests.bundle.js` : `http://localhost:5610/bundles/tests.bundle.js?shards=${TOTAL_CI_SHARDS}&shard_num=${shardNum}`, + `http://localhost:5610/bundles/kbn-ui-shared-deps/${UiSharedDeps.baseCssDistFilename}`, // this causes tilemap tests to fail, probably because the eui styles haven't been // included in the karma harness a long some time, if ever // `http://localhost:5610/bundles/kbn-ui-shared-deps/${UiSharedDeps.lightCssDistFilename}`, From 4b8b9a42181e9ea8db0532f4827f5b98a687a7d8 Mon Sep 17 00:00:00 2001 From: Justin Juno <50022106+justinjunodev@users.noreply.github.com> Date: Wed, 26 Feb 2020 10:13:53 -0600 Subject: [PATCH 05/64] [DOCS] Add Homebrew start + stop instructions for Kibana (#58495) * add brew start and stop instructions to docs * add float to start-stop doc * Update start-stop.asciidoc Co-authored-by: Elastic Machine --- docs/setup/install/brew-running.asciidoc | 9 +++++++++ docs/setup/start-stop.asciidoc | 10 +++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 docs/setup/install/brew-running.asciidoc diff --git a/docs/setup/install/brew-running.asciidoc b/docs/setup/install/brew-running.asciidoc new file mode 100644 index 0000000000000..ba78dd1659d04 --- /dev/null +++ b/docs/setup/install/brew-running.asciidoc @@ -0,0 +1,9 @@ +==== Running Kibana with `brew services` + +With Homebrew, Kibana can be started and stopped as follows: + +[source,sh] +-------------------------------------------------- +brew services start elastic/tap/kibana-full +brew services stop elastic/tap/kibana-full +-------------------------------------------------- diff --git a/docs/setup/start-stop.asciidoc b/docs/setup/start-stop.asciidoc index 2bbc49d9e2ae2..2fcc440680f12 100644 --- a/docs/setup/start-stop.asciidoc +++ b/docs/setup/start-stop.asciidoc @@ -46,4 +46,12 @@ include::install/init-systemd.asciidoc[] include::install/rpm-init.asciidoc[] [float] -include::install/systemd.asciidoc[] \ No newline at end of file +include::install/systemd.asciidoc[] + +[float] +=== Homebrew packages + +If you installed {kib} with the Elastic Homebrew formulae, you can start and stop {kib} from the command line using `brew services`. + +[float] +include::install/brew-running.asciidoc[] From 32fb5c15325b27fe98b6cbace708d6bbb04bdc60 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Wed, 26 Feb 2020 16:30:10 +0000 Subject: [PATCH 06/64] [ML] Fixes creation of a watch for an anomaly detection job (#58597) --- x-pack/legacy/plugins/ml/public/application/app.tsx | 2 -- .../create_watch_flyout/create_watch_service.js | 12 +++++++++--- .../create_watch_flyout/select_severity.tsx | 4 ++-- .../ml/public/application/util/dependency_cache.ts | 10 ---------- x-pack/legacy/plugins/ml/public/legacy.ts | 2 -- 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/application/app.tsx b/x-pack/legacy/plugins/ml/public/application/app.tsx index add27193deb77..3acb24ac6e173 100644 --- a/x-pack/legacy/plugins/ml/public/application/app.tsx +++ b/x-pack/legacy/plugins/ml/public/application/app.tsx @@ -24,7 +24,6 @@ export interface MlDependencies extends AppMountParameters { security: SecurityPluginSetup; __LEGACY: { XSRF: string; - APP_URL: string; }; } @@ -48,7 +47,6 @@ const App: FC = ({ coreStart, deps }) => { basePath: coreStart.http.basePath, savedObjectsClient: coreStart.savedObjects.client, XSRF: deps.__LEGACY.XSRF, - APP_URL: deps.__LEGACY.APP_URL, application: coreStart.application, http: coreStart.http, security: deps.security, diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_service.js b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_service.js index 887afeb3ba818..89589c98b52c2 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_service.js +++ b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_service.js @@ -9,9 +9,10 @@ import { http } from '../../../../services/http_service'; import emailBody from './email.html'; import emailInfluencersBody from './email_influencers.html'; +import { DEFAULT_WATCH_SEVERITY } from './select_severity'; import { watch } from './watch.js'; import { i18n } from '@kbn/i18n'; -import { getBasePath, getAppUrl } from '../../../../util/dependency_cache'; +import { getBasePath, getApplication } from '../../../../util/dependency_cache'; const compiledEmailBody = template(emailBody); const compiledEmailInfluencersBody = template(emailInfluencersBody); @@ -75,7 +76,10 @@ class CreateWatchService { this.config.interval = '20m'; this.config.watcherEditURL = ''; this.config.includeInfluencers = false; - this.config.threshold = { display: 'critical', val: 75 }; + + // Current implementation means that default needs to match that of the select severity control. + const { display, val } = DEFAULT_WATCH_SEVERITY; + this.config.threshold = { display, val }; } createNewWatch = function(jobId) { @@ -91,12 +95,13 @@ class CreateWatchService { watch.input.search.request.body.aggs.bucket_results.filter.range.anomaly_score.gte = this.config.threshold.val; if (this.config.includeEmail && this.config.email !== '') { + const { getUrlForApp } = getApplication(); const emails = this.config.email.split(','); emailSection.send_email.email.to = emails; // create the html by adding the variables to the compiled email body. emailSection.send_email.email.body.html = compiledEmailBody({ - serverAddress: getAppUrl(), + serverAddress: getUrlForApp('ml', { absolute: true }), influencersSection: this.config.includeInfluencers === true ? compiledEmailInfluencersBody({ @@ -153,6 +158,7 @@ class CreateWatchService { upstreamJSON: { id, type: 'json', + isNew: false, // Set to false, as we want to allow watches to be overwritten. watch, }, }; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/select_severity.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/select_severity.tsx index 8b0e7da2a5637..727830a58bb41 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/select_severity.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/select_severity.tsx @@ -78,7 +78,7 @@ function optionValueToThreshold(value: number) { return threshold; } -const TABLE_SEVERITY_DEFAULT = SEVERITY_OPTIONS[0]; +export const DEFAULT_WATCH_SEVERITY = SEVERITY_OPTIONS[3]; const getSeverityOptions = () => SEVERITY_OPTIONS.map(({ color, display, val }) => ({ @@ -114,7 +114,7 @@ interface Props { } export const SelectSeverity: FC = ({ onChange }) => { - const [severity, setSeverity] = useState(TABLE_SEVERITY_DEFAULT); + const [severity, setSeverity] = useState(DEFAULT_WATCH_SEVERITY); const onSeverityChange = (valueDisplay: string) => { const option = optionValueToThreshold(optionsMap[valueDisplay]); diff --git a/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts b/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts index f837d90dba8fe..6d1dfa96ca03e 100644 --- a/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts +++ b/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts @@ -36,7 +36,6 @@ export interface DependencyCache { basePath: IBasePath | null; savedObjectsClient: SavedObjectsClientContract | null; XSRF: string | null; - APP_URL: string | null; application: ApplicationStart | null; http: HttpStart | null; security: SecurityPluginSetup | null; @@ -56,7 +55,6 @@ const cache: DependencyCache = { basePath: null, savedObjectsClient: null, XSRF: null, - APP_URL: null, application: null, http: null, security: null, @@ -76,7 +74,6 @@ export function setDependencyCache(deps: Partial) { cache.basePath = deps.basePath || null; cache.savedObjectsClient = deps.savedObjectsClient || null; cache.XSRF = deps.XSRF || null; - cache.APP_URL = deps.APP_URL || null; cache.application = deps.application || null; cache.http = deps.http || null; } @@ -171,13 +168,6 @@ export function getXSRF() { return cache.XSRF; } -export function getAppUrl() { - if (cache.APP_URL === null) { - throw new Error("app url hasn't been initialized"); - } - return cache.APP_URL; -} - export function getApplication() { if (cache.application === null) { throw new Error("application hasn't been initialized"); diff --git a/x-pack/legacy/plugins/ml/public/legacy.ts b/x-pack/legacy/plugins/ml/public/legacy.ts index 40a1afa06b5a6..7dfcf6a99c213 100644 --- a/x-pack/legacy/plugins/ml/public/legacy.ts +++ b/x-pack/legacy/plugins/ml/public/legacy.ts @@ -18,8 +18,6 @@ export const setup = pluginInstance.setup(npSetup.core, { security: ((npSetup.plugins as unknown) as { security: SecurityPluginSetup }).security, // security isn't in the PluginsSetup interface, but does exist __LEGACY: { XSRF: chrome.getXsrfToken(), - // @ts-ignore getAppUrl is missing from chrome's definition - APP_URL: chrome.getAppUrl(), }, }); export const start = pluginInstance.start(npStart.core, npStart.plugins); From 613e4b9b15dcdd42db456655635daa0d1247e5a7 Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Wed, 26 Feb 2020 11:33:42 -0500 Subject: [PATCH 07/64] Median label shows "Median" instead of "50th percentile of" (#58521) * Median label shows "Median" instead of "50th percentile of" * Update test Co-authored-by: Elastic Machine --- .../public/search/aggs/metrics/median.test.ts | 18 +++++++++++++----- .../data/public/search/aggs/metrics/median.ts | 14 +++++--------- .../aggs/metrics/percentiles_get_value.ts | 2 +- .../functional/apps/visualize/_metric_chart.js | 2 +- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts index 9affb0e3b2814..4755a873e6977 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts @@ -47,7 +47,6 @@ describe('AggTypeMetricMedianProvider class', () => { schema: 'metric', params: { field: 'bytes', - percents: [70], }, }, ], @@ -58,12 +57,21 @@ describe('AggTypeMetricMedianProvider class', () => { it('requests the percentiles aggregation in the Elasticsearch query DSL', () => { const dsl: Record = aggConfigs.toDsl(); - expect(dsl.median.percentiles.percents).toEqual([70]); + expect(dsl.median.percentiles.field).toEqual('bytes'); + expect(dsl.median.percentiles.percents).toEqual([50]); }); - it('asks Elasticsearch for array-based values in the aggregation response', () => { - const dsl: Record = aggConfigs.toDsl(); + it('converts the response', () => { + const agg = aggConfigs.getResponseAggs()[0]; - expect(dsl.median.percentiles.keyed).toBeFalsy(); + expect( + agg.getValue({ + [agg.id]: { + values: { + '50.0': 10, + }, + }, + }) + ).toEqual(10); }); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts index be080aaa5ee6f..53a5ffff418f1 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts @@ -43,17 +43,13 @@ export const medianMetricAgg = new MetricAggType({ name: 'field', type: 'field', filterFieldTypes: [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.DATE], - }, - { - name: 'percents', - default: [50], - }, - { write(agg, output) { - output.params.keyed = false; + output.params.field = agg.getParam('field').name; + output.params.percents = [50]; }, }, ], - getResponseAggs: percentilesMetricAgg.getResponseAggs, - getValue: percentilesMetricAgg.getValue, + getValue(agg, bucket) { + return bucket[agg.id].values['50.0']; + }, }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles_get_value.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles_get_value.ts index c357d7bb0a903..980d969a8ea0c 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles_get_value.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles_get_value.ts @@ -24,7 +24,7 @@ export const getPercentileValue = ( agg: TAggConfig, bucket: any ) => { - const { values } = bucket[agg.parentId] && bucket[agg.parentId]; + const { values } = bucket[agg.parentId]; const percentile: any = find(values, ({ key }) => key === agg.key); diff --git a/test/functional/apps/visualize/_metric_chart.js b/test/functional/apps/visualize/_metric_chart.js index 6a95f7553943c..dab9d2213b764 100644 --- a/test/functional/apps/visualize/_metric_chart.js +++ b/test/functional/apps/visualize/_metric_chart.js @@ -78,7 +78,7 @@ export default function({ getService, getPageObjects }) { }); it('should show Median', async function() { - const medianBytes = ['5,565.263', '50th percentile of bytes']; + const medianBytes = ['5,565.263', 'Median bytes']; // For now, only comparing the text label part of the metric log.debug('Aggregation = Median'); await PageObjects.visEditor.selectAggregation('Median', 'metrics'); From 8021fd887ab5f86ed17489e580d2c3cdc0cb9e84 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Wed, 26 Feb 2020 09:36:43 -0700 Subject: [PATCH 08/64] [Metrics UI] Custom Metrics for Inventory View (#58072) * [Metrics UI] Add custom metrics interface to Inventory View * WIP * Adding workflows for editing custom metrics * Polishing visual design * Removing extra text * Fixing types and return values * fixing i18n * Adding aria labels for clearity * Changing custom group by to match same width as custom metric * updating integration test for custom metrics * Fixing type def --- .../infra/common/http_api/snapshot_api.ts | 34 ++- .../metrics_and_groupby_toolbar_items.tsx | 11 +- .../infra/common/inventory_models/types.ts | 1 + .../common/saved_objects/inventory_view.ts | 32 +++ .../components/inventory/toolbars/toolbar.tsx | 10 +- .../inventory/toolbars/toolbar_wrapper.tsx | 6 +- .../components/nodes_overview/index.tsx | 7 +- .../components/waffle/custom_field_panel.tsx | 5 +- .../metric_control/custom_metric_form.tsx | 247 ++++++++++++++++++ .../metric_control/get_custom_metric_label.ts | 30 +++ .../waffle/metric_control/index.tsx | 199 ++++++++++++++ .../metric_control/metrics_context_menu.tsx | 75 ++++++ .../metric_control/metrics_edit_mode.tsx | 73 ++++++ .../waffle/metric_control/mode_switcher.tsx | 113 ++++++++ .../components/waffle/metric_control/types.ts | 7 + .../waffle/waffle_group_by_controls.tsx | 1 + .../waffle/waffle_inventory_switcher.tsx | 19 +- .../waffle/waffle_metric_controls.tsx | 97 ------- .../containers/waffle/with_waffle_options.tsx | 28 +- .../waffle/with_waffle_view_state.tsx | 9 +- .../pages/infrastructure/snapshot/toolbar.tsx | 2 + .../store/local/waffle_options/actions.ts | 9 +- .../store/local/waffle_options/reducer.ts | 14 +- .../store/local/waffle_options/selector.ts | 1 + .../server/lib/snapshot/query_helpers.ts | 31 ++- .../test/api_integration/apis/infra/waffle.ts | 45 +++- 26 files changed, 986 insertions(+), 120 deletions(-) create mode 100644 x-pack/plugins/infra/public/components/waffle/metric_control/custom_metric_form.tsx create mode 100644 x-pack/plugins/infra/public/components/waffle/metric_control/get_custom_metric_label.ts create mode 100644 x-pack/plugins/infra/public/components/waffle/metric_control/index.tsx create mode 100644 x-pack/plugins/infra/public/components/waffle/metric_control/metrics_context_menu.tsx create mode 100644 x-pack/plugins/infra/public/components/waffle/metric_control/metrics_edit_mode.tsx create mode 100644 x-pack/plugins/infra/public/components/waffle/metric_control/mode_switcher.tsx create mode 100644 x-pack/plugins/infra/public/components/waffle/metric_control/types.ts delete mode 100644 x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx diff --git a/x-pack/plugins/infra/common/http_api/snapshot_api.ts b/x-pack/plugins/infra/common/http_api/snapshot_api.ts index c7c15fd8af161..6b666b39b0094 100644 --- a/x-pack/plugins/infra/common/http_api/snapshot_api.ts +++ b/x-pack/plugins/infra/common/http_api/snapshot_api.ts @@ -54,16 +54,41 @@ export const SnapshotGroupByRT = rt.array( }) ); -export const SnapshotMetricInputRT = rt.type({ +export const SnapshotNamedMetricInputRT = rt.type({ type: SnapshotMetricTypeRT, }); +export const SNAPSHOT_CUSTOM_AGGREGATIONS = ['avg', 'max', 'min', 'rate'] as const; + +export type SnapshotCustomAggregation = typeof SNAPSHOT_CUSTOM_AGGREGATIONS[number]; + +const snapshotCustomAggregationKeys = SNAPSHOT_CUSTOM_AGGREGATIONS.reduce< + Record +>((acc, agg) => ({ ...acc, [agg]: null }), {} as Record); + +export const SnapshotCustomAggregationRT = rt.keyof(snapshotCustomAggregationKeys); + +export const SnapshotCustomMetricInputRT = rt.intersection([ + rt.type({ + type: rt.literal('custom'), + field: rt.string, + aggregation: SnapshotCustomAggregationRT, + id: rt.string, + }), + rt.partial({ + label: rt.string, + }), +]); + +export const SnapshotMetricInputRT = rt.union([ + SnapshotNamedMetricInputRT, + SnapshotCustomMetricInputRT, +]); + export const SnapshotRequestRT = rt.intersection([ rt.type({ timerange: InfraTimerangeInputRT, - metric: rt.type({ - type: SnapshotMetricTypeRT, - }), + metric: SnapshotMetricInputRT, groupBy: SnapshotGroupByRT, nodeType: ItemTypeRT, sourceId: rt.string, @@ -77,6 +102,7 @@ export const SnapshotRequestRT = rt.intersection([ export type SnapshotNodePath = rt.TypeOf; export type SnapshotMetricInput = rt.TypeOf; +export type SnapshotCustomMetricInput = rt.TypeOf; export type InfraTimerangeInput = rt.TypeOf; export type SnapshotNodeMetric = rt.TypeOf; export type SnapshotGroupBy = rt.TypeOf; diff --git a/x-pack/plugins/infra/common/inventory_models/shared/compontents/metrics_and_groupby_toolbar_items.tsx b/x-pack/plugins/infra/common/inventory_models/shared/compontents/metrics_and_groupby_toolbar_items.tsx index fcaedcdd080b8..738fce45ee99f 100644 --- a/x-pack/plugins/infra/common/inventory_models/shared/compontents/metrics_and_groupby_toolbar_items.tsx +++ b/x-pack/plugins/infra/common/inventory_models/shared/compontents/metrics_and_groupby_toolbar_items.tsx @@ -9,7 +9,7 @@ import { EuiFlexItem } from '@elastic/eui'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { ToolbarProps } from '../../../../public/components/inventory/toolbars/toolbar'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { WaffleMetricControls } from '../../../../public/components/waffle/waffle_metric_controls'; +import { WaffleMetricControls } from '../../../../public/components/waffle/metric_control'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { WaffleGroupByControls } from '../../../../public/components/waffle/waffle_group_by_controls'; import { @@ -25,7 +25,11 @@ interface Props extends ToolbarProps { } export const MetricsAndGroupByToolbarItems = (props: Props) => { - const metricOptions = useMemo(() => props.metricTypes.map(toMetricOpt), [props.metricTypes]); + const metricOptions = useMemo( + () => + props.metricTypes.map(toMetricOpt).filter(v => v) as Array<{ text: string; value: string }>, + [props.metricTypes] + ); const groupByOptions = useMemo(() => props.groupByFields.map(toGroupByOpt), [ props.groupByFields, @@ -35,9 +39,12 @@ export const MetricsAndGroupByToolbarItems = (props: Props) => { <> diff --git a/x-pack/plugins/infra/common/inventory_models/types.ts b/x-pack/plugins/infra/common/inventory_models/types.ts index 2f61b16fb3df8..a6773d0a07450 100644 --- a/x-pack/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/plugins/infra/common/inventory_models/types.ts @@ -305,6 +305,7 @@ export const SnapshotMetricTypeRT = rt.keyof({ sqsMessagesSent: null, sqsMessagesEmpty: null, sqsOldestMessage: null, + custom: null, }); export type SnapshotMetricType = rt.TypeOf; diff --git a/x-pack/plugins/infra/common/saved_objects/inventory_view.ts b/x-pack/plugins/infra/common/saved_objects/inventory_view.ts index 3ab9042947f97..bccffadc0a1ba 100644 --- a/x-pack/plugins/infra/common/saved_objects/inventory_view.ts +++ b/x-pack/plugins/infra/common/saved_objects/inventory_view.ts @@ -26,6 +26,18 @@ export const inventoryViewSavedObjectMappings: { type: { type: 'keyword', }, + field: { + type: 'keyword', + }, + aggregation: { + type: 'keyword', + }, + id: { + type: 'keyword', + }, + label: { + type: 'keyword', + }, }, }, groupBy: { @@ -56,6 +68,26 @@ export const inventoryViewSavedObjectMappings: { }, }, }, + customMetrics: { + type: 'nested', + properties: { + type: { + type: 'keyword', + }, + field: { + type: 'keyword', + }, + aggregation: { + type: 'keyword', + }, + id: { + type: 'keyword', + }, + label: { + type: 'keyword', + }, + }, + }, boundsOverride: { properties: { max: { diff --git a/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar.tsx b/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar.tsx index a2882a3cd3124..c59ab994a018c 100644 --- a/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar.tsx +++ b/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar.tsx @@ -7,7 +7,11 @@ import React, { FunctionComponent } from 'react'; import { Action } from 'typescript-fsa'; import { EuiFlexItem } from '@elastic/eui'; -import { SnapshotMetricInput, SnapshotGroupBy } from '../../../../common/http_api/snapshot_api'; +import { + SnapshotMetricInput, + SnapshotGroupBy, + SnapshotCustomMetricInput, +} from '../../../../common/http_api/snapshot_api'; import { InventoryCloudAccount } from '../../../../common/http_api/inventory_meta_api'; import { findToolbar } from '../../../../common/inventory_models/toolbars'; import { ToolbarWrapper } from './toolbar_wrapper'; @@ -35,6 +39,10 @@ export interface ToolbarProps { region: ReturnType; accounts: InventoryCloudAccount[]; regions: string[]; + customMetrics: ReturnType; + changeCustomMetrics: ( + payload: SnapshotCustomMetricInput[] + ) => Action; } const wrapToolbarItems = ( diff --git a/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx b/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx index 231030362438f..735539d063b01 100644 --- a/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx +++ b/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx @@ -37,6 +37,8 @@ export const ToolbarWrapper = (props: Props) => { nodeType, accountId, region, + customMetrics, + changeCustomMetrics, }) => props.children({ createDerivedIndexPattern, @@ -51,6 +53,8 @@ export const ToolbarWrapper = (props: Props) => { nodeType, region, accountId, + customMetrics, + changeCustomMetrics, }) } @@ -146,7 +150,7 @@ export const toGroupByOpt = (field: string) => ({ export const toMetricOpt = ( metric: SnapshotMetricType -): { text: string; value: SnapshotMetricType } => { +): { text: string; value: SnapshotMetricType } | undefined => { switch (metric) { case 'cpu': return { diff --git a/x-pack/plugins/infra/public/components/nodes_overview/index.tsx b/x-pack/plugins/infra/public/components/nodes_overview/index.tsx index 8cd3faabd1e12..4d61568a63b9f 100644 --- a/x-pack/plugins/infra/public/components/nodes_overview/index.tsx +++ b/x-pack/plugins/infra/public/components/nodes_overview/index.tsx @@ -19,9 +19,10 @@ import { InfraLoadingPanel } from '../loading'; import { Map } from '../waffle/map'; import { ViewSwitcher } from '../waffle/view_switcher'; import { TableView } from './table'; -import { SnapshotNode } from '../../../common/http_api/snapshot_api'; +import { SnapshotNode, SnapshotCustomMetricInputRT } from '../../../common/http_api/snapshot_api'; import { convertIntervalToString } from '../../utils/convert_interval_to_string'; import { InventoryItemType } from '../../../common/inventory_models/types'; +import { createFormatterForMetric } from '../metrics_explorer/helpers/create_formatter_for_metric'; interface Props { options: InfraWaffleMapOptions; @@ -211,6 +212,10 @@ export const NodesOverview = class extends React.Component { // TODO: Change this to a real implimentation using the tickFormatter from the prototype as an example. private formatter = (val: string | number) => { const { metric } = this.props.options; + if (SnapshotCustomMetricInputRT.is(metric)) { + const formatter = createFormatterForMetric(metric); + return formatter(val); + } const metricFormatter = get(METRIC_FORMATTERS, metric.type, METRIC_FORMATTERS.count); if (val == null) { return ''; diff --git a/x-pack/plugins/infra/public/components/waffle/custom_field_panel.tsx b/x-pack/plugins/infra/public/components/waffle/custom_field_panel.tsx index 15d8b8b0e42b8..d2dc535f6d6b3 100644 --- a/x-pack/plugins/infra/public/components/waffle/custom_field_panel.tsx +++ b/x-pack/plugins/infra/public/components/waffle/custom_field_panel.tsx @@ -50,10 +50,10 @@ export const CustomFieldPanel = class extends React.PureComponent helpText={i18n.translate('xpack.infra.waffle.customGroupByHelpText', { defaultMessage: 'This is the field used for the terms aggregation', })} - compressed + display="rowCompressed" + fullWidth > selectedOptions={this.state.selectedOptions} options={options} onChange={this.handleFieldSelection} + fullWidth isClearable={false} />
diff --git a/x-pack/plugins/infra/public/components/waffle/metric_control/custom_metric_form.tsx b/x-pack/plugins/infra/public/components/waffle/metric_control/custom_metric_form.tsx new file mode 100644 index 0000000000000..26e42061ed10b --- /dev/null +++ b/x-pack/plugins/infra/public/components/waffle/metric_control/custom_metric_form.tsx @@ -0,0 +1,247 @@ +/* + * 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, useCallback } from 'react'; +import uuid from 'uuid'; +import { + EuiForm, + EuiButton, + EuiButtonEmpty, + EuiFormRow, + EuiFieldText, + EuiComboBox, + EuiSelect, + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiPopoverTitle, +} from '@elastic/eui'; +import { IFieldType } from 'src/plugins/data/public'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + SnapshotCustomAggregation, + SnapshotCustomMetricInput, + SNAPSHOT_CUSTOM_AGGREGATIONS, + SnapshotCustomAggregationRT, +} from '../../../../common/http_api/snapshot_api'; +import { EuiTheme, withTheme } from '../../../../../../legacy/common/eui_styled_components'; + +interface SelectedOption { + label: string; +} + +const AGGREGATION_LABELS = { + ['avg']: i18n.translate('xpack.infra.waffle.customMetrics.aggregationLables.avg', { + defaultMessage: 'Average', + }), + ['max']: i18n.translate('xpack.infra.waffle.customMetrics.aggregationLables.max', { + defaultMessage: 'Max', + }), + ['min']: i18n.translate('xpack.infra.waffle.customMetrics.aggregationLables.min', { + defaultMessage: 'Min', + }), + ['rate']: i18n.translate('xpack.infra.waffle.customMetrics.aggregationLables.rate', { + defaultMessage: 'Rate', + }), +}; + +interface Props { + theme: EuiTheme; + metric?: SnapshotCustomMetricInput; + fields: IFieldType[]; + customMetrics: SnapshotCustomMetricInput[]; + onChange: (metric: SnapshotCustomMetricInput) => void; + onCancel: () => void; +} + +export const CustomMetricForm = withTheme( + ({ theme, onCancel, fields, onChange, metric }: Props) => { + const [label, setLabel] = useState(metric ? metric.label : void 0); + const [aggregation, setAggregation] = useState( + metric ? metric.aggregation : 'avg' + ); + const [field, setField] = useState(metric ? metric.field : void 0); + + const handleSubmit = useCallback(() => { + if (metric && aggregation && field) { + onChange({ + ...metric, + label, + aggregation, + field, + }); + } else if (aggregation && field) { + const newMetric: SnapshotCustomMetricInput = { + type: 'custom', + id: uuid.v1(), + label, + aggregation, + field, + }; + onChange(newMetric); + } + }, [metric, aggregation, field, onChange, label]); + + const handleLabelChange = useCallback( + e => { + setLabel(e.target.value); + }, + [setLabel] + ); + + const handleFieldChange = useCallback( + (selectedOptions: SelectedOption[]) => { + setField(selectedOptions[0].label); + }, + [setField] + ); + + const handleAggregationChange = useCallback( + e => { + const value = e.target.value; + const aggValue: SnapshotCustomAggregation = SnapshotCustomAggregationRT.is(value) + ? value + : 'avg'; + setAggregation(aggValue); + }, + [setAggregation] + ); + + const fieldOptions = fields + .filter(f => f.aggregatable && f.type === 'number' && !(field && field === f.name)) + .map(f => ({ label: f.name })); + + const aggregationOptions = SNAPSHOT_CUSTOM_AGGREGATIONS.map(k => ({ + text: AGGREGATION_LABELS[k as SnapshotCustomAggregation], + value: k, + })); + + const isSubmitDisabled = !field || !aggregation; + + const title = metric + ? i18n.translate('xpack.infra.waffle.customMetricPanelLabel.edit', { + defaultMessage: 'Edit custom metric', + }) + : i18n.translate('xpack.infra.waffle.customMetricPanelLabel.add', { + defaultMessage: 'Add custom metric', + }); + + const titleAriaLabel = metric + ? i18n.translate('xpack.infra.waffle.customMetricPanelLabel.editAriaLabel', { + defaultMessage: 'Back to custom metrics edit mode', + }) + : i18n.translate('xpack.infra.waffle.customMetricPanelLabel.addAriaLabel', { + defaultMessage: 'Back to metric picker', + }); + + return ( +
+ + + + {title} + + +
+ + + + + + + + of + + + + + + + + + + +
+
+ + + + + + +
+
+
+ ); + } +); diff --git a/x-pack/plugins/infra/public/components/waffle/metric_control/get_custom_metric_label.ts b/x-pack/plugins/infra/public/components/waffle/metric_control/get_custom_metric_label.ts new file mode 100644 index 0000000000000..4f88c1b29c1f2 --- /dev/null +++ b/x-pack/plugins/infra/public/components/waffle/metric_control/get_custom_metric_label.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { SnapshotCustomMetricInput } from '../../../../common/http_api/snapshot_api'; + +export const getCustomMetricLabel = (metric: SnapshotCustomMetricInput) => { + const METRIC_LABELS = { + avg: i18n.translate('xpack.infra.waffle.aggregationNames.avg', { + defaultMessage: 'Avg of {field}', + values: { field: metric.field }, + }), + max: i18n.translate('xpack.infra.waffle.aggregationNames.max', { + defaultMessage: 'Max of {field}', + values: { field: metric.field }, + }), + min: i18n.translate('xpack.infra.waffle.aggregationNames.min', { + defaultMessage: 'Min of {field}', + values: { field: metric.field }, + }), + rate: i18n.translate('xpack.infra.waffle.aggregationNames.rate', { + defaultMessage: 'Rate of {field}', + values: { field: metric.field }, + }), + }; + return metric.label ? metric.label : METRIC_LABELS[metric.aggregation]; +}; diff --git a/x-pack/plugins/infra/public/components/waffle/metric_control/index.tsx b/x-pack/plugins/infra/public/components/waffle/metric_control/index.tsx new file mode 100644 index 0000000000000..0f2034fe9cb25 --- /dev/null +++ b/x-pack/plugins/infra/public/components/waffle/metric_control/index.tsx @@ -0,0 +1,199 @@ +/* + * 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 { EuiFilterButton, EuiFilterGroup, EuiPopover } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import React, { useState, useCallback } from 'react'; +import { IFieldType } from 'src/plugins/data/public'; +import { + SnapshotMetricInput, + SnapshotCustomMetricInput, + SnapshotCustomMetricInputRT, +} from '../../../../common/http_api/snapshot_api'; +import { CustomMetricForm } from './custom_metric_form'; +import { getCustomMetricLabel } from './get_custom_metric_label'; +import { MetricsContextMenu } from './metrics_context_menu'; +import { ModeSwitcher } from './mode_switcher'; +import { MetricsEditMode } from './metrics_edit_mode'; +import { CustomMetricMode } from './types'; +import { SnapshotMetricType } from '../../../../common/inventory_models/types'; + +interface Props { + options: Array<{ text: string; value: string }>; + metric: SnapshotMetricInput; + fields: IFieldType[]; + onChange: (metric: SnapshotMetricInput) => void; + onChangeCustomMetrics: (metrics: SnapshotCustomMetricInput[]) => void; + customMetrics: SnapshotCustomMetricInput[]; +} + +export const WaffleMetricControls = ({ + fields, + onChange, + onChangeCustomMetrics, + metric, + options, + customMetrics, +}: Props) => { + const [isPopoverOpen, setPopoverState] = useState(false); + const [mode, setMode] = useState('pick'); + const [editModeCustomMetrics, setEditModeCustomMetrics] = useState( + [] + ); + const [editCustomMetric, setEditCustomMetric] = useState(); + const handleClose = useCallback(() => { + setPopoverState(false); + }, [setPopoverState]); + + const handleToggle = useCallback(() => { + setPopoverState(!isPopoverOpen); + }, [isPopoverOpen]); + + const handleCustomMetric = useCallback( + (newMetric: SnapshotCustomMetricInput) => { + onChangeCustomMetrics([...customMetrics, newMetric]); + onChange(newMetric); + setMode('pick'); + }, + [customMetrics, onChange, onChangeCustomMetrics, setMode] + ); + + const setModeToEdit = useCallback(() => { + setMode('edit'); + setEditModeCustomMetrics(customMetrics); + }, [customMetrics]); + + const setModeToAdd = useCallback(() => { + setMode('addMetric'); + }, [setMode]); + + const setModeToPick = useCallback(() => { + setMode('pick'); + setEditModeCustomMetrics([]); + }, [setMode]); + + const handleDeleteCustomMetric = useCallback( + (m: SnapshotCustomMetricInput) => { + // If the metric we are deleting is the currently selected metric + // we need to change to the default. + if (SnapshotCustomMetricInputRT.is(metric) && m.id === metric.id) { + onChange({ type: options[0].value as SnapshotMetricType }); + } + // Filter out the deleted metric from the editbale. + const newMetrics = editModeCustomMetrics.filter(v => v.id !== m.id); + setEditModeCustomMetrics(newMetrics); + }, + [editModeCustomMetrics, metric, onChange, options] + ); + + const handleEditCustomMetric = useCallback( + (currentMetric: SnapshotCustomMetricInput) => { + const newMetrics = customMetrics.map(m => (m.id === currentMetric.id && currentMetric) || m); + onChangeCustomMetrics(newMetrics); + setModeToPick(); + setEditCustomMetric(void 0); + setEditModeCustomMetrics([]); + }, + [customMetrics, onChangeCustomMetrics, setModeToPick] + ); + + const handleSelectMetricToEdit = useCallback( + (currentMetric: SnapshotCustomMetricInput) => { + setEditCustomMetric(currentMetric); + setMode('editMetric'); + }, + [setMode, setEditCustomMetric] + ); + + const handleSaveEdit = useCallback(() => { + onChangeCustomMetrics(editModeCustomMetrics); + setMode('pick'); + }, [editModeCustomMetrics, onChangeCustomMetrics]); + + if (!options.length || !metric.type) { + throw Error( + i18n.translate('xpack.infra.waffle.unableToSelectMetricErrorTitle', { + defaultMessage: 'Unable to select options or value for metric.', + }) + ); + } + + const id = SnapshotCustomMetricInputRT.is(metric) && metric.id ? metric.id : metric.type; + const currentLabel = SnapshotCustomMetricInputRT.is(metric) + ? getCustomMetricLabel(metric) + : options.find(o => o.value === id)?.text; + + if (!currentLabel) { + return null; + } + + const button = ( + + + + ); + + return ( + + + {mode === 'pick' ? ( + + ) : null} + {mode === 'addMetric' ? ( + + ) : null} + {mode === 'editMetric' ? ( + + ) : null} + {mode === 'edit' ? ( + + ) : null} + + + + ); +}; diff --git a/x-pack/plugins/infra/public/components/waffle/metric_control/metrics_context_menu.tsx b/x-pack/plugins/infra/public/components/waffle/metric_control/metrics_context_menu.tsx new file mode 100644 index 0000000000000..1aacf54244c37 --- /dev/null +++ b/x-pack/plugins/infra/public/components/waffle/metric_control/metrics_context_menu.tsx @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React, { useCallback } from 'react'; +import { EuiContextMenuPanelDescriptor, EuiContextMenu } from '@elastic/eui'; +import { + SnapshotMetricInput, + SnapshotCustomMetricInput, + SnapshotCustomMetricInputRT, +} from '../../../../common/http_api/snapshot_api'; +import { + SnapshotMetricTypeRT, + SnapshotMetricType, +} from '../../../../common/inventory_models/types'; +import { getCustomMetricLabel } from './get_custom_metric_label'; + +interface Props { + options: Array<{ text: string; value: string }>; + metric: SnapshotMetricInput; + onChange: (metric: SnapshotMetricInput) => void; + onClose: () => void; + customMetrics: SnapshotCustomMetricInput[]; +} + +export const MetricsContextMenu = ({ + onClose, + onChange, + metric, + options, + customMetrics, +}: Props) => { + const id = SnapshotCustomMetricInputRT.is(metric) && metric.id ? metric.id : metric.type; + + const handleClick = useCallback( + (val: string) => { + if (!SnapshotMetricTypeRT.is(val)) { + const selectedMetric = customMetrics.find(m => m.id === val); + if (selectedMetric) { + onChange(selectedMetric); + } + } else { + onChange({ type: val as SnapshotMetricType }); + } + onClose(); + }, + [customMetrics, onChange, onClose] + ); + + const panels: EuiContextMenuPanelDescriptor[] = [ + { + id: 0, + title: '', + items: [ + ...options.map(o => { + const icon = o.value === id ? 'check' : 'empty'; + const panel = { name: o.text, onClick: () => handleClick(o.value), icon }; + return panel; + }), + ...customMetrics.map(m => { + const icon = m.id === id ? 'check' : 'empty'; + const panel = { + name: getCustomMetricLabel(m), + onClick: () => handleClick(m.id), + icon, + }; + return panel; + }), + ], + }, + ]; + + return ; +}; diff --git a/x-pack/plugins/infra/public/components/waffle/metric_control/metrics_edit_mode.tsx b/x-pack/plugins/infra/public/components/waffle/metric_control/metrics_edit_mode.tsx new file mode 100644 index 0000000000000..ba1f46815db20 --- /dev/null +++ b/x-pack/plugins/infra/public/components/waffle/metric_control/metrics_edit_mode.tsx @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import { EuiFlexItem, EuiFlexGroup, EuiButtonIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { SnapshotCustomMetricInput } from '../../../../common/http_api/snapshot_api'; +import { getCustomMetricLabel } from './get_custom_metric_label'; +import { EuiTheme, withTheme } from '../../../../../../legacy/common/eui_styled_components'; + +interface Props { + theme: EuiTheme; + customMetrics: SnapshotCustomMetricInput[]; + options: Array<{ text: string; value: string }>; + onEdit: (metric: SnapshotCustomMetricInput) => void; + onDelete: (metric: SnapshotCustomMetricInput) => void; +} +const ICON_WIDTH = 36; + +export const MetricsEditMode = withTheme( + ({ theme, customMetrics, options, onEdit, onDelete }: Props) => { + return ( +
+ {options.map(option => ( +
+ {option.text} +
+ ))} + {customMetrics.map(metric => ( + + + onEdit(metric)} + aria-label={i18n.translate( + 'xpack.infra.waffle.customMetrics.editMode.editButtonAriaLabel', + { + defaultMessage: 'Edit custom metric for {name}', + values: { name: getCustomMetricLabel(metric) }, + } + )} + /> + + + {getCustomMetricLabel(metric)} + + + onDelete(metric)} + aria-label={i18n.translate( + 'xpack.infra.waffle.customMetrics.editMode.deleteAriaLabel', + { + defaultMessage: 'Delete custom metric for {name}', + values: { name: getCustomMetricLabel(metric) }, + } + )} + /> + + + ))} +
+ ); + } +); diff --git a/x-pack/plugins/infra/public/components/waffle/metric_control/mode_switcher.tsx b/x-pack/plugins/infra/public/components/waffle/metric_control/mode_switcher.tsx new file mode 100644 index 0000000000000..43bb904594c68 --- /dev/null +++ b/x-pack/plugins/infra/public/components/waffle/metric_control/mode_switcher.tsx @@ -0,0 +1,113 @@ +/* + * 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, EuiButtonEmpty, EuiButton } from '@elastic/eui'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CustomMetricMode } from './types'; +import { SnapshotCustomMetricInput } from '../../../../common/http_api/snapshot_api'; +import { EuiTheme, withTheme } from '../../../../../../legacy/common/eui_styled_components'; + +interface Props { + theme: EuiTheme; + onEdit: () => void; + onAdd: () => void; + onSave: () => void; + onEditCancel: () => void; + mode: CustomMetricMode; + customMetrics: SnapshotCustomMetricInput[]; +} + +export const ModeSwitcher = withTheme( + ({ onSave, onEditCancel, onEdit, onAdd, mode, customMetrics, theme }: Props) => { + if (['editMetric', 'addMetric'].includes(mode)) { + return null; + } + return ( +
+ + {mode === 'edit' ? ( + <> + + + + + + + + + + + + ) : ( + <> + + + + + + + + + + + + )} + +
+ ); + } +); diff --git a/x-pack/plugins/infra/public/components/waffle/metric_control/types.ts b/x-pack/plugins/infra/public/components/waffle/metric_control/types.ts new file mode 100644 index 0000000000000..79e42b12f9976 --- /dev/null +++ b/x-pack/plugins/infra/public/components/waffle/metric_control/types.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export type CustomMetricMode = 'pick' | 'addMetric' | 'editMetric' | 'edit'; diff --git a/x-pack/plugins/infra/public/components/waffle/waffle_group_by_controls.tsx b/x-pack/plugins/infra/public/components/waffle/waffle_group_by_controls.tsx index 81f82ec27b4a3..1a3cef591bc07 100644 --- a/x-pack/plugins/infra/public/components/waffle/waffle_group_by_controls.tsx +++ b/x-pack/plugins/infra/public/components/waffle/waffle_group_by_controls.tsx @@ -104,6 +104,7 @@ export const WaffleGroupByControls = class extends React.PureComponent void; changeGroupBy: (groupBy: SnapshotGroupBy) => void; changeMetric: (metric: SnapshotMetricInput) => void; + changeCustomMetrics: (metrics: SnapshotCustomMetricInput[]) => void; changeAccount: (id: string) => void; changeRegion: (name: string) => void; } @@ -38,6 +43,7 @@ export const WaffleInventorySwitcher: React.FC = ( changeMetric, changeAccount, changeRegion, + changeCustomMetrics, nodeType, }) => { const [isOpen, setIsOpen] = useState(false); @@ -48,6 +54,7 @@ export const WaffleInventorySwitcher: React.FC = ( closePopover(); changeNodeType(targetNodeType); changeGroupBy([]); + changeCustomMetrics([]); changeAccount(''); changeRegion(''); const inventoryModel = findInventoryModel(targetNodeType); @@ -55,7 +62,15 @@ export const WaffleInventorySwitcher: React.FC = ( type: inventoryModel.metrics.defaultSnapshot, }); }, - [closePopover, changeNodeType, changeGroupBy, changeMetric, changeAccount, changeRegion] + [ + closePopover, + changeNodeType, + changeGroupBy, + changeCustomMetrics, + changeAccount, + changeRegion, + changeMetric, + ] ); const goToHost = useCallback(() => goToNodeType('host'), [goToNodeType]); const goToK8 = useCallback(() => goToNodeType('pod'), [goToNodeType]); diff --git a/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx b/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx deleted file mode 100644 index f9e48730eaaf2..0000000000000 --- a/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - EuiContextMenu, - EuiContextMenuPanelDescriptor, - EuiFilterButton, - EuiFilterGroup, - EuiPopover, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; -import { SnapshotMetricInput } from '../../../common/http_api/snapshot_api'; -import { SnapshotMetricType } from '../../../common/inventory_models/types'; - -interface Props { - options: Array<{ text: string; value: SnapshotMetricType }>; - metric: SnapshotMetricInput; - onChange: (metric: SnapshotMetricInput) => void; -} - -const initialState = { - isPopoverOpen: false, -}; -type State = Readonly; - -export const WaffleMetricControls = class extends React.PureComponent { - public static displayName = 'WaffleMetricControls'; - public readonly state: State = initialState; - public render() { - const { metric, options } = this.props; - const value = metric.type; - - if (!options.length || !value) { - throw Error( - i18n.translate('xpack.infra.waffle.unableToSelectMetricErrorTitle', { - defaultMessage: 'Unable to select options or value for metric.', - }) - ); - } - const currentLabel = options.find(o => o.value === metric.type); - if (!currentLabel) { - return null; - } - const panels: EuiContextMenuPanelDescriptor[] = [ - { - id: 0, - title: '', - items: options.map(o => { - const icon = o.value === metric.type ? 'check' : 'empty'; - const panel = { name: o.text, onClick: this.handleClick(o.value), icon }; - return panel; - }), - }, - ]; - const button = ( - - - - ); - - return ( - - - - - - ); - } - private handleClose = () => { - this.setState({ isPopoverOpen: false }); - }; - - private handleToggle = () => { - this.setState(state => ({ isPopoverOpen: !state.isPopoverOpen })); - }; - - private handleClick = (value: SnapshotMetricType) => () => { - this.props.onChange({ type: value }); - this.handleClose(); - }; -}; diff --git a/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx b/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx index 45222b32aa51f..47dd6a5a73a73 100644 --- a/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx +++ b/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx @@ -14,7 +14,11 @@ import { State, waffleOptionsActions, waffleOptionsSelectors } from '../../store import { asChildFunctionRenderer } from '../../utils/typed_react'; import { bindPlainActionCreators } from '../../utils/typed_redux'; import { UrlStateContainer } from '../../utils/url_state'; -import { SnapshotMetricInput, SnapshotGroupBy } from '../../../common/http_api/snapshot_api'; +import { + SnapshotMetricInput, + SnapshotGroupBy, + SnapshotCustomMetricInputRT, +} from '../../../common/http_api/snapshot_api'; import { SnapshotMetricTypeRT, InventoryItemType, @@ -31,6 +35,7 @@ const selectOptionsUrlState = createSelector( waffleOptionsSelectors.selectAutoBounds, waffleOptionsSelectors.selectAccountId, waffleOptionsSelectors.selectRegion, + waffleOptionsSelectors.selectCustomMetrics, ( metric, view, @@ -40,7 +45,8 @@ const selectOptionsUrlState = createSelector( boundsOverride, autoBounds, accountId, - region + region, + customMetrics ) => ({ metric, groupBy, @@ -51,6 +57,7 @@ const selectOptionsUrlState = createSelector( autoBounds, accountId, region, + customMetrics, }) ); @@ -66,6 +73,7 @@ export const withWaffleOptions = connect( accountId: waffleOptionsSelectors.selectAccountId(state), region: waffleOptionsSelectors.selectRegion(state), urlState: selectOptionsUrlState(state), + customMetrics: waffleOptionsSelectors.selectCustomMetrics(state), }), bindPlainActionCreators({ changeMetric: waffleOptionsActions.changeMetric, @@ -77,6 +85,7 @@ export const withWaffleOptions = connect( changeAutoBounds: waffleOptionsActions.changeAutoBounds, changeAccount: waffleOptionsActions.changeAccount, changeRegion: waffleOptionsActions.changeRegion, + changeCustomMetrics: waffleOptionsActions.changeCustomMetrics, }) ); @@ -96,6 +105,7 @@ interface WaffleOptionsUrlState { auto?: ReturnType; accountId?: ReturnType; region?: ReturnType; + customMetrics?: ReturnType; } export const WithWaffleOptionsUrlState = () => ( @@ -111,6 +121,7 @@ export const WithWaffleOptionsUrlState = () => ( changeBoundsOverride, changeAccount, changeRegion, + changeCustomMetrics, }) => ( urlState={urlState} @@ -144,6 +155,9 @@ export const WithWaffleOptionsUrlState = () => ( if (newUrlState && newUrlState.region) { changeRegion(newUrlState.region); } + if (newUrlState && newUrlState.customMetrics) { + changeCustomMetrics(newUrlState.customMetrics); + } }} onInitialize={initialUrlState => { if (initialUrlState && initialUrlState.metric) { @@ -173,6 +187,9 @@ export const WithWaffleOptionsUrlState = () => ( if (initialUrlState && initialUrlState.region) { changeRegion(initialUrlState.region); } + if (initialUrlState && initialUrlState.customMetrics) { + changeCustomMetrics(initialUrlState.customMetrics); + } }} /> )} @@ -191,6 +208,7 @@ const mapToUrlState = (value: any): WaffleOptionsUrlState | undefined => auto: mapToAutoBoundsUrlState(value.autoBounds), accountId: value.accountId, region: value.region, + customMetrics: mapToCustomMetricsUrlState(value.customMetrics), } : undefined; @@ -232,6 +250,12 @@ const mapToCustomOptionsUrlState = (subject: any) => { : undefined; }; +const mapToCustomMetricsUrlState = (subject: any) => { + return subject && Array.isArray(subject) && subject.every(s => SnapshotCustomMetricInputRT.is(s)) + ? subject + : []; +}; + const mapToBoundsOverideUrlState = (subject: any) => { return subject != null && isNumber(subject.max) && isNumber(subject.min) ? subject : undefined; }; diff --git a/x-pack/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx b/x-pack/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx index 4e8a051bf8697..421c506166d04 100644 --- a/x-pack/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx +++ b/x-pack/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx @@ -30,6 +30,7 @@ const selectViewState = createSelector( waffleTimeSelectors.selectCurrentTime, waffleTimeSelectors.selectIsAutoReloading, waffleFilterSelectors.selectWaffleFilterQuery, + waffleOptionsSelectors.selectCustomMetrics, ( metric, view, @@ -40,7 +41,8 @@ const selectViewState = createSelector( autoBounds, time, autoReload, - filterQuery + filterQuery, + customMetrics ) => ({ time, autoReload, @@ -52,6 +54,7 @@ const selectViewState = createSelector( boundsOverride, autoBounds, filterQuery, + customMetrics, }) ); @@ -90,6 +93,9 @@ export const withWaffleViewState = connect( if (viewState.customOptions) { dispatch(waffleOptionsActions.changeCustomOptions(viewState.customOptions)); } + if (viewState.customMetrics) { + dispatch(waffleOptionsActions.changeCustomMetrics(viewState.customMetrics)); + } if (viewState.boundsOverride) { dispatch(waffleOptionsActions.changeBoundsOverride(viewState.boundsOverride)); } @@ -130,6 +136,7 @@ export interface WaffleViewState { nodeType?: ReturnType; view?: ReturnType; customOptions?: ReturnType; + customMetrics?: ReturnType; boundsOverride?: ReturnType; autoBounds?: ReturnType; time?: ReturnType; diff --git a/x-pack/plugins/infra/public/pages/infrastructure/snapshot/toolbar.tsx b/x-pack/plugins/infra/public/pages/infrastructure/snapshot/toolbar.tsx index a5780f44050e1..3606580e86504 100644 --- a/x-pack/plugins/infra/public/pages/infrastructure/snapshot/toolbar.tsx +++ b/x-pack/plugins/infra/public/pages/infrastructure/snapshot/toolbar.tsx @@ -29,6 +29,7 @@ export const SnapshotToolbar = () => ( changeGroupBy, changeAccount, changeRegion, + changeCustomMetrics, nodeType, }) => ( ( changeGroupBy={changeGroupBy} changeAccount={changeAccount} changeRegion={changeRegion} + changeCustomMetrics={changeCustomMetrics} /> )} diff --git a/x-pack/plugins/infra/public/store/local/waffle_options/actions.ts b/x-pack/plugins/infra/public/store/local/waffle_options/actions.ts index 4a1b45084b08a..88229c31b2056 100644 --- a/x-pack/plugins/infra/public/store/local/waffle_options/actions.ts +++ b/x-pack/plugins/infra/public/store/local/waffle_options/actions.ts @@ -5,7 +5,11 @@ */ import actionCreatorFactory from 'typescript-fsa'; -import { SnapshotGroupBy, SnapshotMetricInput } from '../../../../common/http_api/snapshot_api'; +import { + SnapshotGroupBy, + SnapshotMetricInput, + SnapshotCustomMetricInput, +} from '../../../../common/http_api/snapshot_api'; import { InventoryItemType } from '../../../../common/inventory_models/types'; import { InfraGroupByOptions, InfraWaffleMapBounds } from '../../../lib/lib'; @@ -20,3 +24,6 @@ export const changeBoundsOverride = actionCreator('CHANGE_ export const changeAutoBounds = actionCreator('CHANGE_AUTO_BOUNDS'); export const changeAccount = actionCreator('CHANGE_ACCOUNT'); export const changeRegion = actionCreator('CHANGE_REGION'); +export const changeCustomMetrics = actionCreator( + 'CHANGE_CUSTOM_METRICS' +); diff --git a/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts b/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts index 9d86ffe612a28..3789228a7c16b 100644 --- a/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts +++ b/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts @@ -6,7 +6,11 @@ import { combineReducers } from 'redux'; import { reducerWithInitialState } from 'typescript-fsa-reducers'; -import { SnapshotMetricInput, SnapshotGroupBy } from '../../../../common/http_api/snapshot_api'; +import { + SnapshotMetricInput, + SnapshotGroupBy, + SnapshotCustomMetricInput, +} from '../../../../common/http_api/snapshot_api'; import { InfraGroupByOptions, InfraWaffleMapBounds } from '../../../lib/lib'; import { changeAutoBounds, @@ -18,6 +22,7 @@ import { changeView, changeAccount, changeRegion, + changeCustomMetrics, } from './actions'; import { InventoryItemType } from '../../../../common/inventory_models/types'; @@ -31,6 +36,7 @@ export interface WaffleOptionsState { autoBounds: boolean; accountId: string; region: string; + customMetrics: SnapshotCustomMetricInput[]; } export const initialWaffleOptionsState: WaffleOptionsState = { @@ -43,6 +49,7 @@ export const initialWaffleOptionsState: WaffleOptionsState = { autoBounds: true, accountId: '', region: '', + customMetrics: [], }; const currentMetricReducer = reducerWithInitialState(initialWaffleOptionsState.metric).case( @@ -88,6 +95,10 @@ const currentRegionReducer = reducerWithInitialState(initialWaffleOptionsState.r (current, target) => target ); +const currentCustomMetricsReducer = reducerWithInitialState( + initialWaffleOptionsState.customMetrics +).case(changeCustomMetrics, (current, target) => target); + export const waffleOptionsReducer = combineReducers({ metric: currentMetricReducer, groupBy: currentGroupByReducer, @@ -98,4 +109,5 @@ export const waffleOptionsReducer = combineReducers({ autoBounds: currentAutoBoundsReducer, accountId: currentAccountIdReducer, region: currentRegionReducer, + customMetrics: currentCustomMetricsReducer, }); diff --git a/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts b/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts index 255fbd5ec4266..4487af156df97 100644 --- a/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts +++ b/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts @@ -15,3 +15,4 @@ export const selectBoundsOverride = (state: WaffleOptionsState) => state.boundsO export const selectAutoBounds = (state: WaffleOptionsState) => state.autoBounds; export const selectAccountId = (state: WaffleOptionsState) => state.accountId; export const selectRegion = (state: WaffleOptionsState) => state.region; +export const selectCustomMetrics = (state: WaffleOptionsState) => state.customMetrics; diff --git a/x-pack/plugins/infra/server/lib/snapshot/query_helpers.ts b/x-pack/plugins/infra/server/lib/snapshot/query_helpers.ts index 44d32c7b915a8..383dc9a773abe 100644 --- a/x-pack/plugins/infra/server/lib/snapshot/query_helpers.ts +++ b/x-pack/plugins/infra/server/lib/snapshot/query_helpers.ts @@ -8,7 +8,16 @@ import { i18n } from '@kbn/i18n'; import { findInventoryModel, findInventoryFields } from '../../../common/inventory_models/index'; import { InfraSnapshotRequestOptions } from './types'; import { getIntervalInSeconds } from '../../utils/get_interval_in_seconds'; -import { SnapshotModelRT, SnapshotModel } from '../../../common/inventory_models/types'; +import { + SnapshotModelRT, + SnapshotModel, + InventoryItemType, +} from '../../../common/inventory_models/types'; +import { + SnapshotMetricInput, + SnapshotCustomMetricInputRT, +} from '../../../common/http_api/snapshot_api'; +import { networkTraffic } from '../../../common/inventory_models/shared/metrics/snapshot/network_traffic'; interface GroupBySource { [id: string]: { @@ -45,9 +54,25 @@ export const getMetricsSources = (options: InfraSnapshotRequestOptions) => { return [{ id: { terms: { field: fields.id } } }]; }; +export const metricToAggregation = (nodeType: InventoryItemType, metric: SnapshotMetricInput) => { + const inventoryModel = findInventoryModel(nodeType); + if (SnapshotCustomMetricInputRT.is(metric)) { + if (metric.aggregation === 'rate') { + return networkTraffic(metric.type, metric.field); + } + return { + custom: { + [metric.aggregation]: { + field: metric.field, + }, + }, + }; + } + return inventoryModel.metrics.snapshot?.[metric.type]; +}; + export const getMetricsAggregations = (options: InfraSnapshotRequestOptions): SnapshotModel => { - const inventoryModel = findInventoryModel(options.nodeType); - const aggregation = inventoryModel.metrics.snapshot?.[options.metric.type]; + const aggregation = metricToAggregation(options.nodeType, options.metric); if (!SnapshotModelRT.is(aggregation)) { throw new Error( i18n.translate('xpack.infra.snapshot.missingSnapshotMetricError', { diff --git a/x-pack/test/api_integration/apis/infra/waffle.ts b/x-pack/test/api_integration/apis/infra/waffle.ts index 80fea1cdcd295..3413fc283556c 100644 --- a/x-pack/test/api_integration/apis/infra/waffle.ts +++ b/x-pack/test/api_integration/apis/infra/waffle.ts @@ -14,12 +14,15 @@ import { InfraSnapshotGroupbyInput, } from '../../../../plugins/infra/server/graphql/types'; import { FtrProviderContext } from '../../ftr_provider_context'; -import { SnapshotNodeResponse } from '../../../../plugins/infra/common/http_api/snapshot_api'; +import { + SnapshotNodeResponse, + SnapshotMetricInput, +} from '../../../../plugins/infra/common/http_api/snapshot_api'; import { DATES } from './constants'; interface SnapshotRequest { filterQuery?: string | null; - metric: InfraSnapshotMetricInput; + metric: SnapshotMetricInput; groupBy: InfraSnapshotGroupbyInput[]; nodeType: InfraNodeType; sourceId: string; @@ -197,6 +200,44 @@ export default function({ getService }: FtrProviderContext) { }); }); + it('should work with custom metrics', async () => { + const data = await fetchSnapshot({ + sourceId: 'default', + timerange: { + to: max, + from: min, + interval: '1m', + }, + metric: { + type: 'custom', + field: 'system.cpu.user.pct', + aggregation: 'avg', + id: '1', + } as SnapshotMetricInput, + nodeType: 'host' as InfraNodeType, + groupBy: [], + }); + + const snapshot = data; + expect(snapshot).to.have.property('nodes'); + if (snapshot) { + const { nodes } = snapshot; + expect(nodes.length).to.equal(1); + const firstNode = first(nodes); + expect(firstNode).to.have.property('path'); + expect(firstNode.path.length).to.equal(1); + expect(first(firstNode.path)).to.have.property('value', 'demo-stack-mysql-01'); + expect(first(firstNode.path)).to.have.property('label', 'demo-stack-mysql-01'); + expect(firstNode).to.have.property('metric'); + expect(firstNode.metric).to.eql({ + name: 'custom', + value: 0.0041964285714285714, + max: 0.0041964285714285714, + avg: 0.0006994047619047619, + }); + } + }); + it('should basically work with 1 grouping', () => { const resp = fetchSnapshot({ sourceId: 'default', From e97b451cc186e47a4621b85cf2bd814a8529c0b6 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Wed, 26 Feb 2020 16:42:15 +0000 Subject: [PATCH 09/64] [SIEM] add custom reputation link (#57814) * add custom reputation link * fix unit test * add number of limitation to reputation links * fix dependency * apply defaultFieldRendererOverflow to reputation link * fix unit test * fix url template * fix display links * fix types * fix for review * update test case * update snapshot * add icons and tooltips * fix style * update test * add external link component * update test * fix types * fix style * update snapshot * remove useMemo * update description * code review * review II * code review * update description * fix unit test * fix unit test * fix unit test * fix unit test * fix types * fix styles * fix style * fix style * fix review Co-authored-by: Elastic Machine --- .../legacy/plugins/siem/common/constants.ts | 9 + x-pack/legacy/plugins/siem/index.ts | 15 + .../field_renderers.test.tsx.snap | 20 +- .../field_renderers/field_renderers.tsx | 111 +- .../public/components/links/index.test.tsx | 365 +- .../siem/public/components/links/index.tsx | 203 +- .../__snapshots__/zeek_details.test.tsx.snap | 3261 +++++++++++++++++ .../body/renderers/zeek/zeek_details.test.tsx | 5 +- .../renderers/zeek/zeek_signature.test.tsx | 11 +- .../body/renderers/zeek/zeek_signature.tsx | 10 +- .../step_about_rule/helpers.test.ts | 18 + 11 files changed, 3876 insertions(+), 152 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/helpers.test.ts diff --git a/x-pack/legacy/plugins/siem/common/constants.ts b/x-pack/legacy/plugins/siem/common/constants.ts index 0d9e092e21d82..2a30293c244af 100644 --- a/x-pack/legacy/plugins/siem/common/constants.ts +++ b/x-pack/legacy/plugins/siem/common/constants.ts @@ -38,6 +38,15 @@ export const NEWS_FEED_URL_SETTING = 'siem:newsFeedUrl'; /** The default value for News feed widget */ export const NEWS_FEED_URL_SETTING_DEFAULT = 'https://feeds.elastic.co/security-solution'; +/** This Kibana Advanced Setting specifies the URLs of `IP Reputation Links`*/ +export const IP_REPUTATION_LINKS_SETTING = 'siem:ipReputationLinks'; + +/** The default value for `IP Reputation Links` */ +export const IP_REPUTATION_LINKS_SETTING_DEFAULT = `[ + { "name": "virustotal.com", "url_template": "https://www.virustotal.com/gui/search/{{ip}}" }, + { "name": "talosIntelligence.com", "url_template": "https://talosintelligence.com/reputation_center/lookup?search={{ip}}" } +]`; + /** * Id for the signals alerting type */ diff --git a/x-pack/legacy/plugins/siem/index.ts b/x-pack/legacy/plugins/siem/index.ts index 731ef10aa225e..db398821aecfd 100644 --- a/x-pack/legacy/plugins/siem/index.ts +++ b/x-pack/legacy/plugins/siem/index.ts @@ -28,6 +28,8 @@ import { NEWS_FEED_URL_SETTING, NEWS_FEED_URL_SETTING_DEFAULT, SIGNALS_INDEX_KEY, + IP_REPUTATION_LINKS_SETTING, + IP_REPUTATION_LINKS_SETTING_DEFAULT, } from './common/constants'; import { defaultIndexPattern } from './default_index_pattern'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; @@ -144,6 +146,19 @@ export const siem = (kibana: any) => { category: ['siem'], requiresPageReload: true, }, + [IP_REPUTATION_LINKS_SETTING]: { + name: i18n.translate('xpack.siem.uiSettings.ipReputationLinks', { + defaultMessage: 'IP Reputation Links', + }), + value: IP_REPUTATION_LINKS_SETTING_DEFAULT, + type: 'json', + description: i18n.translate('xpack.siem.uiSettings.ipReputationLinksDescription', { + defaultMessage: + 'Array of URL templates to build the list of reputation URLs to be displayed on the IP Details page.', + }), + category: ['siem'], + requiresPageReload: true, + }, }, mappings: savedObjectMappings, }, 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 2ff93b2ecada4..59010ab80af63 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 @@ -122,25 +122,17 @@ exports[`Field Renderers #reputationRenderer it renders correctly against snapsh - - virustotal.com - - , - - talosIntelligence.com - + /> `; exports[`Field Renderers #whoisRenderer it renders correctly against snapshot 1`] = ` - iana.org - + `; 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 80d68dfe1b731..222eef515958c 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 @@ -15,7 +15,7 @@ import { escapeDataProviderId } from '../drag_and_drop/helpers'; import { DefaultDraggable } from '../draggables'; import { getEmptyTagValue } from '../empty_value'; import { FormattedRelativePreferenceDate } from '../formatted_date'; -import { HostDetailsLink, ReputationLink, VirusTotalLink, WhoIsLink } from '../links'; +import { HostDetailsLink, ReputationLink, WhoIsLink, ReputationLinkSetting } from '../links'; import { Spacer } from '../page'; import * as i18n from '../page/network/ip_overview/translations'; @@ -132,11 +132,7 @@ export const hostNameRenderer = (host: HostEcsFields, ipFilter?: string): React. export const whoisRenderer = (ip: string) => {i18n.VIEW_WHOIS}; export const reputationRenderer = (ip: string): React.ReactElement => ( - <> - {i18n.VIEW_VIRUS_TOTAL} - {', '} - {i18n.VIEW_TALOS_INTELLIGENCE} - + ); interface DefaultFieldRendererProps { @@ -148,73 +144,78 @@ interface DefaultFieldRendererProps { moreMaxHeight?: string; } +type OverflowRenderer = (item: string | ReputationLinkSetting) => JSX.Element; + // TODO: This causes breaks between elements until the ticket below is fixed // https://github.com/elastic/ingest-dev/issues/474 -export const DefaultFieldRenderer = React.memo( - ({ - attrName, - displayCount = 1, - idPrefix, - moreMaxHeight = DEFAULT_MORE_MAX_HEIGHT, - render, - rowItems, - }) => { - if (rowItems != null && rowItems.length > 0) { - const draggables = rowItems.slice(0, displayCount).map((rowItem, index) => { - const id = escapeDataProviderId( - `default-field-renderer-default-draggable-${idPrefix}-${attrName}-${rowItem}` - ); - return ( - - {index !== 0 && ( - <> - {','} - - - )} +export const DefaultFieldRendererComponent: React.FC = ({ + attrName, + displayCount = 1, + idPrefix, + moreMaxHeight = DEFAULT_MORE_MAX_HEIGHT, + render, + rowItems, +}) => { + if (rowItems != null && rowItems.length > 0) { + const draggables = rowItems.slice(0, displayCount).map((rowItem, index) => { + const id = escapeDataProviderId( + `default-field-renderer-default-draggable-${idPrefix}-${attrName}-${rowItem}` + ); + return ( + + {index !== 0 && ( + <> + {','} + + + )} + {typeof rowItem === 'string' && ( {render ? render(rowItem) : rowItem} - - ); - }); - - return draggables.length > 0 ? ( - - {draggables}{' '} - { - - } - - ) : ( - getEmptyTagValue() + )} + ); - } else { - return getEmptyTagValue(); - } + }); + + return draggables.length > 0 ? ( + + {draggables} + + + + + ) : ( + getEmptyTagValue() + ); + } else { + return getEmptyTagValue(); } -); +}; + +export const DefaultFieldRenderer = React.memo(DefaultFieldRendererComponent); DefaultFieldRenderer.displayName = 'DefaultFieldRenderer'; +type RowItemTypes = string | ReputationLinkSetting; interface DefaultFieldRendererOverflowProps { - rowItems: string[]; + rowItems: string[] | ReputationLinkSetting[]; idPrefix: string; - render?: (item: string) => React.ReactNode; + render?: (item: RowItemTypes) => React.ReactNode; overflowIndexStart?: number; moreMaxHeight: string; } interface MoreContainerProps { idPrefix: string; - render?: (item: string) => React.ReactNode; - rowItems: string[]; + render?: (item: RowItemTypes) => React.ReactNode; + rowItems: RowItemTypes[]; moreMaxHeight: string; overflowIndexStart: number; } diff --git a/x-pack/legacy/plugins/siem/public/components/links/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/links/index.test.tsx index ceef7e353b521..d2d1d6569854d 100644 --- a/x-pack/legacy/plugins/siem/public/components/links/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/links/index.test.tsx @@ -4,24 +4,32 @@ * you may not use this file except in compliance with the Elastic License. */ -import { mount } from 'enzyme'; +import { mount, shallow, ShallowWrapper } from 'enzyme'; import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { encodeIpv6 } from '../../lib/helpers'; +import { useUiSetting$ } from '../../lib/kibana'; import { GoogleLink, HostDetailsLink, IPDetailsLink, ReputationLink, - VirusTotalLink, WhoIsLink, CertificateFingerprintLink, Ja3FingerprintLink, PortOrServiceNameLink, + DEFAULT_NUMBER_OF_LINK, + ExternalLink, } from '.'; +jest.mock('../../lib/kibana', () => { + return { + useUiSetting$: jest.fn(), + }; +}); + describe('Custom Links', () => { const hostName = 'Host Name'; const ipv4 = '192.0.2.255'; @@ -101,53 +109,332 @@ describe('Custom Links', () => { }); }); - describe('ReputationLink', () => { - test('it renders link text', () => { - const wrapper = mountWithIntl( - {'Example Link'} - ); - expect(wrapper.text()).toEqual('Example Link'); - }); + describe('External Link', () => { + const mockLink = 'https://www.virustotal.com/gui/search/'; + const mockLinkName = 'Link'; + let wrapper: ShallowWrapper; - test('it renders correct href', () => { - const wrapper = mountWithIntl( - {'Example Link'} - ); - expect(wrapper.find('a').prop('href')).toEqual( - 'https://www.talosintelligence.com/reputation_center/lookup?search=192.0.2.0' - ); + describe('render', () => { + beforeAll(() => { + wrapper = shallow( + + {mockLinkName} + + ); + }); + + test('it renders tooltip', () => { + expect(wrapper.find('[data-test-subj="externalLinkTooltip"]').exists()).toBeTruthy(); + }); + + test('it renders ExternalLinkIcon', () => { + expect(wrapper.find('[data-test-subj="externalLinkIcon"]').exists()).toBeTruthy(); + }); + + test('it renders correct url', () => { + expect(wrapper.find('[data-test-subj="externalLink"]').prop('href')).toEqual(mockLink); + }); + + test('it renders comma if id is given', () => { + expect(wrapper.find('[data-test-subj="externalLinkComma"]').exists()).toBeTruthy(); + }); }); - test("it encodes ", () => { - const wrapper = mountWithIntl( - alert('XSS')"}>{'Example Link'} - ); - expect(wrapper.find('a').prop('href')).toEqual( - "https://www.talosintelligence.com/reputation_center/lookup?search=%3Cscript%3Ealert('XSS')%3C%2Fscript%3E" - ); + describe('not render', () => { + test('it should not render if childen prop is not given', () => { + wrapper = shallow( + + ); + expect(wrapper.find('[data-test-subj="externalLinkTooltip"]').exists()).toBeFalsy(); + }); + + test('it should not render if url prop is not given', () => { + wrapper = shallow( + + ); + expect(wrapper.find('[data-test-subj="externalLinkTooltip"]').exists()).toBeFalsy(); + }); + + test('it should not render if url prop is invalid', () => { + wrapper = shallow( + + ); + expect(wrapper.find('[data-test-subj="externalLinkTooltip"]').exists()).toBeFalsy(); + }); + + test('it should not render comma if id is not given', () => { + wrapper = shallow( + + {mockLinkName} + + ); + expect(wrapper.find('[data-test-subj="externalLinkComma"]').exists()).toBeFalsy(); + }); + + test('it should not render comma for the last item', () => { + wrapper = shallow( + + {mockLinkName} + + ); + expect(wrapper.find('[data-test-subj="externalLinkComma"]').exists()).toBeFalsy(); + }); }); + + describe.each<[number, number, number, boolean]>([ + [0, 2, 5, true], + [1, 2, 5, false], + [2, 2, 5, false], + [3, 2, 5, false], + [4, 2, 5, false], + [5, 2, 5, false], + ])( + 'renders Comma when overflowIndex is smaller than allItems limit', + (idx, overflowIndexStart, allItemsLimit, showComma) => { + beforeAll(() => { + wrapper = shallow( + + {mockLinkName} + + ); + }); + + test(`should render Comma if current id (${idx}) is smaller than the index of last visible item`, () => { + expect(wrapper.find('[data-test-subj="externalLinkComma"]').exists()).toEqual(showComma); + }); + } + ); + + describe.each<[number, number, number, boolean]>([ + [0, 5, 4, true], + [1, 5, 4, true], + [2, 5, 4, true], + [3, 5, 4, false], + [4, 5, 4, false], + [5, 5, 4, false], + ])( + 'When overflowIndex is grater than allItems limit', + (idx, overflowIndexStart, allItemsLimit, showComma) => { + beforeAll(() => { + wrapper = shallow( + + {mockLinkName} + + ); + }); + + test(`Current item (${idx}) should render Comma execpt the last item`, () => { + expect(wrapper.find('[data-test-subj="externalLinkComma"]').exists()).toEqual(showComma); + }); + } + ); + + describe.each<[number, number, number, boolean]>([ + [0, 5, 5, true], + [1, 5, 5, true], + [2, 5, 5, true], + [3, 5, 5, true], + [4, 5, 5, false], + [5, 5, 5, false], + ])( + 'when overflowIndex equals to allItems limit', + (idx, overflowIndexStart, allItemsLimit, showComma) => { + beforeAll(() => { + wrapper = shallow( + + {mockLinkName} + + ); + }); + + test(`Current item (${idx}) should render Comma correctly`, () => { + expect(wrapper.find('[data-test-subj="externalLinkComma"]').exists()).toEqual(showComma); + }); + } + ); }); - describe('VirusTotalLink', () => { - test('it renders sha passed in as value', () => { - const wrapper = mountWithIntl({'Example Link'}); - expect(wrapper.text()).toEqual('Example Link'); + describe('ReputationLink', () => { + const mockCustomizedReputationLinks = [ + { name: 'Link 1', url_template: 'https://www.virustotal.com/gui/search/{{ip}}' }, + { + name: 'Link 2', + url_template: 'https://talosintelligence.com/reputation_center/lookup?search={{ip}}', + }, + { name: 'Link 3', url_template: 'https://www.virustotal.com/gui/search/{{ip}}' }, + { + name: 'Link 4', + url_template: 'https://talosintelligence.com/reputation_center/lookup?search={{ip}}', + }, + { name: 'Link 5', url_template: 'https://www.virustotal.com/gui/search/{{ip}}' }, + { + name: 'Link 6', + url_template: 'https://talosintelligence.com/reputation_center/lookup?search={{ip}}', + }, + ]; + const mockDefaultReputationLinks = mockCustomizedReputationLinks.slice(0, 2); + + describe('links property', () => { + beforeEach(() => { + (useUiSetting$ as jest.Mock).mockReset(); + (useUiSetting$ as jest.Mock).mockReturnValue([mockDefaultReputationLinks]); + }); + + test('it renders default link text', () => { + const wrapper = shallow(); + wrapper.find('[data-test-subj="externalLink"]').forEach((node, idx) => { + expect(node.at(idx).text()).toEqual(mockDefaultReputationLinks[idx].name); + }); + }); + + test('it renders customized link text', () => { + (useUiSetting$ as jest.Mock).mockReset(); + (useUiSetting$ as jest.Mock).mockReturnValue([mockCustomizedReputationLinks]); + const wrapper = shallow(); + wrapper.find('[data-test-subj="externalLink"]').forEach((node, idx) => { + expect(node.at(idx).text()).toEqual(mockCustomizedReputationLinks[idx].name); + }); + }); + + test('it renders correct href', () => { + const wrapper = shallow(); + wrapper.find('[data-test-subj="externalLink"]').forEach((node, idx) => { + expect(node.prop('href')).toEqual( + mockDefaultReputationLinks[idx].url_template.replace('{{ip}}', '192.0.2.0') + ); + }); + }); }); - test('it renders sha passed in as link', () => { - const wrapper = mountWithIntl( - {'Example Link'} - ); - expect(wrapper.find('a').prop('href')).toEqual('https://www.virustotal.com/#/search/abc'); + describe('number of links', () => { + beforeAll(() => { + (useUiSetting$ as jest.Mock).mockReset(); + (useUiSetting$ as jest.Mock).mockReturnValue([mockCustomizedReputationLinks]); + }); + + afterEach(() => { + (useUiSetting$ as jest.Mock).mockClear(); + }); + + test('it renders correct number of links by default', () => { + const wrapper = mountWithIntl(); + expect(wrapper.find('[data-test-subj="externalLinkComponent"]')).toHaveLength( + DEFAULT_NUMBER_OF_LINK + ); + }); + + test('it renders correct number of tooltips by default', () => { + const wrapper = mountWithIntl(); + expect(wrapper.find('[data-test-subj="externalLinkTooltip"]')).toHaveLength( + DEFAULT_NUMBER_OF_LINK + ); + }); + + test('it renders correct number of visible link', () => { + (useUiSetting$ as jest.Mock).mockReset(); + (useUiSetting$ as jest.Mock).mockReturnValue([mockCustomizedReputationLinks]); + + const wrapper = mountWithIntl( + + ); + expect(wrapper.find('[data-test-subj="externalLinkComponent"]')).toHaveLength(1); + }); + + test('it renders correct number of tooltips for visible links', () => { + (useUiSetting$ as jest.Mock).mockReset(); + (useUiSetting$ as jest.Mock).mockReturnValue([mockCustomizedReputationLinks]); + + const wrapper = mountWithIntl( + + ); + expect(wrapper.find('[data-test-subj="externalLinkTooltip"]')).toHaveLength(1); + }); }); - test("it encodes ", () => { - const wrapper = mountWithIntl( - alert('XSS')"}>{'Example Link'} - ); - expect(wrapper.find('a').prop('href')).toEqual( - "https://www.virustotal.com/#/search/%3Cscript%3Ealert('XSS')%3C%2Fscript%3E" - ); + describe('invalid customized links', () => { + const mockInvalidLinksEmptyObj = [{}]; + const mockInvalidLinksNoName = [ + { url_template: 'https://talosintelligence.com/reputation_center/lookup?search={{ip}}' }, + ]; + const mockInvalidLinksNoUrl = [{ name: 'Link 1' }]; + const mockInvalidUrl = [{ name: 'Link 1', url_template: "" }]; + afterEach(() => { + (useUiSetting$ as jest.Mock).mockReset(); + }); + + test('it filters empty object', () => { + (useUiSetting$ as jest.Mock).mockReturnValue([mockInvalidLinksEmptyObj]); + + const wrapper = mountWithIntl( + + ); + expect(wrapper.find('[data-test-subj="externalLink"]')).toHaveLength(0); + }); + + test('it filters object without name property', () => { + (useUiSetting$ as jest.Mock).mockReturnValue([mockInvalidLinksNoName]); + + const wrapper = mountWithIntl( + + ); + expect(wrapper.find('[data-test-subj="externalLink"]')).toHaveLength(0); + }); + + test('it filters object without url_template property', () => { + (useUiSetting$ as jest.Mock).mockReturnValue([mockInvalidLinksNoUrl]); + + const wrapper = mountWithIntl( + + ); + expect(wrapper.find('[data-test-subj="externalLink"]')).toHaveLength(0); + }); + + test('it filters object with invalid url', () => { + (useUiSetting$ as jest.Mock).mockReturnValue([mockInvalidUrl]); + + const wrapper = mountWithIntl( + + ); + expect(wrapper.find('[data-test-subj="externalLink"]')).toHaveLength(0); + }); + }); + + describe('external icon', () => { + beforeAll(() => { + (useUiSetting$ as jest.Mock).mockReset(); + (useUiSetting$ as jest.Mock).mockReturnValue([mockCustomizedReputationLinks]); + }); + + afterEach(() => { + (useUiSetting$ as jest.Mock).mockClear(); + }); + + test('it renders correct number of external icons by default', () => { + const wrapper = mountWithIntl(); + expect(wrapper.find('[data-test-subj="externalLinkIcon"]')).toHaveLength(5); + }); + + test('it renders correct number of external icons', () => { + const wrapper = mountWithIntl( + + ); + expect(wrapper.find('[data-test-subj="externalLinkIcon"]')).toHaveLength(1); + }); }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/links/index.tsx b/x-pack/legacy/plugins/siem/public/components/links/index.tsx index b6548e3e950ba..04de0b1d5d3bf 100644 --- a/x-pack/legacy/plugins/siem/public/components/links/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/links/index.tsx @@ -4,9 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiLink } from '@elastic/eui'; -import React from 'react'; +import { EuiLink, EuiToolTip, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import React, { useMemo } from 'react'; +import { isNil } from 'lodash/fp'; +import styled from 'styled-components'; +import { + DefaultFieldRendererOverflow, + DEFAULT_MORE_MAX_HEIGHT, +} from '../field_renderers/field_renderers'; import { encodeIpv6 } from '../../lib/helpers'; import { getCaseDetailsUrl, @@ -15,6 +21,13 @@ import { getCreateCaseUrl, } from '../link_to'; import { FlowTarget, FlowTargetSourceDest } from '../../graphql/types'; +import { useUiSetting$ } from '../../lib/kibana'; +import { IP_REPUTATION_LINKS_SETTING } from '../../../common/constants'; +import * as i18n from '../page/network/ip_overview/translations'; +import { isUrlInvalid } from '../../pages/detection_engine/rules/components/step_about_rule/helpers'; +import { ExternalLinkIcon } from '../external_link_icon'; + +export const DEFAULT_NUMBER_OF_LINK = 5; // Internal Links const HostDetailsLinkComponent: React.FC<{ children?: React.ReactNode; hostName: string }> = ({ @@ -26,6 +39,39 @@ const HostDetailsLinkComponent: React.FC<{ children?: React.ReactNode; hostName: ); +const whitelistUrlSchemes = ['http://', 'https://']; +export const ExternalLink = React.memo<{ + url: string; + children?: React.ReactNode; + idx?: number; + overflowIndexStart?: number; + allItemsLimit?: number; +}>( + ({ + url, + children, + idx, + overflowIndexStart = DEFAULT_NUMBER_OF_LINK, + allItemsLimit = DEFAULT_NUMBER_OF_LINK, + }) => { + const lastVisibleItemIndex = overflowIndexStart - 1; + const lastItemIndex = allItemsLimit - 1; + const lastIndexToShow = Math.max(0, Math.min(lastVisibleItemIndex, lastItemIndex)); + const inWhitelist = whitelistUrlSchemes.some(scheme => url.indexOf(scheme) === 0); + return url && inWhitelist && !isUrlInvalid(url) && children ? ( + + + {children} + + {!isNil(idx) && idx < lastIndexToShow && } + + + ) : null; + } +); + +ExternalLink.displayName = 'ExternalLink'; + export const HostDetailsLink = React.memo(HostDetailsLinkComponent); const IPDetailsLinkComponent: React.FC<{ @@ -63,9 +109,9 @@ CreateCaseLink.displayName = 'CreateCaseLink'; // External Links export const GoogleLink = React.memo<{ children?: React.ReactNode; link: string }>( ({ children, link }) => ( - + {children ? children : link} - + ) ); @@ -120,39 +166,136 @@ export const CertificateFingerprintLink = React.memo<{ CertificateFingerprintLink.displayName = 'CertificateFingerprintLink'; -export const ReputationLink = React.memo<{ children?: React.ReactNode; domain: string }>( - ({ children, domain }) => ( - - {children ? children : domain} - - ) -); +enum DefaultReputationLink { + 'virustotal.com' = 'virustotal.com', + 'talosIntelligence.com' = 'talosIntelligence.com', +} -ReputationLink.displayName = 'ReputationLink'; +export interface ReputationLinkSetting { + name: string; + url_template: string; +} -export const VirusTotalLink = React.memo<{ children?: React.ReactNode; link: string }>( - ({ children, link }) => ( - - {children ? children : link} - - ) -); +function isDefaultReputationLink(name: string): name is DefaultReputationLink { + return ( + name === DefaultReputationLink['virustotal.com'] || + name === DefaultReputationLink['talosIntelligence.com'] + ); +} +const isReputationLink = ( + rowItem: string | ReputationLinkSetting +): rowItem is ReputationLinkSetting => + (rowItem as ReputationLinkSetting).url_template !== undefined && + (rowItem as ReputationLinkSetting).name !== undefined; + +export const Comma = styled('span')` + margin-right: 5px; + margin-left: 5px; + &::after { + content: ' ,'; + } +`; + +Comma.displayName = 'Comma'; + +const defaultNameMapping: Record = { + [DefaultReputationLink['virustotal.com']]: i18n.VIEW_VIRUS_TOTAL, + [DefaultReputationLink['talosIntelligence.com']]: i18n.VIEW_TALOS_INTELLIGENCE, +}; + +const ReputationLinkComponent: React.FC<{ + overflowIndexStart?: number; + allItemsLimit?: number; + showDomain?: boolean; + domain: string; + direction?: 'row' | 'column'; +}> = ({ + overflowIndexStart = DEFAULT_NUMBER_OF_LINK, + allItemsLimit = DEFAULT_NUMBER_OF_LINK, + showDomain = false, + domain, + direction = 'row', +}) => { + const [ipReputationLinksSetting] = useUiSetting$( + IP_REPUTATION_LINKS_SETTING + ); + + const ipReputationLinks: ReputationLinkSetting[] = useMemo( + () => + ipReputationLinksSetting + ?.slice(0, allItemsLimit) + .filter( + ({ url_template, name }) => + !isNil(url_template) && !isNil(name) && !isUrlInvalid(url_template) + ) + .map(({ name, url_template }: { name: string; url_template: string }) => ({ + name: isDefaultReputationLink(name) ? defaultNameMapping[name] : name, + url_template: url_template.replace(`{{ip}}`, encodeURIComponent(domain)), + })), + [ipReputationLinksSetting, domain, defaultNameMapping, allItemsLimit] + ); + + return ipReputationLinks?.length > 0 ? ( +
+ + + {ipReputationLinks + ?.slice(0, overflowIndexStart) + .map(({ name, url_template: urlTemplate }: ReputationLinkSetting, id) => ( + + <>{showDomain ? domain : name ?? domain} + + ))} + + + + { + return ( + isReputationLink(rowItem) && ( + + <>{rowItem.name ?? domain} + + ) + ); + }} + moreMaxHeight={DEFAULT_MORE_MAX_HEIGHT} + overflowIndexStart={overflowIndexStart} + /> + + +
+ ) : null; +}; + +ReputationLinkComponent.displayName = 'ReputationLinkComponent'; -VirusTotalLink.displayName = 'VirusTotalLink'; +export const ReputationLink = React.memo(ReputationLinkComponent); export const WhoIsLink = React.memo<{ children?: React.ReactNode; domain: string }>( ({ children, domain }) => ( - + {children ? children : domain} - +
) ); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap index 0a60c8facff9c..6b866aeecc831 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap @@ -498,3 +498,3264 @@ exports[`ZeekDetails rendering it renders the default ZeekDetails 1`] = ` timelineId="test" /> `; + +exports[`ZeekDetails rendering it returns zeek.files if the data does contain zeek.files data 1`] = ` +.c3, +.c3::before, +.c3::after { + -webkit-transition: background 150ms ease, color 150ms ease; + transition: background 150ms ease, color 150ms ease; +} + +.c3 { + border-radius: 2px; + padding: 0 4px 0 8px; + position: relative; + z-index: 0 !important; +} + +.c3::before { + background-image: linear-gradient( 135deg, #535966 25%, transparent 25% ), linear-gradient( -135deg, #535966 25%, transparent 25% ), linear-gradient( 135deg, transparent 75%, #535966 75% ), linear-gradient( -135deg, transparent 75%, #535966 75% ); + background-position: 0 0,1px 0,1px -1px,0px 1px; + background-size: 2px 2px; + bottom: 2px; + content: ''; + display: block; + left: 2px; + position: absolute; + top: 2px; + width: 4px; +} + +.c3:hover, +.c3:hover .euiBadge, +.c3:hover .euiBadge__text { + cursor: move; + cursor: -webkit-grab; + cursor: -moz-grab; + cursor: grab; +} + +.event-column-view:hover .c3, +tr:hover .c3 { + background-color: #343741; +} + +.event-column-view:hover .c3::before, +tr:hover .c3::before { + background-image: linear-gradient( 135deg, #98a2b3 25%, transparent 25% ), linear-gradient( -135deg, #98a2b3 25%, transparent 25% ), linear-gradient( 135deg, transparent 75%, #98a2b3 75% ), linear-gradient( -135deg, transparent 75%, #98a2b3 75% ); +} + +.c3:hover, +.c3:focus, +.event-column-view:hover .c3:hover, +.event-column-view:focus .c3:focus, +tr:hover .c3:hover, +tr:hover .c3:focus { + background-color: #1ba9f5; +} + +.c3:hover, +.c3:focus, +.event-column-view:hover .c3:hover, +.event-column-view:focus .c3:focus, +tr:hover .c3:hover, +tr:hover .c3:focus, +.c3:hover a, +.c3:focus a, +.event-column-view:hover .c3:hover a, +.event-column-view:focus .c3:focus a, +tr:hover .c3:hover a, +tr:hover .c3:focus a, +.c3:hover a:hover, +.c3:focus a:hover, +.event-column-view:hover .c3:hover a:hover, +.event-column-view:focus .c3:focus a:hover, +tr:hover .c3:hover a:hover, +tr:hover .c3:focus a:hover { + color: #1d1e24; +} + +.c3:hover::before, +.c3:focus::before, +.event-column-view:hover .c3:hover::before, +.event-column-view:focus .c3:focus::before, +tr:hover .c3:hover::before, +tr:hover .c3:focus::before { + background-image: linear-gradient( 135deg, #1d1e24 25%, transparent 25% ), linear-gradient( -135deg, #1d1e24 25%, transparent 25% ), linear-gradient( 135deg, transparent 75%, #1d1e24 75% ), linear-gradient( -135deg, transparent 75%, #1d1e24 75% ); +} + +.c2 { + display: inline-block; + max-width: 100%; +} + +.c2 [data-rbd-placeholder-context-id] { + display: none !important; +} + +.c4 > span.euiToolTipAnchor { + display: block; +} + +.c8 { + margin: 0 2px; +} + +.c7 { + margin-top: 3px; +} + +.c6 { + margin-right: 10px; +} + +.c1 { + margin-left: 3px; +} + +.c5 { + margin-left: 6px; +} + +.c0 { + margin: 5px 0; +} + + + + + + + + + + + + + + + +
+
+ + +
+ + + +
+ + + +
+ + +
+ + + + + + +
+ + + + + + + + + + + Cu0n232QMyvNtzb75j + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ + + +
+ + + +
+ + +
+ + + + + + +
+ + + + + + + + + + + files + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ + + +
+ + + +
+ + +
+ + + + + + +
+ + + + + + + + + + + sha1: fa5195a... + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ + + +
+ + + +
+ + +
+ + + + + + +
+ + + + + + + + + + + md5: f7653f1... + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + +
+
+ +
+ + + + + + + + +
+
+ +
+
+
+
+
+
+
+
+ +
+ + + + +
+ +
+ + +
+ + +
+ + +
+ + +
+ + + + +
+ + +
+ + +
+ + + +
+ + +
+ +
+ + +
+ + +
+ + + +
+ + +
+ +
+ +
+
+ + + +
+ + + + +
+ +
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ +
+
+ +
+ + +
+ + +
+ +
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_details.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_details.test.tsx index 7617a01acf1d9..db51ade6df4c5 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_details.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_details.test.tsx @@ -113,9 +113,8 @@ describe('ZeekDetails', () => { /> ); - expect(wrapper.text()).toEqual( - 'Cu0n232QMyvNtzb75jfilessha1: fa5195a...md5: f7653f1...fa5195a5dfacc9d1c68d43600f0e0262cad14dde' - ); + expect(wrapper).toMatchSnapshot(); + expect(wrapper.text()).toEqual('Cu0n232QMyvNtzb75jfilessha1: fa5195a...md5: f7653f1...'); }); test('it returns null for text if the data contains no zeek data', () => { diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.test.tsx index c09bd6b7a356d..f199b537f1be0 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.test.tsx @@ -79,14 +79,9 @@ describe('ZeekSignature', () => { ).toBeFalsy(); }); - test('should render value', () => { - const wrapper = mount(); - expect(wrapper.text()).toEqual('abc'); - }); - - test('should render link with sha', () => { - const wrapper = mount(); - expect(wrapper.find('a').prop('href')).toEqual('https://www.virustotal.com/#/search/abcdefg'); + test('should render', () => { + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="reputationLinkSha"]').exists()).toBeTruthy(); }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.tsx index 72f58df5677e4..57e5ff19eb815 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.tsx @@ -13,7 +13,7 @@ import { Ecs } from '../../../../../graphql/types'; import { DragEffects, DraggableWrapper } from '../../../../drag_and_drop/draggable_wrapper'; import { escapeDataProviderId } from '../../../../drag_and_drop/helpers'; import { ExternalLinkIcon } from '../../../../external_link_icon'; -import { GoogleLink, VirusTotalLink } from '../../../../links'; +import { GoogleLink, ReputationLink } from '../../../../links'; import { Provider } from '../../../../timeline/data_providers/provider'; import { IS_OPERATOR } from '../../../data_providers/data_provider'; @@ -148,8 +148,12 @@ export const TotalVirusLinkSha = React.memo(({ value }) value != null ? (
- {value} - +
) : null diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/helpers.test.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/helpers.test.ts new file mode 100644 index 0000000000000..5eb503f8ba074 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/helpers.test.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { isUrlInvalid } from './helpers'; + +describe('helpers', () => { + describe('isUrlInvalid', () => { + test('verifies invalid url', () => { + expect(isUrlInvalid('this is not a url')).toBeTruthy(); + }); + + test('verifies valid url', () => { + expect(isUrlInvalid('https://www.elastic.co/')).toBeFalsy(); + }); + }); +}); From 0764380ffd50b9f07d8e48bbc2ce90d4c0fabb05 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Wed, 26 Feb 2020 09:51:47 -0700 Subject: [PATCH 10/64] [Metrics UI / Logs UI] Remove field filtering in Source API call (#58553) * [Metrics UI / Logs UI] Remove field filtering in Source API call. * Fixing type_check issues --- .../lib/adapters/fields/adapter_types.ts | 3 +- .../fields/framework_fields_adapter.ts | 99 +------------------ .../infra/server/lib/domains/fields_domain.ts | 3 +- 3 files changed, 4 insertions(+), 101 deletions(-) diff --git a/x-pack/plugins/infra/server/lib/adapters/fields/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/fields/adapter_types.ts index 3aaa23b378096..a1630281c2f75 100644 --- a/x-pack/plugins/infra/server/lib/adapters/fields/adapter_types.ts +++ b/x-pack/plugins/infra/server/lib/adapters/fields/adapter_types.ts @@ -9,8 +9,7 @@ import { RequestHandlerContext } from 'src/core/server'; export interface FieldsAdapter { getIndexFields( requestContext: RequestHandlerContext, - indices: string, - timefield: string + indices: string ): Promise; } diff --git a/x-pack/plugins/infra/server/lib/adapters/fields/framework_fields_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/fields/framework_fields_adapter.ts index 834c991d5c6a4..8119c06dedaef 100644 --- a/x-pack/plugins/infra/server/lib/adapters/fields/framework_fields_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/fields/framework_fields_adapter.ts @@ -4,28 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { startsWith, uniq, first } from 'lodash'; import { RequestHandlerContext } from 'src/core/server'; -import { InfraDatabaseSearchResponse } from '../framework'; import { KibanaFramework } from '../framework/kibana_framework_adapter'; import { FieldsAdapter, IndexFieldDescriptor } from './adapter_types'; -import { getAllowedListForPrefix } from '../../../../common/ecs_allowed_list'; -import { getAllCompositeData } from '../../../utils/get_all_composite_data'; -import { createAfterKeyHandler } from '../../../utils/create_afterkey_handler'; - -interface Bucket { - key: { dataset: string }; - doc_count: number; -} - -interface DataSetResponse { - datasets: { - buckets: Bucket[]; - after_key: { - dataset: string; - }; - }; -} export class FrameworkFieldsAdapter implements FieldsAdapter { private framework: KibanaFramework; @@ -36,91 +17,15 @@ export class FrameworkFieldsAdapter implements FieldsAdapter { public async getIndexFields( requestContext: RequestHandlerContext, - indices: string, - timefield: string + indices: string ): Promise { const indexPatternsService = this.framework.getIndexPatternsService(requestContext); const response = await indexPatternsService.getFieldsForWildcard({ pattern: indices, }); - const { dataSets, modules } = await this.getDataSetsAndModules( - requestContext, - indices, - timefield - ); - const allowedList = modules.reduce( - (acc, name) => uniq([...acc, ...getAllowedListForPrefix(name)]), - [] as string[] - ); - const dataSetsWithAllowedList = [...allowedList, ...dataSets]; return response.map(field => ({ ...field, - displayable: dataSetsWithAllowedList.some(name => startsWith(field.name, name)), + displayable: true, })); } - - private async getDataSetsAndModules( - requestContext: RequestHandlerContext, - indices: string, - timefield: string - ): Promise<{ dataSets: string[]; modules: string[] }> { - const params = { - index: indices, - allowNoIndices: true, - ignoreUnavailable: true, - body: { - size: 0, - query: { - bool: { - filter: [ - { - range: { - [timefield]: { - gte: 'now-24h', - lte: 'now', - }, - }, - }, - ], - }, - }, - aggs: { - datasets: { - composite: { - sources: [ - { - dataset: { - terms: { - field: 'event.dataset', - }, - }, - }, - ], - }, - }, - }, - }, - }; - - const bucketSelector = (response: InfraDatabaseSearchResponse<{}, DataSetResponse>) => - (response.aggregations && response.aggregations.datasets.buckets) || []; - const handleAfterKey = createAfterKeyHandler( - 'body.aggs.datasets.composite.after', - input => input?.aggregations?.datasets?.after_key - ); - - const buckets = await getAllCompositeData( - this.framework, - requestContext, - params, - bucketSelector, - handleAfterKey - ); - const dataSets = buckets.map(bucket => bucket.key.dataset); - const modules = dataSets.reduce((acc, dataset) => { - const module = first(dataset.split(/\./)); - return module ? uniq([...acc, module]) : acc; - }, [] as string[]); - return { modules, dataSets }; - } } diff --git a/x-pack/plugins/infra/server/lib/domains/fields_domain.ts b/x-pack/plugins/infra/server/lib/domains/fields_domain.ts index a00c76216da4c..d2e151ca2c3f5 100644 --- a/x-pack/plugins/infra/server/lib/domains/fields_domain.ts +++ b/x-pack/plugins/infra/server/lib/domains/fields_domain.ts @@ -31,8 +31,7 @@ export class InfraFieldsDomain { requestContext, `${includeMetricIndices ? configuration.metricAlias : ''},${ includeLogIndices ? configuration.logAlias : '' - }`, - configuration.fields.timestamp + }` ); return fields; From 55fb05c09f34f371478fd9a951ddb48f07c7a458 Mon Sep 17 00:00:00 2001 From: Maryia Lapata Date: Wed, 26 Feb 2020 20:12:23 +0300 Subject: [PATCH 11/64] [NP] Move ui/kbn_top_nav/kbn_top_nav to kibana_legacy (#58221) * Migrate kbn_top_nav.js to kibana_legacy * Wrap TopNavMenu into i18nContext * Move the kbnTopNav directive definition to kibana_legacy and remove ui/kbn_top_nav Co-authored-by: Elastic Machine --- src/core/MIGRATION.md | 2 +- .../kibana/public/dashboard/legacy_imports.ts | 2 -- .../public/dashboard/np_ready/application.ts | 8 ++++--- .../public/discover/get_inner_angular.ts | 6 ++--- .../core_plugins/kibana/public/kibana.js | 1 - .../kibana/public/visualize/legacy_imports.ts | 2 -- .../public/visualize/np_ready/application.ts | 6 +++-- .../core_plugins/timelion/public/app.js | 4 +++- src/legacy/ui/public/kbn_top_nav/index.js | 20 ----------------- .../kibana_legacy/public/angular/index.ts | 2 ++ .../public/angular}/kbn_top_nav.js | 22 +++++++++++-------- src/plugins/navigation/public/plugin.ts | 4 ++-- .../top_nav_menu/create_top_nav_menu.tsx | 13 +++++++++-- .../public/top_nav_menu/top_nav_menu.tsx | 3 +-- .../dashboard_mode/public/dashboard_viewer.js | 1 - .../plugins/graph/public/application.ts | 10 ++++----- .../plugins/graph/public/legacy_imports.ts | 2 -- .../maps/public/angular/map_controller.js | 2 ++ x-pack/legacy/plugins/maps/public/index.ts | 1 - .../public/np_imports/angular/modules.ts | 6 +++-- .../public/np_imports/legacy_imports.ts | 2 -- 21 files changed, 56 insertions(+), 63 deletions(-) delete mode 100644 src/legacy/ui/public/kbn_top_nav/index.js rename src/{legacy/ui/public/kbn_top_nav => plugins/kibana_legacy/public/angular}/kbn_top_nav.js (90%) diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 6ee432635a947..4dd6bedfa4f0c 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -1169,7 +1169,7 @@ import { setup, start } from '../core_plugins/visualizations/public/legacy'; | `import 'ui/filter_bar'` | `import { FilterBar } from '../data/public'` | Directive is deprecated. | | `import 'ui/query_bar'` | `import { QueryStringInput } 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 '../navigation/public'` | Directive is still available in `ui/kbn_top_nav`. | +| `import 'ui/kbn_top_nav'` | `import { TopNavMenu } from '../navigation/public'` | Directive was moved to `src/plugins/kibana_legacy`. | | `ui/saved_objects/components/saved_object_finder` | `import { SavedObjectFinder } from '../saved_objects/public'` | | | `core_plugins/interpreter` | `data.expressions` | still in progress | | `ui/courier` | `data.search` | still in progress | diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts index c1f679e9eb7ac..beadcda595288 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts @@ -28,8 +28,6 @@ export { npSetup, npStart } from 'ui/new_platform'; export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; export { KbnUrl } from 'ui/url/kbn_url'; // @ts-ignore -export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; -// @ts-ignore export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url/index'; export { IInjector } from 'ui/chrome'; export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts index 7239d8f2258a7..257ba8a4711b0 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts @@ -31,8 +31,6 @@ import { import { Storage } from '../../../../../../plugins/kibana_utils/public'; import { configureAppAngularModule, - createTopNavDirective, - createTopNavHelper, IPrivate, KbnUrlProvider, PrivateProvider, @@ -45,7 +43,11 @@ import { IEmbeddableStart } from '../../../../../../plugins/embeddable/public'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../../plugins/navigation/public'; import { DataPublicPluginStart } from '../../../../../../plugins/data/public'; import { SharePluginStart } from '../../../../../../plugins/share/public'; -import { KibanaLegacyStart } from '../../../../../../plugins/kibana_legacy/public'; +import { + KibanaLegacyStart, + createTopNavDirective, + createTopNavHelper, +} from '../../../../../../plugins/kibana_legacy/public'; import { SavedObjectLoader } from '../../../../../../plugins/saved_objects/public'; export interface RenderDeps { diff --git a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts index 373395c86636c..bae938d1fb61e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts +++ b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts @@ -37,8 +37,6 @@ import { GlobalStateProvider } from 'ui/state_management/global_state'; import { StateManagementConfigProvider } from 'ui/state_management/config_provider'; // @ts-ignore import { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url'; -// @ts-ignore -import { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; import { DataPublicPluginStart } from '../../../../../plugins/data/public'; import { Storage } from '../../../../../plugins/kibana_utils/public'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; @@ -63,7 +61,6 @@ import { createFieldChooserDirective } from './np_ready/components/field_chooser import { createDiscoverFieldDirective } from './np_ready/components/field_chooser/discover_field'; import { CollapsibleSidebarProvider } from './np_ready/angular/directives/collapsible_sidebar/collapsible_sidebar'; import { DiscoverStartPlugins } from './plugin'; -import { initAngularBootstrap } from '../../../../../plugins/kibana_legacy/public'; import { createCssTruncateDirective } from './np_ready/angular/directives/css_truncate'; // @ts-ignore import { FixedScrollProvider } from './np_ready/angular/directives/fixed_scroll'; @@ -71,6 +68,7 @@ import { FixedScrollProvider } from './np_ready/angular/directives/fixed_scroll' import { DebounceProviderTimeout } from './np_ready/angular/directives/debounce/debounce'; import { createRenderCompleteDirective } from './np_ready/angular/directives/render_complete'; import { + initAngularBootstrap, configureAppAngularModule, IPrivate, KbnAccessibleClickProvider, @@ -78,6 +76,8 @@ import { PromiseServiceCreator, registerListenEventListener, watchMultiDecorator, + createTopNavDirective, + createTopNavHelper, } from '../../../../../plugins/kibana_legacy/public'; /** diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index 384c6bd80ec33..a83d1176a7197 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -44,7 +44,6 @@ import 'uiExports/shareContextMenuExtensions'; import 'uiExports/interpreter'; import 'ui/autoload/all'; -import 'ui/kbn_top_nav'; import './home'; import './discover/legacy'; import './visualize/legacy'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts index d9565938c838d..d52d31c2dd79e 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts @@ -34,8 +34,6 @@ export { PersistedState } from 'ui/persisted_state'; export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; // @ts-ignore export { EventsProvider } from 'ui/events'; -// @ts-ignore -export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router'; // @ts-ignore export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts index 6a8d9ce106f9d..0e1abff4b46f2 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts @@ -23,8 +23,6 @@ import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; import { AppMountContext } from 'kibana/public'; import { configureAppAngularModule, - createTopNavDirective, - createTopNavHelper, EventsProvider, GlobalStateProvider, KbnUrlProvider, @@ -36,6 +34,10 @@ import { StateManagementConfigProvider, } from '../legacy_imports'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../../plugins/navigation/public'; +import { + createTopNavDirective, + createTopNavHelper, +} from '../../../../../../plugins/kibana_legacy/public'; // @ts-ignore import { initVisualizeApp } from './legacy_app'; diff --git a/src/legacy/core_plugins/timelion/public/app.js b/src/legacy/core_plugins/timelion/public/app.js index ff8f75c23435e..e4a48c09db832 100644 --- a/src/legacy/core_plugins/timelion/public/app.js +++ b/src/legacy/core_plugins/timelion/public/app.js @@ -37,7 +37,6 @@ require('ui/autoload/all'); import 'ui/directives/input_focus'; import './directives/saved_object_finder'; import 'ui/directives/listen'; -import 'ui/kbn_top_nav'; import './directives/saved_object_save_as_checkbox'; import '../../data/public/legacy'; import './services/saved_sheet_register'; @@ -45,6 +44,9 @@ import './services/saved_sheet_register'; import rootTemplate from 'plugins/timelion/index.html'; import { createSavedVisLoader, TypesService } from '../../visualizations/public'; +import { loadKbnTopNavDirectives } from '../../../../plugins/kibana_legacy/public'; +loadKbnTopNavDirectives(npStart.plugins.navigation.ui); + require('plugins/timelion/directives/cells/cells'); require('plugins/timelion/directives/fixed_element'); require('plugins/timelion/directives/fullscreen/fullscreen'); diff --git a/src/legacy/ui/public/kbn_top_nav/index.js b/src/legacy/ui/public/kbn_top_nav/index.js deleted file mode 100644 index 8a93972c4b226..0000000000000 --- a/src/legacy/ui/public/kbn_top_nav/index.js +++ /dev/null @@ -1,20 +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 './kbn_top_nav'; diff --git a/src/plugins/kibana_legacy/public/angular/index.ts b/src/plugins/kibana_legacy/public/angular/index.ts index 0e18869f1c08b..0b234b7042850 100644 --- a/src/plugins/kibana_legacy/public/angular/index.ts +++ b/src/plugins/kibana_legacy/public/angular/index.ts @@ -22,3 +22,5 @@ export { PromiseServiceCreator } from './promises'; export { watchMultiDecorator } from './watch_multi'; export * from './angular_config'; export { ensureDefaultIndexPattern } from './ensure_default_index_pattern'; +// @ts-ignore +export { createTopNavDirective, createTopNavHelper, loadKbnTopNavDirectives } from './kbn_top_nav'; diff --git a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js b/src/plugins/kibana_legacy/public/angular/kbn_top_nav.js similarity index 90% rename from src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js rename to src/plugins/kibana_legacy/public/angular/kbn_top_nav.js index 12c3ca2acc3cd..b0ccb4dbc2375 100644 --- a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js +++ b/src/plugins/kibana_legacy/public/angular/kbn_top_nav.js @@ -17,12 +17,8 @@ * under the License. */ +import angular from 'angular'; import 'ngreact'; -import { wrapInI18nContext } from 'ui/i18n'; -import { uiModules } from 'ui/modules'; -import { npStart } from 'ui/new_platform'; - -const module = uiModules.get('kibana'); export function createTopNavDirective() { return { @@ -75,10 +71,8 @@ export function createTopNavDirective() { }; } -module.directive('kbnTopNav', createTopNavDirective); - export const createTopNavHelper = ({ TopNavMenu }) => reactDirective => { - return reactDirective(wrapInI18nContext(TopNavMenu), [ + return reactDirective(TopNavMenu, [ ['config', { watchDepth: 'value' }], ['disabledButtons', { watchDepth: 'reference' }], @@ -121,4 +115,14 @@ export const createTopNavHelper = ({ TopNavMenu }) => reactDirective => { ]); }; -module.directive('kbnTopNavHelper', createTopNavHelper(npStart.plugins.navigation.ui)); +let isLoaded = false; + +export function loadKbnTopNavDirectives(navUi) { + if (!isLoaded) { + isLoaded = true; + angular + .module('kibana') + .directive('kbnTopNav', createTopNavDirective) + .directive('kbnTopNavHelper', createTopNavHelper(navUi)); + } +} diff --git a/src/plugins/navigation/public/plugin.ts b/src/plugins/navigation/public/plugin.ts index e8df5bcd616d9..5b30ff4913a40 100644 --- a/src/plugins/navigation/public/plugin.ts +++ b/src/plugins/navigation/public/plugin.ts @@ -40,14 +40,14 @@ export class NavigationPublicPlugin } public start( - core: CoreStart, + { i18n }: CoreStart, { data }: NavigationPluginStartDependencies ): NavigationPublicPluginStart { const extensions = this.topNavMenuExtensionsRegistry.getAll(); return { ui: { - TopNavMenu: createTopNav(data, extensions), + TopNavMenu: createTopNav(data, extensions, i18n), }, }; } diff --git a/src/plugins/navigation/public/top_nav_menu/create_top_nav_menu.tsx b/src/plugins/navigation/public/top_nav_menu/create_top_nav_menu.tsx index a78c48b675911..79201a9da88c5 100644 --- a/src/plugins/navigation/public/top_nav_menu/create_top_nav_menu.tsx +++ b/src/plugins/navigation/public/top_nav_menu/create_top_nav_menu.tsx @@ -18,17 +18,26 @@ */ import React from 'react'; +import { I18nStart } from 'kibana/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { TopNavMenuProps, TopNavMenu } from './top_nav_menu'; import { RegisteredTopNavMenuData } from './top_nav_menu_data'; -export function createTopNav(data: DataPublicPluginStart, extraConfig: RegisteredTopNavMenuData[]) { +export function createTopNav( + data: DataPublicPluginStart, + extraConfig: RegisteredTopNavMenuData[], + i18n: I18nStart +) { return (props: TopNavMenuProps) => { const relevantConfig = extraConfig.filter( dataItem => dataItem.appName === undefined || dataItem.appName === props.appName ); const config = (props.config || []).concat(relevantConfig); - return ; + return ( + + + + ); }; } diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx index cf39c82eff3ce..80d1a53cd417f 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx @@ -20,7 +20,6 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { I18nProvider } from '@kbn/i18n/react'; import { TopNavMenuData } from './top_nav_menu_data'; import { TopNavMenuItem } from './top_nav_menu_item'; @@ -78,7 +77,7 @@ export function TopNavMenu(props: TopNavMenuProps) { ); } - return {renderLayout()}; + return renderLayout(); } TopNavMenu.defaultProps = { diff --git a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js index e0e49fe59daf4..e76a204a6f27d 100644 --- a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js +++ b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js @@ -29,7 +29,6 @@ import 'uiExports/search'; import 'uiExports/shareContextMenuExtensions'; import _ from 'lodash'; import 'ui/autoload/all'; -import 'ui/kbn_top_nav'; import 'ui/agg_response'; import 'ui/agg_types'; import 'leaflet'; diff --git a/x-pack/legacy/plugins/graph/public/application.ts b/x-pack/legacy/plugins/graph/public/application.ts index 7bd18f841b478..536382e62d473 100644 --- a/x-pack/legacy/plugins/graph/public/application.ts +++ b/x-pack/legacy/plugins/graph/public/application.ts @@ -20,11 +20,7 @@ import { IUiSettingsClient, OverlayStart, } from 'kibana/public'; -import { - configureAppAngularModule, - createTopNavDirective, - createTopNavHelper, -} from './legacy_imports'; +import { configureAppAngularModule } from './legacy_imports'; // @ts-ignore import { initGraphApp } from './app'; import { @@ -36,6 +32,10 @@ import { checkLicense } from '../../../../plugins/graph/common/check_license'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../src/plugins/navigation/public'; import { createSavedWorkspacesLoader } from './services/persistence/saved_workspace_loader'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; +import { + createTopNavDirective, + createTopNavHelper, +} from '../../../../../src/plugins/kibana_legacy/public'; import { addAppRedirectMessageToUrl } from '../../../../../src/plugins/kibana_legacy/public'; /** diff --git a/x-pack/legacy/plugins/graph/public/legacy_imports.ts b/x-pack/legacy/plugins/graph/public/legacy_imports.ts index 84fafdb580abe..274cdc65232e2 100644 --- a/x-pack/legacy/plugins/graph/public/legacy_imports.ts +++ b/x-pack/legacy/plugins/graph/public/legacy_imports.ts @@ -6,6 +6,4 @@ import 'ace'; -// @ts-ignore -export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; export { configureAppAngularModule } from '../../../../../src/plugins/kibana_legacy/public'; diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index c90560a4fcfdf..95c8ff975b1d6 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -57,6 +57,8 @@ import { SavedObjectSaveModal, showSaveModal, } from '../../../../../../src/plugins/saved_objects/public'; +import { loadKbnTopNavDirectives } from '../../../../../../src/plugins/kibana_legacy/public'; +loadKbnTopNavDirectives(npStart.plugins.navigation.ui); const savedQueryService = npStart.plugins.data.query.savedQueries; diff --git a/x-pack/legacy/plugins/maps/public/index.ts b/x-pack/legacy/plugins/maps/public/index.ts index 404909c5c51b8..f3213a36bb66d 100644 --- a/x-pack/legacy/plugins/maps/public/index.ts +++ b/x-pack/legacy/plugins/maps/public/index.ts @@ -13,7 +13,6 @@ import 'uiExports/embeddableFactories'; import 'uiExports/embeddableActions'; import 'ui/agg_types'; -import 'ui/kbn_top_nav'; import 'ui/autoload/all'; import 'react-vis/dist/style.css'; diff --git a/x-pack/legacy/plugins/monitoring/public/np_imports/angular/modules.ts b/x-pack/legacy/plugins/monitoring/public/np_imports/angular/modules.ts index 2acb6031c6773..09ac0f95a1dd9 100644 --- a/x-pack/legacy/plugins/monitoring/public/np_imports/angular/modules.ts +++ b/x-pack/legacy/plugins/monitoring/public/np_imports/angular/modules.ts @@ -9,6 +9,10 @@ import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; import { AppMountContext } from 'kibana/public'; import { Storage } from '../../../../../../../src/plugins/kibana_utils/public'; +import { + createTopNavDirective, + createTopNavHelper, +} from '../../../../../../../src/plugins/kibana_legacy/public'; import { GlobalStateProvider, @@ -16,8 +20,6 @@ import { AppStateProvider, EventsProvider, PersistedState, - createTopNavDirective, - createTopNavHelper, KbnUrlProvider, RedirectWhenMissingProvider, npStart, diff --git a/x-pack/legacy/plugins/monitoring/public/np_imports/legacy_imports.ts b/x-pack/legacy/plugins/monitoring/public/np_imports/legacy_imports.ts index 012cbc77ce9c8..ea29ac95eb03f 100644 --- a/x-pack/legacy/plugins/monitoring/public/np_imports/legacy_imports.ts +++ b/x-pack/legacy/plugins/monitoring/public/np_imports/legacy_imports.ts @@ -19,7 +19,5 @@ export { AppStateProvider } from 'ui/state_management/app_state'; export { EventsProvider } from 'ui/events'; export { PersistedState } from 'ui/persisted_state'; // @ts-ignore -export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; -// @ts-ignore export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url'; export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router'; From 8511fe378018156b86b651435c9f8eb36b25ac2c Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 26 Feb 2020 12:17:00 -0500 Subject: [PATCH 12/64] Fixing Newsfeed Cloud test bug (#58566) --- test/functional/apps/home/_newsfeed.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/test/functional/apps/home/_newsfeed.ts b/test/functional/apps/home/_newsfeed.ts index 35d7ac8adefa5..096e237850c72 100644 --- a/test/functional/apps/home/_newsfeed.ts +++ b/test/functional/apps/home/_newsfeed.ts @@ -47,10 +47,17 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { it('shows all news from newsfeed', async () => { const objects = await PageObjects.newsfeed.getNewsfeedList(); - expect(objects).to.eql([ - '21 June 2019\nYou are functionally testing the newsfeed widget with fixtures!\nSee test/common/fixtures/plugins/newsfeed/newsfeed_simulation\nGeneric feed-viewer could go here', - '21 June 2019\nStaging too!\nHello world\nGeneric feed-viewer could go here', - ]); + + if (await PageObjects.common.isOss()) { + expect(objects).to.eql([ + '21 June 2019\nYou are functionally testing the newsfeed widget with fixtures!\nSee test/common/fixtures/plugins/newsfeed/newsfeed_simulation\nGeneric feed-viewer could go here', + '21 June 2019\nStaging too!\nHello world\nGeneric feed-viewer could go here', + ]); + } else { + // can't shim the API in cloud so going to check that at least something is rendered + // to test that the API was called and returned something that could be rendered + expect(objects.length).to.be.above(0); + } }); it('clicking on newsfeed icon should close opened newsfeed', async () => { From fa5400f606d77e0f7c2252961242898b96e9ad7f Mon Sep 17 00:00:00 2001 From: Elizabet Oliveira Date: Wed, 26 Feb 2020 18:20:03 +0000 Subject: [PATCH 13/64] [Maps] Improve Layer Style UI (#58406) * Improving Layer Style UI * Removing unnecessary method * Updating snapshot * Changing width value to make use of sass variable Co-authored-by: Elastic Machine --- .../layer_panel/_index.scss | 3 +- .../style_settings/_style_settings.scss | 3 + .../style_settings/style_settings.js | 2 +- .../vector/components/color/_color_stops.scss | 21 ------ .../components/color/color_map_select.js | 1 + .../vector/components/color/color_stops.js | 64 ++++++++++--------- .../components/color/dynamic_color_form.js | 6 +- .../components/color/static_color_form.js | 6 +- .../components/label/dynamic_label_form.js | 6 +- .../components/label/static_label_form.js | 6 +- .../orientation/dynamic_orientation_form.js | 6 +- .../orientation/static_orientation_form.js | 6 +- .../components/size/dynamic_size_form.js | 6 +- .../components/size/static_size_form.js | 6 +- .../vector/components/style_prop_editor.js | 6 +- .../__snapshots__/icon_select.test.js.snap | 2 +- .../components/symbol/dynamic_icon_form.js | 6 +- .../vector/components/symbol/icon_select.js | 1 + .../components/symbol/static_icon_form.js | 6 +- 19 files changed, 88 insertions(+), 75 deletions(-) create mode 100644 x-pack/legacy/plugins/maps/public/connected_components/layer_panel/style_settings/_style_settings.scss diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/_index.scss b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/_index.scss index b219f59476ce9..fd074edf032fa 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/_index.scss +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/_index.scss @@ -1,3 +1,4 @@ @import './layer_panel'; @import './filter_editor/filter_editor'; -@import './join_editor/resources/join'; \ No newline at end of file +@import './join_editor/resources/join'; +@import './style_settings/style_settings'; \ No newline at end of file diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/style_settings/_style_settings.scss b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/style_settings/_style_settings.scss new file mode 100644 index 0000000000000..249b6dfca5c76 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/style_settings/_style_settings.scss @@ -0,0 +1,3 @@ +.mapStyleSettings__fixedBox { + width: $euiSize * 7.5; +} \ No newline at end of file diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/style_settings/style_settings.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/style_settings/style_settings.js index 2857065f04c70..69cf51fb29c0d 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/style_settings/style_settings.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/style_settings/style_settings.js @@ -21,7 +21,7 @@ export function StyleSettings({ layer, updateStyleDescriptor }) { return ( - + diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/_color_stops.scss b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/_color_stops.scss index 001ca0685d0e9..519e97f4b30cd 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/_color_stops.scss +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/_color_stops.scss @@ -1,6 +1,5 @@ .mapColorStop { position: relative; - padding-right: $euiSizeXL + $euiSizeS; & + & { margin-top: $euiSizeS; @@ -17,23 +16,3 @@ } } -.mapColorStop__icons { - flex-shrink: 0; - display: none; - position: absolute; - right: 0; - top: 50%; - margin-right: -$euiSizeS; - margin-top: -$euiSizeM; -} - -@keyframes mapColorStopBecomeVisible { - - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js index e8d5754ef4206..436a92b619909 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js @@ -105,6 +105,7 @@ export class ColorMapSelect extends Component { onChange={this._onColorMapSelect} valueOfSelected={valueOfSelected} hasDividers={true} + compressed /> {this._renderColorStopsInput()} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops.js index 47c2d037e0c79..3e9b9e2aafc47 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops.js @@ -10,7 +10,19 @@ import { removeRow, isColorInvalid } from './color_stops_utils'; import { i18n } from '@kbn/i18n'; import { EuiButtonIcon, EuiColorPicker, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui'; -function getColorStopRow({ index, errors, stopInput, colorInput, deleteButton, onAdd }) { +function getColorStopRow({ index, errors, stopInput, onColorChange, color, deleteButton, onAdd }) { + const colorPickerButtons = ( +
+ {deleteButton} + +
+ ); return ( -
- - {stopInput} - {colorInput} - -
- {deleteButton} - + + {stopInput} + + + -
-
+ +
); } @@ -80,17 +89,6 @@ export const ColorStops = ({ }; } - function getColorInput(onColorChange, color) { - return { - colorError: isColorInvalid(color) - ? i18n.translate('xpack.maps.styles.colorStops.hexWarningLabel', { - defaultMessage: 'Color must provide a valid hex value', - }) - : undefined, - colorInput: , - }; - } - const rows = colorStops.map((colorStop, index) => { const onColorChange = color => { const newColorStops = _.cloneDeep(colorStops); @@ -102,7 +100,15 @@ export const ColorStops = ({ }; const { stopError, stopInput } = getStopInput(colorStop.stop, index); - const { colorError, colorInput } = getColorInput(onColorChange, colorStop.color); + + const color = colorStop.color; + + const colorError = isColorInvalid(color) + ? i18n.translate('xpack.maps.styles.colorStops.hexWarningLabel', { + defaultMessage: 'Color must provide a valid hex value', + }) + : undefined; + const errors = []; if (stopError) { errors.push(stopError); @@ -131,7 +137,7 @@ export const ColorStops = ({ deleteButton = getDeleteButton(onRemove); } - return getColorStopRow({ index, errors, stopInput, colorInput, deleteButton, onAdd }); + return getColorStopRow({ index, errors, stopInput, onColorChange, color, deleteButton, onAdd }); }); return
{rows}
; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js index af5e5b37f5467..3dc356c31cf30 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js @@ -90,8 +90,10 @@ export function DynamicColorForm({ return ( - - {staticDynamicSelect} + + + {staticDynamicSelect} + - {staticDynamicSelect} + + + {staticDynamicSelect} + - {staticDynamicSelect} + + + {staticDynamicSelect} + - {staticDynamicSelect} + + + {staticDynamicSelect} + - {staticDynamicSelect} + + + {staticDynamicSelect} + - {staticDynamicSelect} + + + {staticDynamicSelect} + - - {staticDynamicSelect} + + + {staticDynamicSelect} + - {staticDynamicSelect} + + + {staticDynamicSelect} + - - {staticDynamicSelect} + + + {staticDynamicSelect} + diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/__snapshots__/icon_select.test.js.snap b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/__snapshots__/icon_select.test.js.snap index 706dc0763b7ca..8fa69e1a5b467 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/__snapshots__/icon_select.test.js.snap +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/__snapshots__/icon_select.test.js.snap @@ -34,7 +34,7 @@ exports[`Should render icon select 1`] = ` } closePopover={[Function]} - display="inlineBlock" + display="block" hasArrow={true} isOpen={false} ownFocus={true} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/dynamic_icon_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/dynamic_icon_form.js index afa11daf45217..9065102dc8bd7 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/dynamic_icon_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/dynamic_icon_form.js @@ -53,8 +53,10 @@ export function DynamicIconForm({ return ( - - {staticDynamicSelect} + + + {staticDynamicSelect} + {this._renderIconSelectable()} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/static_icon_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/static_icon_form.js index b20d8f2eba162..9b00b2fe38d7b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/static_icon_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/static_icon_form.js @@ -20,8 +20,10 @@ export function StaticIconForm({ }; return ( - - {staticDynamicSelect} + + + {staticDynamicSelect} + Date: Wed, 26 Feb 2020 19:00:54 +0000 Subject: [PATCH 14/64] Migrate existing Cypress tests to Cypress + Cucumber (#57299) * chore: move gitignore to the cypress directory * chore: ignore more test files * fix: do not check the Loading Message It seems not relevant to the main purpose of these tests * chore: use cypres + webpack + cucumber scaffolding See https://github.com/TheBrainFamily/cypress-cucumber-webpack-typescript-example * chore: add eslint and prettier for code linting * feat: convert existing Cypress test into BDD style * feat: add support for using proper Node version in MacOSX * chore: use tslint * chore: use old layout We are keeping cypress as rootDir to follow project's structure. On the other hand, having a second cypress directory at the 2nd level is the default structure, as shown in the examples: - https://github.com/TheBrainFamily/cypress-cucumber-webpack-typescript-example - https://github.com/cypress-io/cypress-example-recipes/tree/a240054d7f5626ffcd7bd668dded96d219c4a7eb/examples/preprocessors__typescript-webpack * chore: remove prelint script meanwhile we fix TS lint * chore: move test results to a specific directory * chore: rename variable following old code * chore: remove non-needed lints, as we are going to use kibana build * chore: import snapshot function from cypress * chore: add readFile utils back from a bad removal * chore: change format of JSON spec file It was automatically changed by tests * chore: move CI directory to the proper layout in order for Jenkins to work * chore: store test-results from proper dir on Jenkins * chore: store artifacts properly on Jenkins * Fix type issues * chore: rename test application to e2e (end-to-end) We are keeping the build system within the test application, isolating dependencies * docs: reorganise docs for APM UI e2e tests * fix: Use proper cypress support file * chore: use existing NPM script for running cypress on CI * chore: update paths in CI scripts * docs: document how the CI runs the tests * chore: use Node 10 for tests * chore: Use kibana's Node version for tests * chore: run yarn install * docs: update docs * fix: path was wrong * docs: fix paths and flags used to load data * docs: elasticsearch fix flag * docs: Bootstrap kibana before running it * docs: remove outdated info * chore: move background steps to the scenario This would avoid not reading the background when the number of scenarios grows Co-authored-by: Dario Gieselaar Co-authored-by: Elastic Machine --- .ci/end2end.groovy | 8 +- .eslintignore | 2 +- src/cli/cluster/cluster_manager.ts | 2 +- src/dev/ci_setup/setup_env.sh | 2 +- src/dev/run_check_lockfile_symlinks.js | 2 +- src/dev/typescript/projects.ts | 2 +- x-pack/legacy/plugins/apm/cypress/README.md | 63 - .../legacy/plugins/apm/cypress/cypress.json | 18 - .../apm/cypress/integration/apm.spec.ts | 53 - .../apm/cypress/screenshots/.gitignore | 1 - .../legacy/plugins/apm/cypress/snapshots.js | 3 - .../plugins/apm/cypress/support/index.ts | 10 - x-pack/legacy/plugins/apm/e2e/.gitignore | 4 + x-pack/legacy/plugins/apm/e2e/README.md | 68 + .../apm/{cypress => e2e}/ci/Dockerfile | 3 +- .../apm/{cypress => e2e}/ci/entrypoint.sh | 6 +- .../apm/{cypress => e2e}/ci/kibana.dev.yml | 0 .../apm/{cypress => e2e}/ci/prepare-kibana.sh | 2 +- x-pack/legacy/plugins/apm/e2e/cypress.json | 19 + .../{ => e2e}/cypress/fixtures/example.json | 0 .../{ => e2e}/cypress/ingest-data/replay.js | 0 .../apm/e2e/cypress/integration/apm.feature | 7 + .../{ => e2e}/cypress/integration/helpers.ts | 0 .../cypress/integration/snapshots.js | 9 +- .../apm/{ => e2e}/cypress/plugins/index.js | 16 +- .../apm/e2e/cypress/support/commands.js | 31 + .../plugins/apm/e2e/cypress/support/index.ts | 27 + .../cypress/support/step_definitions/apm.ts | 45 + .../cypress/typings/index.d.ts} | 0 .../plugins/apm/e2e/cypress/webpack.config.js | 41 + .../plugins/apm/{cypress => e2e}/package.json | 7 +- .../apm/{cypress => e2e}/tsconfig.json | 9 +- .../plugins/apm/{cypress => e2e}/yarn.lock | 2759 ++++++++++++----- x-pack/tsconfig.json | 2 +- 34 files changed, 2302 insertions(+), 919 deletions(-) delete mode 100644 x-pack/legacy/plugins/apm/cypress/README.md delete mode 100644 x-pack/legacy/plugins/apm/cypress/cypress.json delete mode 100644 x-pack/legacy/plugins/apm/cypress/integration/apm.spec.ts delete mode 100644 x-pack/legacy/plugins/apm/cypress/screenshots/.gitignore delete mode 100644 x-pack/legacy/plugins/apm/cypress/snapshots.js delete mode 100644 x-pack/legacy/plugins/apm/cypress/support/index.ts create mode 100644 x-pack/legacy/plugins/apm/e2e/.gitignore create mode 100644 x-pack/legacy/plugins/apm/e2e/README.md rename x-pack/legacy/plugins/apm/{cypress => e2e}/ci/Dockerfile (92%) rename x-pack/legacy/plugins/apm/{cypress => e2e}/ci/entrypoint.sh (87%) rename x-pack/legacy/plugins/apm/{cypress => e2e}/ci/kibana.dev.yml (100%) rename x-pack/legacy/plugins/apm/{cypress => e2e}/ci/prepare-kibana.sh (95%) create mode 100644 x-pack/legacy/plugins/apm/e2e/cypress.json rename x-pack/legacy/plugins/apm/{ => e2e}/cypress/fixtures/example.json (100%) rename x-pack/legacy/plugins/apm/{ => e2e}/cypress/ingest-data/replay.js (100%) create mode 100644 x-pack/legacy/plugins/apm/e2e/cypress/integration/apm.feature rename x-pack/legacy/plugins/apm/{ => e2e}/cypress/integration/helpers.ts (100%) rename x-pack/legacy/plugins/apm/{ => e2e}/cypress/integration/snapshots.js (61%) rename x-pack/legacy/plugins/apm/{ => e2e}/cypress/plugins/index.js (79%) create mode 100644 x-pack/legacy/plugins/apm/e2e/cypress/support/commands.js create mode 100644 x-pack/legacy/plugins/apm/e2e/cypress/support/index.ts create mode 100644 x-pack/legacy/plugins/apm/e2e/cypress/support/step_definitions/apm.ts rename x-pack/legacy/plugins/apm/{cypress/cypress.d.ts => e2e/cypress/typings/index.d.ts} (100%) create mode 100644 x-pack/legacy/plugins/apm/e2e/cypress/webpack.config.js rename x-pack/legacy/plugins/apm/{cypress => e2e}/package.json (66%) rename x-pack/legacy/plugins/apm/{cypress => e2e}/tsconfig.json (51%) rename x-pack/legacy/plugins/apm/{cypress => e2e}/yarn.lock (61%) diff --git a/.ci/end2end.groovy b/.ci/end2end.groovy index 38fed4aca19dc..8ad810717d86e 100644 --- a/.ci/end2end.groovy +++ b/.ci/end2end.groovy @@ -13,7 +13,7 @@ pipeline { BASE_DIR = 'src/github.com/elastic/kibana' HOME = "${env.WORKSPACE}" APM_ITS = 'apm-integration-testing' - CYPRESS_DIR = 'x-pack/legacy/plugins/apm/cypress' + CYPRESS_DIR = 'x-pack/legacy/plugins/apm/e2e' PIPELINE_LOG_LEVEL = 'DEBUG' } options { @@ -107,7 +107,7 @@ pipeline { dir("${BASE_DIR}"){ sh ''' jobs -l - docker build --tag cypress ${CYPRESS_DIR}/ci + docker build --tag cypress --build-arg NODE_VERSION=$(cat .node-version) ${CYPRESS_DIR}/ci docker run --rm -t --user "$(id -u):$(id -g)" \ -v `pwd`:/app --network="host" \ --name cypress cypress''' @@ -116,8 +116,8 @@ pipeline { post { always { dir("${BASE_DIR}"){ - archiveArtifacts(allowEmptyArchive: false, artifacts: "${CYPRESS_DIR}/screenshots/**,${CYPRESS_DIR}/videos/**,${CYPRESS_DIR}/*e2e-tests.xml") - junit(allowEmptyResults: true, testResults: "${CYPRESS_DIR}/*e2e-tests.xml") + archiveArtifacts(allowEmptyArchive: false, artifacts: "${CYPRESS_DIR}/**/screenshots/**,${CYPRESS_DIR}/**/videos/**,${CYPRESS_DIR}/**/test-results/*e2e-tests.xml") + junit(allowEmptyResults: true, testResults: "${CYPRESS_DIR}/**/test-results/*e2e-tests.xml") } dir("${APM_ITS}"){ sh 'docker-compose logs > apm-its.log || true' diff --git a/.eslintignore b/.eslintignore index c3921bd22e1ab..357d735e8044b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -39,7 +39,7 @@ src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/moc /x-pack/legacy/plugins/infra/common/graphql/types.ts /x-pack/legacy/plugins/infra/public/graphql/types.ts /x-pack/legacy/plugins/infra/server/graphql/types.ts -/x-pack/legacy/plugins/apm/cypress/**/snapshots.js +/x-pack/legacy/plugins/apm/e2e/cypress/**/snapshots.js /src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/broken **/graphql/types.ts **/*.js.snap diff --git a/src/cli/cluster/cluster_manager.ts b/src/cli/cluster/cluster_manager.ts index 2f308915fb332..8862b96e74401 100644 --- a/src/cli/cluster/cluster_manager.ts +++ b/src/cli/cluster/cluster_manager.ts @@ -264,7 +264,7 @@ export class ClusterManager { 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/apm/e2e/cypress'), fromRoot('x-pack/legacy/plugins/apm/scripts'), fromRoot('x-pack/legacy/plugins/canvas/canvas_plugin_src'), // prevents server from restarting twice for Canvas plugin changes, 'plugins/java_languageserver', diff --git a/src/dev/ci_setup/setup_env.sh b/src/dev/ci_setup/setup_env.sh index 823c70e80fe7c..dc3fa38f3129c 100644 --- a/src/dev/ci_setup/setup_env.sh +++ b/src/dev/ci_setup/setup_env.sh @@ -168,4 +168,4 @@ if [[ -d "$ES_DIR" && -f "$ES_JAVA_PROP_PATH" ]]; then export JAVA_HOME=$HOME/.java/$ES_BUILD_JAVA fi -export CI_ENV_SETUP=true +export CI_ENV_SETUP=true \ No newline at end of file diff --git a/src/dev/run_check_lockfile_symlinks.js b/src/dev/run_check_lockfile_symlinks.js index e7fd7e8831405..54a8cdf638a78 100644 --- a/src/dev/run_check_lockfile_symlinks.js +++ b/src/dev/run_check_lockfile_symlinks.js @@ -35,7 +35,7 @@ const IGNORE_FILE_GLOBS = [ // fixtures aren't used in production, ignore them '**/*fixtures*/**/*', // cypress isn't used in production, ignore it - 'x-pack/legacy/plugins/apm/cypress/*', + 'x-pack/legacy/plugins/apm/e2e/*', ]; run(async ({ log }) => { diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index fb35e5ce526ed..34756912fc247 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -30,7 +30,7 @@ export const PROJECTS = [ new Project(resolve(REPO_ROOT, 'x-pack/legacy/plugins/siem/cypress/tsconfig.json'), { name: 'siem/cypress', }), - new Project(resolve(REPO_ROOT, 'x-pack/legacy/plugins/apm/cypress/tsconfig.json'), { + new Project(resolve(REPO_ROOT, 'x-pack/legacy/plugins/apm/e2e/tsconfig.json'), { name: 'apm/cypress', disableTypeCheck: true, }), diff --git a/x-pack/legacy/plugins/apm/cypress/README.md b/x-pack/legacy/plugins/apm/cypress/README.md deleted file mode 100644 index 7b44e0d9fce28..0000000000000 --- a/x-pack/legacy/plugins/apm/cypress/README.md +++ /dev/null @@ -1,63 +0,0 @@ -### How to run - -_Note: Run the following commands from `kibana/x-pack/legacy/plugins/apm/cypress`._ - -#### Interactive mode - -``` -yarn cypress open -``` - -#### Headless mode - -``` -yarn cypress run -``` - -### Connect to Elasticsearch on Cloud (internal devs only) - -Find the credentials for the cluster [here](https://github.com/elastic/apm-dev/blob/master/docs/credentials/apm-ui-clusters.md#e2e-cluster). The cloud instance contains the static data set - -### Kibana - -#### `--no-base-path` - -Kibana must be started with `yarn start --no-base-path` - -#### Content Security Policy (CSP) Settings - -Your local or cloud Kibana server must have the `csp.strict: false` setting -configured in `kibana.dev.yml`, or `kibana.yml`, as shown in the example below: - -```yaml -csp.strict: false -``` - -The above setting is required to prevent the _Please upgrade -your browser_ / _This Kibana installation has strict security requirements -enabled that your current browser does not meet._ warning that's displayed for -unsupported user agents, like the one reported by Cypress when running tests. - -### Ingest static data into Elasticsearch via APM Server - -1. Download [static data file](https://storage.googleapis.com/apm-ui-e2e-static-data/events.json) - -2. Post to APM Server - -``` -node ingest-data/replay.js --server-url http://localhost:8200 --secret-token abcd --events ./events.json -``` - -### Generate static data - -Capture data from all agents with [apm-integration-testing](https://github.com/elastic/apm-integration-testing): - -``` -./scripts/compose.py start master --all --apm-server-record -``` - -To copy the captured data from the container to the host: - -``` -docker cp localtesting_8.0.0_apm-server-2:/app/events.json . -``` diff --git a/x-pack/legacy/plugins/apm/cypress/cypress.json b/x-pack/legacy/plugins/apm/cypress/cypress.json deleted file mode 100644 index 69852346359fa..0000000000000 --- a/x-pack/legacy/plugins/apm/cypress/cypress.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "baseUrl": "http://localhost:5601", - "video": false, - "trashAssetsBeforeRuns": false, - "fileServerFolder": "../", - "fixturesFolder": "./fixtures", - "integrationFolder": "./integration", - "pluginsFile": "./plugins/index.js", - "screenshotsFolder": "./screenshots", - "supportFile": "./support/index.ts", - "videosFolder": "./videos", - "useRelativeSnapshots": true, - "reporter": "junit", - "reporterOptions": { - "mochaFile": "[hash]-e2e-tests.xml", - "toConsole": false - } -} diff --git a/x-pack/legacy/plugins/apm/cypress/integration/apm.spec.ts b/x-pack/legacy/plugins/apm/cypress/integration/apm.spec.ts deleted file mode 100644 index 3d0ff276fcdd8..0000000000000 --- a/x-pack/legacy/plugins/apm/cypress/integration/apm.spec.ts +++ /dev/null @@ -1,53 +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 { loginAndWaitForPage } from './helpers'; - -describe('When clicking opbeans-go service', () => { - before(() => { - // open service overview page - loginAndWaitForPage(`/app/apm#/services`); - - // show loading text for services - cy.contains('Loading...'); - - // click opbeans-go service - cy.get(':contains(opbeans-go)') - .last() - .click({ force: true }); - }); - - it('should redirect to correct path with correct params', () => { - cy.url().should('contain', `/app/apm#/services/opbeans-go/transactions`); - cy.url().should('contain', `transactionType=request`); - }); - - describe('transaction duration charts', () => { - it('should have correct y-axis ticks', () => { - const yAxisTick = - '[data-cy=transaction-duration-charts] .rv-xy-plot__axis--vertical .rv-xy-plot__axis__tick__text'; - - cy.get(yAxisTick) - .eq(2) - .invoke('text') - .snapshot(); - - cy.get(yAxisTick) - .eq(1) - .invoke('text') - .snapshot(); - - cy.get(yAxisTick) - .eq(0) - .invoke('text') - .snapshot(); - }); - }); - - describe('TPM charts', () => {}); - - describe('Transaction group list', () => {}); -}); diff --git a/x-pack/legacy/plugins/apm/cypress/screenshots/.gitignore b/x-pack/legacy/plugins/apm/cypress/screenshots/.gitignore deleted file mode 100644 index 72e8ffc0db8aa..0000000000000 --- a/x-pack/legacy/plugins/apm/cypress/screenshots/.gitignore +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/x-pack/legacy/plugins/apm/cypress/snapshots.js b/x-pack/legacy/plugins/apm/cypress/snapshots.js deleted file mode 100644 index 58e58fdaf8684..0000000000000 --- a/x-pack/legacy/plugins/apm/cypress/snapshots.js +++ /dev/null @@ -1,3 +0,0 @@ -// auto-generated by @cypress/snapshot -{ -} diff --git a/x-pack/legacy/plugins/apm/cypress/support/index.ts b/x-pack/legacy/plugins/apm/cypress/support/index.ts deleted file mode 100644 index 08acd31affeda..0000000000000 --- a/x-pack/legacy/plugins/apm/cypress/support/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -// @ts-ignore -import { register } from '@cypress/snapshot'; - -register(); diff --git a/x-pack/legacy/plugins/apm/e2e/.gitignore b/x-pack/legacy/plugins/apm/e2e/.gitignore new file mode 100644 index 0000000000000..10c769065fc28 --- /dev/null +++ b/x-pack/legacy/plugins/apm/e2e/.gitignore @@ -0,0 +1,4 @@ +cypress/ingest-data/events.json +cypress/screenshots/* + +cypress/test-results diff --git a/x-pack/legacy/plugins/apm/e2e/README.md b/x-pack/legacy/plugins/apm/e2e/README.md new file mode 100644 index 0000000000000..73a1e860f5564 --- /dev/null +++ b/x-pack/legacy/plugins/apm/e2e/README.md @@ -0,0 +1,68 @@ +# End-To-End (e2e) Test for APM UI + +## Ingest static data into Elasticsearch via APM Server + +1. Start Elasticsearch and APM Server, using [apm-integration-testing](https://github.com/elastic/apm-integration-testing): + +```shell +$ git clone https://github.com/elastic/apm-integration-testing.git +$ cd apm-integration-testing +./scripts/compose.py start master --no-kibana --no-xpack-secure +``` + +2. Download [static data file](https://storage.googleapis.com/apm-ui-e2e-static-data/events.json) + +```shell +$ cd x-pack/legacy/plugins/apm/e2e/cypress/ingest-data +$ curl https://storage.googleapis.com/apm-ui-e2e-static-data/events.json --output events.json +``` + +3. Post to APM Server + +```shell +$ cd x-pack/legacy/plugins/apm/e2e/cypress/ingest-data +$ node replay.js --server-url http://localhost:8200 --secret-token abcd --events ./events.json +``` +>This process will take a few minutes to ingest all data + +4. Start Kibana + +```shell +$ yarn kbn bootstrap +$ yarn start --no-base-path --csp.strict=false +``` + +> Content Security Policy (CSP) Settings: Your Kibana instance must have the `csp.strict: false`. + +## How to run the tests + +_Note: Run the following commands from `kibana/x-pack/legacy/plugins/apm/e2e/cypress`._ + +### Interactive mode + +``` +yarn cypress open +``` + +### Headless mode + +``` +yarn cypress run +``` + +## Reproducing CI builds + +>This process is very slow compared to the local development described above. Consider that the CI must install and configure the build tools and create a Docker image for the project to run tests in a consistent manner. + +The Jenkins CI uses a shell script to prepare Kibana: + +```shell +# Prepare and run Kibana locally +$ x-pack/legacy/plugins/apm/e2e/ci/prepare-kibana.sh +# Build Docker image for Kibana +$ docker build --tag cypress --build-arg NODE_VERSION=$(cat .node-version) x-pack/legacy/plugins/apm/e2e/ci +# Run Docker image +$ docker run --rm -t --user "$(id -u):$(id -g)" \ + -v `pwd`:/app --network="host" \ + --name cypress cypress +``` diff --git a/x-pack/legacy/plugins/apm/cypress/ci/Dockerfile b/x-pack/legacy/plugins/apm/e2e/ci/Dockerfile similarity index 92% rename from x-pack/legacy/plugins/apm/cypress/ci/Dockerfile rename to x-pack/legacy/plugins/apm/e2e/ci/Dockerfile index e59e1f47da0b9..2bcc5a5fd843a 100644 --- a/x-pack/legacy/plugins/apm/cypress/ci/Dockerfile +++ b/x-pack/legacy/plugins/apm/e2e/ci/Dockerfile @@ -1,4 +1,5 @@ -FROM node:12 +ARG NODE_VERSION +FROM node:$NODE_VERSION RUN apt-get -qq update \ && apt-get -y -qq install xvfb \ diff --git a/x-pack/legacy/plugins/apm/cypress/ci/entrypoint.sh b/x-pack/legacy/plugins/apm/e2e/ci/entrypoint.sh similarity index 87% rename from x-pack/legacy/plugins/apm/cypress/ci/entrypoint.sh rename to x-pack/legacy/plugins/apm/e2e/ci/entrypoint.sh index 1bcddac3b8020..f7226dca1d276 100755 --- a/x-pack/legacy/plugins/apm/cypress/ci/entrypoint.sh +++ b/x-pack/legacy/plugins/apm/e2e/ci/entrypoint.sh @@ -21,9 +21,9 @@ npm config set cache ${HOME} # --exclude=packages/ \ # --exclude=built_assets --exclude=target \ # --exclude=data /app ${HOME}/ -#cd ${HOME}/app/x-pack/legacy/plugins/apm/cypress +#cd ${HOME}/app/x-pack/legacy/plugins/apm/e2e/cypress -cd /app/x-pack/legacy/plugins/apm/cypress +cd /app/x-pack/legacy/plugins/apm/e2e ## Install dependencies for cypress CI=true npm install yarn install @@ -33,4 +33,4 @@ npm install wait-on ./node_modules/.bin/wait-on ${CYPRESS_BASE_URL}/status && echo 'Kibana is up and running' # Run cypress -./node_modules/.bin/cypress run +npm run cypress:run diff --git a/x-pack/legacy/plugins/apm/cypress/ci/kibana.dev.yml b/x-pack/legacy/plugins/apm/e2e/ci/kibana.dev.yml similarity index 100% rename from x-pack/legacy/plugins/apm/cypress/ci/kibana.dev.yml rename to x-pack/legacy/plugins/apm/e2e/ci/kibana.dev.yml diff --git a/x-pack/legacy/plugins/apm/cypress/ci/prepare-kibana.sh b/x-pack/legacy/plugins/apm/e2e/ci/prepare-kibana.sh similarity index 95% rename from x-pack/legacy/plugins/apm/cypress/ci/prepare-kibana.sh rename to x-pack/legacy/plugins/apm/e2e/ci/prepare-kibana.sh index d6fd620195b94..4f176fd0070f5 100755 --- a/x-pack/legacy/plugins/apm/cypress/ci/prepare-kibana.sh +++ b/x-pack/legacy/plugins/apm/e2e/ci/prepare-kibana.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -CYPRESS_DIR="x-pack/legacy/plugins/apm/cypress" +CYPRESS_DIR="x-pack/legacy/plugins/apm/e2e" echo "1/3 Install dependencies ..." # shellcheck disable=SC1091 diff --git a/x-pack/legacy/plugins/apm/e2e/cypress.json b/x-pack/legacy/plugins/apm/e2e/cypress.json new file mode 100644 index 0000000000000..310964656f107 --- /dev/null +++ b/x-pack/legacy/plugins/apm/e2e/cypress.json @@ -0,0 +1,19 @@ +{ + "baseUrl": "http://localhost:5601", + "video": false, + "trashAssetsBeforeRuns": false, + "fileServerFolder": "../", + "fixturesFolder": "./cypress/fixtures", + "integrationFolder": "./cypress/integration", + "pluginsFile": "./cypress/plugins/index.js", + "screenshotsFolder": "./cypress/screenshots", + "supportFile": "./cypress/support/index.ts", + "videosFolder": "./cypress/videos", + "useRelativeSnapshots": true, + "reporter": "junit", + "reporterOptions": { + "mochaFile": "./cypress/test-results/[hash]-e2e-tests.xml", + "toConsole": false + }, + "testFiles": "**/*.{feature,features}" +} diff --git a/x-pack/legacy/plugins/apm/cypress/fixtures/example.json b/x-pack/legacy/plugins/apm/e2e/cypress/fixtures/example.json similarity index 100% rename from x-pack/legacy/plugins/apm/cypress/fixtures/example.json rename to x-pack/legacy/plugins/apm/e2e/cypress/fixtures/example.json diff --git a/x-pack/legacy/plugins/apm/cypress/ingest-data/replay.js b/x-pack/legacy/plugins/apm/e2e/cypress/ingest-data/replay.js similarity index 100% rename from x-pack/legacy/plugins/apm/cypress/ingest-data/replay.js rename to x-pack/legacy/plugins/apm/e2e/cypress/ingest-data/replay.js diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/integration/apm.feature b/x-pack/legacy/plugins/apm/e2e/cypress/integration/apm.feature new file mode 100644 index 0000000000000..01fee2bf68b09 --- /dev/null +++ b/x-pack/legacy/plugins/apm/e2e/cypress/integration/apm.feature @@ -0,0 +1,7 @@ +Feature: APM + + Scenario: Transaction duration charts + Given a user browses the APM UI application + When the user inspects the opbeans-go service + Then should redirect to correct path with correct params + And should have correct y-axis ticks \ No newline at end of file diff --git a/x-pack/legacy/plugins/apm/cypress/integration/helpers.ts b/x-pack/legacy/plugins/apm/e2e/cypress/integration/helpers.ts similarity index 100% rename from x-pack/legacy/plugins/apm/cypress/integration/helpers.ts rename to x-pack/legacy/plugins/apm/e2e/cypress/integration/helpers.ts diff --git a/x-pack/legacy/plugins/apm/cypress/integration/snapshots.js b/x-pack/legacy/plugins/apm/e2e/cypress/integration/snapshots.js similarity index 61% rename from x-pack/legacy/plugins/apm/cypress/integration/snapshots.js rename to x-pack/legacy/plugins/apm/e2e/cypress/integration/snapshots.js index a2ff071645732..0e4b91ab45a40 100644 --- a/x-pack/legacy/plugins/apm/cypress/integration/snapshots.js +++ b/x-pack/legacy/plugins/apm/e2e/cypress/integration/snapshots.js @@ -8,5 +8,12 @@ module.exports = { } } }, - "__version": "3.4.1" + "__version": "3.8.3", + "APM": { + "Transaction duration charts": { + "1": "3.7 min", + "2": "1.8 min", + "3": "0.0 min" + } + } } diff --git a/x-pack/legacy/plugins/apm/cypress/plugins/index.js b/x-pack/legacy/plugins/apm/e2e/cypress/plugins/index.js similarity index 79% rename from x-pack/legacy/plugins/apm/cypress/plugins/index.js rename to x-pack/legacy/plugins/apm/e2e/cypress/plugins/index.js index 4dd55c16d4a0e..15e469f187651 100644 --- a/x-pack/legacy/plugins/apm/cypress/plugins/index.js +++ b/x-pack/legacy/plugins/apm/e2e/cypress/plugins/index.js @@ -22,22 +22,8 @@ const wp = require('@cypress/webpack-preprocessor'); const fs = require('fs'); module.exports = on => { - // add typescript support const options = { - webpackOptions: { - resolve: { - extensions: ['.ts', '.tsx', '.js'] - }, - module: { - rules: [ - { - test: /\.tsx?$/, - loader: 'ts-loader', - options: { transpileOnly: true } - } - ] - } - } + webpackOptions: require('../webpack.config.js') }; on('file:preprocessor', wp(options)); diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/support/commands.js b/x-pack/legacy/plugins/apm/e2e/cypress/support/commands.js new file mode 100644 index 0000000000000..9a2e54b102c5e --- /dev/null +++ b/x-pack/legacy/plugins/apm/e2e/cypress/support/commands.js @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add("login", (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This is will overwrite an existing command -- +// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/support/index.ts b/x-pack/legacy/plugins/apm/e2e/cypress/support/index.ts new file mode 100644 index 0000000000000..8a7a9f64cc461 --- /dev/null +++ b/x-pack/legacy/plugins/apm/e2e/cypress/support/index.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +import './commands'; + +// @ts-ignore +import { register } from '@cypress/snapshot'; + +register(); diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/support/step_definitions/apm.ts b/x-pack/legacy/plugins/apm/e2e/cypress/support/step_definitions/apm.ts new file mode 100644 index 0000000000000..f2f1e515f967a --- /dev/null +++ b/x-pack/legacy/plugins/apm/e2e/cypress/support/step_definitions/apm.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 { Given, When, Then } from 'cypress-cucumber-preprocessor/steps'; +import { loginAndWaitForPage } from '../../integration/helpers'; + +Given(`a user browses the APM UI application`, () => { + // open service overview page + loginAndWaitForPage(`/app/apm#/services`); +}); + +When(`the user inspects the opbeans-go service`, () => { + // click opbeans-go service + cy.get(':contains(opbeans-go)') + .last() + .click({ force: true }); +}); + +Then(`should redirect to correct path with correct params`, () => { + cy.url().should('contain', `/app/apm#/services/opbeans-go/transactions`); + cy.url().should('contain', `transactionType=request`); +}); + +Then(`should have correct y-axis ticks`, () => { + const yAxisTick = + '[data-cy=transaction-duration-charts] .rv-xy-plot__axis--vertical .rv-xy-plot__axis__tick__text'; + + cy.get(yAxisTick) + .eq(2) + .invoke('text') + .snapshot(); + + cy.get(yAxisTick) + .eq(1) + .invoke('text') + .snapshot(); + + cy.get(yAxisTick) + .eq(0) + .invoke('text') + .snapshot(); +}); diff --git a/x-pack/legacy/plugins/apm/cypress/cypress.d.ts b/x-pack/legacy/plugins/apm/e2e/cypress/typings/index.d.ts similarity index 100% rename from x-pack/legacy/plugins/apm/cypress/cypress.d.ts rename to x-pack/legacy/plugins/apm/e2e/cypress/typings/index.d.ts diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/webpack.config.js b/x-pack/legacy/plugins/apm/e2e/cypress/webpack.config.js new file mode 100644 index 0000000000000..823b23cfdffec --- /dev/null +++ b/x-pack/legacy/plugins/apm/e2e/cypress/webpack.config.js @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +module.exports = { + resolve: { + extensions: ['.ts', '.js'] + }, + node: { fs: 'empty', child_process: 'empty', readline: 'empty' }, + module: { + rules: [ + { + test: /\.ts$/, + exclude: [/node_modules/], + use: [ + { + loader: 'ts-loader' + } + ] + }, + { + test: /\.feature$/, + use: [ + { + loader: 'cypress-cucumber-preprocessor/loader' + } + ] + }, + { + test: /\.features$/, + use: [ + { + loader: 'cypress-cucumber-preprocessor/lib/featuresLoader' + } + ] + } + ] + } +}; diff --git a/x-pack/legacy/plugins/apm/cypress/package.json b/x-pack/legacy/plugins/apm/e2e/package.json similarity index 66% rename from x-pack/legacy/plugins/apm/cypress/package.json rename to x-pack/legacy/plugins/apm/e2e/package.json index 59f76ba250ad7..c9026636e64fb 100644 --- a/x-pack/legacy/plugins/apm/cypress/package.json +++ b/x-pack/legacy/plugins/apm/e2e/package.json @@ -5,17 +5,20 @@ "license": "MIT", "scripts": { "cypress:open": "cypress open", - "cypress:run": "cypress run" + "cypress:run": "cypress run --spec **/*.feature" }, "dependencies": { "@cypress/snapshot": "^2.1.3", "@cypress/webpack-preprocessor": "^4.1.0", + "@types/cypress-cucumber-preprocessor": "^1.14.0", "@types/js-yaml": "^3.12.1", + "@types/node": "^10.12.11", "cypress": "^3.5.0", + "cypress-cucumber-preprocessor": "^2.0.1", "js-yaml": "^3.13.1", "p-limit": "^2.2.1", "ts-loader": "^6.1.0", - "typescript": "3.7.2", + "typescript": "3.7.5", "webpack": "^4.41.5" } } diff --git a/x-pack/legacy/plugins/apm/cypress/tsconfig.json b/x-pack/legacy/plugins/apm/e2e/tsconfig.json similarity index 51% rename from x-pack/legacy/plugins/apm/cypress/tsconfig.json rename to x-pack/legacy/plugins/apm/e2e/tsconfig.json index e57b9c86a8f03..de498816e30a4 100644 --- a/x-pack/legacy/plugins/apm/cypress/tsconfig.json +++ b/x-pack/legacy/plugins/apm/e2e/tsconfig.json @@ -1,8 +1,13 @@ { "extends": "../../../../tsconfig.json", "exclude": [], - "include": ["./**/*"], + "include": [ + "./**/*" + ], "compilerOptions": { - "types": ["cypress", "node"] + "types": [ + "cypress", + "node" + ] } } diff --git a/x-pack/legacy/plugins/apm/cypress/yarn.lock b/x-pack/legacy/plugins/apm/e2e/yarn.lock similarity index 61% rename from x-pack/legacy/plugins/apm/cypress/yarn.lock rename to x-pack/legacy/plugins/apm/e2e/yarn.lock index 4940217fa7ce3..48e6013fb6986 100644 --- a/x-pack/legacy/plugins/apm/cypress/yarn.lock +++ b/x-pack/legacy/plugins/apm/e2e/yarn.lock @@ -2,592 +2,758 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== dependencies: - "@babel/highlight" "^7.0.0" + "@babel/highlight" "^7.8.3" -"@babel/core@^7.0.1": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.0.tgz#9b00f73554edd67bebc86df8303ef678be3d7b48" - integrity sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.0" - "@babel/helpers" "^7.6.0" - "@babel/parser" "^7.6.0" - "@babel/template" "^7.6.0" - "@babel/traverse" "^7.6.0" - "@babel/types" "^7.6.0" +"@babel/compat-data@^7.8.4": + version "7.8.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.5.tgz#d28ce872778c23551cbb9432fc68d28495b613b9" + integrity sha512-jWYUqQX/ObOhG1UiEkbH5SANsE/8oKXiQWjj7p7xgj9Zmnt//aUvyz4dBkK0HNsS8/cbyC5NmmH87VekW+mXFg== + dependencies: + browserslist "^4.8.5" + invariant "^2.2.4" + semver "^5.5.0" + +"@babel/core@7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.5.tgz#081f97e8ffca65a9b4b0fdc7e274e703f000c06a" + integrity sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/generator" "^7.4.4" + "@babel/helpers" "^7.4.4" + "@babel/parser" "^7.4.5" + "@babel/template" "^7.4.4" + "@babel/traverse" "^7.4.5" + "@babel/types" "^7.4.4" convert-source-map "^1.1.0" debug "^4.1.0" json5 "^2.1.0" + lodash "^4.17.11" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.0.1": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e" + integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.4" + "@babel/helpers" "^7.8.4" + "@babel/parser" "^7.8.4" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.4" + "@babel/types" "^7.8.3" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.0" lodash "^4.17.13" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.0.tgz#e2c21efbfd3293ad819a2359b448f002bfdfda56" - integrity sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA== +"@babel/generator@^7.4.4", "@babel/generator@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e" + integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA== dependencies: - "@babel/types" "^7.6.0" + "@babel/types" "^7.8.3" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" - trim-right "^1.0.1" -"@babel/helper-annotate-as-pure@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" - integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== +"@babel/helper-annotate-as-pure@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" + integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.8.3" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" - integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" + integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== dependencies: - "@babel/helper-explode-assignable-expression" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-explode-assignable-expression" "^7.8.3" + "@babel/types" "^7.8.3" -"@babel/helper-call-delegate@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz#87c1f8ca19ad552a736a7a27b1c1fcf8b1ff1f43" - integrity sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ== +"@babel/helper-builder-react-jsx@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz#dee98d7d79cc1f003d80b76fe01c7f8945665ff6" + integrity sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ== dependencies: - "@babel/helper-hoist-variables" "^7.4.4" - "@babel/traverse" "^7.4.4" - "@babel/types" "^7.4.4" + "@babel/types" "^7.8.3" + esutils "^2.0.0" -"@babel/helper-define-map@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" - integrity sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg== +"@babel/helper-call-delegate@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz#de82619898aa605d409c42be6ffb8d7204579692" + integrity sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A== dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.5.5" + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-compilation-targets@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz#03d7ecd454b7ebe19a254f76617e61770aed2c88" + integrity sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg== + dependencies: + "@babel/compat-data" "^7.8.4" + browserslist "^4.8.5" + invariant "^2.2.4" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/helper-create-class-features-plugin@^7.3.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz#5b94be88c255f140fd2c10dd151e7f98f4bff397" + integrity sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + +"@babel/helper-create-regexp-features-plugin@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz#c774268c95ec07ee92476a3862b75cc2839beb79" + integrity sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q== + dependencies: + "@babel/helper-regex" "^7.8.3" + regexpu-core "^4.6.0" + +"@babel/helper-define-map@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" + integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/types" "^7.8.3" lodash "^4.17.13" -"@babel/helper-explode-assignable-expression@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" - integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA== +"@babel/helper-explode-assignable-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" + integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== dependencies: - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" -"@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== +"@babel/helper-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" + integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" -"@babel/helper-get-function-arity@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.8.3" -"@babel/helper-hoist-variables@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" - integrity sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w== +"@babel/helper-hoist-variables@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" + integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== dependencies: - "@babel/types" "^7.4.4" + "@babel/types" "^7.8.3" -"@babel/helper-member-expression-to-functions@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" - integrity sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA== +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" + integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== dependencies: - "@babel/types" "^7.5.5" + "@babel/types" "^7.8.3" -"@babel/helper-module-imports@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" - integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" + integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.8.3" -"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" - integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== +"@babel/helper-module-transforms@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz#d305e35d02bee720fbc2c3c3623aa0c316c01590" + integrity sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q== dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/template" "^7.4.4" - "@babel/types" "^7.5.5" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" lodash "^4.17.13" -"@babel/helper-optimise-call-expression@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" - integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g== +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" + integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.8.3" -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" + integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== -"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" - integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== +"@babel/helper-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" + integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== dependencies: lodash "^4.17.13" -"@babel/helper-remap-async-to-generator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" - integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-wrap-function" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-replace-supers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" - integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.5.5" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - -"@babel/helper-simple-access@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" - integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== +"@babel/helper-remap-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" + integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-wrap-function" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-replace-supers@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc" + integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-simple-access@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" + integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== + dependencies: + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-wrap-function@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" + integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helpers@^7.4.4", "@babel/helpers@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73" + integrity sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.4" + "@babel/types" "^7.8.3" + +"@babel/highlight@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" + integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== dependencies: - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" -"@babel/helper-split-export-declaration@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" - integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== +"@babel/parser@^7.4.5", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" + integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== + +"@babel/plugin-proposal-async-generator-functions@^7.2.0", "@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" + integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== dependencies: - "@babel/types" "^7.4.4" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/helper-wrap-function@^7.1.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" - integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== +"@babel/plugin-proposal-class-properties@7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.0.tgz#272636bc0fa19a0bc46e601ec78136a173ea36cd" + integrity sha512-wNHxLkEKTQ2ay0tnsam2z7fGZUi+05ziDJflEt3AZTP3oXLKHJp9HqhfroB/vdMvt3sda9fAbq7FsG8QPDrZBg== dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.2.0" + "@babel/helper-create-class-features-plugin" "^7.3.0" + "@babel/helper-plugin-utils" "^7.0.0" -"@babel/helpers@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.0.tgz#21961d16c6a3c3ab597325c34c465c0887d31c6e" - integrity sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ== +"@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" + integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== dependencies: - "@babel/template" "^7.6.0" - "@babel/traverse" "^7.6.0" - "@babel/types" "^7.6.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== +"@babel/plugin-proposal-json-strings@^7.2.0", "@babel/plugin-proposal-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" + integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/parser@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b" - integrity sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" + integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-async-generator-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" - integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== +"@babel/plugin-proposal-object-rest-spread@7.3.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.2.tgz#6d1859882d4d778578e41f82cc5d7bf3d5daf6c1" + integrity sha512-DjeMS+J2+lpANkYLLO+m6GjoTMygYglKmRe6cDTbFv3L9i6mmiE8fe6B8MtCSLZpVXscD5kn7s6SgtHrDoBWoA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" -"@babel/plugin-proposal-dynamic-import@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz#e532202db4838723691b10a67b8ce509e397c506" - integrity sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw== +"@babel/plugin-proposal-object-rest-spread@^7.4.4", "@babel/plugin-proposal-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz#eb5ae366118ddca67bed583b53d7554cad9951bb" + integrity sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" -"@babel/plugin-proposal-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" - integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== +"@babel/plugin-proposal-optional-catch-binding@^7.2.0", "@babel/plugin-proposal-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" + integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-object-rest-spread@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58" - integrity sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw== +"@babel/plugin-proposal-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz#ae10b3214cb25f7adb1f3bc87ba42ca10b7e2543" + integrity sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" - integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== +"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz#b646c3adea5f98800c9ab45105ac34d06cd4a47f" + integrity sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" - integrity sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA== +"@babel/plugin-syntax-async-generators@^7.2.0", "@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-async-generators@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" - integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== +"@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-dynamic-import@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" - integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== +"@babel/plugin-syntax-json-strings@^7.2.0", "@babel/plugin-syntax-json-strings@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" - integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== +"@babel/plugin-syntax-jsx@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz#521b06c83c40480f1e58b4fd33b92eceb1d6ea94" + integrity sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-object-rest-spread@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" - integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" - integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== +"@babel/plugin-syntax-object-rest-spread@^7.2.0", "@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-arrow-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" - integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== +"@babel/plugin-syntax-optional-catch-binding@^7.2.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-async-to-generator@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e" - integrity sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg== +"@babel/plugin-syntax-optional-chaining@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-transform-block-scoped-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" - integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" + integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-block-scoping@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.0.tgz#c49e21228c4bbd4068a35667e6d951c75439b1dc" - integrity sha512-tIt4E23+kw6TgL/edACZwP1OUKrjOTyMrFMLoT5IOFrfMRabCgekjqFd5o6PaAMildBu46oFkekIdMuGkkPEpA== +"@babel/plugin-transform-arrow-functions@^7.2.0", "@babel/plugin-transform-arrow-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" + integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - lodash "^4.17.13" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-classes@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz#d094299d9bd680a14a2a0edae38305ad60fb4de9" - integrity sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg== +"@babel/plugin-transform-async-to-generator@^7.4.4", "@babel/plugin-transform-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" + integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" - "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + +"@babel/plugin-transform-block-scoped-functions@^7.2.0", "@babel/plugin-transform-block-scoped-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" + integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-block-scoping@^7.4.4", "@babel/plugin-transform-block-scoping@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" + integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + lodash "^4.17.13" + +"@babel/plugin-transform-classes@^7.4.4", "@babel/plugin-transform-classes@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz#46fd7a9d2bb9ea89ce88720477979fe0d71b21b8" + integrity sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-define-map" "^7.8.3" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" - integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== +"@babel/plugin-transform-computed-properties@^7.2.0", "@babel/plugin-transform-computed-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" + integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-destructuring@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" - integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ== +"@babel/plugin-transform-destructuring@^7.4.4", "@babel/plugin-transform-destructuring@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz#20ddfbd9e4676906b1056ee60af88590cc7aaa0b" + integrity sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" - integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== +"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" + integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-duplicate-keys@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" - integrity sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ== +"@babel/plugin-transform-duplicate-keys@^7.2.0", "@babel/plugin-transform-duplicate-keys@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" + integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-exponentiation-operator@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" - integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== +"@babel/plugin-transform-exponentiation-operator@^7.2.0", "@babel/plugin-transform-exponentiation-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" + integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-for-of@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" - integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== +"@babel/plugin-transform-for-of@^7.4.4", "@babel/plugin-transform-for-of@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz#6fe8eae5d6875086ee185dd0b098a8513783b47d" + integrity sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-function-name@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" - integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== +"@babel/plugin-transform-function-name@^7.4.4", "@babel/plugin-transform-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" + integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" - integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== +"@babel/plugin-transform-literals@^7.2.0", "@babel/plugin-transform-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" + integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-member-expression-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" - integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== +"@babel/plugin-transform-member-expression-literals@^7.2.0", "@babel/plugin-transform-member-expression-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" + integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-modules-amd@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" - integrity sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg== +"@babel/plugin-transform-modules-amd@^7.2.0", "@babel/plugin-transform-modules-amd@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz#65606d44616b50225e76f5578f33c568a0b876a5" + integrity sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ== dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-commonjs@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz#39dfe957de4420445f1fcf88b68a2e4aa4515486" - integrity sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g== +"@babel/plugin-transform-modules-commonjs@7.8.3", "@babel/plugin-transform-modules-commonjs@^7.4.4", "@babel/plugin-transform-modules-commonjs@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz#df251706ec331bd058a34bdd72613915f82928a5" + integrity sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg== dependencies: - "@babel/helper-module-transforms" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-systemjs@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz#e75266a13ef94202db2a0620977756f51d52d249" - integrity sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg== +"@babel/plugin-transform-modules-systemjs@^7.4.4", "@babel/plugin-transform-modules-systemjs@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz#d8bbf222c1dbe3661f440f2f00c16e9bb7d0d420" + integrity sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg== dependencies: - "@babel/helper-hoist-variables" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-umd@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" - integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw== +"@babel/plugin-transform-modules-umd@^7.2.0", "@babel/plugin-transform-modules-umd@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz#592d578ce06c52f5b98b02f913d653ffe972661a" + integrity sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw== dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-named-capturing-groups-regex@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.0.tgz#1e6e663097813bb4f53d42df0750cf28ad3bb3f1" - integrity sha512-jem7uytlmrRl3iCAuQyw8BpB4c4LWvSpvIeXKpMb+7j84lkx4m4mYr5ErAcmN5KM7B6BqrAvRGjBIbbzqCczew== +"@babel/plugin-transform-named-capturing-groups-regex@^7.4.5", "@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" + integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== dependencies: - regexp-tree "^0.1.13" + "@babel/helper-create-regexp-features-plugin" "^7.8.3" -"@babel/plugin-transform-new-target@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" - integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== +"@babel/plugin-transform-new-target@^7.4.4", "@babel/plugin-transform-new-target@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" + integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-object-super@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" - integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== +"@babel/plugin-transform-object-super@^7.2.0", "@babel/plugin-transform-object-super@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" + integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" -"@babel/plugin-transform-parameters@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" - integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== +"@babel/plugin-transform-parameters@^7.4.4", "@babel/plugin-transform-parameters@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz#1d5155de0b65db0ccf9971165745d3bb990d77d3" + integrity sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA== dependencies: - "@babel/helper-call-delegate" "^7.4.4" - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-call-delegate" "^7.8.3" + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-property-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" - integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== +"@babel/plugin-transform-property-literals@^7.2.0", "@babel/plugin-transform-property-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" + integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-regenerator@^7.4.5": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" - integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== +"@babel/plugin-transform-react-display-name@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz#70ded987c91609f78353dd76d2fb2a0bb991e8e5" + integrity sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-react-jsx-self@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.8.3.tgz#c4f178b2aa588ecfa8d077ea80d4194ee77ed702" + integrity sha512-01OT7s5oa0XTLf2I8XGsL8+KqV9lx3EZV+jxn/L2LQ97CGKila2YMroTkCEIE0HV/FF7CMSRsIAybopdN9NTdg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + +"@babel/plugin-transform-react-jsx-source@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz#951e75a8af47f9f120db731be095d2b2c34920e0" + integrity sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz#4220349c0390fdefa505365f68c103562ab2fc4a" + integrity sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g== + dependencies: + "@babel/helper-builder-react-jsx" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + +"@babel/plugin-transform-regenerator@^7.4.5", "@babel/plugin-transform-regenerator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz#b31031e8059c07495bf23614c97f3d9698bc6ec8" + integrity sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA== dependencies: regenerator-transform "^0.14.0" -"@babel/plugin-transform-reserved-words@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" - integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw== +"@babel/plugin-transform-reserved-words@^7.2.0", "@babel/plugin-transform-reserved-words@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" + integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-shorthand-properties@^7.2.0": +"@babel/plugin-transform-runtime@7.2.0": version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" - integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.2.0.tgz#566bc43f7d0aedc880eaddbd29168d0f248966ea" + integrity sha512-jIgkljDdq4RYDnJyQsiWbdvGeei/0MOTtSHKO/rfbd/mXBxNpdlulMx49L0HQ4pug1fXannxoqCI+fYSle9eSw== dependencies: + "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" + resolve "^1.8.1" + semver "^5.5.1" -"@babel/plugin-transform-spread@^7.2.0": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" - integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== +"@babel/plugin-transform-shorthand-properties@^7.2.0", "@babel/plugin-transform-shorthand-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" + integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-sticky-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" - integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== +"@babel/plugin-transform-spread@^7.2.0", "@babel/plugin-transform-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" + integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-template-literals@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" - integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== +"@babel/plugin-transform-sticky-regex@^7.2.0", "@babel/plugin-transform-sticky-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" + integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-regex" "^7.8.3" -"@babel/plugin-transform-typeof-symbol@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" - integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== +"@babel/plugin-transform-template-literals@^7.4.4", "@babel/plugin-transform-template-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" + integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-unicode-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" - integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA== +"@babel/plugin-transform-typeof-symbol@^7.2.0", "@babel/plugin-transform-typeof-symbol@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" + integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/preset-env@^7.0.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.0.tgz#aae4141c506100bb2bfaa4ac2a5c12b395619e50" - integrity sha512-1efzxFv/TcPsNXlRhMzRnkBFMeIqBBgzwmZwlFDw5Ubj0AGLeufxugirwZmkkX/ayi3owsSqoQ4fw8LkfK9SYg== +"@babel/plugin-transform-unicode-regex@^7.4.4", "@babel/plugin-transform-unicode-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" + integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/preset-env@7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.5.tgz#2fad7f62983d5af563b5f3139242755884998a58" + integrity sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-async-generator-functions" "^7.2.0" - "@babel/plugin-proposal-dynamic-import" "^7.5.0" "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.5.5" + "@babel/plugin-proposal-object-rest-spread" "^7.4.4" "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" "@babel/plugin-syntax-async-generators" "^7.2.0" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" "@babel/plugin-syntax-json-strings" "^7.2.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" "@babel/plugin-transform-arrow-functions" "^7.2.0" - "@babel/plugin-transform-async-to-generator" "^7.5.0" + "@babel/plugin-transform-async-to-generator" "^7.4.4" "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.6.0" - "@babel/plugin-transform-classes" "^7.5.5" + "@babel/plugin-transform-block-scoping" "^7.4.4" + "@babel/plugin-transform-classes" "^7.4.4" "@babel/plugin-transform-computed-properties" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.6.0" + "@babel/plugin-transform-destructuring" "^7.4.4" "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/plugin-transform-duplicate-keys" "^7.5.0" + "@babel/plugin-transform-duplicate-keys" "^7.2.0" "@babel/plugin-transform-exponentiation-operator" "^7.2.0" "@babel/plugin-transform-for-of" "^7.4.4" "@babel/plugin-transform-function-name" "^7.4.4" "@babel/plugin-transform-literals" "^7.2.0" "@babel/plugin-transform-member-expression-literals" "^7.2.0" - "@babel/plugin-transform-modules-amd" "^7.5.0" - "@babel/plugin-transform-modules-commonjs" "^7.6.0" - "@babel/plugin-transform-modules-systemjs" "^7.5.0" + "@babel/plugin-transform-modules-amd" "^7.2.0" + "@babel/plugin-transform-modules-commonjs" "^7.4.4" + "@babel/plugin-transform-modules-systemjs" "^7.4.4" "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.4.5" "@babel/plugin-transform-new-target" "^7.4.4" - "@babel/plugin-transform-object-super" "^7.5.5" + "@babel/plugin-transform-object-super" "^7.2.0" "@babel/plugin-transform-parameters" "^7.4.4" "@babel/plugin-transform-property-literals" "^7.2.0" "@babel/plugin-transform-regenerator" "^7.4.5" @@ -598,46 +764,150 @@ "@babel/plugin-transform-template-literals" "^7.4.4" "@babel/plugin-transform-typeof-symbol" "^7.2.0" "@babel/plugin-transform-unicode-regex" "^7.4.4" - "@babel/types" "^7.6.0" + "@babel/types" "^7.4.4" browserslist "^4.6.0" core-js-compat "^3.1.1" invariant "^2.2.2" js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/template@^7.1.0", "@babel/template@^7.4.4", "@babel/template@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" - integrity sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ== +"@babel/preset-env@^7.0.0": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.4.tgz#9dac6df5f423015d3d49b6e9e5fa3413e4a72c4e" + integrity sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w== + dependencies: + "@babel/compat-data" "^7.8.4" + "@babel/helper-compilation-targets" "^7.8.4" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-async-generator-functions" "^7.8.3" + "@babel/plugin-proposal-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-json-strings" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.8.3" + "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.8.3" + "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.8.3" + "@babel/plugin-transform-async-to-generator" "^7.8.3" + "@babel/plugin-transform-block-scoped-functions" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-classes" "^7.8.3" + "@babel/plugin-transform-computed-properties" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.8.3" + "@babel/plugin-transform-dotall-regex" "^7.8.3" + "@babel/plugin-transform-duplicate-keys" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator" "^7.8.3" + "@babel/plugin-transform-for-of" "^7.8.4" + "@babel/plugin-transform-function-name" "^7.8.3" + "@babel/plugin-transform-literals" "^7.8.3" + "@babel/plugin-transform-member-expression-literals" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.8.3" + "@babel/plugin-transform-modules-commonjs" "^7.8.3" + "@babel/plugin-transform-modules-systemjs" "^7.8.3" + "@babel/plugin-transform-modules-umd" "^7.8.3" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" + "@babel/plugin-transform-new-target" "^7.8.3" + "@babel/plugin-transform-object-super" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.8.4" + "@babel/plugin-transform-property-literals" "^7.8.3" + "@babel/plugin-transform-regenerator" "^7.8.3" + "@babel/plugin-transform-reserved-words" "^7.8.3" + "@babel/plugin-transform-shorthand-properties" "^7.8.3" + "@babel/plugin-transform-spread" "^7.8.3" + "@babel/plugin-transform-sticky-regex" "^7.8.3" + "@babel/plugin-transform-template-literals" "^7.8.3" + "@babel/plugin-transform-typeof-symbol" "^7.8.4" + "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/types" "^7.8.3" + browserslist "^4.8.5" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/preset-react@7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.0.0.tgz#e86b4b3d99433c7b3e9e91747e2653958bc6b3c0" + integrity sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w== dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.6.0" - "@babel/types" "^7.6.0" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.0.tgz#389391d510f79be7ce2ddd6717be66d3fed4b516" - integrity sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.0" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.6.0" - "@babel/types" "^7.6.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-react-jsx-self" "^7.0.0" + "@babel/plugin-transform-react-jsx-source" "^7.0.0" + +"@babel/runtime@7.3.1": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.1.tgz#574b03e8e8a9898eaf4a872a92ea20b7846f6f2a" + integrity sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA== + dependencies: + regenerator-runtime "^0.12.0" + +"@babel/template@^7.4.4", "@babel/template@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" + integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/traverse@^7.4.5", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c" + integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.4" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.8.4" + "@babel/types" "^7.8.3" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648" - integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g== +"@babel/types@^7.4.4", "@babel/types@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" + integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== dependencies: esutils "^2.0.2" lodash "^4.17.13" to-fast-properties "^2.0.0" +"@cypress/browserify-preprocessor@^2.1.1": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@cypress/browserify-preprocessor/-/browserify-preprocessor-2.1.3.tgz#abbb8ba52ff33d70745c056e8fc675db2276a539" + integrity sha512-vZskc/EKejnmdm4fMGB1Fm39WelsF4HJHeI5q8I0LvGnrdvxSiCbn27TbhCM5Enq6Fkinf3f7oiHS/m2OUgzdA== + dependencies: + "@babel/core" "7.4.5" + "@babel/plugin-proposal-class-properties" "7.3.0" + "@babel/plugin-proposal-object-rest-spread" "7.3.2" + "@babel/plugin-transform-modules-commonjs" "7.8.3" + "@babel/plugin-transform-runtime" "7.2.0" + "@babel/preset-env" "7.4.5" + "@babel/preset-react" "7.0.0" + "@babel/runtime" "7.3.1" + babelify "10.0.0" + bluebird "3.5.3" + browserify "16.2.3" + coffeeify "3.0.1" + coffeescript "1.12.7" + debug "4.1.1" + fs-extra "7.0.1" + lodash.clonedeep "4.5.0" + watchify "3.11.1" + "@cypress/listr-verbose-renderer@0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a" @@ -649,26 +919,26 @@ figures "^1.7.0" "@cypress/snapshot@^2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@cypress/snapshot/-/snapshot-2.1.3.tgz#85f5c40c4c27df9185773062a5d29e3f1a8d0b1f" - integrity sha512-NAkyxFxeFSJt6K/McsF3u8RoSqLi3trYlO5ZkfoeiKcNm8J0eX4o6Uz12xMPcfTi5Ql9RMyZg6/j6XJU6tBjiQ== + version "2.1.7" + resolved "https://registry.yarnpkg.com/@cypress/snapshot/-/snapshot-2.1.7.tgz#e7360eb628b062f28f03036382619ec72cfb1831" + integrity sha512-f8AcfIg7wOOHSdBODlIwCJE/rG5Yb+kUY+WVTKynB2pLLoDy9nc8CtcazqX19q2Lh++nTJLNRihpbbWvk33mbg== dependencies: - "@wildpeaks/snapshot-dom" "1.2.1" + "@wildpeaks/snapshot-dom" "1.6.0" am-i-a-dependency "1.1.2" check-more-types "2.24.0" its-name "1.0.0" - js-beautify "1.10.0" + js-beautify "1.10.3" lazy-ass "1.6.0" snap-shot-compare "2.8.3" snap-shot-store "1.2.3" "@cypress/webpack-preprocessor@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@cypress/webpack-preprocessor/-/webpack-preprocessor-4.1.0.tgz#8c4debc0b1abf045b62524d1996dd9aeaf7e86a8" - integrity sha512-LbxsdYVpHGoC2fMOdW0aQvuvVRD7aZx8p8DrP53HISpl7bD1PqLGWKzhHn7cGG24UHycBJrbaEeKEosW29W1dg== + version "4.1.1" + resolved "https://registry.yarnpkg.com/@cypress/webpack-preprocessor/-/webpack-preprocessor-4.1.1.tgz#3c0b5b8de6eaac605dac3b1f1c3f5916c1c6eaea" + integrity sha512-SfzDqOvWBSlfGRm8ak/XHUXAnndwHU2qJIRr1LIC7j2UqWcZoJ+286CuNloJbkwfyEAO6tQggLd4E/WHUAcKZQ== dependencies: - bluebird "3.5.0" - debug "3.1.0" + bluebird "3.7.1" + debug "4.1.1" optionalDependencies: "@babel/core" "^7.0.1" "@babel/preset-env" "^7.0.0" @@ -682,10 +952,25 @@ debug "^3.1.0" lodash.once "^4.1.1" +"@types/cypress-cucumber-preprocessor@^1.14.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@types/cypress-cucumber-preprocessor/-/cypress-cucumber-preprocessor-1.14.0.tgz#41d8ffb2b608d3ed4ab998a0c4394056f75af1e0" + integrity sha512-bOl4u6seZtxNIGa6J6xydroPntTxxWy8uqIrZ3OY10C96fUes4mZvJKY6NvOoe61/OVafG/UEFa+X2ZWKE6Ltw== + "@types/js-yaml@^3.12.1": - version "3.12.1" - resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.1.tgz#5c6f4a1eabca84792fbd916f0cb40847f123c656" - integrity sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA== + version "3.12.2" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.2.tgz#a35a1809c33a68200fb6403d1ad708363c56470a" + integrity sha512-0CFu/g4mDSNkodVwWijdlr8jH7RoplRWNgovjFLEZeT+QEbbZXjBmCe3HwaWheAlCbHwomTwzZoSedeOycABug== + +"@types/node@^10.12.11": + version "10.17.14" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.14.tgz#b6c60ebf2fb5e4229fdd751ff9ddfae0f5f31541" + integrity sha512-G0UmX5uKEmW+ZAhmZ6PLTQ5eu/VPaT+d/tdLd5IFsKRPcbe6lPxocBtcYBFSaLaCW8O60AX90e91Nsp8lVHCNw== + +"@types/sizzle@2.3.2": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" + integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== "@webassemblyjs/ast@1.8.5": version "1.8.5" @@ -833,10 +1118,10 @@ "@webassemblyjs/wast-parser" "1.8.5" "@xtuc/long" "4.2.2" -"@wildpeaks/snapshot-dom@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@wildpeaks/snapshot-dom/-/snapshot-dom-1.2.1.tgz#c4af08cdb175d61dca2878c7a2d91253158f6086" - integrity sha1-xK8IzbF11h3KKHjHotkSUxWPYIY= +"@wildpeaks/snapshot-dom@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@wildpeaks/snapshot-dom/-/snapshot-dom-1.6.0.tgz#83297612bf93b97983beafbe6ae71672642ac884" + integrity sha512-fCM5tYK6VZ1nhbk3Q11lkf6UOJlOCRU0oScQ8NV8OYBPC58wQmQaOF9g+rk+yhNYf3beybOBr+ZuiNen3B0Bxw== "@xtuc/ieee754@^1.2.0": version "1.2.0" @@ -848,15 +1133,42 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +JSONStream@^1.0.3: + version "1.3.5" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" + integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" + integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== + dependencies: + acorn "^7.0.0" + acorn-walk "^7.0.0" + xtend "^4.0.2" + +acorn-walk@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.0.tgz#48387aa9a83bba67a9909164acab4bbc5796cf87" + integrity sha512-4ufNLdC8gOf1dlOjC1nrn2NfzevyDtrDPp/DOtmoOHAFA/1pQc6bWf7oZ71qDURTODPLQ03+oFOvwxq5BvjXug== + acorn@^6.2.1: - version "6.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" - integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== + version "6.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" + integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== + +acorn@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" + integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== ajv-errors@^1.0.0: version "1.0.1" @@ -869,11 +1181,11 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5: - version "6.10.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" - integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== + version "6.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.11.0.tgz#c3607cbc8ae392d8a5a536f25b21f8e5f3f87fe9" + integrity sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA== dependencies: - fast-deep-equal "^2.0.1" + fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" @@ -915,6 +1227,11 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -989,7 +1306,7 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -assert@^1.1.1: +assert@^1.1.1, assert@^1.4.0: version "1.5.0" resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== @@ -997,6 +1314,20 @@ assert@^1.1.1: object-assign "^4.1.1" util "0.10.3" +assertion-error-formatter@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error-formatter/-/assertion-error-formatter-2.0.1.tgz#6bbdffaec8e2fa9e2b0eb158bfe353132d7c0a9b" + integrity sha512-cjC3jUCh9spkroKue5PDSKH5RFQ/KNuZJhk3GwHYmB/8qqETxLOmMdLH+ohi/VukNzxDlMvIe7zScvLoOdhb6Q== + dependencies: + diff "^3.0.0" + pad-right "^0.2.2" + repeat-string "^1.6.1" + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -1019,7 +1350,7 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== @@ -1030,9 +1361,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + version "1.9.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" + integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== babel-loader@^8.0.2: version "8.0.6" @@ -1051,6 +1382,19 @@ babel-plugin-dynamic-import-node@^2.3.0: dependencies: object.assign "^4.1.0" +babel-runtime@^6.11.6: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babelify@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/babelify/-/babelify-10.0.0.tgz#fe73b1a22583f06680d8d072e25a1e0d1d1d7fb5" + integrity sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg== + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -1081,6 +1425,11 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +becke-ch--regex--s0-0-v1--base--pl--lib@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/becke-ch--regex--s0-0-v1--base--pl--lib/-/becke-ch--regex--s0-0-v1--base--pl--lib-1.4.0.tgz#429ceebbfa5f7e936e78d73fbdc7da7162b20e20" + integrity sha1-Qpzuu/pffpNueNc/vcfacWKyDiA= + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -1091,15 +1440,32 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + bluebird@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" integrity sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw= -bluebird@^3.5.5: - version "3.5.5" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" - integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== +bluebird@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" + integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== + +bluebird@3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" + integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== + +bluebird@^3.4.1, bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" @@ -1142,6 +1508,25 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= +browser-pack@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.1.0.tgz#c34ba10d0b9ce162b5af227c7131c92c2ecd5774" + integrity sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA== + dependencies: + JSONStream "^1.0.3" + combine-source-map "~0.8.0" + defined "^1.0.0" + safe-buffer "^5.1.1" + through2 "^2.0.0" + umd "^3.0.0" + +browser-resolve@^1.11.0, browser-resolve@^1.7.0: + version "1.11.3" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" + integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== + dependencies: + resolve "1.1.7" + browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -1194,21 +1579,129 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@^0.2.0: +browserify-zlib@^0.2.0, browserify-zlib@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" -browserslist@^4.6.0, browserslist@^4.6.6: - version "4.7.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.0.tgz#9ee89225ffc07db03409f2fee524dc8227458a17" - integrity sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA== +browserify@16.2.3: + version "16.2.3" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.2.3.tgz#7ee6e654ba4f92bce6ab3599c3485b1cc7a0ad0b" + integrity sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ== + dependencies: + JSONStream "^1.0.3" + assert "^1.4.0" + browser-pack "^6.0.1" + browser-resolve "^1.11.0" + browserify-zlib "~0.2.0" + buffer "^5.0.2" + cached-path-relative "^1.0.0" + concat-stream "^1.6.0" + console-browserify "^1.1.0" + constants-browserify "~1.0.0" + crypto-browserify "^3.0.0" + defined "^1.0.0" + deps-sort "^2.0.0" + domain-browser "^1.2.0" + duplexer2 "~0.1.2" + events "^2.0.0" + glob "^7.1.0" + has "^1.0.0" + htmlescape "^1.1.0" + https-browserify "^1.0.0" + inherits "~2.0.1" + insert-module-globals "^7.0.0" + labeled-stream-splicer "^2.0.0" + mkdirp "^0.5.0" + module-deps "^6.0.0" + os-browserify "~0.3.0" + parents "^1.0.1" + path-browserify "~0.0.0" + process "~0.11.0" + punycode "^1.3.2" + querystring-es3 "~0.2.0" + read-only-stream "^2.0.0" + readable-stream "^2.0.2" + resolve "^1.1.4" + shasum "^1.0.0" + shell-quote "^1.6.1" + stream-browserify "^2.0.0" + stream-http "^2.0.0" + string_decoder "^1.1.1" + subarg "^1.0.0" + syntax-error "^1.1.1" + through2 "^2.0.0" + timers-browserify "^1.0.1" + tty-browserify "0.0.1" + url "~0.11.0" + util "~0.10.1" + vm-browserify "^1.0.0" + xtend "^4.0.0" + +browserify@^16.1.0: + version "16.5.0" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.5.0.tgz#a1c2bc0431bec11fd29151941582e3f645ede881" + integrity sha512-6bfI3cl76YLAnCZ75AGu/XPOsqUhRyc0F/olGIJeCxtfxF2HvPKEcmjU9M8oAPxl4uBY1U7Nry33Q6koV3f2iw== + dependencies: + JSONStream "^1.0.3" + assert "^1.4.0" + browser-pack "^6.0.1" + browser-resolve "^1.11.0" + browserify-zlib "~0.2.0" + buffer "^5.0.2" + cached-path-relative "^1.0.0" + concat-stream "^1.6.0" + console-browserify "^1.1.0" + constants-browserify "~1.0.0" + crypto-browserify "^3.0.0" + defined "^1.0.0" + deps-sort "^2.0.0" + domain-browser "^1.2.0" + duplexer2 "~0.1.2" + events "^2.0.0" + glob "^7.1.0" + has "^1.0.0" + htmlescape "^1.1.0" + https-browserify "^1.0.0" + inherits "~2.0.1" + insert-module-globals "^7.0.0" + labeled-stream-splicer "^2.0.0" + mkdirp "^0.5.0" + module-deps "^6.0.0" + os-browserify "~0.3.0" + parents "^1.0.1" + path-browserify "~0.0.0" + process "~0.11.0" + punycode "^1.3.2" + querystring-es3 "~0.2.0" + read-only-stream "^2.0.0" + readable-stream "^2.0.2" + resolve "^1.1.4" + shasum "^1.0.0" + shell-quote "^1.6.1" + stream-browserify "^2.0.0" + stream-http "^3.0.0" + string_decoder "^1.1.1" + subarg "^1.0.0" + syntax-error "^1.1.1" + through2 "^2.0.0" + timers-browserify "^1.0.1" + tty-browserify "0.0.1" + url "~0.11.0" + util "~0.10.1" + vm-browserify "^1.0.0" + xtend "^4.0.0" + +browserslist@^4.6.0, browserslist@^4.8.3, browserslist@^4.8.5: + version "4.8.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.6.tgz#96406f3f5f0755d272e27a66f4163ca821590a7e" + integrity sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg== dependencies: - caniuse-lite "^1.0.30000989" - electron-to-chromium "^1.3.247" - node-releases "^1.1.29" + caniuse-lite "^1.0.30001023" + electron-to-chromium "^1.3.341" + node-releases "^1.1.47" buffer-crc32@~0.2.3: version "0.2.13" @@ -1226,14 +1719,22 @@ buffer-xor@^1.0.3: integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^4.3.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.0.2: + version "5.4.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" + integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -1275,6 +1776,11 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.2.tgz#a13df4196d26776220cc3356eb147a52dba2c6db" + integrity sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg== + cachedir@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-1.3.0.tgz#5e01928bf2d95b5edd94b0942188246740e0dbc4" @@ -1282,16 +1788,28 @@ cachedir@1.3.0: dependencies: os-homedir "^1.0.1" -caniuse-lite@^1.0.30000989: - version "1.0.30000989" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz#b9193e293ccf7e4426c5245134b8f2a56c0ac4b9" - integrity sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw== +caniuse-lite@^1.0.30001023: + version "1.0.30001027" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001027.tgz#283e2ef17d94889cc216a22c6f85303d78ca852d" + integrity sha512-7xvKeErvXZFtUItTHgNtLgS9RJpVnwBlWX8jSo/BO8VsF6deszemZSkJJJA1KOKrXuzZH4WALpAJdq5EyfgMLg== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= +chai@^4.1.2: + version "4.2.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" + integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.0" + type-detect "^4.0.5" + chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1312,12 +1830,17 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + check-more-types@2.24.0: version "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= -chokidar@^2.0.2: +chokidar@^2.0.2, chokidar@^2.0.4, chokidar@^2.1.1: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -1337,9 +1860,9 @@ chokidar@^2.0.2: fsevents "^1.2.7" chownr@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" - integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== + version "1.1.3" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" + integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== chrome-trace-event@^1.0.2: version "1.0.2" @@ -1383,6 +1906,13 @@ cli-spinners@^0.1.2: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" integrity sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw= +cli-table@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" + integrity sha1-9TsFJmqLGguTSz0IIebi3FkUriM= + dependencies: + colors "1.0.3" + cli-truncate@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" @@ -1396,6 +1926,19 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= +coffeeify@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/coffeeify/-/coffeeify-3.0.1.tgz#5e2753000c50bd24c693115f33864248dd11136c" + integrity sha512-Qjnr7UX6ldK1PHV7wCnv7AuCd4q19KTUtwJnu/6JRJB4rfm12zvcXtKdacUoePOKr1I4ka/ydKiwWpNAdsQb0g== + dependencies: + convert-source-map "^1.3.0" + through2 "^2.0.0" + +coffeescript@1.12.7: + version "1.12.7" + resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.12.7.tgz#e57ee4c4867cf7f606bfc4a0f2d550c0981ddd27" + integrity sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA== + collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -1416,6 +1959,26 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +colors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= + +colors@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +combine-source-map@^0.8.0, combine-source-map@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" + integrity sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos= + dependencies: + convert-source-map "~1.1.0" + inline-source-map "~0.6.0" + lodash.memoize "~3.0.3" + source-map "~0.5.3" + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -1428,10 +1991,10 @@ commander@2.15.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== -commander@^2.19.0, commander@^2.20.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" - integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== +commander@^2.19.0, commander@^2.20.0, commander@^2.9.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== common-tags@1.8.0: version "1.8.0" @@ -1453,7 +2016,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@1.6.2, concat-stream@^1.5.0: +concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@~1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -1472,29 +2035,32 @@ config-chain@^1.1.12: proto-list "~1.2.1" console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= - dependencies: - date-now "^0.1.4" + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -constants-browserify@^1.0.0: +constants-browserify@^1.0.0, constants-browserify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -convert-source-map@^1.1.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== +convert-source-map@^1.1.0, convert-source-map@^1.3.0, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== dependencies: safe-buffer "~5.1.1" +convert-source-map@~1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" + integrity sha1-SCnId+n+SbMWHzvzZziI4gRpmGA= + copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -1512,19 +2078,34 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.1.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.2.1.tgz#0cbdbc2e386e8e00d3b85dc81c848effec5b8150" - integrity sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A== +core-js-compat@^3.1.1, core-js-compat@^3.6.2: + version "3.6.4" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.4.tgz#938476569ebb6cda80d339bcf199fae4f16fff17" + integrity sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA== dependencies: - browserslist "^4.6.6" - semver "^6.3.0" + browserslist "^4.8.3" + semver "7.0.0" + +core-js@^2.4.0: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cosmiconfig@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" + integrity sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ== + dependencies: + is-directory "^0.3.1" + js-yaml "^3.9.0" + parse-json "^4.0.0" + require-from-string "^2.0.1" + create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -1567,7 +2148,7 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -crypto-browserify@^3.11.0: +crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== @@ -1584,18 +2165,91 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" +cucumber-expressions@^5.0.13: + version "5.0.18" + resolved "https://registry.yarnpkg.com/cucumber-expressions/-/cucumber-expressions-5.0.18.tgz#6c70779efd3aebc5e9e7853938b1110322429596" + integrity sha1-bHB3nv0668Xp54U5OLERAyJClZY= + dependencies: + becke-ch--regex--s0-0-v1--base--pl--lib "^1.2.0" + +cucumber-expressions@^6.0.1: + version "6.6.2" + resolved "https://registry.yarnpkg.com/cucumber-expressions/-/cucumber-expressions-6.6.2.tgz#d89640eccc72a78380b6c210eae36a64e7462b81" + integrity sha512-WcFSVBiWNLJbIcAAC3t/ACU46vaOKfe1UIF5H3qveoq+Y4XQm9j3YwHurQNufRKBBg8nCnpU7Ttsx7egjS3hwA== + dependencies: + becke-ch--regex--s0-0-v1--base--pl--lib "^1.2.0" + +cucumber-tag-expressions@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/cucumber-tag-expressions/-/cucumber-tag-expressions-1.1.1.tgz#7f5c7b70009bc2b666591bfe64854578bedee85a" + integrity sha1-f1x7cACbwrZmWRv+ZIVFeL7e6Fo= + +cucumber@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/cucumber/-/cucumber-4.2.1.tgz#64cfff6150bbe6b5e94b173470057353d6206719" + integrity sha512-3gQ0Vv4kSHsvXEFC6b1c+TfLRDzWD1/kU7e5vm8Kh8j35b95k6favan9/4ixcBNqd7UsU1T6FYcawC87+DlNKw== + dependencies: + assertion-error-formatter "^2.0.1" + babel-runtime "^6.11.6" + bluebird "^3.4.1" + cli-table "^0.3.1" + colors "^1.1.2" + commander "^2.9.0" + cucumber-expressions "^5.0.13" + cucumber-tag-expressions "^1.1.1" + duration "^0.2.0" + escape-string-regexp "^1.0.5" + figures "2.0.0" + gherkin "^5.0.0" + glob "^7.0.0" + indent-string "^3.1.0" + is-generator "^1.0.2" + is-stream "^1.1.0" + knuth-shuffle-seeded "^1.0.6" + lodash "^4.17.4" + mz "^2.4.0" + progress "^2.0.0" + resolve "^1.3.3" + serialize-error "^2.1.0" + stack-chain "^2.0.0" + stacktrace-js "^2.0.0" + string-argv "0.0.2" + title-case "^2.1.1" + util-arity "^1.0.2" + verror "^1.9.0" + cyclist@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= -cypress@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.4.1.tgz#ca2e4e9864679da686c6a6189603efd409664c30" - integrity sha512-1HBS7t9XXzkt6QHbwfirWYty8vzxNMawGj1yI+Fu6C3/VZJ8UtUngMW6layqwYZzLTZV8tiDpdCNBypn78V4Dg== +cypress-cucumber-preprocessor@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/cypress-cucumber-preprocessor/-/cypress-cucumber-preprocessor-2.0.1.tgz#b6e64041efb4620ca559487152784bc044b35af5" + integrity sha512-i7WjLtv18O6/RoHeVLtfwNZmDL9DgPv4E8+6z5bQ4lqtBSjAKzRNrTnxAKAgUvaLK0TMeUm8GJu4eQ7B4LBqew== + dependencies: + "@cypress/browserify-preprocessor" "^2.1.1" + chai "^4.1.2" + chokidar "^2.0.4" + cosmiconfig "^4.0.0" + cucumber "^4.2.1" + cucumber-expressions "^6.0.1" + cucumber-tag-expressions "^1.1.1" + debug "^3.0.1" + gherkin "^5.1.0" + glob "^7.1.2" + js-string-escape "^1.0.1" + minimist "^1.2.0" + through "^2.3.8" + +cypress@^3.5.0: + version "3.8.3" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.8.3.tgz#e921f5482f1cbe5814891c878f26e704bbffd8f4" + integrity sha512-I9L/d+ilTPPA4vq3NC1OPKmw7jJIpMKNdyfR8t1EXYzYCjyqbc59migOm1YSse/VRbISLJ+QGb5k4Y3bz2lkYw== dependencies: "@cypress/listr-verbose-renderer" "0.4.1" "@cypress/xvfb" "1.2.4" + "@types/sizzle" "2.3.2" arch "2.1.1" bluebird "3.5.0" cachedir "1.3.0" @@ -1604,6 +2258,7 @@ cypress@^3.4.1: commander "2.15.1" common-tags "1.8.0" debug "3.2.6" + eventemitter2 "4.1.2" execa "0.10.0" executable "4.1.1" extract-zip "1.6.7" @@ -1622,9 +2277,23 @@ cypress@^3.4.1: request-progress "3.0.0" supports-color "5.5.0" tmp "0.1.0" + untildify "3.0.3" url "0.11.0" yauzl "2.10.0" +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dash-ast@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-1.0.0.tgz#12029ba5fb2f8aa6f0a861795b23c1b4b6c27d37" + integrity sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA== + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -1637,11 +2306,6 @@ date-fns@^1.27.2: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= - debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -1656,7 +2320,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.1.0, debug@^3.2.6: +debug@3.2.6, debug@^3.0.1, debug@^3.1.0, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -1675,6 +2339,13 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -1709,6 +2380,11 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -1719,10 +2395,20 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +deps-sort@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.1.tgz#9dfdc876d2bcec3386b6829ac52162cda9fa208d" + integrity sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw== + dependencies: + JSONStream "^1.0.3" + shasum-object "^1.0.0" + subarg "^1.0.0" + through2 "^2.0.0" + des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -1732,11 +2418,25 @@ detect-libc@^1.0.2: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +detective@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" + integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg== + dependencies: + acorn-node "^1.6.1" + defined "^1.0.0" + minimist "^1.1.1" + diff@^1.3.2: version "1.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" integrity sha1-fyjS657nsVqX79ic5j3P2qPMur8= +diff@^3.0.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -1754,11 +2454,18 @@ disparity@2.0.0: ansi-styles "^2.0.1" diff "^1.3.2" -domain-browser@^1.1.1: +domain-browser@^1.1.1, domain-browser@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== +duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= + dependencies: + readable-stream "^2.0.2" + duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -1769,6 +2476,14 @@ duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +duration@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/duration/-/duration-0.2.2.tgz#ddf149bc3bc6901150fe9017111d016b3357f529" + integrity sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg== + dependencies: + d "1" + es5-ext "~0.10.46" + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -1787,10 +2502,10 @@ editorconfig@^0.15.3: semver "^5.6.0" sigmund "^1.0.1" -electron-to-chromium@^1.3.247: - version "1.3.258" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.258.tgz#829b03be37424099b91aefb6815e8801bf30b509" - integrity sha512-rkPYrgFU7k/8ngjHYvzOZ44OQQ1GeIRIQnhGv00RkSlQXEnJKsGonQppbEEWHuuxZegpMao+WZmYraWQJQJMMg== +electron-to-chromium@^1.3.341: + version "1.3.348" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.348.tgz#61fa7d43f6c4fd8b046b0b69213cb55b7a4c76a5" + integrity sha512-6O0IInybavGdYtcbI4ryF/9e3Qi8/soi6C68ELRseJuTwQPKq39uGgVVeQHG28t69Sgsky09nXBRhUiFXsZyFQ== elegant-spinner@^1.0.1: version "1.0.1" @@ -1798,9 +2513,9 @@ elegant-spinner@^1.0.1: integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= elliptic@^6.0.0: - version "6.5.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" - integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== + version "6.5.2" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" + integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -1816,19 +2531,19 @@ emojis-list@^2.0.0: integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" - integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== + version "4.1.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" + integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== dependencies: graceful-fs "^4.1.2" - memory-fs "^0.4.0" + memory-fs "^0.5.0" tapable "^1.0.0" errno@^0.1.3, errno@~0.1.7: @@ -1838,6 +2553,46 @@ errno@^0.1.3, errno@~0.1.7: dependencies: prr "~1.0.1" +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" + integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== + dependencies: + stackframe "^1.1.1" + +es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@~0.10.46: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1868,15 +2623,25 @@ estraverse@^4.1.0, estraverse@^4.1.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -esutils@^2.0.2: +esutils@^2.0.0, esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +eventemitter2@4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-4.1.2.tgz#0e1a8477af821a6ef3995b311bf74c23a5247f15" + integrity sha1-DhqEd6+CGm7zmVsxG/dMI6UkfxU= + +events@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/events/-/events-2.1.0.tgz#2a9a1e18e6106e0e812aa9ebd4a819b3c29c0ba5" + integrity sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg== + events@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" + integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" @@ -1924,6 +2689,13 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +ext@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" + integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== + dependencies: + type "^2.0.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -1978,15 +2750,20 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-deep-equal@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" + integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-safe-stringify@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" + integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== fd-slicer@~1.0.1: version "1.0.1" @@ -2007,6 +2784,13 @@ figgy-pudding@^3.5.1: resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== +figures@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -2015,6 +2799,11 @@ figures@^1.7.0: escape-string-regexp "^1.0.5" object-assign "^4.1.0" +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -2109,12 +2898,21 @@ fs-extra@5.0.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" - integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== dependencies: - minipass "^2.2.1" + minipass "^2.6.0" fs-write-stream-atomic@^1.0.8: version "1.0.10" @@ -2132,12 +2930,12 @@ fs.realpath@^1.0.0: integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== + version "1.2.11" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3" + integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw== dependencies: + bindings "^1.5.0" nan "^2.12.1" - node-pre-gyp "^0.12.0" function-bind@^1.1.1: version "1.1.1" @@ -2158,6 +2956,21 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + +get-assigned-identifiers@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" + integrity sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -2182,6 +2995,11 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +gherkin@^5.0.0, gherkin@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/gherkin/-/gherkin-5.1.0.tgz#684bbb03add24eaf7bdf544f58033eb28fb3c6d5" + integrity sha1-aEu7A63STq9731RPWAM+so+zxtU= + glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -2190,10 +3008,10 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob@^7.1.3, glob@^7.1.4: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== +glob@^7.0.0, glob@^7.1.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -2215,9 +3033,9 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.2.2" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" - integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== har-schema@^2.0.0: version "2.0.0" @@ -2245,9 +3063,9 @@ has-flag@^3.0.0: integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== has-unicode@^2.0.0: version "2.0.1" @@ -2285,6 +3103,13 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" +has@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + hash-base@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" @@ -2310,6 +3135,11 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +htmlescape@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" + integrity sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E= + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -2342,9 +3172,9 @@ iferr@^0.1.5: integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= ignore-walk@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.2.tgz#99d83a246c196ea5c93ef9315ad7b0819c35069b" - integrity sha512-EXyErtpHbn75ZTsOADsfx6J/FPo6/5cjev46PXrcTpd8z3BoRkXgYu9/JVqrI7tusjmwCZutGeRJeU0Wo1e4Cw== + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== dependencies: minimatch "^3.0.4" @@ -2360,7 +3190,7 @@ indent-string@^2.1.0: dependencies: repeating "^2.0.0" -indent-string@^3.0.0: +indent-string@^3.0.0, indent-string@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= @@ -2398,7 +3228,30 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== -invariant@^2.2.2: +inline-source-map@~0.6.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" + integrity sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU= + dependencies: + source-map "~0.5.3" + +insert-module-globals@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" + integrity sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw== + dependencies: + JSONStream "^1.0.3" + acorn-node "^1.5.2" + combine-source-map "^0.8.0" + concat-stream "^1.6.1" + is-buffer "^1.1.0" + path-is-absolute "^1.0.1" + process "~0.11.0" + through2 "^2.0.0" + undeclared-identifiers "^1.1.2" + xtend "^4.0.0" + +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -2419,6 +3272,11 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -2426,7 +3284,7 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" -is-buffer@^1.1.5: +is-buffer@^1.1.0, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -2470,6 +3328,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -2488,11 +3351,9 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= - dependencies: - number-is-nan "^1.0.0" + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== is-fullwidth-code-point@^1.0.0: version "1.0.0" @@ -2506,6 +3367,11 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= +is-generator@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-generator/-/is-generator-1.0.3.tgz#c14c21057ed36e328db80347966c693f886389f3" + integrity sha1-wUwhBX7TbjKNuANHlmxpP4hjifM= + is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -2611,10 +3477,10 @@ its-name@1.0.0: resolved "https://registry.yarnpkg.com/its-name/-/its-name-1.0.0.tgz#2065f1883ecb568c65f7112ddbf123401fae4af0" integrity sha1-IGXxiD7LVoxl9xEt2/EjQB+uSvA= -js-beautify@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.0.tgz#9753a13c858d96828658cd18ae3ca0e5783ea672" - integrity sha512-OMwf/tPDpE/BLlYKqZOhqWsd3/z2N3KOlyn1wsCRGFwViE8LOQTcDtathQvHvZc+q+zWmcNAbwKSC+iJoMaH2Q== +js-beautify@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.3.tgz#c73fa10cf69d3dfa52d8ed624f23c64c0a6a94c1" + integrity sha512-wfk/IAWobz1TfApSdivH5PJ0miIHgDoYb1ugSqHcODPmaYu46rYe5FVuIEkhjg8IQiv6rDNPyhsqbsohI/C2vQ== dependencies: config-chain "^1.1.12" editorconfig "^0.15.3" @@ -2627,12 +3493,17 @@ js-levenshtein@^1.1.3: resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== +js-string-escape@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" 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.13.1, js-yaml@^3.9.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -2655,7 +3526,7 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= -json-parse-better-errors@^1.0.2: +json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== @@ -2670,6 +3541,13 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-stable-stringify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" + integrity sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U= + dependencies: + jsonify "~0.0.0" + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -2683,9 +3561,9 @@ json5@^1.0.1: minimist "^1.2.0" json5@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" - integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== + version "2.1.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" + integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== dependencies: minimist "^1.2.0" @@ -2696,6 +3574,16 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -2726,15 +3614,42 @@ kind-of@^5.0.0: integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +knuth-shuffle-seeded@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/knuth-shuffle-seeded/-/knuth-shuffle-seeded-1.0.6.tgz#01f1b65733aa7540ee08d8b0174164d22081e4e1" + integrity sha1-AfG2VzOqdUDuCNiwF0Fk0iCB5OE= + dependencies: + seed-random "~2.2.0" + +labeled-stream-splicer@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz#42a41a16abcd46fd046306cf4f2c3576fffb1c21" + integrity sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw== + dependencies: + inherits "^2.0.1" + stream-splicer "^2.0.0" lazy-ass@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levenary@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" + integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== + dependencies: + leven "^3.1.0" + listr-silent-renderer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" @@ -2808,12 +3723,22 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +lodash.clonedeep@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.memoize@~3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" + integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= + 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@4.17.15, lodash@^4.17.10, lodash@^4.17.13: +lodash@4.17.15, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.4: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -2847,6 +3772,11 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lower-case@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= + lru-cache@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -2896,7 +3826,7 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -memory-fs@^0.4.0, memory-fs@^0.4.1: +memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= @@ -2904,6 +3834,14 @@ memory-fs@^0.4.0, memory-fs@^0.4.1: errno "^0.1.3" readable-stream "^2.0.1" +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -2939,17 +3877,17 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.40.0: - version "1.40.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" - integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== +mime-db@1.43.0: + version "1.43.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" + integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.24" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" - integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== + version "2.1.26" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" + integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== dependencies: - mime-db "1.40.0" + mime-db "1.43.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" @@ -2973,25 +3911,25 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@1.2.0, minimist@^1.2.0: +minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= -minipass@^2.2.1, minipass@^2.3.5: - version "2.5.1" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.5.1.tgz#cf435a9bf9408796ca3a3525a8b851464279c9b8" - integrity sha512-dmpSnLJtNQioZFI5HfQ55Ad0DzzsMAb+HfokwRTNXwEQjepbTkl5mtIlSVxGIkOkxlpX7wIn5ET/oAd9fZ/Y/Q== +minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" minizlib@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.2.tgz#6f0ccc82fa53e1bf2ff145f220d2da9fa6e3a166" - integrity sha512-hR3At21uSrsjjDTWrbu0IMLTpnkpv8IIMFDFaoz43Tmu4LkmAXfH44vNNzpTnf+OAQQCHrb91y/wc2J4x5XgSQ== + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== dependencies: - minipass "^2.2.1" + minipass "^2.9.0" mississippi@^3.0.0: version "3.0.0" @@ -3024,6 +3962,27 @@ mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" +module-deps@^6.0.0: + version "6.2.2" + resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-6.2.2.tgz#d8a15c2265dfc119153c29bb47386987d0ee423b" + integrity sha512-a9y6yDv5u5I4A+IPHTnqFxcaKr4p50/zxTjcQJaX2ws9tN/W6J6YXnEKhqRyPhl494dkcxx951onSKVezmI+3w== + dependencies: + JSONStream "^1.0.3" + browser-resolve "^1.7.0" + cached-path-relative "^1.0.2" + concat-stream "~1.6.0" + defined "^1.0.0" + detective "^5.2.0" + duplexer2 "^0.1.2" + inherits "^2.0.1" + parents "^1.0.0" + readable-stream "^2.0.2" + resolve "^1.4.0" + stream-combiner2 "^1.1.1" + subarg "^1.0.0" + through2 "^2.0.0" + xtend "^4.0.0" + moment@2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" @@ -3051,6 +4010,15 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +mz@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + nan@^2.12.1: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" @@ -3074,9 +4042,9 @@ nanomatch@^1.2.9: to-regex "^3.0.1" needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== + version "2.3.2" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.2.tgz#3342dea100b7160960a450dc8c22160ac712a528" + integrity sha512-DUzITvPVDUy6vczKKYTnWc/pBZ0EnjMJnQ3y+Jo5zfKFimJs7S3HFCxCRZYB9FUZcrzUQr3WsmvZgddMEIZv6w== dependencies: debug "^3.2.6" iconv-lite "^0.4.4" @@ -3087,11 +4055,23 @@ neo-async@^2.5.0, neo-async@^2.6.1: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +no-case@^2.2.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== + dependencies: + lower-case "^1.1.1" + node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -3121,10 +4101,10 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== +node-pre-gyp@*: + version "0.14.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" + integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -3135,14 +4115,14 @@ node-pre-gyp@^0.12.0: rc "^1.2.7" rimraf "^2.6.1" semver "^5.3.0" - tar "^4" + tar "^4.4.2" -node-releases@^1.1.29: - version "1.1.30" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.30.tgz#35eebf129c63baeb6d8ddeda3c35b05abfd37f7f" - integrity sha512-BHcr1g6NeUH12IL+X3Flvs4IOnl1TL0JczUhEZjDE+FXXPQcVCNr8NEPb01zqGxzhTpdyJL5GXemaCW7aw6Khw== +node-releases@^1.1.47: + version "1.1.48" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.48.tgz#7f647f0c453a0495bcd64cbd4778c26035c2f03a" + integrity sha512-Hr8BbmUl1ujAST0K0snItzEA5zkJTQup8VNTKNfT6Zw8vTJkIiagUPNfxHmgDOyfFYNfKAul40sD0UEYTvwebw== dependencies: - semver "^5.3.0" + semver "^6.3.0" nopt@^4.0.1, nopt@~4.0.1: version "4.0.1" @@ -3165,17 +4145,25 @@ normalize-path@^3.0.0: integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" + integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== + dependencies: + npm-normalize-package-bin "^1.0.1" + +npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== npm-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== + version "1.4.8" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" + integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" + npm-normalize-package-bin "^1.0.1" npm-run-path@^2.0.0: version "2.0.2" @@ -3269,7 +4257,7 @@ ora@^0.2.3: cli-spinners "^0.1.2" object-assign "^4.0.1" -os-browserify@^0.3.0: +os-browserify@^0.3.0, os-browserify@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= @@ -3292,15 +4280,22 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +outpipe@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/outpipe/-/outpipe-1.1.1.tgz#50cf8616365e87e031e29a5ec9339a3da4725fa2" + integrity sha1-UM+GFjZeh+Ax4ppeyTOaPaRyX6I= + dependencies: + shell-quote "^1.4.2" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-limit@^2.0.0, p-limit@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== dependencies: p-try "^2.0.0" @@ -3321,10 +4316,17 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +pad-right@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/pad-right/-/pad-right-0.2.2.tgz#6fbc924045d244f2a2a244503060d3bfc6009774" + integrity sha1-b7ySQEXSRPKiokRQMGDTv8YAl3Q= + dependencies: + repeat-string "^1.5.2" + pako@~1.0.5: - version "1.0.10" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" - integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== parallel-transform@^1.1.0: version "1.2.0" @@ -3335,10 +4337,17 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" +parents@^1.0.0, parents@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" + integrity sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E= + dependencies: + path-platform "~0.11.15" + parse-asn1@^5.0.0: - version "5.1.4" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" - integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -3347,12 +4356,20 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@0.0.1: +path-browserify@0.0.1, path-browserify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== @@ -3367,7 +4384,7 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= -path-is-absolute@^1.0.0: +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= @@ -3387,6 +4404,16 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-platform@~0.11.15: + version "0.11.15" + resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" + integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I= + +pathval@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" + integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= + pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -3409,9 +4436,9 @@ performance-now@^2.1.0: integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= picomatch@^2.0.5: - version "2.0.7" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" - integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== + version "2.2.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" + integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== pify@^2.2.0: version "2.3.0" @@ -3445,11 +4472,16 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -process@^0.11.10: +process@^0.11.10, process@~0.11.0: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" @@ -3471,9 +4503,9 @@ pseudomap@^1.0.2: integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24: - version "1.4.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" - integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + version "1.7.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" + integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== public-encrypt@^4.0.0: version "4.0.3" @@ -3517,7 +4549,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4, punycode@^1.4.1: +punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -3532,7 +4564,7 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -querystring-es3@^0.2.0: +querystring-es3@^0.2.0, querystring-es3@~0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= @@ -3577,10 +4609,17 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +read-only-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" + integrity sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A= + dependencies: + readable-stream "^2.0.2" + "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -3590,6 +4629,15 @@ rc@^1.2.7: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.0.6: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.5.0.tgz#465d70e6d1087f6162d079cd0b5db7fbebfd1606" + integrity sha512-gSz026xs2LfxBPudDuI41V1lka8cxg64E66SGe78zJlsUofOg/yqwezdIcdfwik6B4h8LFmWPA9ef9X3FiNFLA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -3611,6 +4659,16 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-runtime@^0.12.0: + version "0.12.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" + integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== + regenerator-transform@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" @@ -3626,12 +4684,7 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp-tree@^0.1.13: - version "0.1.13" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.13.tgz#5b19ab9377edc68bc3679256840bb29afc158d7f" - integrity sha512-hwdV/GQY5F8ReLZWO+W1SRoN5YfpOKY6852+tBFcma72DKBIcHjPRIlIvQN35bCOljuAfP2G2iB0FC/w236mUw== - -regexpu-core@^4.5.4: +regexpu-core@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== @@ -3644,14 +4697,14 @@ regexpu-core@^4.5.4: unicode-match-property-value-ecmascript "^1.1.0" regjsgen@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" - integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== regjsparser@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" - integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== + version "0.6.2" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.2.tgz#fd62c753991467d9d1ffe0a9f67f27a529024b96" + integrity sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q== dependencies: jsesc "~0.5.0" @@ -3665,7 +4718,7 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== -repeat-string@^1.6.1: +repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -3710,15 +4763,25 @@ request@2.88.0: tunnel-agent "^0.6.0" uuid "^3.3.2" +require-from-string@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.3.2: - version "1.12.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= + +resolve@^1.1.4, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.8.1: + version "1.15.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" + integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== dependencies: path-parse "^1.0.6" @@ -3800,7 +4863,17 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +seed-random@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/seed-random/-/seed-random-2.2.0.tgz#2a9b19e250a817099231a5b99a4daf80b7fbed54" + integrity sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ= + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -3810,10 +4883,15 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -serialize-javascript@^1.7.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" - integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== +serialize-error@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" + integrity sha1-ULZ51WNc34Rme9yOWa9OW4HV9go= + +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== set-blocking@~2.0.0: version "2.0.0" @@ -3835,7 +4913,7 @@ setimmediate@^1.0.4: resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= -sha.js@^2.4.0, sha.js@^2.4.8: +sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== @@ -3843,6 +4921,21 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +shasum-object@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shasum-object/-/shasum-object-1.0.0.tgz#0b7b74ff5b66ecf9035475522fa05090ac47e29e" + integrity sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg== + dependencies: + fast-safe-stringify "^2.0.7" + +shasum@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f" + integrity sha1-5wEjENj0F/TetXEhUOVni4euVl8= + dependencies: + json-stable-stringify "~0.0.0" + sha.js "~2.4.4" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -3855,6 +4948,11 @@ shebang-regex@^1.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shell-quote@^1.4.2, shell-quote@^1.6.1: + version "1.7.2" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" + integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== + sigmund@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" @@ -3865,6 +4963,11 @@ signal-exit@^3.0.0: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= + slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" @@ -3930,20 +5033,20 @@ source-list-map@^2.0.0: integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" source-map-support@~0.5.12: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -3953,7 +5056,12 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.5.0, source-map@^0.5.6: +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= + +source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -3997,6 +5105,40 @@ ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" +stack-chain@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-2.0.0.tgz#d73d1172af89565f07438b5bcc086831b6689b2d" + integrity sha512-GGrHXePi305aW7XQweYZZwiRwR7Js3MWoK/EHzzB9ROdc75nCnjSJVi21rdAGxFl+yCx2L2qdfl5y7NO4lTyqg== + +stack-generator@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.5.tgz#fb00e5b4ee97de603e0773ea78ce944d81596c36" + integrity sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q== + dependencies: + stackframe "^1.1.1" + +stackframe@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.1.1.tgz#ffef0a3318b1b60c3b58564989aca5660729ec71" + integrity sha512-0PlYhdKh6AfFxRyK/v+6/k+/mMfyiEBbTM5L94D0ZytQnJ166wuwoTYLHFWGbs2dpA8Rgq763KGWmN1EQEYHRQ== + +stacktrace-gps@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz#7688dc2fc09ffb3a13165ebe0dbcaf41bcf0c69a" + integrity sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg== + dependencies: + source-map "0.5.6" + stackframe "^1.1.1" + +stacktrace-js@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b" + integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg== + dependencies: + error-stack-parser "^2.0.6" + stack-generator "^2.0.5" + stacktrace-gps "^3.0.4" + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -4005,7 +5147,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -stream-browserify@^2.0.1: +stream-browserify@^2.0.0, stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== @@ -4013,6 +5155,14 @@ stream-browserify@^2.0.1: inherits "~2.0.1" readable-stream "^2.0.2" +stream-combiner2@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" + integrity sha1-+02KFCDqNidk4hrUeAOXvry0HL4= + dependencies: + duplexer2 "~0.1.0" + readable-stream "^2.0.2" + stream-each@^1.1.0: version "1.2.3" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" @@ -4021,7 +5171,7 @@ stream-each@^1.1.0: end-of-stream "^1.1.0" stream-shift "^1.0.0" -stream-http@^2.7.2: +stream-http@^2.0.0, stream-http@^2.7.2: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== @@ -4032,16 +5182,39 @@ stream-http@^2.7.2: to-arraybuffer "^1.0.0" xtend "^4.0.0" +stream-http@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.0.tgz#22fb33fe9b4056b4eccf58bd8f400c4b993ffe57" + integrity sha512-cuB6RgO7BqC4FBYzmnvhob5Do3wIdIsXAgGycHJnW+981gHqoYcYz9lqjJrk8WXRddbwPuqPYRl+bag6mYv4lw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^3.0.6" + xtend "^4.0.0" + stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + +stream-splicer@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.1.tgz#0b13b7ee2b5ac7e0609a7463d83899589a363fcd" + integrity sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.2" 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" integrity sha1-Rb8dny19wJvtgfHDB8Qw5ouEz/4= +string-argv@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.0.2.tgz#dac30408690c21f3c3630a3ff3a05877bdcbd736" + integrity sha1-2sMECGkMIfPDYwo/86BYd73L1zY= + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -4059,7 +5232,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string_decoder@^1.0.0: +string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -4104,6 +5277,13 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +subarg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" + integrity sha1-9izxdYHplrSPyWVpn1TAauJouNI= + dependencies: + minimist "^1.1.0" + supports-color@5.5.0, supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -4121,48 +5301,69 @@ symbol-observable@1.0.1: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= +syntax-error@^1.1.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" + integrity sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w== + dependencies: + acorn-node "^1.2.0" + tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar@^4: - version "4.4.10" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" - integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== +tar@^4.4.2: + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== dependencies: chownr "^1.1.1" fs-minipass "^1.2.5" - minipass "^2.3.5" + minipass "^2.8.6" minizlib "^1.2.1" mkdirp "^0.5.0" safe-buffer "^5.1.2" yallist "^3.0.3" -terser-webpack-plugin@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" - integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== +terser-webpack-plugin@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" + integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== dependencies: cacache "^12.0.2" find-cache-dir "^2.1.0" is-wsl "^1.1.0" schema-utils "^1.0.0" - serialize-javascript "^1.7.0" + serialize-javascript "^2.1.2" source-map "^0.6.1" terser "^4.1.2" webpack-sources "^1.4.0" worker-farm "^1.7.0" terser@^4.1.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.1.tgz#09820bcb3398299c4b48d9a86aefc65127d0ed65" - integrity sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg== + version "4.6.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.3.tgz#e33aa42461ced5238d352d2df2a67f21921f8d87" + integrity sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ== dependencies: commander "^2.20.0" source-map "~0.6.1" source-map-support "~0.5.12" +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.0" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" + integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= + dependencies: + any-promise "^1.0.0" + throttleit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" @@ -4176,6 +5377,18 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" +"through@>=2.2.7 <3", through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +timers-browserify@^1.0.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" + integrity sha1-ycWLV1voQHN1y14kYtrO50NZ9B0= + dependencies: + process "~0.11.0" + timers-browserify@^2.0.4: version "2.0.11" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" @@ -4183,6 +5396,14 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +title-case@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa" + integrity sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o= + dependencies: + no-case "^2.2.0" + upper-case "^1.0.3" + tmp@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" @@ -4240,15 +5461,10 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - ts-loader@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.1.0.tgz#999cb0a7644f9c7c6c0901802dce50ceb0a76e5b" - integrity sha512-7JedeOu2rsYHQDEr2fwmMozABwbQTZXEaEMZPSIWG7gpzRefOLJCqwdazcegHtyaxp04PeEgs/b0m08WMpnIzQ== + version "6.2.1" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.1.tgz#67939d5772e8a8c6bdaf6277ca023a4812da02ef" + integrity sha512-Dd9FekWuABGgjE1g0TlQJ+4dFUfYGbYcs52/HQObE0ZmUNjQlmLAS7xXsSzy23AMaMwipsx5sNHvoEpT2CZq1g== dependencies: chalk "^2.3.0" enhanced-resolve "^4.0.0" @@ -4266,6 +5482,11 @@ tty-browserify@0.0.0: resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= +tty-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -4278,15 +5499,46 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" + integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^3.6.3: - version "3.6.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.3.tgz#fea942fabb20f7e1ca7164ff626f1a9f3f70b4da" - integrity sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw== +typescript@3.7.5: + version "3.7.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" + integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== + +umd@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" + integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow== + +undeclared-identifiers@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz#9254c1d37bdac0ac2b52de4b6722792d2a91e30f" + integrity sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw== + dependencies: + acorn-node "^1.3.0" + dash-ast "^1.0.0" + get-assigned-identifiers "^1.2.0" + simple-concat "^1.0.0" + xtend "^4.0.1" unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" @@ -4348,11 +5600,21 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +untildify@3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.3.tgz#1e7b42b140bcfd922b22e70ca1265bfe3634c7c9" + integrity sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA== + upath@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== +upper-case@^1.0.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= + uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" @@ -4365,7 +5627,7 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -url@0.11.0, url@^0.11.0: +url@0.11.0, url@^0.11.0, url@~0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= @@ -4378,7 +5640,12 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@~1.0.1: +util-arity@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/util-arity/-/util-arity-1.1.0.tgz#59d01af1fdb3fede0ac4e632b0ab5f6ce97c9330" + integrity sha1-WdAa8f2z/t4KxOYysKtfbOl8kzA= + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -4397,10 +5664,17 @@ util@^0.11.0: dependencies: inherits "2.0.3" +util@~0.10.1: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== + dependencies: + inherits "2.0.3" + uuid@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" - integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== variable-diff@1.1.0: version "1.1.0" @@ -4410,7 +5684,7 @@ variable-diff@1.1.0: chalk "^1.1.1" object-assign "^4.0.1" -verror@1.10.0: +verror@1.10.0, verror@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= @@ -4419,10 +5693,23 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vm-browserify@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" - integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== +vm-browserify@^1.0.0, vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +watchify@3.11.1: + version "3.11.1" + resolved "https://registry.yarnpkg.com/watchify/-/watchify-3.11.1.tgz#8e4665871fff1ef64c0430d1a2c9d084d9721881" + integrity sha512-WwnUClyFNRMB2NIiHgJU9RQPQNqVeFk7OmZaWf5dC5EnNa0Mgr7imBydbaJ7tGTuPM2hz1Cb4uiBvK9NVxMfog== + dependencies: + anymatch "^2.0.0" + browserify "^16.1.0" + chokidar "^2.1.1" + defined "^1.0.0" + outpipe "^1.1.0" + through2 "^2.0.0" + xtend "^4.0.0" watchpack@^1.6.0: version "1.6.0" @@ -4442,9 +5729,9 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1: source-map "~0.6.1" webpack@^4.40.2: - version "4.40.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.40.2.tgz#d21433d250f900bf0facbabe8f50d585b2dc30a7" - integrity sha512-5nIvteTDCUws2DVvP9Qe+JPla7kWPPIDFZv55To7IycHWZ+Z5qBdaBYPyuXWdhggTufZkQwfIK+5rKQTVovm2A== + version "4.41.5" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.5.tgz#3210f1886bce5310e62bb97204d18c263341b77c" + integrity sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" @@ -4466,7 +5753,7 @@ webpack@^4.40.2: node-libs-browser "^2.2.1" schema-utils "^1.0.0" tapable "^1.1.3" - terser-webpack-plugin "^1.4.1" + terser-webpack-plugin "^1.4.3" watchpack "^1.6.0" webpack-sources "^1.4.1" @@ -4496,7 +5783,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -xtend@^4.0.0, xtend@~4.0.1: +xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== @@ -4512,9 +5799,9 @@ yallist@^2.1.2: integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yauzl@2.10.0: version "2.10.0" diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index 723da7cef6a77..31ef0bef18a85 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -12,7 +12,7 @@ "exclude": [ "test/**/*", "legacy/plugins/siem/cypress/**/*", - "legacy/plugins/apm/cypress/**/*", + "legacy/plugins/apm/e2e/cypress/**/*", "**/typespec_tests.ts" ], "compilerOptions": { From 07fec2f7251e6b2fe0ed30ce9d08f1133416806e Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Wed, 26 Feb 2020 14:17:59 -0500 Subject: [PATCH 15/64] Documentation for numeral pattern formatting (#57616) * Documentation for Elastic Numeral formatting * Tweaks from feedback * Updates from feedback * Fix and update examples * Add TODOs * Fix typo Co-authored-by: Elastic Machine --- .../canvas/canvas-function-reference.asciidoc | 6 +- docs/management/advanced-options.asciidoc | 10 +- docs/management/managing-fields.asciidoc | 6 +- docs/management/numeral.asciidoc | 184 ++++++++++++++++++ docs/user/management.asciidoc | 2 + package.json | 2 +- .../legacy/plugins/canvas/i18n/constants.ts | 2 +- .../i18n/functions/dict/formatnumber.ts | 8 +- .../canvas/i18n/functions/dict/metric.ts | 5 +- .../canvas/public/lib/documentation_links.ts | 3 + x-pack/package.json | 2 +- .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - yarn.lock | 13 +- 14 files changed, 212 insertions(+), 37 deletions(-) create mode 100644 docs/management/numeral.asciidoc diff --git a/docs/canvas/canvas-function-reference.asciidoc b/docs/canvas/canvas-function-reference.asciidoc index 330cc63d10548..85e9d22490497 100644 --- a/docs/canvas/canvas-function-reference.asciidoc +++ b/docs/canvas/canvas-function-reference.asciidoc @@ -1244,7 +1244,7 @@ Alias: `format` [[formatnumber_fn]] === `formatnumber` -Formats a number into a formatted number string using NumeralJS. For more information, see http://numeraljs.com/#format. +Formats a number into a formatted number string using the <>. *Expression syntax* [source,js] @@ -1276,7 +1276,7 @@ The `formatnumber` subexpression receives the same `context` as the `progress` f Alias: `format` |`string` -|A NumeralJS format string. For example, `"0.0a"` or `"0%"`. See http://numeraljs.com/#format. +|A <> string. For example, `"0.0a"` or `"0%"`. |=== *Returns:* `string` @@ -1675,7 +1675,7 @@ Default: `${font size=48 family="'Open Sans', Helvetica, Arial, sans-serif" colo Alias: `format` |`string` -|A NumeralJS format string. For example, `"0.0a"` or `"0%"`. See http://numeraljs.com/#format. +|A <> string. For example, `"0.0a"` or `"0%"`. |=== *Returns:* `render` diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 9d4052bbd0156..c698e2db86ddb 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -51,13 +51,13 @@ adapt to the interval between measurements. Keys are http://en.wikipedia.org/wik `fields:popularLimit`:: The top N most popular fields to show. `filterEditor:suggestValues`:: Set this property to `false` to prevent the filter editor from suggesting values for fields. `filters:pinnedByDefault`:: Set this property to `true` to make filters have a global state (be pinned) by default. -`format:bytes:defaultPattern`:: The default http://numeraljs.com/[numeral format] for the "bytes" format. -`format:currency:defaultPattern`:: The default http://numeraljs.com/[numeral format] for the "currency" format. +`format:bytes:defaultPattern`:: The default <> format for the "bytes" format. +`format:currency:defaultPattern`:: The default <> format for the "currency" format. `format:defaultTypeMap`:: A map of the default format name for each field type. Field types that are not explicitly mentioned use "\_default_". -`format:number:defaultLocale`:: The http://numeraljs.com/[numeral language] locale. -`format:number:defaultPattern`:: The default http://numeraljs.com/[numeral format] for the "number" format. -`format:percent:defaultPattern`:: The default http://numeraljs.com/[numeral format] for the "percent" format. +`format:number:defaultLocale`:: The <> locale. +`format:number:defaultPattern`:: The <> for the "number" format. +`format:percent:defaultPattern`:: The <> for the "percent" format. `histogram:barTarget`:: When date histograms use the `auto` interval, Kibana attempts to generate this number of bars. `histogram:maxBars`:: Date histograms are not generated with more bars than the value of this property, scaling values when necessary. diff --git a/docs/management/managing-fields.asciidoc b/docs/management/managing-fields.asciidoc index f66976b3715d1..b54f4fe5194ad 100644 --- a/docs/management/managing-fields.asciidoc +++ b/docs/management/managing-fields.asciidoc @@ -92,6 +92,9 @@ include::field-formatters/string-formatter.asciidoc[] Numeric fields support the `Url`, `Bytes`, `Duration`, `Number`, `Percentage`, `String`, and `Color` formatters. +The `Bytes`, `Number`, and `Percentage` formatters enable you to choose the display formats of numbers in this field using +the <> syntax that Kibana maintains. + include::field-formatters/url-formatter.asciidoc[] include::field-formatters/string-formatter.asciidoc[] @@ -100,9 +103,6 @@ include::field-formatters/duration-formatter.asciidoc[] include::field-formatters/color-formatter.asciidoc[] -The `Bytes`, `Number`, and `Percentage` formatters enable you to choose the display formats of numbers in this field using -the https://adamwdraper.github.io/Numeral-js/[numeral.js] standard format definitions. - [[scripted-fields]] === Scripted Fields diff --git a/docs/management/numeral.asciidoc b/docs/management/numeral.asciidoc new file mode 100644 index 0000000000000..861277fd18478 --- /dev/null +++ b/docs/management/numeral.asciidoc @@ -0,0 +1,184 @@ +[[numeral]] +== Numeral Formatting + +Numeral formatting in {kib} is done through a pattern-based syntax. +These patterns express common number formats in a concise way, similar +to date formatting. While these patterns are originally based on Numeral.js, +they are now maintained by {kib}. + +Numeral formatting patterns are used in multiple places in {kib}, including: + +* <> +* <> +* <> +* <> + +The simplest pattern format is `0`, and the default {kib} pattern is `0,0.[000]`. +The numeral pattern syntax expresses: + +Number of decimal places:: The `.` character turns on the option to show decimal +places using a locale-specific decimal separator, most often `.` or `,`. +To add trailing zeroes such as `5.00`, use a pattern like `0.00`. +To have optional zeroes, use the `[]` characters. Examples below. +Thousands separator:: The thousands separator `,` turns on the option to group +thousands using a locale-specific separator. The separator is most often `,` or `.`, +and sometimes ` `. +Accounting notation:: Putting parentheses around your format like `(0.00)` will use accounting notation to show negative numbers. + +The display of these patterns is affected by the <> `format:number:defaultLocale`. +The default locale is `en`, but some examples will specify that they are using an alternate locale. + +Most basic examples: + +|=== +| **Input** | **Pattern** | **Locale** | **Output** +| 10000.23 | 0,0 | en (English) | 10,000 +| 10000.23 | 0.0 | en (English) | 10000.2 +| 10000.23 | 0,0.0 | fr (French) | 10 000,2 +| 10000.23 | 0,0.000 | fr (French) | 10 000,230 +| 10000.23 | 0,0[.]0 | en (English) | 10,000.2 +| 10000.23 | 0.00[0] | en (English) | 10,000.23 +| -10000.23 | (0) | en (English) | (10000) +|=== + +[float] +=== Percentages + +By adding the `%` symbol to any of the previous patterns, the value +is multiplied by 100 and the `%` symbol is added in the place indicated. + +The default percentage formatter in {kib} is `0,0.[000]%`, which shows +up to three decimal places. + +|=== +| **Input** | **Pattern** | **Locale** | **Output** +| 0.43 | 0,0.[000]% | en (English) | 43.00% +| 0.43 | 0,0.[000]% | fr (French) | 43,00% +| 1 | 0% | en (English) | 100% +| -0.43 | 0 % | en (English) | -43 % +|=== + +[float] +=== Bytes and bits + +The bytes and bits formatters will shorten the input by adding a suffix like `GB` or `TB`. Bytes and bits formatters include the following suffixes: + +`b`:: Bytes with binary values and suffixes. 1024 = `1KB` +`bb`:: Bytes with binary values and binary suffixes. 1024 = `1KiB` +`bd`:: Bytes with decimal values and suffixes. 1000 = `1kB` +`bitb`:: Bits with binary values and suffixes. 1024 = `1Kibit` +`bitd`:: Bits with decimal values and suffixes. 1000 = `1kbit` + +Suffixes are not localized with this formatter. + +|=== +| **Input** | **Pattern** | **Locale** | **Output** +| 2000 | 0.00b | en (English) | 1.95KB +| 2000 | 0.00bb | en (English) | 1.95KiB +| 2000 | 0.00bd | en (English) | 2.00kB +| 3153654400000 | 0.00bd | en (English) | 3.15GB +| 2000 | 0.00bitb | en (English) | 1.95Kibit +| 2000 | 0.00bitd | en (English) | 2.00kbit +|=== + +[float] +=== Currency + +Currency formatting is limited in {kib} due to the limitations of the pattern +syntax. To enable currency formatting, use the symbol `$` in the pattern syntax. +The number formatting locale will affect the result. + +|=== +| **Input** | **Pattern** | **Locale** | **Output** +| 1000.234 | $0,0.00 | en (English) | $1,000.23 +| 1000.234 | $0,0.00 | fr (French) | €1 000,23 +| 1000.234 | $0,0.00 | chs (Simplified Chinese) | ¥1,000.23 +|=== + +[float] +=== Duration formatting + +Converts a value in seconds to display hours, minutes, and seconds. + +|=== +| **Input** | **Pattern** | **Output** +| 25 | 00:00:00 | 0:00:25 +| 25 | 00:00 | 0:00:25 +| 238 | 00:00:00 | 0:03:58 +| 63846 | 00:00:00 | 17:44:06 +| -1 | 00:00:00 | -0:00:01 +|=== + +[float] +=== Displaying abbreviated numbers + +The `a` pattern will look for the shortest abbreviation for your +number, and use a locale-specific display for it. The abbreviations +`aK`, `aM`, `aB`, and `aT` can indicate that the number should be +abbreviated to a specific order of magnitude. + +|=== +| **Input** | **Pattern** | **Locale** | **Output** +| 2000000000 | 0.00a | en (English) | 2.00b +| 2000000000 | 0.00a | ja (Japanese) | 2.00十億 +| -5444333222111 | 0,0 aK | en (English) | -5,444,333,222 k +| -5444333222111 | 0,0 aM | en (English) | -5,444,333 m +| -5444333222111 | 0,0 aB | en (English) | -5,444 b +| -5444333222111 | 0,0 aT | en (English) | -5 t +|=== + +[float] +=== Ordinal numbers + +The `o` pattern will display a locale-specific positional value like `1st` or `2nd`. +This pattern has limited support for localization, especially in languages +with multiple forms, such as German. + +|=== +| **Input** | **Pattern** | **Locale** | **Output** +| 3 | 0o | en (English) | 3rd +| 34 | 0o | en (English) | 34th +| 3 | 0o | es (Spanish) | 2er +| 3 | 0o | ru (Russian) | 3. +|=== + +[float] +=== Complete number pattern reference + +These number formats, combined with the patterns described above, +produce the complete set of options for numeral formatting. +The output here is all for the `en` locale. + +|=== +| **Input** | **Pattern** | **Output** +| 10000 | 0,0.0000 | 10,000.0000 +| 10000.23 | 0,0 | 10,000 +| -10000 | 0,0.0 | -10,000.0 +| 10000.1234 | 0.000 | 10000.123 +| 10000 | 0[.]00 | 10000 +| 10000.1 | 0[.]00 | 10000.10 +| 10000.123 | 0[.]00 | 10000.12 +| 10000.456 | 0[.]00 | 10000.46 +| 10000.001 | 0[.]00 | 10000 +| 10000.45 | 0[.]00[0] | 10000.45 +| 10000.456 | 0[.]00[0] | 10000.456 +| -10000 | (0,0.0000) | (10,000.0000) +| -12300 | +0,0.0000 | -12,300.0000 +| 1230 | +0,0 | +1,230 +| 100.78 | 0 | 101 +| 100.28 | 0 | 100 +| 1.932 | 0.0 | 1.9 +| 1.9687 | 0 | 2 +| 1.9687 | 0.0 | 2.0 +| -0.23 | .00 | -.23 +| -0.23 | (.00) | (.23) +| 0.23 | 0.00000 | 0.23000 +| 0.67 | 0.0[0000] | 0.67 +| 1.005 | 0.00 | 1.01 +| 1e35 | 000 | 1e+35 +| -1e35 | 000 | -1e+35 +| 1e-27 | 000 | 1e-27 +| -1e-27 | 000 | -1e-27 +|=== + + diff --git a/docs/user/management.asciidoc b/docs/user/management.asciidoc index 1c55ffc73ca72..34a3790529ca3 100644 --- a/docs/user/management.asciidoc +++ b/docs/user/management.asciidoc @@ -129,6 +129,8 @@ include::{kib-repo-dir}/management/managing-fields.asciidoc[] include::{kib-repo-dir}/management/managing-licenses.asciidoc[] +include::{kib-repo-dir}/management/numeral.asciidoc[] + include::{kib-repo-dir}/management/managing-remote-clusters.asciidoc[] include::{kib-repo-dir}/management/rollups/create_and_manage_rollups.asciidoc[] diff --git a/package.json b/package.json index c3fe290e7934f..0f04a2fba3b65 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,7 @@ "@elastic/eui": "19.0.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", - "@elastic/numeral": "2.3.5", + "@elastic/numeral": "2.4.0", "@elastic/request-crypto": "^1.0.2", "@elastic/ui-ace": "0.2.3", "@hapi/wreck": "^15.0.1", diff --git a/x-pack/legacy/plugins/canvas/i18n/constants.ts b/x-pack/legacy/plugins/canvas/i18n/constants.ts index 8aee6ca148681..4cb05b0426fa1 100644 --- a/x-pack/legacy/plugins/canvas/i18n/constants.ts +++ b/x-pack/legacy/plugins/canvas/i18n/constants.ts @@ -28,7 +28,7 @@ export const LUCENE = 'Lucene'; export const MARKDOWN = 'Markdown'; export const MOMENTJS = 'MomentJS'; export const MOMENTJS_TIMEZONE_URL = 'https://momentjs.com/timezone/'; -export const NUMERALJS = 'NumeralJS'; +export const NUMERALJS = 'Numeral pattern'; export const PDF = 'PDF'; export const POST = 'POST'; export const RGB = 'RGB'; diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/formatnumber.ts b/x-pack/legacy/plugins/canvas/i18n/functions/dict/formatnumber.ts index df306eb1c04ed..f3e8a8858fc36 100644 --- a/x-pack/legacy/plugins/canvas/i18n/functions/dict/formatnumber.ts +++ b/x-pack/legacy/plugins/canvas/i18n/functions/dict/formatnumber.ts @@ -12,21 +12,19 @@ import { NUMERALJS } from '../../constants'; export const help: FunctionHelp> = { help: i18n.translate('xpack.canvas.functions.formatnumberHelpText', { - defaultMessage: 'Formats a number into a formatted number string using {NUMERALJS}. See {url}.', + defaultMessage: 'Formats a number into a formatted number string using {NUMERALJS}.', values: { NUMERALJS, - url: 'http://numeraljs.com/#format', }, }), args: { + // TODO: Find a way to generate the docs URL here format: i18n.translate('xpack.canvas.functions.formatnumber.args.formatHelpText', { - defaultMessage: - 'A {NUMERALJS} format string. For example, {example1} or {example2}. See {url}.', + defaultMessage: 'A {NUMERALJS} format string. For example, {example1} or {example2}.', values: { example1: `"0.0a"`, example2: `"0%"`, NUMERALJS, - url: 'http://numeraljs.com/#format', }, }), }, diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/metric.ts b/x-pack/legacy/plugins/canvas/i18n/functions/dict/metric.ts index 8fa98667212a5..8258226e5dfc3 100644 --- a/x-pack/legacy/plugins/canvas/i18n/functions/dict/metric.ts +++ b/x-pack/legacy/plugins/canvas/i18n/functions/dict/metric.ts @@ -36,14 +36,13 @@ export const help: FunctionHelp> = { FONT_WEIGHT, }, }), + // TODO: Find a way to generate the docs URL here metricFormat: i18n.translate('xpack.canvas.functions.metric.args.metricFormatHelpText', { - defaultMessage: - 'A {NUMERALJS} format string. For example, {example1} or {example2}. See {url}.', + defaultMessage: 'A {NUMERALJS} format string. For example, {example1} or {example2}.', values: { example1: `"0.0a"`, example2: `"0%"`, NUMERALJS, - url: 'http://numeraljs.com/#format', }, }), }, diff --git a/x-pack/legacy/plugins/canvas/public/lib/documentation_links.ts b/x-pack/legacy/plugins/canvas/public/lib/documentation_links.ts index a43653f420ce0..40e09ee39d714 100644 --- a/x-pack/legacy/plugins/canvas/public/lib/documentation_links.ts +++ b/x-pack/legacy/plugins/canvas/public/lib/documentation_links.ts @@ -10,4 +10,7 @@ export const getDocumentationLinks = () => ({ canvas: `${getCoreStart().docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${ getCoreStart().docLinks.DOC_LINK_VERSION }/canvas.html`, + numeral: `${getCoreStart().docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${ + getCoreStart().docLinks.DOC_LINK_VERSION + }/guide/numeral.html`, }); diff --git a/x-pack/package.json b/x-pack/package.json index b8fe0326903b6..96e06dd71b3fe 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -183,7 +183,7 @@ "@elastic/filesaver": "1.1.2", "@elastic/maki": "6.1.0", "@elastic/node-crypto": "^1.0.0", - "@elastic/numeral": "2.3.3", + "@elastic/numeral": "2.4.0", "@kbn/babel-preset": "1.0.0", "@kbn/config-schema": "1.0.0", "@kbn/i18n": "1.0.0", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 3c7d0ce47acb7..b99a54160bb65 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4586,8 +4586,6 @@ "xpack.canvas.functions.filtersHelpText": "ワークパッドのエレメントフィルターを他 (通常データソース) で使用できるように集約します。", "xpack.canvas.functions.formatdate.args.formatHelpText": "{MOMENTJS} フォーマットです。例: {example}。{url} を参照。", "xpack.canvas.functions.formatdateHelpText": "{MOMENTJS} を使って {ISO8601} 日付文字列、または新世紀からのミリ秒での日付をフォーマットします。{url} を参照。", - "xpack.canvas.functions.formatnumber.args.formatHelpText": "{NUMERALJS} 文字列のフォーマットです。例: {example1} または {example2}。{url} を参照。", - "xpack.canvas.functions.formatnumberHelpText": "{NUMERALJS} を使って数字をフォーマットされた数字文字列にフォーマットします。{url} を参照。", "xpack.canvas.functions.getCell.args.columnHelpText": "値を取得する元の列の名前です。この値は入力されていないと、初めの列から取得されます。", "xpack.canvas.functions.getCell.args.rowHelpText": "行番号で、0 から開始します。", "xpack.canvas.functions.getCell.columnNotFoundErrorMessage": "列が見つかりません: 「{column}」", @@ -4633,7 +4631,6 @@ "xpack.canvas.functions.metric.args.labelFontHelpText": "ラベルの {CSS} フォントプロパティです。例: {FONT_FAMILY} または {FONT_WEIGHT}。", "xpack.canvas.functions.metric.args.labelHelpText": "メトリックを説明するテキストです。", "xpack.canvas.functions.metric.args.metricFontHelpText": "メトリックの {CSS} フォントプロパティです。例: {FONT_FAMILY} または {FONT_WEIGHT}。", - "xpack.canvas.functions.metric.args.metricFormatHelpText": "{NUMERALJS} 文字列のフォーマットです。例: {example1} または {example2}。{url} を参照。", "xpack.canvas.functions.metricHelpText": "ラベルの上に数字を表示します。", "xpack.canvas.functions.neq.args.valueHelpText": "{CONTEXT} と比較される値です。", "xpack.canvas.functions.neqHelpText": "{CONTEXT} が引数と等しくないかを戻します。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index b262be626aa53..32f648826da84 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4587,8 +4587,6 @@ "xpack.canvas.functions.filtersHelpText": "聚合 Workpad 的元素筛选以用于他处,通常用于数据源。", "xpack.canvas.functions.formatdate.args.formatHelpText": "{MOMENTJS} 格式。例如:{example}。请参见 {url}。", "xpack.canvas.functions.formatdateHelpText": "使用 {MOMENTJS} 格式化 {ISO8601} 日期字符串或自 Epoch 起以毫秒表示的日期。请参见 {url}。", - "xpack.canvas.functions.formatnumber.args.formatHelpText": "{NUMERALJS} 格式字符串。例如 {example1} 或 {example2}。请参见 {url}。", - "xpack.canvas.functions.formatnumberHelpText": "使用 {NUMERALJS} 将数字格式化为带格式数字字符串。请参见 {url}。", "xpack.canvas.functions.getCell.args.columnHelpText": "从其中提取值的列的名称。如果未提供,将从第一列检索值。", "xpack.canvas.functions.getCell.args.rowHelpText": "行编号,从 0 开始。", "xpack.canvas.functions.getCell.columnNotFoundErrorMessage": "找不到列:“{column}”", @@ -4634,7 +4632,6 @@ "xpack.canvas.functions.metric.args.labelFontHelpText": "标签的 {CSS} 字体属性。例如 {FONT_FAMILY} 或 {FONT_WEIGHT}。", "xpack.canvas.functions.metric.args.labelHelpText": "描述指标的文本。", "xpack.canvas.functions.metric.args.metricFontHelpText": "指标的 {CSS} 字体属性。例如 {FONT_FAMILY} 或 {FONT_WEIGHT}。", - "xpack.canvas.functions.metric.args.metricFormatHelpText": "{NUMERALJS} 格式字符串。例如 {example1} 或 {example2}。请参见 {url}。", "xpack.canvas.functions.metricHelpText": "在标签上显示数字。", "xpack.canvas.functions.neq.args.valueHelpText": "与 {CONTEXT} 比较的值。", "xpack.canvas.functions.neqHelpText": "返回 {CONTEXT} 是否不等于参数。", diff --git a/yarn.lock b/yarn.lock index 7906f363813b8..7f38495c20f4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2037,15 +2037,10 @@ resolved "https://registry.yarnpkg.com/@elastic/node-crypto/-/node-crypto-1.0.0.tgz#4d325df333fe1319556bb4d54214098ada1171d4" integrity sha512-bbjbEyILPRTRt0xnda18OttLtlkJBPuXx3CjISUSn9jhWqHoFMzfOaZ73D5jxZE2SaFZUrJYfPpqXP6qqPufAQ== -"@elastic/numeral@2.3.3": - version "2.3.3" - resolved "https://registry.yarnpkg.com/@elastic/numeral/-/numeral-2.3.3.tgz#94d38a35bd315efa7a6918b22695128fc40a885e" - integrity sha512-0OyB9oztlYIq8F1LHjcNf+T089PKfYw78tgUY+q2dtox/jmb4xzFKtI9kv1hwAt5tcgBUTtUMK9kszpSh1UZaQ== - -"@elastic/numeral@2.3.5": - version "2.3.5" - resolved "https://registry.yarnpkg.com/@elastic/numeral/-/numeral-2.3.5.tgz#fcaeac57ddc55cd4b7f0b9c7e070c242dd5d0600" - integrity sha512-lJVZHPuI2csrfwDIEdKedFqNIF+5YsyqvX2soAqhu49iKOd9n7tifLRn30vP6D7oKd+6HsiGfPzT0nzdJWsexQ== +"@elastic/numeral@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@elastic/numeral/-/numeral-2.4.0.tgz#883197b7f4bf3c2dd994f53b274769ddfa2bf79a" + integrity sha512-uGBKGCNghTgUZPHClji/00v+AKt5nidPTGOIbcT+lbTPVxNB6QPpPLGWtXyrg3QZAxobPM/LAZB1mAqtJeq44Q== "@elastic/request-crypto@^1.0.2": version "1.0.2" From 68624da3d57abf191ab1a52b004fbd8bef6fc38f Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 26 Feb 2020 14:34:44 -0500 Subject: [PATCH 16/64] [Maps] Add XYZTMSSource and TileLayer unit test suites (#58567) --- .../legacy/plugins/maps/common/constants.ts | 2 +- .../plugins/maps/common/descriptor_types.d.ts | 7 ++- .../plugins/maps/public/layers/layer.d.ts | 21 +++++++ .../maps/public/layers/sources/source.d.ts | 19 +++++++ .../public/layers/sources/tms_source.d.ts | 15 +++++ .../public/layers/sources/xyz_tms_source.d.ts | 11 ++++ .../public/layers/sources/xyz_tms_source.js | 3 +- .../layers/sources/xyz_tms_source.test.ts | 30 ++++++++++ .../maps/public/layers/tile_layer.d.ts | 18 ++++++ .../maps/public/layers/tile_layer.test.ts | 55 +++++++++++++++++++ 10 files changed, 177 insertions(+), 4 deletions(-) create mode 100644 x-pack/legacy/plugins/maps/public/layers/layer.d.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/sources/source.d.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/sources/tms_source.d.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.d.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.test.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/tile_layer.d.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/tile_layer.test.ts diff --git a/x-pack/legacy/plugins/maps/common/constants.ts b/x-pack/legacy/plugins/maps/common/constants.ts index 542abfb004d0d..0e93fd6593710 100644 --- a/x-pack/legacy/plugins/maps/common/constants.ts +++ b/x-pack/legacy/plugins/maps/common/constants.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; - export const EMS_CATALOGUE_PATH = 'ems/catalogue'; export const EMS_FILES_CATALOGUE_PATH = 'ems/files'; @@ -54,6 +53,7 @@ export const EMS_FILE = 'EMS_FILE'; export const ES_GEO_GRID = 'ES_GEO_GRID'; export const ES_SEARCH = 'ES_SEARCH'; export const ES_PEW_PEW = 'ES_PEW_PEW'; +export const EMS_XYZ = 'EMS_XYZ'; // identifies a custom TMS source. Name is a little unfortunate. export const FIELD_ORIGIN = { SOURCE: 'source', diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts index 05123c9c86b63..c024721dfb870 100644 --- a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts @@ -4,14 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IFieldType } from '../../../../../src/plugins/data/common/index_patterns/fields'; - export interface ISourceDescriptor { id: string; type: string; } +export interface IXYZTMSSourceDescriptor extends ISourceDescriptor { + urlTemplate: string; +} + export interface ILayerDescriptor { sourceDescriptor: ISourceDescriptor; id: string; + label?: string; } diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/layer.d.ts new file mode 100644 index 0000000000000..ed7dcb062d8c4 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/layer.d.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { ILayerDescriptor } from '../../common/descriptor_types'; +import { ISource } from './sources/source'; + +export interface ILayer { + getDisplayName(): Promise; +} + +export interface ILayerArguments { + layerDescriptor: ILayerDescriptor; + source: ISource; +} + +export class AbstractLayer implements ILayer { + constructor(layerArguments: ILayerArguments); + getDisplayName(): Promise; +} diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/source.d.ts new file mode 100644 index 0000000000000..372981de42597 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/sources/source.d.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ISourceDescriptor } from '../../../common/descriptor_types'; +import { ILayer } from '../layer'; + +export interface ISource { + createDefaultLayer(): ILayer; + getDisplayName(): Promise; +} + +export class AbstractSource implements ISource { + constructor(sourceDescriptor: ISourceDescriptor, inspectorAdapters: object); + createDefaultLayer(): ILayer; + getDisplayName(): Promise; +} diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/tms_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/tms_source.d.ts new file mode 100644 index 0000000000000..90b6f28e050fd --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/sources/tms_source.d.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { AbstractSource, ISource } from './source'; + +export interface ITMSSource extends ISource { + getUrlTemplate(): Promise; +} + +export class AbstractTMSSource extends AbstractSource implements ITMSSource { + getUrlTemplate(): Promise; +} diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.d.ts new file mode 100644 index 0000000000000..1150c39b79db5 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.d.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 { AbstractTMSSource } from './tms_source'; +import { IXYZTMSSourceDescriptor } from '../../../common/descriptor_types'; + +export class XYZTMSSource extends AbstractTMSSource { + constructor(sourceDescriptor: IXYZTMSSourceDescriptor, inspectorAdapters: unknown); +} diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.js index a4d331f48beae..354883372e244 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.js @@ -12,9 +12,10 @@ import { TileLayer } from '../tile_layer'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel, getUrlLabel } from '../../../common/i18n_getters'; import _ from 'lodash'; +import { EMS_XYZ } from '../../../common/constants'; export class XYZTMSSource extends AbstractTMSSource { - static type = 'EMS_XYZ'; + static type = EMS_XYZ; static title = i18n.translate('xpack.maps.source.ems_xyzTitle', { defaultMessage: 'Tile Map Service', }); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.test.ts b/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.test.ts new file mode 100644 index 0000000000000..5de85adde158f --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.test.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { XYZTMSSource } from './xyz_tms_source'; +import { ILayer } from '../layer'; +import { TileLayer } from '../tile_layer'; +import { EMS_XYZ } from '../../../common/constants'; +import { IXYZTMSSourceDescriptor } from '../../../common/descriptor_types'; + +const descriptor: IXYZTMSSourceDescriptor = { + type: EMS_XYZ, + urlTemplate: 'https://example.com/{x}/{y}/{z}.png', + id: 'foobar', +}; +describe('xyz Tilemap Source', () => { + it('should create a tile-layer', () => { + const source = new XYZTMSSource(descriptor, null); + const layer: ILayer = source.createDefaultLayer(); + expect(layer instanceof TileLayer).toEqual(true); + }); + + it('should echo url template for url template', async () => { + const source = new XYZTMSSource(descriptor, null); + const template = await source.getUrlTemplate(); + expect(template).toEqual(descriptor.urlTemplate); + }); +}); diff --git a/x-pack/legacy/plugins/maps/public/layers/tile_layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/tile_layer.d.ts new file mode 100644 index 0000000000000..fdb37a8af805f --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/tile_layer.d.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { AbstractLayer, ILayerArguments } from './layer'; +import { ITMSSource } from './sources/tms_source'; +import { ILayerDescriptor } from '../../common/descriptor_types'; + +interface ITileLayerArguments extends ILayerArguments { + source: ITMSSource; + layerDescriptor: ILayerDescriptor; +} + +export class TileLayer extends AbstractLayer { + constructor(args: ITileLayerArguments); +} diff --git a/x-pack/legacy/plugins/maps/public/layers/tile_layer.test.ts b/x-pack/legacy/plugins/maps/public/layers/tile_layer.test.ts new file mode 100644 index 0000000000000..b2d2b08c637cf --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/tile_layer.test.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { TileLayer } from './tile_layer'; +import { EMS_XYZ } from '../../common/constants'; +import { IXYZTMSSourceDescriptor } from '../../common/descriptor_types'; +import { ITMSSource } from './sources/tms_source'; +import { ILayer } from './layer'; + +const sourceDescriptor: IXYZTMSSourceDescriptor = { + type: EMS_XYZ, + urlTemplate: 'https://example.com/{x}/{y}/{z}.png', + id: 'foobar', +}; + +class MockTileSource implements ITMSSource { + private _descriptor: IXYZTMSSourceDescriptor; + constructor(descriptor: IXYZTMSSourceDescriptor) { + this._descriptor = descriptor; + } + createDefaultLayer(): ILayer { + throw new Error('not implemented'); + } + + async getDisplayName(): Promise { + return this._descriptor.urlTemplate; + } + + async getUrlTemplate(): Promise { + return 'template/{x}/{y}/{z}.png'; + } +} + +describe('TileLayer', () => { + it('should use display-label from source', async () => { + const source = new MockTileSource(sourceDescriptor); + const layer: ILayer = new TileLayer({ + source, + layerDescriptor: { id: 'layerid', sourceDescriptor }, + }); + expect(await source.getDisplayName()).toEqual(await layer.getDisplayName()); + }); + + it('should override with custom display-label if present', async () => { + const source = new MockTileSource(sourceDescriptor); + const layer: ILayer = new TileLayer({ + source, + layerDescriptor: { id: 'layerid', sourceDescriptor, label: 'custom' }, + }); + expect('custom').toEqual(await layer.getDisplayName()); + }); +}); From 4cb9bc44721e26ac2898eb11621b85f4418d913e Mon Sep 17 00:00:00 2001 From: Josh Dover Date: Wed, 26 Feb 2020 12:43:12 -0700 Subject: [PATCH 17/64] Add ScopedHistory to AppMountParams (#56705) --- .../core/public/kibana-plugin-public.app.md | 4 +- .../public/kibana-plugin-public.app.mount.md | 2 +- ...plugin-public.applicationsetup.register.md | 4 +- .../public/kibana-plugin-public.appmount.md | 2 +- ...kibana-plugin-public.appmountdeprecated.md | 2 +- ...n-public.appmountparameters.appbasepath.md | 9 +- ...lugin-public.appmountparameters.history.md | 58 +++ ...kibana-plugin-public.appmountparameters.md | 3 +- .../core/public/kibana-plugin-public.md | 1 + ...ugin-public.scopedhistory._constructor_.md | 21 ++ ...bana-plugin-public.scopedhistory.action.md | 13 + ...ibana-plugin-public.scopedhistory.block.md | 18 + ...-plugin-public.scopedhistory.createhref.md | 13 + ...n-public.scopedhistory.createsubhistory.md | 13 + .../kibana-plugin-public.scopedhistory.go.md | 13 + ...bana-plugin-public.scopedhistory.goback.md | 13 + ...a-plugin-public.scopedhistory.goforward.md | 13 + ...bana-plugin-public.scopedhistory.length.md | 13 + ...bana-plugin-public.scopedhistory.listen.md | 13 + ...na-plugin-public.scopedhistory.location.md | 13 + .../kibana-plugin-public.scopedhistory.md | 41 +++ ...kibana-plugin-public.scopedhistory.push.md | 13 + ...ana-plugin-public.scopedhistory.replace.md | 13 + .../application/application_service.test.ts | 30 ++ .../application/application_service.tsx | 17 +- src/core/public/application/index.ts | 1 + .../integration_tests/router.test.tsx | 136 ++++++-- .../application/integration_tests/utils.tsx | 22 +- .../public/application/scoped_history.mock.ts | 57 +++ .../public/application/scoped_history.test.ts | 329 ++++++++++++++++++ src/core/public/application/scoped_history.ts | 318 +++++++++++++++++ src/core/public/application/types.ts | 76 +++- .../application/ui/app_container.test.tsx | 7 + .../public/application/ui/app_container.tsx | 9 +- src/core/public/application/ui/app_router.tsx | 22 +- src/core/public/index.ts | 1 + src/core/public/mocks.ts | 1 + src/core/public/public.api.md | 36 +- .../local_application_service.ts | 8 +- .../new_platform/new_platform.test.mocks.ts | 7 + .../public/new_platform/new_platform.test.ts | 6 +- .../ui/public/new_platform/new_platform.ts | 19 +- src/plugins/dev_tools/public/application.tsx | 8 +- .../core_plugin_a/public/application.tsx | 14 +- .../core_plugin_b/public/application.tsx | 14 +- .../plugins/core_plugin_legacy/index.ts | 1 + .../plugins/legacy_plugin/index.ts | 34 ++ .../plugins/legacy_plugin/package.json | 17 + .../plugins/legacy_plugin/public/index.tsx | 35 ++ .../plugins/legacy_plugin/tsconfig.json | 15 + .../core_plugins/application_leave_confirm.ts | 2 +- .../test_suites/core_plugins/applications.ts | 28 +- .../core_plugins/legacy_plugins.ts | 2 +- .../test_suites/core_plugins/rendering.ts | 8 +- .../public/legacy.ts | 4 +- .../public/register_route.ts | 4 +- x-pack/legacy/plugins/ml/public/plugin.ts | 1 + .../plugins/uptime/public/apps/plugin.ts | 1 - 58 files changed, 1479 insertions(+), 119 deletions(-) create mode 100644 docs/development/core/public/kibana-plugin-public.appmountparameters.history.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory._constructor_.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.action.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.block.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.createhref.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.createsubhistory.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.go.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.goback.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.goforward.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.length.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.listen.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.location.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.push.md create mode 100644 docs/development/core/public/kibana-plugin-public.scopedhistory.replace.md create mode 100644 src/core/public/application/scoped_history.mock.ts create mode 100644 src/core/public/application/scoped_history.test.ts create mode 100644 src/core/public/application/scoped_history.ts create mode 100644 test/plugin_functional/plugins/legacy_plugin/index.ts create mode 100644 test/plugin_functional/plugins/legacy_plugin/package.json create mode 100644 test/plugin_functional/plugins/legacy_plugin/public/index.tsx create mode 100644 test/plugin_functional/plugins/legacy_plugin/tsconfig.json diff --git a/docs/development/core/public/kibana-plugin-public.app.md b/docs/development/core/public/kibana-plugin-public.app.md index faea94c467726..f31db3674f5ba 100644 --- a/docs/development/core/public/kibana-plugin-public.app.md +++ b/docs/development/core/public/kibana-plugin-public.app.md @@ -9,7 +9,7 @@ Extension of [common app properties](./kibana-plugin-public.appbase.md) with the Signature: ```typescript -export interface App extends AppBase +export interface App extends AppBase ``` ## Properties @@ -18,5 +18,5 @@ export interface App extends AppBase | --- | --- | --- | | [appRoute](./kibana-plugin-public.app.approute.md) | string | Override the application's routing path from /app/${id}. Must be unique across registered applications. Should not include the base path from HTTP. | | [chromeless](./kibana-plugin-public.app.chromeless.md) | boolean | Hide the UI chrome when the application is mounted. Defaults to false. Takes precedence over chrome service visibility settings. | -| [mount](./kibana-plugin-public.app.mount.md) | AppMount | AppMountDeprecated | A mount function called when the user navigates to this app's route. May have signature of [AppMount](./kibana-plugin-public.appmount.md) or [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md). | +| [mount](./kibana-plugin-public.app.mount.md) | AppMount<HistoryLocationState> | AppMountDeprecated<HistoryLocationState> | A mount function called when the user navigates to this app's route. May have signature of [AppMount](./kibana-plugin-public.appmount.md) or [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md). | diff --git a/docs/development/core/public/kibana-plugin-public.app.mount.md b/docs/development/core/public/kibana-plugin-public.app.mount.md index 2af5f0277759a..4829307ff267c 100644 --- a/docs/development/core/public/kibana-plugin-public.app.mount.md +++ b/docs/development/core/public/kibana-plugin-public.app.mount.md @@ -9,7 +9,7 @@ A mount function called when the user navigates to this app's route. May have si Signature: ```typescript -mount: AppMount | AppMountDeprecated; +mount: AppMount | AppMountDeprecated; ``` ## Remarks diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md index 5c6c7cd252b0a..27c3e28c05a0d 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md +++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md @@ -9,14 +9,14 @@ Register an mountable application to the system. Signature: ```typescript -register(app: App): void; +register(app: App): void; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| app | App | an [App](./kibana-plugin-public.app.md) | +| app | App<HistoryLocationState> | an [App](./kibana-plugin-public.app.md) | Returns: diff --git a/docs/development/core/public/kibana-plugin-public.appmount.md b/docs/development/core/public/kibana-plugin-public.appmount.md index 84a52b09a119c..a001b1f75c99e 100644 --- a/docs/development/core/public/kibana-plugin-public.appmount.md +++ b/docs/development/core/public/kibana-plugin-public.appmount.md @@ -9,5 +9,5 @@ A mount function called when the user navigates to this app's route. Signature: ```typescript -export declare type AppMount = (params: AppMountParameters) => AppUnmount | Promise; +export declare type AppMount = (params: AppMountParameters) => AppUnmount | Promise; ``` diff --git a/docs/development/core/public/kibana-plugin-public.appmountdeprecated.md b/docs/development/core/public/kibana-plugin-public.appmountdeprecated.md index 8c8114182b60f..2bd2e956124c0 100644 --- a/docs/development/core/public/kibana-plugin-public.appmountdeprecated.md +++ b/docs/development/core/public/kibana-plugin-public.appmountdeprecated.md @@ -13,7 +13,7 @@ A mount function called when the user navigates to this app's route. Signature: ```typescript -export declare type AppMountDeprecated = (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise; +export declare type AppMountDeprecated = (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise; ``` ## Remarks diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md index 041d976aa42a2..beedda98d8f4d 100644 --- a/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md +++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md @@ -4,6 +4,11 @@ ## AppMountParameters.appBasePath property +> Warning: This API is now obsolete. +> +> Use [AppMountParameters.history](./kibana-plugin-public.appmountparameters.history.md) instead. +> + The route path for configuring navigation to the application. This string should not include the base path from HTTP. Signature: @@ -39,10 +44,10 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter, Route } from 'react-router-dom'; -import { CoreStart, AppMountParams } from 'src/core/public'; +import { CoreStart, AppMountParameters } from 'src/core/public'; import { MyPluginDepsStart } from './plugin'; -export renderApp = ({ appBasePath, element }: AppMountParams) => { +export renderApp = ({ appBasePath, element }: AppMountParameters) => { ReactDOM.render( // pass `appBasePath` to `basename` diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.history.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.history.md new file mode 100644 index 0000000000000..9a3fa1a1bb48a --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.history.md @@ -0,0 +1,58 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) > [history](./kibana-plugin-public.appmountparameters.history.md) + +## AppMountParameters.history property + +A scoped history instance for your application. Should be used to wire up your applications Router. + +Signature: + +```typescript +history: ScopedHistory; +``` + +## Example + +How to configure react-router with a base path: + +```ts +// inside your plugin's setup function +export class MyPlugin implements Plugin { + setup({ application }) { + application.register({ + id: 'my-app', + appRoute: '/my-app', + async mount(params) { + const { renderApp } = await import('./application'); + return renderApp(params); + }, + }); + } +} + +``` + +```ts +// application.tsx +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Router, Route } from 'react-router-dom'; + +import { CoreStart, AppMountParameters } from 'src/core/public'; +import { MyPluginDepsStart } from './plugin'; + +export renderApp = ({ element, history }: AppMountParameters) => { + ReactDOM.render( + // pass `appBasePath` to `basename` + + + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +} + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.md index c21889c28bda4..e652379fc3034 100644 --- a/docs/development/core/public/kibana-plugin-public.appmountparameters.md +++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.md @@ -8,7 +8,7 @@ Signature: ```typescript -export interface AppMountParameters +export interface AppMountParameters ``` ## Properties @@ -17,5 +17,6 @@ export interface AppMountParameters | --- | --- | --- | | [appBasePath](./kibana-plugin-public.appmountparameters.appbasepath.md) | string | The route path for configuring navigation to the application. This string should not include the base path from HTTP. | | [element](./kibana-plugin-public.appmountparameters.element.md) | HTMLElement | The container element to render the application into. | +| [history](./kibana-plugin-public.appmountparameters.history.md) | ScopedHistory<HistoryLocationState> | A scoped history instance for your application. Should be used to wire up your applications Router. | | [onAppLeave](./kibana-plugin-public.appmountparameters.onappleave.md) | (handler: AppLeaveHandler) => void | A function that can be used to register a handler that will be called when the user is leaving the current application, allowing to prompt a confirmation message before actually changing the page.This will be called either when the user goes to another application, or when trying to close the tab or manually changing the url. | diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md index 95a4327728139..79bdb11b80fa4 100644 --- a/docs/development/core/public/kibana-plugin-public.md +++ b/docs/development/core/public/kibana-plugin-public.md @@ -15,6 +15,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | Class | Description | | --- | --- | | [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state. The client-side SavedObjectsClient is a thin convenience library around the SavedObjects HTTP API for interacting with Saved Objects. | +| [ScopedHistory](./kibana-plugin-public.scopedhistory.md) | A wrapper around a History instance that is scoped to a particular base path of the history stack. Behaves similarly to the basename option except that this wrapper hides any history stack entries from outside the scope of this base path.This wrapper also allows Core and Plugins to share a single underlying global History instance without exposing the history of other applications.The [createSubHistory](./kibana-plugin-public.scopedhistory.createsubhistory.md) method is particularly useful for applications that contain any number of "sub-apps" which should not have access to the main application's history or basePath. | | [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) | This class is a very simple wrapper for SavedObjects loaded from the server with the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md).It provides basic functionality for creating/saving/deleting saved objects, but doesn't include any type-specific implementations. | | [ToastsApi](./kibana-plugin-public.toastsapi.md) | Methods for adding and removing global toast messages. | diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory._constructor_.md b/docs/development/core/public/kibana-plugin-public.scopedhistory._constructor_.md new file mode 100644 index 0000000000000..d21c908890b6b --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory._constructor_.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [(constructor)](./kibana-plugin-public.scopedhistory._constructor_.md) + +## ScopedHistory.(constructor) + +Constructs a new instance of the `ScopedHistory` class + +Signature: + +```typescript +constructor(parentHistory: History, basePath: string); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| parentHistory | History | | +| basePath | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.action.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.action.md new file mode 100644 index 0000000000000..c3b52b9041871 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.action.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [action](./kibana-plugin-public.scopedhistory.action.md) + +## ScopedHistory.action property + +The last action dispatched on the history stack. + +Signature: + +```typescript +get action(): Action; +``` diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.block.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.block.md new file mode 100644 index 0000000000000..b6c5da58d4684 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.block.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [block](./kibana-plugin-public.scopedhistory.block.md) + +## ScopedHistory.block property + +Not supported. Use [AppMountParameters.onAppLeave](./kibana-plugin-public.appmountparameters.onappleave.md). + +Signature: + +```typescript +block: (prompt?: string | boolean | History.TransitionPromptHook | undefined) => UnregisterCallback; +``` + +## Remarks + +We prefer that applications use the `onAppLeave` API because it supports a more graceful experience that prefers a modal when possible, falling back to a confirm dialog box in the beforeunload case. + diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.createhref.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.createhref.md new file mode 100644 index 0000000000000..6bbd78dc9b3c9 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.createhref.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [createHref](./kibana-plugin-public.scopedhistory.createhref.md) + +## ScopedHistory.createHref property + +Creates an href (string) to the location. + +Signature: + +```typescript +createHref: (location: LocationDescriptorObject) => string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.createsubhistory.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.createsubhistory.md new file mode 100644 index 0000000000000..045289c98e4ee --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.createsubhistory.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [createSubHistory](./kibana-plugin-public.scopedhistory.createsubhistory.md) + +## ScopedHistory.createSubHistory property + +Creates a `ScopedHistory` for a subpath of this `ScopedHistory`. Useful for applications that may have sub-apps that do not need access to the containing application's history. + +Signature: + +```typescript +createSubHistory: (basePath: string) => ScopedHistory; +``` diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.go.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.go.md new file mode 100644 index 0000000000000..b9d124d06a109 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.go.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [go](./kibana-plugin-public.scopedhistory.go.md) + +## ScopedHistory.go property + +Send the user forward or backwards in the history stack. + +Signature: + +```typescript +go: (n: number) => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.goback.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.goback.md new file mode 100644 index 0000000000000..8f1d4b25ebcbf --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.goback.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [goBack](./kibana-plugin-public.scopedhistory.goback.md) + +## ScopedHistory.goBack property + +Send the user one location back in the history stack. Equivalent to calling [ScopedHistory.go(-1)](./kibana-plugin-public.scopedhistory.go.md). If no more entries are available backwards, this is a no-op. + +Signature: + +```typescript +goBack: () => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.goforward.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.goforward.md new file mode 100644 index 0000000000000..587d5035bb5b5 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.goforward.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [goForward](./kibana-plugin-public.scopedhistory.goforward.md) + +## ScopedHistory.goForward property + +Send the user one location forward in the history stack. Equivalent to calling [ScopedHistory.go(1)](./kibana-plugin-public.scopedhistory.go.md). If no more entries are available forwards, this is a no-op. + +Signature: + +```typescript +goForward: () => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.length.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.length.md new file mode 100644 index 0000000000000..8a8d6accc1fbc --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.length.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [length](./kibana-plugin-public.scopedhistory.length.md) + +## ScopedHistory.length property + +The number of entries in the history stack, including all entries forwards and backwards from the current location. + +Signature: + +```typescript +get length(): number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.listen.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.listen.md new file mode 100644 index 0000000000000..a0693e5a0428d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.listen.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [listen](./kibana-plugin-public.scopedhistory.listen.md) + +## ScopedHistory.listen property + +Adds a listener for location updates. + +Signature: + +```typescript +listen: (listener: (location: Location, action: Action) => void) => UnregisterCallback; +``` diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.location.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.location.md new file mode 100644 index 0000000000000..c40f73333ec7d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.location.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [location](./kibana-plugin-public.scopedhistory.location.md) + +## ScopedHistory.location property + +The current location of the history stack. + +Signature: + +```typescript +get location(): Location; +``` diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.md new file mode 100644 index 0000000000000..5b429c1e6ec9e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.md @@ -0,0 +1,41 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) + +## ScopedHistory class + +A wrapper around a `History` instance that is scoped to a particular base path of the history stack. Behaves similarly to the `basename` option except that this wrapper hides any history stack entries from outside the scope of this base path. + +This wrapper also allows Core and Plugins to share a single underlying global `History` instance without exposing the history of other applications. + +The [createSubHistory](./kibana-plugin-public.scopedhistory.createsubhistory.md) method is particularly useful for applications that contain any number of "sub-apps" which should not have access to the main application's history or basePath. + +Signature: + +```typescript +export declare class ScopedHistory implements History +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(parentHistory, basePath)](./kibana-plugin-public.scopedhistory._constructor_.md) | | Constructs a new instance of the ScopedHistory class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [action](./kibana-plugin-public.scopedhistory.action.md) | | Action | The last action dispatched on the history stack. | +| [block](./kibana-plugin-public.scopedhistory.block.md) | | (prompt?: string | boolean | History.TransitionPromptHook<HistoryLocationState> | undefined) => UnregisterCallback | Not supported. Use [AppMountParameters.onAppLeave](./kibana-plugin-public.appmountparameters.onappleave.md). | +| [createHref](./kibana-plugin-public.scopedhistory.createhref.md) | | (location: LocationDescriptorObject<HistoryLocationState>) => string | Creates an href (string) to the location. | +| [createSubHistory](./kibana-plugin-public.scopedhistory.createsubhistory.md) | | <SubHistoryLocationState = unknown>(basePath: string) => ScopedHistory<SubHistoryLocationState> | Creates a ScopedHistory for a subpath of this ScopedHistory. Useful for applications that may have sub-apps that do not need access to the containing application's history. | +| [go](./kibana-plugin-public.scopedhistory.go.md) | | (n: number) => void | Send the user forward or backwards in the history stack. | +| [goBack](./kibana-plugin-public.scopedhistory.goback.md) | | () => void | Send the user one location back in the history stack. Equivalent to calling [ScopedHistory.go(-1)](./kibana-plugin-public.scopedhistory.go.md). If no more entries are available backwards, this is a no-op. | +| [goForward](./kibana-plugin-public.scopedhistory.goforward.md) | | () => void | Send the user one location forward in the history stack. Equivalent to calling [ScopedHistory.go(1)](./kibana-plugin-public.scopedhistory.go.md). If no more entries are available forwards, this is a no-op. | +| [length](./kibana-plugin-public.scopedhistory.length.md) | | number | The number of entries in the history stack, including all entries forwards and backwards from the current location. | +| [listen](./kibana-plugin-public.scopedhistory.listen.md) | | (listener: (location: Location<HistoryLocationState>, action: Action) => void) => UnregisterCallback | Adds a listener for location updates. | +| [location](./kibana-plugin-public.scopedhistory.location.md) | | Location<HistoryLocationState> | The current location of the history stack. | +| [push](./kibana-plugin-public.scopedhistory.push.md) | | (pathOrLocation: string | LocationDescriptorObject<HistoryLocationState>, state?: HistoryLocationState | undefined) => void | Pushes a new location onto the history stack. If there are forward entries in the stack, they will be removed. | +| [replace](./kibana-plugin-public.scopedhistory.replace.md) | | (pathOrLocation: string | LocationDescriptorObject<HistoryLocationState>, state?: HistoryLocationState | undefined) => void | Replaces the current location in the history stack. Does not remove forward or backward entries. | + diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.push.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.push.md new file mode 100644 index 0000000000000..0d8d635d0f189 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.push.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [push](./kibana-plugin-public.scopedhistory.push.md) + +## ScopedHistory.push property + +Pushes a new location onto the history stack. If there are forward entries in the stack, they will be removed. + +Signature: + +```typescript +push: (pathOrLocation: string | LocationDescriptorObject, state?: HistoryLocationState | undefined) => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.scopedhistory.replace.md b/docs/development/core/public/kibana-plugin-public.scopedhistory.replace.md new file mode 100644 index 0000000000000..f9c1171d4217e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.scopedhistory.replace.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ScopedHistory](./kibana-plugin-public.scopedhistory.md) > [replace](./kibana-plugin-public.scopedhistory.replace.md) + +## ScopedHistory.replace property + +Replaces the current location in the history stack. Does not remove forward or backward entries. + +Signature: + +```typescript +replace: (pathOrLocation: string | LocationDescriptorObject, state?: HistoryLocationState | undefined) => void; +``` diff --git a/src/core/public/application/application_service.test.ts b/src/core/public/application/application_service.test.ts index 5487ca53170dd..c25918c6b7328 100644 --- a/src/core/public/application/application_service.test.ts +++ b/src/core/public/application/application_service.test.ts @@ -588,6 +588,16 @@ describe('#start()', () => { expect(getUrlForApp('app1', { path: 'deep/link///' })).toBe('/base-path/app/app1/deep/link'); }); + it('does not append trailing slash if hash is provided in path parameter', async () => { + service.setup(setupDeps); + const { getUrlForApp } = await service.start(startDeps); + + expect(getUrlForApp('app1', { path: '#basic-hash' })).toBe('/base-path/app/app1#basic-hash'); + expect(getUrlForApp('app1', { path: '#/hash/router/path' })).toBe( + '/base-path/app/app1#/hash/router/path' + ); + }); + it('creates absolute URLs when `absolute` parameter is true', async () => { service.setup(setupDeps); const { getUrlForApp } = await service.start(startDeps); @@ -646,6 +656,26 @@ describe('#start()', () => { ); }); + it('appends a path if specified with hash', async () => { + const { register } = service.setup(setupDeps); + + register(Symbol(), createApp({ id: 'app2', appRoute: '/custom/path' })); + + const { navigateToApp } = await service.start(startDeps); + + await navigateToApp('myTestApp', { path: '#basic-hash' }); + expect(MockHistory.push).toHaveBeenCalledWith('/app/myTestApp#basic-hash', undefined); + + await navigateToApp('myTestApp', { path: '#/hash/router/path' }); + expect(MockHistory.push).toHaveBeenCalledWith('/app/myTestApp#/hash/router/path', undefined); + + await navigateToApp('app2', { path: '#basic-hash' }); + expect(MockHistory.push).toHaveBeenCalledWith('/custom/path#basic-hash', undefined); + + await navigateToApp('app2', { path: '#/hash/router/path' }); + expect(MockHistory.push).toHaveBeenCalledWith('/custom/path#/hash/router/path', undefined); + }); + it('includes state if specified', async () => { const { register } = service.setup(setupDeps); diff --git a/src/core/public/application/application_service.tsx b/src/core/public/application/application_service.tsx index 77f06e316c0aa..1c9492d81c7f6 100644 --- a/src/core/public/application/application_service.tsx +++ b/src/core/public/application/application_service.tsx @@ -76,10 +76,19 @@ function filterAvailable(m: Map, capabilities: Capabilities) { } const findMounter = (mounters: Map, appRoute?: string) => [...mounters].find(([, mounter]) => mounter.appRoute === appRoute); -const getAppUrl = (mounters: Map, appId: string, path: string = '') => - `/${mounters.get(appId)?.appRoute ?? `/app/${appId}`}/${path}` + +const getAppUrl = (mounters: Map, appId: string, path: string = '') => { + const appBasePath = mounters.get(appId)?.appRoute + ? `/${mounters.get(appId)!.appRoute}` + : `/app/${appId}`; + + // Only preppend slash if not a hash or query path + path = path.startsWith('#') || path.startsWith('?') ? path : `/${path}`; + + return `${appBasePath}${path}` .replace(/\/{2,}/g, '/') // Remove duplicate slashes .replace(/\/$/, ''); // Remove trailing slash +}; const allApplicationsFilter = '__ALL__'; @@ -93,7 +102,7 @@ interface AppUpdaterWrapper { * @internal */ export class ApplicationService { - private readonly apps = new Map(); + private readonly apps = new Map | LegacyApp>(); private readonly mounters = new Map(); private readonly capabilities = new CapabilitiesService(); private readonly appLeaveHandlers = new Map(); @@ -143,7 +152,7 @@ export class ApplicationService { return { registerMountContext: this.mountContext!.registerContext, - register: (plugin, app) => { + register: (plugin, app: App) => { app = { appRoute: `/app/${app.id}`, ...app }; if (this.registrationClosed) { diff --git a/src/core/public/application/index.ts b/src/core/public/application/index.ts index e7ea330657648..ec10d2bc22871 100644 --- a/src/core/public/application/index.ts +++ b/src/core/public/application/index.ts @@ -19,6 +19,7 @@ export { ApplicationService } from './application_service'; export { Capabilities } from './capabilities'; +export { ScopedHistory } from './scoped_history'; export { App, AppBase, diff --git a/src/core/public/application/integration_tests/router.test.tsx b/src/core/public/application/integration_tests/router.test.tsx index 0c5f5a138d58f..2f26bc1409104 100644 --- a/src/core/public/application/integration_tests/router.test.tsx +++ b/src/core/public/application/integration_tests/router.test.tsx @@ -25,15 +25,17 @@ import { AppRouter, AppNotFound } from '../ui'; import { EitherApp, MockedMounterMap, MockedMounterTuple } from '../test_types'; import { createRenderer, createAppMounter, createLegacyAppMounter, getUnmounter } from './utils'; import { AppStatus } from '../types'; +import { ScopedHistory } from '../scoped_history'; describe('AppContainer', () => { let mounters: MockedMounterMap; - let history: History; + let globalHistory: History; let appStatuses$: BehaviorSubject>; let update: ReturnType; + let scopedAppHistory: History; const navigate = (path: string) => { - history.push(path); + globalHistory.push(path); return update(); }; const mockMountersToMounters = () => @@ -53,20 +55,35 @@ describe('AppContainer', () => { beforeEach(() => { mounters = new Map([ - createAppMounter('app1', 'App 1'), + createAppMounter({ appId: 'app1', html: 'App 1' }), createLegacyAppMounter('legacyApp1', jest.fn()), - createAppMounter('app2', '
App 2
'), + createAppMounter({ appId: 'app2', html: '
App 2
' }), createLegacyAppMounter('baseApp:legacyApp2', jest.fn()), - createAppMounter('app3', '
Chromeless A
', '/chromeless-a/path'), - createAppMounter('app4', '
Chromeless B
', '/chromeless-b/path'), - createAppMounter('disabledApp', '
Disabled app
'), + createAppMounter({ + appId: 'app3', + html: '
Chromeless A
', + appRoute: '/chromeless-a/path', + }), + createAppMounter({ + appId: 'app4', + html: '
Chromeless B
', + appRoute: '/chromeless-b/path', + }), + createAppMounter({ appId: 'disabledApp', html: '
Disabled app
' }), createLegacyAppMounter('disabledLegacyApp', jest.fn()), + createAppMounter({ + appId: 'scopedApp', + extraMountHook: ({ history }) => { + scopedAppHistory = history; + history.push('/subpath'); + }, + }), ] as Array>); - history = createMemoryHistory(); + globalHistory = createMemoryHistory(); appStatuses$ = mountersToAppStatus$(); update = createRenderer( { }); it('should not mount when partial route path matches', async () => { - mounters.set(...createAppMounter('spaces', '
Custom Space
', '/spaces/fake-login')); - mounters.set(...createAppMounter('login', '
Login Page
', '/fake-login')); - history = createMemoryHistory(); + mounters.set( + ...createAppMounter({ + appId: 'spaces', + html: '
Custom Space
', + appRoute: '/spaces/fake-login', + }) + ); + mounters.set( + ...createAppMounter({ + appId: 'login', + html: '
Login Page
', + appRoute: '/fake-login', + }) + ); + globalHistory = createMemoryHistory(); update = createRenderer( { }); it('should not mount when partial route path has higher specificity', async () => { - mounters.set(...createAppMounter('login', '
Login Page
', '/fake-login')); - mounters.set(...createAppMounter('spaces', '
Custom Space
', '/spaces/fake-login')); - history = createMemoryHistory(); + mounters.set( + ...createAppMounter({ + appId: 'login', + html: '
Login Page
', + appRoute: '/fake-login', + }) + ); + mounters.set( + ...createAppMounter({ + appId: 'spaces', + html: '
Custom Space
', + appRoute: '/spaces/fake-login', + }) + ); + globalHistory = createMemoryHistory(); update = createRenderer( { // Hitting back button within app does not trigger re-render await navigate('/app/app1/page2'); - history.goBack(); + globalHistory.goBack(); await update(); expect(mounter.mount).toHaveBeenCalledTimes(1); expect(unmount).not.toHaveBeenCalled(); }); it('should not remount when when changing pages within app using hash history', async () => { - history = createHashHistory(); + globalHistory = createHashHistory(); update = createRenderer( { expect(unmount).toHaveBeenCalledTimes(1); }); + it('pushes global history changes to inner scoped history', async () => { + const scopedApp = mounters.get('scopedApp'); + await navigate('/app/scopedApp'); + + // Verify that internal app's redirect propagated + expect(scopedApp?.mounter.mount).toHaveBeenCalledTimes(1); + expect(scopedAppHistory.location.pathname).toEqual('/subpath'); + expect(globalHistory.location.pathname).toEqual('/app/scopedApp/subpath'); + + // Simulate user clicking on navlink again to return to app root + globalHistory.push('/app/scopedApp'); + // Should not call mount again + expect(scopedApp?.mounter.mount).toHaveBeenCalledTimes(1); + expect(scopedApp?.unmount).not.toHaveBeenCalled(); + // Inner scoped history should be synced + expect(scopedAppHistory.location.pathname).toEqual(''); + + // Make sure going back to subpath works + globalHistory.goBack(); + expect(scopedApp?.mounter.mount).toHaveBeenCalledTimes(1); + expect(scopedApp?.unmount).not.toHaveBeenCalled(); + expect(scopedAppHistory.location.pathname).toEqual('/subpath'); + expect(globalHistory.location.pathname).toEqual('/app/scopedApp/subpath'); + }); + it('calls legacy mount handler', async () => { await navigate('/app/legacyApp1'); - expect(mounters.get('legacyApp1')!.mounter.mount.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "appBasePath": "/app/legacyApp1", - "element":
, - "onAppLeave": [Function], - }, - ] - `); + expect(mounters.get('legacyApp1')!.mounter.mount.mock.calls[0][0]).toMatchObject({ + appBasePath: '/app/legacyApp1', + element: expect.any(HTMLDivElement), + onAppLeave: expect.any(Function), + history: expect.any(ScopedHistory), + }); }); it('handles legacy apps with subapps', async () => { await navigate('/app/baseApp'); - expect(mounters.get('baseApp:legacyApp2')!.mounter.mount.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "appBasePath": "/app/baseApp", - "element":
, - "onAppLeave": [Function], - }, - ] - `); + expect(mounters.get('baseApp:legacyApp2')!.mounter.mount.mock.calls[0][0]).toMatchObject({ + appBasePath: '/app/baseApp', + element: expect.any(HTMLDivElement), + onAppLeave: expect.any(Function), + history: expect.any(ScopedHistory), + }); }); it('displays error page if no app is found', async () => { diff --git a/src/core/public/application/integration_tests/utils.tsx b/src/core/public/application/integration_tests/utils.tsx index 4f34438fc822a..9092177da5ad4 100644 --- a/src/core/public/application/integration_tests/utils.tsx +++ b/src/core/public/application/integration_tests/utils.tsx @@ -40,11 +40,17 @@ export const createRenderer = (element: ReactElement | null): Renderer => { }); }; -export const createAppMounter = ( - appId: string, - html: string, - appRoute = `/app/${appId}` -): MockedMounterTuple => { +export const createAppMounter = ({ + appId, + html = `
App ${appId}
`, + appRoute = `/app/${appId}`, + extraMountHook, +}: { + appId: string; + html?: string; + appRoute?: string; + extraMountHook?: (params: AppMountParameters) => void; +}): MockedMounterTuple => { const unmount = jest.fn(); return [ appId, @@ -52,11 +58,15 @@ export const createAppMounter = ( mounter: { appRoute, appBasePath: appRoute, - mount: jest.fn(async ({ appBasePath: basename, element }: AppMountParameters) => { + mount: jest.fn(async (params: AppMountParameters) => { + const { appBasePath: basename, element } = params; Object.assign(element, { innerHTML: `
\nbasename: ${basename}\nhtml: ${html}\n
`, }); unmount.mockImplementation(() => Object.assign(element, { innerHTML: '' })); + if (extraMountHook) { + extraMountHook(params); + } return unmount; }), }, diff --git a/src/core/public/application/scoped_history.mock.ts b/src/core/public/application/scoped_history.mock.ts new file mode 100644 index 0000000000000..56de97e630bf0 --- /dev/null +++ b/src/core/public/application/scoped_history.mock.ts @@ -0,0 +1,57 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Location } from 'history'; +import { ScopedHistory } from './scoped_history'; + +type ScopedHistoryMock = jest.Mocked>; +const createMock = ({ + pathname = '/', + search = '', + hash = '', + key, + state, +}: Partial = {}) => { + const mock: ScopedHistoryMock = { + block: jest.fn(), + createHref: jest.fn(), + createSubHistory: jest.fn(), + go: jest.fn(), + goBack: jest.fn(), + goForward: jest.fn(), + listen: jest.fn(), + push: jest.fn(), + replace: jest.fn(), + action: 'PUSH', + length: 1, + location: { + pathname, + search, + state, + hash, + key, + }, + }; + + return mock; +}; + +export const scopedHistoryMock = { + create: createMock, +}; diff --git a/src/core/public/application/scoped_history.test.ts b/src/core/public/application/scoped_history.test.ts new file mode 100644 index 0000000000000..c01eb50830516 --- /dev/null +++ b/src/core/public/application/scoped_history.test.ts @@ -0,0 +1,329 @@ +/* + * 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 { ScopedHistory } from './scoped_history'; +import { createMemoryHistory } from 'history'; + +describe('ScopedHistory', () => { + describe('construction', () => { + it('succeeds if current location matches basePath', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + expect(() => new ScopedHistory(gh, '/app/wow')).not.toThrow(); + gh.push('/app/wow/'); + expect(() => new ScopedHistory(gh, '/app/wow')).not.toThrow(); + gh.push('/app/wow/sub-page'); + expect(() => new ScopedHistory(gh, '/app/wow')).not.toThrow(); + }); + + it('fails if current location does not match basePath', () => { + const gh = createMemoryHistory(); + gh.push('/app/other'); + expect(() => new ScopedHistory(gh, '/app/wow')).toThrowErrorMatchingInlineSnapshot( + `"Browser location [/app/other] is not currently in expected basePath [/app/wow]"` + ); + }); + }); + + describe('navigation', () => { + it('supports push', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const pushSpy = jest.spyOn(gh, 'push'); + const h = new ScopedHistory(gh, '/app/wow'); + h.push('/new-page', { some: 'state' }); + expect(pushSpy).toHaveBeenCalledWith('/app/wow/new-page', { some: 'state' }); + expect(gh.length).toBe(3); // ['', '/app/wow', '/app/wow/new-page'] + expect(h.length).toBe(2); + }); + + it('supports unbound push', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const pushSpy = jest.spyOn(gh, 'push'); + const h = new ScopedHistory(gh, '/app/wow'); + const { push } = h; + push('/new-page', { some: 'state' }); + expect(pushSpy).toHaveBeenCalledWith('/app/wow/new-page', { some: 'state' }); + expect(gh.length).toBe(3); // ['', '/app/wow', '/app/wow/new-page'] + expect(h.length).toBe(2); + }); + + it('supports replace', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const replaceSpy = jest.spyOn(gh, 'replace'); + const h = new ScopedHistory(gh, '/app/wow'); // [''] + h.push('/first-page'); // ['', '/first-page'] + h.push('/second-page'); // ['', '/first-page', '/second-page'] + h.goBack(); // ['', '/first-page', '/second-page'] + h.replace('/first-page-replacement', { some: 'state' }); // ['', '/first-page-replacement', '/second-page'] + expect(replaceSpy).toHaveBeenCalledWith('/app/wow/first-page-replacement', { some: 'state' }); + expect(h.length).toBe(3); + expect(gh.length).toBe(4); // ['', '/app/wow', '/app/wow/first-page-replacement', '/app/wow/second-page'] + }); + + it('hides previous stack', () => { + const gh = createMemoryHistory(); + gh.push('/app/alpha'); + gh.push('/app/beta'); + gh.push('/app/wow'); + const h = new ScopedHistory(gh, '/app/wow'); + expect(h.length).toBe(1); + expect(h.location.pathname).toEqual(''); + }); + + it('cannot go back further than local stack', () => { + const gh = createMemoryHistory(); + gh.push('/app/alpha'); + gh.push('/app/beta'); + gh.push('/app/wow'); + const h = new ScopedHistory(gh, '/app/wow'); + h.push('/new-page'); + expect(h.length).toBe(2); + expect(h.location.pathname).toEqual('/new-page'); + + // Test first back + h.goBack(); + expect(h.length).toBe(2); + expect(h.location.pathname).toEqual(''); + expect(gh.location.pathname).toEqual('/app/wow'); + + // Second back should be no-op + h.goBack(); + expect(h.length).toBe(2); + expect(h.location.pathname).toEqual(''); + expect(gh.location.pathname).toEqual('/app/wow'); + }); + + it('cannot go forward further than local stack', () => { + const gh = createMemoryHistory(); + gh.push('/app/alpha'); + gh.push('/app/beta'); + gh.push('/app/wow'); + const h = new ScopedHistory(gh, '/app/wow'); + h.push('/new-page'); + expect(h.length).toBe(2); + + // Go back so we can go forward + h.goBack(); + expect(h.length).toBe(2); + expect(h.location.pathname).toEqual(''); + expect(gh.location.pathname).toEqual('/app/wow'); + + // Going forward should increase length and return to /new-page + h.goForward(); + expect(h.length).toBe(2); + expect(h.location.pathname).toEqual('/new-page'); + expect(gh.location.pathname).toEqual('/app/wow/new-page'); + + // Second forward should be no-op + h.goForward(); + expect(h.length).toBe(2); + expect(h.location.pathname).toEqual('/new-page'); + expect(gh.location.pathname).toEqual('/app/wow/new-page'); + }); + + it('reacts to navigations from parent history', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const h = new ScopedHistory(gh, '/app/wow'); + h.push('/page-1'); + h.push('/page-2'); + + gh.goBack(); + expect(h.location.pathname).toEqual('/page-1'); + expect(h.length).toBe(3); + + gh.goForward(); + expect(h.location.pathname).toEqual('/page-2'); + expect(h.length).toBe(3); + + // Go back to /app/wow and push a new location + gh.goBack(); + gh.goBack(); + gh.push('/app/wow/page-3'); + expect(h.location.pathname).toEqual('/page-3'); + expect(h.length).toBe(2); // ['', '/page-3'] + }); + + it('increments length on push and removes length when going back and then pushing', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + expect(gh.length).toBe(2); + const h = new ScopedHistory(gh, '/app/wow'); + expect(h.length).toBe(1); + h.push('/page1'); + expect(h.length).toBe(2); + h.push('/page2'); + expect(h.length).toBe(3); + h.push('/page3'); + expect(h.length).toBe(4); + h.push('/page4'); + expect(h.length).toBe(5); + h.push('/page5'); + expect(h.length).toBe(6); + h.goBack(); // back/forward should not reduce the length + expect(h.length).toBe(6); + h.goBack(); + expect(h.length).toBe(6); + h.push('/page6'); // length should only change if a new location is pushed from a point further back in the history + expect(h.length).toBe(5); + h.goBack(); + expect(h.length).toBe(5); + h.goBack(); + expect(h.length).toBe(5); + h.push('/page7'); + expect(h.length).toBe(4); + }); + }); + + describe('teardown behavior', () => { + it('throws exceptions after falling out of scope', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + expect(gh.length).toBe(2); + const h = new ScopedHistory(gh, '/app/wow'); + gh.push('/app/other'); + expect(() => h.location).toThrowErrorMatchingInlineSnapshot( + `"ScopedHistory instance has fell out of navigation scope for basePath: /app/wow"` + ); + expect(() => h.push('/new-page')).toThrow(); + expect(() => h.replace('/new-page')).toThrow(); + expect(() => h.goBack()).toThrow(); + expect(() => h.goForward()).toThrow(); + }); + }); + + describe('listen', () => { + it('calls callback with scoped location', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const h = new ScopedHistory(gh, '/app/wow'); + const listenPaths: string[] = []; + h.listen(l => listenPaths.push(l.pathname)); + h.push('/first-page'); + h.push('/second-page'); + h.push('/third-page'); + h.go(-2); + h.goForward(); + expect(listenPaths).toEqual([ + '/first-page', + '/second-page', + '/third-page', + '/first-page', + '/second-page', + ]); + }); + + it('stops calling callback after unlisten is called', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const h = new ScopedHistory(gh, '/app/wow'); + const listenPaths: string[] = []; + const unlisten = h.listen(l => listenPaths.push(l.pathname)); + h.push('/first-page'); + unlisten(); + h.push('/second-page'); + h.push('/third-page'); + h.go(-2); + h.goForward(); + expect(listenPaths).toEqual(['/first-page']); + }); + + it('stops calling callback after browser leaves scope', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const h = new ScopedHistory(gh, '/app/wow'); + const listenPaths: string[] = []; + h.listen(l => listenPaths.push(l.pathname)); + h.push('/first-page'); + gh.push('/app/other'); + gh.push('/second-page'); + gh.push('/third-page'); + gh.go(-2); + gh.goForward(); + expect(listenPaths).toEqual(['/first-page']); + }); + }); + + describe('createHref', () => { + it('creates scoped hrefs', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const h = new ScopedHistory(gh, '/app/wow'); + expect(h.createHref({ pathname: '' })).toEqual(`/`); + expect(h.createHref({ pathname: '/new-page', search: '?alpha=true' })).toEqual( + `/new-page?alpha=true` + ); + }); + }); + + describe('action', () => { + it('provides last history action', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + gh.push('/alpha'); + gh.goBack(); + const h = new ScopedHistory(gh, '/app/wow'); + expect(h.action).toBe('POP'); + gh.push('/app/wow/page-1'); + expect(h.action).toBe('PUSH'); + h.replace('/page-2'); + expect(h.action).toBe('REPLACE'); + }); + }); + + describe('createSubHistory', () => { + it('supports push', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const ghPushSpy = jest.spyOn(gh, 'push'); + const h1 = new ScopedHistory(gh, '/app/wow'); + h1.push('/new-page'); + const h1PushSpy = jest.spyOn(h1, 'push'); + const h2 = h1.createSubHistory('/new-page'); + h2.push('/sub-page', { some: 'state' }); + expect(h1PushSpy).toHaveBeenCalledWith('/new-page/sub-page', { some: 'state' }); + expect(ghPushSpy).toHaveBeenCalledWith('/app/wow/new-page/sub-page', { some: 'state' }); + expect(h2.length).toBe(2); + expect(h1.length).toBe(3); + expect(gh.length).toBe(4); + }); + + it('supports replace', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const ghReplaceSpy = jest.spyOn(gh, 'replace'); + const h1 = new ScopedHistory(gh, '/app/wow'); + h1.push('/new-page'); + const h1ReplaceSpy = jest.spyOn(h1, 'replace'); + const h2 = h1.createSubHistory('/new-page'); + h2.push('/sub-page'); + h2.replace('/other-sub-page', { some: 'state' }); + expect(h1ReplaceSpy).toHaveBeenCalledWith('/new-page/other-sub-page', { some: 'state' }); + expect(ghReplaceSpy).toHaveBeenCalledWith('/app/wow/new-page/other-sub-page', { + some: 'state', + }); + expect(h2.length).toBe(2); + expect(h1.length).toBe(3); + expect(gh.length).toBe(4); + }); + }); +}); diff --git a/src/core/public/application/scoped_history.ts b/src/core/public/application/scoped_history.ts new file mode 100644 index 0000000000000..c5febc7604feb --- /dev/null +++ b/src/core/public/application/scoped_history.ts @@ -0,0 +1,318 @@ +/* + * 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 { + History, + Path, + LocationDescriptorObject, + TransitionPromptHook, + UnregisterCallback, + LocationListener, + Location, + Href, + Action, +} from 'history'; + +/** + * A wrapper around a `History` instance that is scoped to a particular base path of the history stack. Behaves + * similarly to the `basename` option except that this wrapper hides any history stack entries from outside the scope + * of this base path. + * + * This wrapper also allows Core and Plugins to share a single underlying global `History` instance without exposing + * the history of other applications. + * + * The {@link ScopedHistory.createSubHistory | createSubHistory} method is particularly useful for applications that + * contain any number of "sub-apps" which should not have access to the main application's history or basePath. + * + * @public + */ +export class ScopedHistory + implements History { + /** + * Tracks whether or not the user has left this history's scope. All methods throw errors if called after scope has + * been left. + */ + private isActive = true; + /** + * All active listeners on this history instance. + */ + private listeners = new Set>(); + /** + * Array of the local history stack. Only stores {@link Location.key} to use tracking an index of the current + * position of the window in the history stack. + */ + private locationKeys: Array = []; + /** + * The key of the current position of the window in the history stack. + */ + private currentLocationKeyIndex: number = 0; + + constructor(private readonly parentHistory: History, private readonly basePath: string) { + const parentPath = this.parentHistory.location.pathname; + if (!parentPath.startsWith(basePath)) { + throw new Error( + `Browser location [${parentPath}] is not currently in expected basePath [${basePath}]` + ); + } + + this.locationKeys.push(this.parentHistory.location.key); + this.setupHistoryListener(); + } + + /** + * Creates a `ScopedHistory` for a subpath of this `ScopedHistory`. Useful for applications that may have sub-apps + * that do not need access to the containing application's history. + * + * @param basePath the URL path scope for the sub history + */ + public createSubHistory = ( + basePath: string + ): ScopedHistory => { + return new ScopedHistory(this, basePath); + }; + + /** + * The number of entries in the history stack, including all entries forwards and backwards from the current location. + */ + public get length() { + this.verifyActive(); + return this.locationKeys.length; + } + + /** + * The current location of the history stack. + */ + public get location() { + this.verifyActive(); + return this.stripBasePath(this.parentHistory.location); + } + + /** + * The last action dispatched on the history stack. + */ + public get action() { + this.verifyActive(); + return this.parentHistory.action; + } + + /** + * Pushes a new location onto the history stack. If there are forward entries in the stack, they will be removed. + * + * @param pathOrLocation a string or location descriptor + * @param state + */ + public push = ( + pathOrLocation: Path | LocationDescriptorObject, + state?: HistoryLocationState + ): void => { + this.verifyActive(); + if (typeof pathOrLocation === 'string') { + this.parentHistory.push(this.prependBasePath(pathOrLocation), state); + } else { + this.parentHistory.push(this.prependBasePath(pathOrLocation)); + } + }; + + /** + * Replaces the current location in the history stack. Does not remove forward or backward entries. + * + * @param pathOrLocation a string or location descriptor + * @param state + */ + public replace = ( + pathOrLocation: Path | LocationDescriptorObject, + state?: HistoryLocationState + ): void => { + this.verifyActive(); + if (typeof pathOrLocation === 'string') { + this.parentHistory.replace(this.prependBasePath(pathOrLocation), state); + } else { + this.parentHistory.replace(this.prependBasePath(pathOrLocation)); + } + }; + + /** + * Send the user forward or backwards in the history stack. + * + * @param n number of positions in the stack to go. Negative numbers indicate number of entries backward, positive + * numbers for forwards. If passed 0, the current location will be reloaded. If `n` exceeds the number of + * entries available, this is a no-op. + */ + public go = (n: number): void => { + this.verifyActive(); + if (n === 0) { + this.parentHistory.go(n); + } else if (n < 0) { + if (this.currentLocationKeyIndex + 1 + n >= 1) { + this.parentHistory.go(n); + } + } else if (n <= this.currentLocationKeyIndex + this.locationKeys.length - 1) { + this.parentHistory.go(n); + } + // no-op if no conditions above are met + }; + + /** + * Send the user one location back in the history stack. Equivalent to calling + * {@link ScopedHistory.go | ScopedHistory.go(-1)}. If no more entries are available backwards, this is a no-op. + */ + public goBack = () => { + this.verifyActive(); + this.go(-1); + }; + + /** + * Send the user one location forward in the history stack. Equivalent to calling + * {@link ScopedHistory.go | ScopedHistory.go(1)}. If no more entries are available forwards, this is a no-op. + */ + public goForward = () => { + this.verifyActive(); + this.go(1); + }; + + /** + * Not supported. Use {@link AppMountParameters.onAppLeave}. + * + * @remarks + * We prefer that applications use the `onAppLeave` API because it supports a more graceful experience that prefers + * a modal when possible, falling back to a confirm dialog box in the beforeunload case. + */ + public block = ( + prompt?: boolean | string | TransitionPromptHook + ): UnregisterCallback => { + throw new Error( + `history.block is not supported. Please use the AppMountParams.onAppLeave API.` + ); + }; + + /** + * Adds a listener for location updates. + * + * @param listener a function that receives location updates. + * @returns an function to unsubscribe the listener. + */ + public listen = ( + listener: (location: Location, action: Action) => void + ): UnregisterCallback => { + this.verifyActive(); + this.listeners.add(listener); + return () => { + this.listeners.delete(listener); + }; + }; + + /** + * Creates an href (string) to the location. + * + * @param location + */ + public createHref = (location: LocationDescriptorObject): Href => { + this.verifyActive(); + return this.parentHistory.createHref(location); + }; + + private prependBasePath(path: Path): Path; + private prependBasePath( + location: LocationDescriptorObject + ): LocationDescriptorObject; + /** + * Prepends the scoped base path to the Path or Location + */ + private prependBasePath( + pathOrLocation: Path | LocationDescriptorObject + ): Path | LocationDescriptorObject { + if (typeof pathOrLocation === 'string') { + return this.prependBasePathToString(pathOrLocation); + } else { + return { + ...pathOrLocation, + pathname: + pathOrLocation.pathname !== undefined + ? this.prependBasePathToString(pathOrLocation.pathname) + : undefined, + }; + } + } + + /** + * Prepends the base path to string. + */ + private prependBasePathToString(path: string): string { + path = path.startsWith('/') ? path.slice(1) : path; + return path.length ? `${this.basePath}/${path}` : this.basePath; + } + + /** + * Removes the base path from a location. + */ + private stripBasePath(location: Location): Location { + return { + ...location, + pathname: location.pathname.replace(new RegExp(`^${this.basePath}`), ''), + }; + } + + /** Called on each public method to ensure that we have not fallen out of scope yet. */ + private verifyActive() { + if (!this.isActive) { + throw new Error( + `ScopedHistory instance has fell out of navigation scope for basePath: ${this.basePath}` + ); + } + } + + /** + * Sets up the listener on the parent history instance used to follow navigation updates and track our internal + * state. Also forwards events to child listeners with the base path stripped from the location. + */ + private setupHistoryListener() { + const unlisten = this.parentHistory.listen((location, action) => { + // If the user navigates outside the scope of this basePath, tear it down. + if (!location.pathname.startsWith(this.basePath)) { + unlisten(); + this.isActive = false; + return; + } + + /** + * Track location keys using the same algorithm the browser uses internally. + * - On PUSH, remove all items that came after the current location and append the new location. + * - On POP, set the current location, but do not change the entries. + * - On REPLACE, override the location for the current index with the new location. + */ + if (action === 'PUSH') { + this.locationKeys = [ + ...this.locationKeys.slice(0, this.currentLocationKeyIndex + 1), + location.key, + ]; + this.currentLocationKeyIndex = this.locationKeys.indexOf(location.key); // should always be the last index + } else if (action === 'POP') { + this.currentLocationKeyIndex = this.locationKeys.indexOf(location.key); + } else if (action === 'REPLACE') { + this.locationKeys[this.currentLocationKeyIndex] = location.key; + } else { + throw new Error(`Unrecognized history action: ${action}`); + } + + [...this.listeners].forEach(listener => { + listener(this.stripBasePath(location), action); + }); + }); + } +} diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index 977bb7a52da22..facb818c60ff9 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -32,6 +32,7 @@ import { IUiSettingsClient } from '../ui_settings'; import { RecursiveReadonly } from '../../utils'; import { SavedObjectsStart } from '../saved_objects'; import { AppCategory } from '../../types'; +import { ScopedHistory } from './scoped_history'; /** @public */ export interface AppBase { @@ -199,7 +200,7 @@ export type AppUpdater = (app: AppBase) => Partial | undefin * Extension of {@link AppBase | common app properties} with the mount function. * @public */ -export interface App extends AppBase { +export interface App extends AppBase { /** * A mount function called when the user navigates to this app's route. May have signature of {@link AppMount} or * {@link AppMountDeprecated}. @@ -208,7 +209,7 @@ export interface App extends AppBase { * When function has two arguments, it will be called with a {@link AppMountContext | context} as the first argument. * This behavior is **deprecated**, and consumers should instead use {@link CoreSetup.getStartServices}. */ - mount: AppMount | AppMountDeprecated; + mount: AppMount | AppMountDeprecated; /** * Hide the UI chrome when the application is mounted. Defaults to `false`. @@ -240,7 +241,9 @@ export interface LegacyApp extends AppBase { * * @public */ -export type AppMount = (params: AppMountParameters) => AppUnmount | Promise; +export type AppMount = ( + params: AppMountParameters +) => AppUnmount | Promise; /** * A mount function called when the user navigates to this app's route. @@ -256,9 +259,9 @@ export type AppMount = (params: AppMountParameters) => AppUnmount | Promise = ( context: AppMountContext, - params: AppMountParameters + params: AppMountParameters ) => AppUnmount | Promise; /** @@ -304,16 +307,65 @@ export interface AppMountContext { } /** @public */ -export interface AppMountParameters { +export interface AppMountParameters { /** * The container element to render the application into. */ element: HTMLElement; + /** + * A scoped history instance for your application. Should be used to wire up + * your applications Router. + * + * @example + * How to configure react-router with a base path: + * + * ```ts + * // inside your plugin's setup function + * export class MyPlugin implements Plugin { + * setup({ application }) { + * application.register({ + * id: 'my-app', + * appRoute: '/my-app', + * async mount(params) { + * const { renderApp } = await import('./application'); + * return renderApp(params); + * }, + * }); + * } + * } + * ``` + * + * ```ts + * // application.tsx + * import React from 'react'; + * import ReactDOM from 'react-dom'; + * import { Router, Route } from 'react-router-dom'; + * + * import { CoreStart, AppMountParameters } from 'src/core/public'; + * import { MyPluginDepsStart } from './plugin'; + * + * export renderApp = ({ element, history }: AppMountParameters) => { + * ReactDOM.render( + * // pass `appBasePath` to `basename` + * + * + * , + * element + * ); + * + * return () => ReactDOM.unmountComponentAtNode(element); + * } + * ``` + */ + history: ScopedHistory; + /** * The route path for configuring navigation to the application. * This string should not include the base path from HTTP. * + * @deprecated Use {@link AppMountParameters.history} instead. + * * @example * * How to configure react-router with a base path: @@ -340,10 +392,10 @@ export interface AppMountParameters { * import ReactDOM from 'react-dom'; * import { BrowserRouter, Route } from 'react-router-dom'; * - * import { CoreStart, AppMountParams } from 'src/core/public'; + * import { CoreStart, AppMountParameters } from 'src/core/public'; * import { MyPluginDepsStart } from './plugin'; * - * export renderApp = ({ appBasePath, element }: AppMountParams) => { + * export renderApp = ({ appBasePath, element }: AppMountParameters) => { * ReactDOM.render( * // pass `appBasePath` to `basename` * @@ -498,8 +550,9 @@ export interface ApplicationSetup { /** * Register an mountable application to the system. * @param app - an {@link App} + * @typeParam HistoryLocationState - shape of the `History` state on {@link AppMountParameters.history}, defaults to `unknown`. */ - register(app: App): void; + register(app: App): void; /** * Register an application updater that can be used to change the {@link AppUpdatableFields} fields @@ -551,7 +604,10 @@ export interface InternalApplicationSetup extends Pick( + plugin: PluginOpaqueId, + app: App + ): void; /** * Register metadata about legacy applications. Legacy apps will not be mounted when navigated to. diff --git a/src/core/public/application/ui/app_container.test.tsx b/src/core/public/application/ui/app_container.test.tsx index a46243a2da493..c538227e8f098 100644 --- a/src/core/public/application/ui/app_container.test.tsx +++ b/src/core/public/application/ui/app_container.test.tsx @@ -22,6 +22,8 @@ import { mount } from 'enzyme'; import { AppContainer } from './app_container'; import { Mounter, AppMountParameters, AppStatus } from '../types'; +import { createMemoryHistory } from 'history'; +import { ScopedHistory } from '../scoped_history'; describe('AppContainer', () => { const appId = 'someApp'; @@ -60,10 +62,15 @@ describe('AppContainer', () => { const wrapper = mount( + // Create a history using the appPath as the current location + new ScopedHistory(createMemoryHistory({ initialEntries: [appPath] }), appPath) + } /> ); diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx index 885157843e7df..e12a0f2cf2fcd 100644 --- a/src/core/public/application/ui/app_container.tsx +++ b/src/core/public/application/ui/app_container.tsx @@ -28,18 +28,24 @@ import React, { import { AppLeaveHandler, AppStatus, AppUnmount, Mounter } from '../types'; import { AppNotFound } from './app_not_found_screen'; +import { ScopedHistory } from '../scoped_history'; interface Props { + /** Path application is mounted on without the global basePath */ + appPath: string; appId: string; mounter?: Mounter; appStatus: AppStatus; setAppLeaveHandler: (appId: string, handler: AppLeaveHandler) => void; + createScopedHistory: (appUrl: string) => ScopedHistory; } export const AppContainer: FunctionComponent = ({ mounter, appId, + appPath, setAppLeaveHandler, + createScopedHistory, appStatus, }: Props) => { const [appNotFound, setAppNotFound] = useState(false); @@ -67,6 +73,7 @@ export const AppContainer: FunctionComponent = ({ unmountRef.current = (await mounter.mount({ appBasePath: mounter.appBasePath, + history: createScopedHistory(appPath), element: elementRef.current!, onAppLeave: handler => setAppLeaveHandler(appId, handler), })) || null; @@ -75,7 +82,7 @@ export const AppContainer: FunctionComponent = ({ mount(); return unmount; - }, [appId, appStatus, mounter, setAppLeaveHandler]); + }, [appId, appStatus, mounter, createScopedHistory, setAppLeaveHandler, appPath]); return ( diff --git a/src/core/public/application/ui/app_router.tsx b/src/core/public/application/ui/app_router.tsx index 50e5f5ee1bd62..61c8bc3cadae5 100644 --- a/src/core/public/application/ui/app_router.tsx +++ b/src/core/public/application/ui/app_router.tsx @@ -17,7 +17,7 @@ * under the License. */ -import React, { FunctionComponent } from 'react'; +import React, { FunctionComponent, useMemo } from 'react'; import { Route, RouteComponentProps, Router, Switch } from 'react-router-dom'; import { History } from 'history'; import { Observable } from 'rxjs'; @@ -25,6 +25,7 @@ import { useObservable } from 'react-use'; import { AppLeaveHandler, AppStatus, Mounter } from '../types'; import { AppContainer } from './app_container'; +import { ScopedHistory } from '../scoped_history'; interface Props { mounters: Map; @@ -44,6 +45,11 @@ export const AppRouter: FunctionComponent = ({ appStatuses$, }) => { const appStatuses = useObservable(appStatuses$, new Map()); + const createScopedHistory = useMemo( + () => (appPath: string) => new ScopedHistory(history, appPath), + [history] + ); + return ( @@ -56,12 +62,12 @@ export const AppRouter: FunctionComponent = ({ ( + render={({ match: { url } }) => ( )} />, @@ -72,6 +78,7 @@ export const AppRouter: FunctionComponent = ({ render={({ match: { params: { appId }, + url, }, }: RouteComponentProps) => { // Find the mounter including legacy mounters with subapps: @@ -81,10 +88,11 @@ export const AppRouter: FunctionComponent = ({ return ( ); }} diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 6d756e36d7379..483d4dbfdf7c5 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -108,6 +108,7 @@ export { AppNavLinkStatus, AppUpdatableFields, AppUpdater, + ScopedHistory, } from './application'; export { diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index 3301d71e2cdaf..8ea672890ca29 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -41,6 +41,7 @@ export { notificationServiceMock } from './notifications/notifications_service.m export { overlayServiceMock } from './overlays/overlay_service.mock'; export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; export { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock'; +export { scopedHistoryMock } from './application/scoped_history.mock'; function createCoreSetupMock({ basePath = '' } = {}) { const mock = { diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index ba1988b857385..cd956eb17531a 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -4,25 +4,30 @@ ```ts +import { Action } from 'history'; import { Breadcrumb } from '@elastic/eui'; import { EuiButtonEmptyProps } from '@elastic/eui'; import { EuiConfirmModalProps } from '@elastic/eui'; import { EuiGlobalToastListToast } from '@elastic/eui'; import { ExclusiveUnion } from '@elastic/eui'; +import { History } from 'history'; import { IconType } from '@elastic/eui'; +import { Location } from 'history'; +import { LocationDescriptorObject } from 'history'; import { MaybePromise } from '@kbn/utility-types'; import { Observable } from 'rxjs'; import React from 'react'; import * as Rx from 'rxjs'; import { ShallowPromise } from '@kbn/utility-types'; import { UiSettingsParams as UiSettingsParams_2 } from 'src/core/server/types'; +import { UnregisterCallback } from 'history'; import { UserProvidedValues as UserProvidedValues_2 } from 'src/core/server/types'; // @public -export interface App extends AppBase { +export interface App extends AppBase { appRoute?: string; chromeless?: boolean; - mount: AppMount | AppMountDeprecated; + mount: AppMount | AppMountDeprecated; } // @public (undocumented) @@ -89,7 +94,7 @@ export type AppLeaveHandler = (factory: AppLeaveActionFactory) => AppLeaveAction // @public (undocumented) export interface ApplicationSetup { - register(app: App): void; + register(app: App): void; registerAppUpdater(appUpdater$: Observable): void; // @deprecated registerMountContext(contextName: T, provider: IContextProvider): void; @@ -112,7 +117,7 @@ export interface ApplicationStart { } // @public -export type AppMount = (params: AppMountParameters) => AppUnmount | Promise; +export type AppMount = (params: AppMountParameters) => AppUnmount | Promise; // @public @deprecated export interface AppMountContext { @@ -133,12 +138,14 @@ export interface AppMountContext { } // @public @deprecated -export type AppMountDeprecated = (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise; +export type AppMountDeprecated = (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise; // @public (undocumented) -export interface AppMountParameters { +export interface AppMountParameters { + // @deprecated appBasePath: string; element: HTMLElement; + history: ScopedHistory; onAppLeave: (handler: AppLeaveHandler) => void; } @@ -1175,6 +1182,23 @@ export interface SavedObjectsUpdateOptions { version?: string; } +// @public +export class ScopedHistory implements History { + constructor(parentHistory: History, basePath: string); + get action(): Action; + block: (prompt?: string | boolean | History.TransitionPromptHook | undefined) => UnregisterCallback; + createHref: (location: LocationDescriptorObject) => string; + createSubHistory: (basePath: string) => ScopedHistory; + go: (n: number) => void; + goBack: () => void; + goForward: () => void; + get length(): number; + listen: (listener: (location: Location, action: Action) => void) => UnregisterCallback; + get location(): Location; + push: (pathOrLocation: string | LocationDescriptorObject, state?: HistoryLocationState | undefined) => void; + replace: (pathOrLocation: string | LocationDescriptorObject, state?: HistoryLocationState | undefined) => void; + } + // @public export class SimpleSavedObject { constructor(client: SavedObjectsClientContract, { id, type, version, attributes, error, references, migrationVersion }: SavedObject); diff --git a/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts b/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts index 90328003c8292..14564cfd9ee78 100644 --- a/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts +++ b/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts @@ -68,7 +68,13 @@ export class LocalApplicationService { isUnmounted = true; }); (async () => { - const params = { element, appBasePath: '', onAppLeave: () => undefined }; + const params = { + element, + appBasePath: '', + onAppLeave: () => undefined, + // TODO: adapt to use Core's ScopedHistory + history: {} as any, + }; unmountHandler = isAppMountDeprecated(app.mount) ? await app.mount({ core: npStart.core }, params) : await app.mount(params); diff --git a/src/legacy/ui/public/new_platform/new_platform.test.mocks.ts b/src/legacy/ui/public/new_platform/new_platform.test.mocks.ts index e660ad1f55840..f44efe17ef8ee 100644 --- a/src/legacy/ui/public/new_platform/new_platform.test.mocks.ts +++ b/src/legacy/ui/public/new_platform/new_platform.test.mocks.ts @@ -17,8 +17,15 @@ * under the License. */ +import { scopedHistoryMock } from '../../../../core/public/mocks'; + export const setRootControllerMock = jest.fn(); jest.doMock('ui/chrome', () => ({ setRootController: setRootControllerMock, })); + +export const historyMock = scopedHistoryMock.create(); +jest.doMock('../../../../core/public', () => ({ + ScopedHistory: jest.fn(() => historyMock), +})); diff --git a/src/legacy/ui/public/new_platform/new_platform.test.ts b/src/legacy/ui/public/new_platform/new_platform.test.ts index e050ffd5b530c..498f05457bba9 100644 --- a/src/legacy/ui/public/new_platform/new_platform.test.ts +++ b/src/legacy/ui/public/new_platform/new_platform.test.ts @@ -17,7 +17,9 @@ * under the License. */ -import { setRootControllerMock } from './new_platform.test.mocks'; +jest.mock('history'); + +import { setRootControllerMock, historyMock } from './new_platform.test.mocks'; import { legacyAppRegister, __reset__, __setup__ } from './new_platform'; import { coreMock } from '../../../../core/public/mocks'; @@ -63,6 +65,7 @@ describe('ui/new_platform', () => { element: elementMock[0], appBasePath: '/test/base/path/app/test', onAppLeave: expect.any(Function), + history: historyMock, }); }); @@ -84,6 +87,7 @@ describe('ui/new_platform', () => { element: elementMock[0], appBasePath: '/test/base/path/app/test', onAppLeave: expect.any(Function), + history: historyMock, }); }); diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts index b7994c7f68afb..00d76bc341322 100644 --- a/src/legacy/ui/public/new_platform/new_platform.ts +++ b/src/legacy/ui/public/new_platform/new_platform.ts @@ -20,7 +20,14 @@ import { IScope } from 'angular'; import { UiActionsStart, UiActionsSetup } from 'src/plugins/ui_actions/public'; import { IEmbeddableStart, IEmbeddableSetup } from 'src/plugins/embeddable/public'; -import { LegacyCoreSetup, LegacyCoreStart, App, AppMountDeprecated } from '../../../../core/public'; +import { createBrowserHistory } from 'history'; +import { + LegacyCoreSetup, + LegacyCoreStart, + App, + AppMountDeprecated, + ScopedHistory, +} from '../../../../core/public'; import { Plugin as DataPlugin } from '../../../../plugins/data/public'; import { Plugin as ExpressionsPlugin } from '../../../../plugins/expressions/public'; import { @@ -126,7 +133,7 @@ let legacyAppRegistered = false; * Exported for testing only. Use `npSetup.core.application.register` in legacy apps. * @internal */ -export const legacyAppRegister = (app: App) => { +export const legacyAppRegister = (app: App) => { if (legacyAppRegistered) { throw new Error(`core.application.register may only be called once for legacy plugins.`); } @@ -137,9 +144,15 @@ export const legacyAppRegister = (app: App) => { // Root controller cannot return a Promise so use an internal async function and call it immediately (async () => { + const appRoute = app.appRoute || `/app/${app.id}`; + const appBasePath = npSetup.core.http.basePath.prepend(appRoute); const params = { element, - appBasePath: npSetup.core.http.basePath.prepend(`/app/${app.id}`), + appBasePath, + history: new ScopedHistory( + createBrowserHistory({ basename: npSetup.core.http.basePath.get() }), + appRoute + ), onAppLeave: () => undefined, }; const unmount = isAppMountDeprecated(app.mount) diff --git a/src/plugins/dev_tools/public/application.tsx b/src/plugins/dev_tools/public/application.tsx index a179be6946c76..2c21b451cb9f7 100644 --- a/src/plugins/dev_tools/public/application.tsx +++ b/src/plugins/dev_tools/public/application.tsx @@ -91,7 +91,13 @@ function DevToolsWrapper({ if (mountedTool.current) { mountedTool.current.unmountHandler(); } - const params = { element, appBasePath: '', onAppLeave: () => undefined }; + const params = { + element, + appBasePath: '', + onAppLeave: () => undefined, + // TODO: adapt to use Core's ScopedHistory + history: {} as any, + }; const unmountHandler = isAppMountDeprecated(activeDevTool.mount) ? await activeDevTool.mount(appMountContext, params) : await activeDevTool.mount(params); diff --git a/test/plugin_functional/plugins/core_plugin_a/public/application.tsx b/test/plugin_functional/plugins/core_plugin_a/public/application.tsx index 7c1406f5b20c3..abea970749cbc 100644 --- a/test/plugin_functional/plugins/core_plugin_a/public/application.tsx +++ b/test/plugin_functional/plugins/core_plugin_a/public/application.tsx @@ -17,9 +17,10 @@ * under the License. */ +import { History } from 'history'; import React from 'react'; import ReactDOM from 'react-dom'; -import { BrowserRouter as Router, Route, withRouter, RouteComponentProps } from 'react-router-dom'; +import { Router, Route, withRouter, RouteComponentProps } from 'react-router-dom'; import { EuiPage, @@ -115,8 +116,8 @@ const Nav = withRouter(({ history, navigateToApp }: NavProps) => ( /> )); -const FooApp = ({ basename, context }: { basename: string; context: AppMountContext }) => ( - +const FooApp = ({ history, context }: { history: History; context: AppMountContext }) => ( +
@@ -64,9 +66,11 @@ exports[`FieldName renders a number field by providing a field record, useShortD class="euiFlexItem eui-textTruncate" > - test.test.test + + test.test.test + @@ -100,9 +104,11 @@ exports[`FieldName renders a string field by providing fieldType and fieldName 1 class="euiFlexItem eui-textTruncate" > - test + + test + diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/field_name/field_name.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/field_name/field_name.tsx index 54e1c1706a856..e2aa33179f632 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/field_name/field_name.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/field_name/field_name.tsx @@ -18,7 +18,7 @@ */ import React from 'react'; import classNames from 'classnames'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; import { FieldIcon, FieldIconProps } from '../../../../../../../../../plugins/kibana_react/public'; import { shortenDottedString } from '../../../../../../../../../plugins/data/common/utils'; @@ -64,7 +64,14 @@ export function FieldName({ field, fieldName, fieldType, useShortDots, fieldIcon />
- {displayName} + + {displayName} +
); From 92840fe2181ccb43d032df94c1a277f49c52a503 Mon Sep 17 00:00:00 2001 From: Maryia Lapata Date: Thu, 27 Feb 2020 10:35:44 +0300 Subject: [PATCH 32/64] [NP] Import saved objects styles directly (#58208) * Import styles for saved objects * Rename index.scss Co-authored-by: Elastic Machine --- src/legacy/ui/public/_index.scss | 1 - src/legacy/ui/public/saved_objects/_index.scss | 1 - src/plugins/saved_objects/public/{_index.scss => index.scss} | 0 src/plugins/saved_objects/public/plugin.ts | 2 ++ 4 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 src/legacy/ui/public/saved_objects/_index.scss rename src/plugins/saved_objects/public/{_index.scss => index.scss} (100%) diff --git a/src/legacy/ui/public/_index.scss b/src/legacy/ui/public/_index.scss index e990ba2a46de5..3c3067776a161 100644 --- a/src/legacy/ui/public/_index.scss +++ b/src/legacy/ui/public/_index.scss @@ -15,7 +15,6 @@ @import './error_url_overflow/index'; @import './exit_full_screen/index'; @import './field_editor/index'; -@import './saved_objects/index'; @import './share/index'; @import './style_compile/index'; @import '../../../plugins/management/public/components/index'; diff --git a/src/legacy/ui/public/saved_objects/_index.scss b/src/legacy/ui/public/saved_objects/_index.scss deleted file mode 100644 index 89cda29f67744..0000000000000 --- a/src/legacy/ui/public/saved_objects/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import '../../../../plugins/saved_objects/public/index'; diff --git a/src/plugins/saved_objects/public/_index.scss b/src/plugins/saved_objects/public/index.scss similarity index 100% rename from src/plugins/saved_objects/public/_index.scss rename to src/plugins/saved_objects/public/index.scss diff --git a/src/plugins/saved_objects/public/plugin.ts b/src/plugins/saved_objects/public/plugin.ts index e937c271b6faf..5092f7a0b7b33 100644 --- a/src/plugins/saved_objects/public/plugin.ts +++ b/src/plugins/saved_objects/public/plugin.ts @@ -19,6 +19,8 @@ import { Plugin } from 'src/core/public'; +import './index.scss'; + export class SavedObjectsPublicPlugin implements Plugin { public setup() {} public start() {} From 320e292ea8b32f397b59ec595af3822f37b11f1c Mon Sep 17 00:00:00 2001 From: patrykkopycinski Date: Thu, 27 Feb 2020 09:25:37 +0100 Subject: [PATCH 33/64] [SIEM] apollo@3 (#51926) --- package.json | 17 +- .../basic_optimization.test.ts | 1 - .../integration_tests/bundle_cache.test.ts | 1 - .../src/worker/webpack.config.ts | 2 +- packages/kbn-pm/dist/index.js | 26323 +--------------- .../siem/common/graphql/root/schema.gql.ts | 2 +- .../siem/common/graphql/shared/schema.gql.ts | 2 +- x-pack/legacy/plugins/siem/public/app/app.tsx | 20 +- .../drag_drop_context_wrapper.test.tsx | 4 +- .../drag_and_drop/draggable_wrapper.test.tsx | 4 +- .../drag_and_drop/droppable_wrapper.test.tsx | 4 +- .../components/event_details/columns.tsx | 4 +- .../components/event_details/helpers.tsx | 4 +- .../events_viewer/events_viewer.test.tsx | 11 +- .../events_viewer/events_viewer.tsx | 3 +- .../components/events_viewer/index.test.tsx | 7 +- .../siem/public/components/flyout/index.tsx | 13 +- .../__snapshots__/index.test.tsx.snap | 103 +- .../components/header_global/index.test.tsx | 7 +- .../public/components/header_global/index.tsx | 108 +- .../components/open_timeline/helpers.ts | 2 +- .../components/open_timeline/index.test.tsx | 115 +- .../public/components/open_timeline/index.tsx | 5 +- .../open_timeline/open_timeline.test.tsx | 2 +- .../open_timeline_modal/index.test.tsx | 8 +- .../open_timeline_modal/index.tsx | 44 +- .../open_timeline_modal_body.test.tsx | 2 +- .../open_timeline_modal_button.test.tsx | 7 +- .../timelines_table/actions_columns.test.tsx | 2 +- .../timelines_table/common_columns.test.tsx | 2 +- .../timelines_table/extended_columns.test.tsx | 2 +- .../icon_header_columns.test.tsx | 2 +- .../timelines_table/index.test.tsx | 2 +- .../hosts/first_last_seen_host/index.test.tsx | 12 +- .../page/hosts/first_last_seen_host/index.tsx | 68 +- .../__snapshots__/index.test.tsx.snap | 91 - .../page/hosts/hosts_table/index.test.tsx | 11 +- .../page/hosts/hosts_table/index.tsx | 4 - .../components/page/hosts/kpi_hosts/index.tsx | 4 +- .../network/network_dns_table/index.test.tsx | 2 +- .../network/network_http_table/index.test.tsx | 2 +- .../index.test.tsx | 2 +- .../network_top_n_flow_table/index.test.tsx | 2 +- .../page/network/tls_table/index.test.tsx | 2 +- .../page/network/users_table/index.test.tsx | 2 +- .../overview/overview_host/index.test.tsx | 11 +- .../overview/overview_network/index.test.tsx | 11 +- .../page/overview/overview_network/index.tsx | 10 +- .../components/recent_timelines/index.tsx | 6 +- .../public/components/search_bar/index.tsx | 2 +- .../public/components/stat_items/index.tsx | 10 +- .../components/super_date_picker/index.tsx | 2 +- .../components/timeline/body/helpers.test.ts | 4 +- .../__snapshots__/zeek_details.test.tsx.snap | 771 +- .../timeline/body/stateful_body.tsx | 3 +- .../timeline/fetch_kql_timeline.tsx | 12 +- .../components/timeline/footer/index.tsx | 3 - .../components/timeline/header/index.tsx | 18 +- .../public/components/timeline/helpers.tsx | 130 +- .../siem/public/components/timeline/index.tsx | 74 +- .../timeline/search_or_filter/index.tsx | 2 +- .../components/timeline/timeline.test.tsx | 2 +- .../public/components/timeline/timeline.tsx | 31 +- .../components/url_state/index.test.tsx | 29 +- .../public/components/url_state/index.tsx | 2 +- .../url_state/index_mocked.test.tsx | 17 +- .../siem/public/components/url_state/types.ts | 5 +- .../components/url_state/use_url_state.tsx | 2 +- .../authentications/index.gql_query.ts | 2 +- .../containers/authentications/index.tsx | 11 +- .../rules/fetch_index_patterns.test.tsx | 4 +- .../rules/fetch_index_patterns.tsx | 2 +- .../public/containers/errors/index.test.tsx | 3 +- .../events/last_event_time/index.ts | 88 +- .../last_event_time.gql_query.ts | 2 +- .../containers/events/last_event_time/mock.ts | 11 +- .../public/containers/global_time/index.tsx | 71 +- .../plugins/siem/public/containers/helpers.ts | 4 +- .../first_last_seen.gql_query.ts | 2 +- .../containers/hosts/first_last_seen/index.ts | 11 +- .../containers/hosts/first_last_seen/mock.ts | 10 +- .../containers/hosts/hosts_table.gql_query.ts | 2 +- .../siem/public/containers/hosts/index.tsx | 10 +- .../hosts/overview/host_overview.gql_query.ts | 2 +- .../containers/hosts/overview/index.tsx | 15 +- .../containers/ip_overview/index.gql_query.ts | 2 +- .../public/containers/ip_overview/index.tsx | 12 +- ...index.gql_query.tsx => index.gql_query.ts} | 2 +- .../containers/kpi_host_details/index.tsx | 12 +- .../containers/kpi_hosts/index.gql_query.ts | 2 +- .../public/containers/kpi_hosts/index.tsx | 12 +- .../containers/kpi_network/index.gql_query.ts | 2 +- .../public/containers/kpi_network/index.tsx | 12 +- .../matrix_histogram/index.gql_query.ts | 2 +- .../matrix_histogram/index.test.tsx | 5 +- .../containers/matrix_histogram/index.ts | 3 +- .../containers/network_dns/index.gql_query.ts | 2 +- .../public/containers/network_dns/index.tsx | 10 +- .../network_http/index.gql_query.ts | 2 +- .../public/containers/network_http/index.tsx | 10 +- .../network_top_countries/index.gql_query.ts | 2 +- .../network_top_countries/index.tsx | 10 +- .../network_top_n_flow/index.gql_query.ts | 2 +- .../containers/network_top_n_flow/index.tsx | 10 +- .../overview/overview_host/index.gql_query.ts | 2 +- .../overview/overview_host/index.tsx | 64 +- .../overview_network/index.gql_query.ts | 2 +- .../overview/overview_network/index.tsx | 12 +- .../siem/public/containers/query_template.tsx | 8 +- .../containers/query_template_paginated.tsx | 11 +- .../containers/source/index.gql_query.ts | 2 +- .../public/containers/source/index.test.tsx | 44 +- .../siem/public/containers/source/index.tsx | 127 +- .../timeline/all/index.gql_query.ts | 2 +- .../public/containers/timeline/all/index.tsx | 11 +- .../timeline/delete/persist.gql_query.ts | 2 +- .../timeline/details/index.gql_query.ts | 2 +- .../containers/timeline/details/index.tsx | 14 +- .../timeline/favorite/persist.gql_query.ts | 2 +- .../containers/timeline/index.gql_query.ts | 2 +- .../siem/public/containers/timeline/index.tsx | 16 +- .../timeline/notes/persist.gql_query.ts | 2 +- .../timeline/one/index.gql_query.ts | 2 +- .../containers/timeline/persist.gql_query.ts | 2 +- .../pinned_event/persist.gql_query.ts | 2 +- .../public/containers/tls/index.gql_query.ts | 2 +- .../siem/public/containers/tls/index.tsx | 10 +- .../uncommon_processes/index.gql_query.ts | 2 +- .../containers/uncommon_processes/index.tsx | 11 +- .../containers/users/index.gql_query.ts | 2 +- .../siem/public/containers/users/index.tsx | 18 +- .../siem/public/graphql/introspection.json | 12556 -------- .../plugins/siem/public/graphql/types.ts | 5943 ---- .../plugins/siem/public/graphql/types.tsx | 5314 ++++ .../siem/public/lib/compose/helpers.test.ts | 25 +- .../siem/public/lib/compose/helpers.ts | 12 +- .../public/lib/compose/kibana_compose.tsx | 21 +- x-pack/legacy/plugins/siem/public/lib/lib.ts | 3 +- .../siem/public/mock/test_providers.tsx | 7 +- .../siem/public/mock/timeline_results.ts | 10 +- .../components/signals/default_config.tsx | 4 +- .../components/signals/index.tsx | 2 +- .../components/signals/types.ts | 4 +- .../detection_engine/detection_engine.tsx | 166 +- .../detection_engine/rules/details/index.tsx | 291 +- .../plugins/siem/public/pages/home/index.tsx | 151 +- .../pages/hosts/details/details_tabs.test.tsx | 12 +- .../pages/hosts/details/details_tabs.tsx | 1 - .../siem/public/pages/hosts/details/index.tsx | 216 +- .../siem/public/pages/hosts/hosts.test.tsx | 5 +- .../plugins/siem/public/pages/hosts/hosts.tsx | 152 +- .../siem/public/pages/hosts/hosts_tabs.tsx | 39 +- .../plugins/siem/public/pages/hosts/index.tsx | 116 +- .../navigation/events_query_tab_body.tsx | 4 +- .../hosts/navigation/hosts_query_tab_body.tsx | 2 - .../public/pages/hosts/navigation/types.ts | 3 +- .../plugins/siem/public/pages/hosts/types.ts | 2 - .../siem/public/pages/network/index.tsx | 111 +- .../__snapshots__/index.test.tsx.snap | 65 +- .../pages/network/ip_details/index.test.tsx | 72 +- .../public/pages/network/ip_details/index.tsx | 305 +- .../public/pages/network/network.test.tsx | 5 +- .../siem/public/pages/network/network.tsx | 176 +- .../pages/overview/event_counts/index.tsx | 28 +- .../siem/public/pages/overview/index.tsx | 4 +- .../public/pages/overview/overview.test.tsx | 5 +- .../siem/public/pages/overview/overview.tsx | 167 +- .../public/pages/overview/sidebar/sidebar.tsx | 4 +- .../siem/public/pages/timelines/index.tsx | 39 +- .../public/pages/timelines/timelines_page.tsx | 48 - .../public/store/timeline/epic_favorite.ts | 3 +- .../siem/public/store/timeline/epic_note.ts | 3 +- .../store/timeline/epic_pinned_event.ts | 3 +- .../siem/public/utils/apollo_context.ts | 19 - .../siem/public/utils/route/spy_routes.tsx | 3 +- .../plugins/siem/scripts/combined_schema.ts | 2 +- .../scripts/generate_types_from_graphql.js | 275 +- .../graphql/authentications/resolvers.ts | 9 +- .../graphql/authentications/schema.gql.ts | 2 +- .../siem/server/graphql/ecs/schema.gql.ts | 2 +- .../siem/server/graphql/events/resolvers.ts | 24 +- .../siem/server/graphql/events/schema.gql.ts | 2 +- .../siem/server/graphql/hosts/resolvers.ts | 23 +- .../siem/server/graphql/hosts/schema.gql.ts | 2 +- .../server/graphql/ip_details/resolvers.ts | 16 +- .../server/graphql/ip_details/schema.gql.ts | 2 +- .../server/graphql/kpi_hosts/resolvers.ts | 16 +- .../server/graphql/kpi_hosts/schema.gql.ts | 2 +- .../server/graphql/kpi_network/resolvers.ts | 9 +- .../server/graphql/kpi_network/schema.gql.ts | 2 +- .../graphql/matrix_histogram/resolvers.ts | 9 +- .../graphql/matrix_histogram/schema.gql.ts | 2 +- .../siem/server/graphql/network/resolvers.ts | 30 +- .../siem/server/graphql/network/schema.gql.ts | 2 +- .../siem/server/graphql/note/resolvers.ts | 38 +- .../siem/server/graphql/note/schema.gql.ts | 2 +- .../siem/server/graphql/overview/resolvers.ts | 16 +- .../server/graphql/overview/schema.gql.ts | 2 +- .../server/graphql/pinned_event/resolvers.ts | 25 +- .../server/graphql/pinned_event/schema.gql.ts | 2 +- .../graphql/scalar_date/resolvers.test.ts | 4 +- .../server/graphql/scalar_date/schema.gql.ts | 2 +- .../graphql/scalar_to_any/schema.gql.ts | 2 +- .../scalar_to_boolean_array/schema.gql.ts | 2 +- .../scalar_to_date_array/schema.gql.ts | 2 +- .../scalar_to_number_array/schema.gql.ts | 2 +- .../server/graphql/source_status/resolvers.ts | 16 +- .../graphql/source_status/schema.gql.ts | 2 +- .../siem/server/graphql/sources/resolvers.ts | 56 +- .../siem/server/graphql/sources/schema.gql.ts | 2 +- .../siem/server/graphql/timeline/resolvers.ts | 28 +- .../server/graphql/timeline/schema.gql.ts | 2 +- .../siem/server/graphql/tls/resolvers.ts | 9 +- .../siem/server/graphql/tls/schema.gql.ts | 2 +- .../plugins/siem/server/graphql/types.ts | 12351 +++----- .../graphql/uncommon_processes/resolvers.ts | 9 +- .../graphql/uncommon_processes/schema.gql.ts | 2 +- .../siem/server/graphql/who_am_i/resolvers.ts | 9 +- .../server/graphql/who_am_i/schema.gql.ts | 2 +- .../legacy/plugins/siem/server/init_server.ts | 2 +- .../siem/server/lib/framework/types.ts | 6 +- .../siem/server/utils/typed_resolvers.ts | 111 - x-pack/package.json | 25 +- .../apis/siem/feature_controls.ts | 2 +- .../apis/siem/saved_objects/notes.ts | 2 +- .../apis/siem/saved_objects/timeline.ts | 2 +- .../services/siem_graphql_client.ts | 11 +- yarn.lock | 1734 +- 228 files changed, 14193 insertions(+), 55777 deletions(-) rename x-pack/legacy/plugins/siem/public/containers/kpi_host_details/{index.gql_query.tsx => index.gql_query.ts} (97%) delete mode 100644 x-pack/legacy/plugins/siem/public/graphql/introspection.json delete mode 100644 x-pack/legacy/plugins/siem/public/graphql/types.ts create mode 100644 x-pack/legacy/plugins/siem/public/graphql/types.tsx delete mode 100644 x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.tsx delete mode 100644 x-pack/legacy/plugins/siem/public/utils/apollo_context.ts delete mode 100644 x-pack/legacy/plugins/siem/server/utils/typed_resolvers.ts diff --git a/package.json b/package.json index 0f04a2fba3b65..4ac4cbea96248 100644 --- a/package.json +++ b/package.json @@ -77,23 +77,31 @@ "url": "https://github.com/elastic/kibana.git" }, "resolutions": { + "**/@apollo/client": "^3.0.0-beta.37", + "**/@graphql-toolkit/common": "^0.9.7", + "**/@graphql-toolkit/core": "^0.9.7", + "**/@graphql-toolkit/graphql-file-loader": "^0.9.7", + "**/@graphql-toolkit/json-file-loader": "^0.9.7", + "**/@graphql-toolkit/schema-merging": "^0.9.7", + "**/@graphql-toolkit/url-loader": "^0.9.7", "**/@types/node": "10.12.27", "**/@types/react": "^16.9.19", "**/@types/react-router": "^5.1.3", "**/@types/hapi": "^17.0.18", "**/@types/angular": "^1.6.56", "**/@types/hoist-non-react-statics": "^3.3.1", - "**/typescript": "3.7.2", - "**/graphql-toolkit/lodash": "^4.17.13", + "**/apollo-link": "^1.2.13", + "**/deepmerge": "^4.2.2", + "**/fast-deep-equal": "^3.1.1", + "**/fast-glob": "3.1.1", "**/hoist-non-react-statics": "^3.3.2", "**/isomorphic-git/**/base64-js": "^1.2.1", "**/image-diff/gm/debug": "^2.6.9", "**/react-dom": "^16.12.0", "**/react": "^16.12.0", "**/react-test-renderer": "^16.12.0", - "**/deepmerge": "^4.2.2", "**/serialize-javascript": "^2.1.1", - "**/fast-deep-equal": "^3.1.1" + "**/typescript": "3.7.2" }, "workspaces": { "packages": [ @@ -325,7 +333,6 @@ "@types/getopts": "^2.0.1", "@types/glob": "^7.1.1", "@types/globby": "^8.0.0", - "@types/graphql": "^0.13.2", "@types/hapi": "^17.0.18", "@types/hapi-auth-cookie": "^9.1.0", "@types/has-ansi": "^3.0.0", diff --git a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts index fec31cbe40dfe..3d9393fd2d005 100644 --- a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts @@ -38,7 +38,6 @@ beforeAll(async () => { await cpy('**/*', MOCK_REPO_DIR, { cwd: MOCK_REPO_SRC, parents: true, - deep: true, }); }); diff --git a/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts b/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts index 1bfd8d3fd073a..3cddbfc53c1b9 100644 --- a/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts @@ -44,7 +44,6 @@ beforeEach(async () => { await cpy('**/*', MOCK_REPO_DIR, { cwd: MOCK_REPO_SRC, parents: true, - deep: true, }); }); diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 3c6ae78bc4d91..9ca0ad5811ef8 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -217,7 +217,7 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) { }, resolve: { - extensions: ['.js', '.ts', '.tsx', '.json'], + extensions: ['.mjs', '.js', '.ts', '.tsx', '.json'], alias: { tinymath: require.resolve('tinymath/lib/tinymath.es5.js'), }, diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index fe0491870e4bd..99b4b82a7e99b 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__(704); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(705); /* 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__(689); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(690); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -2507,8 +2507,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__(586); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(686); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(687); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(687); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(688); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -67704,7 +67704,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__(587); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(675); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(676); /* 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__); @@ -67813,12 +67813,12 @@ const {promisify} = __webpack_require__(29); const path = __webpack_require__(16); const globby = __webpack_require__(588); const isGlob = __webpack_require__(605); -const slash = __webpack_require__(666); +const slash = __webpack_require__(667); const gracefulFs = __webpack_require__(22); -const isPathCwd = __webpack_require__(668); -const isPathInside = __webpack_require__(669); -const rimraf = __webpack_require__(670); -const pMap = __webpack_require__(671); +const isPathCwd = __webpack_require__(669); +const isPathInside = __webpack_require__(670); +const rimraf = __webpack_require__(671); +const pMap = __webpack_require__(672); const rimrafP = promisify(rimraf); @@ -67942,9 +67942,9 @@ const arrayUnion = __webpack_require__(589); const merge2 = __webpack_require__(590); const glob = __webpack_require__(591); const fastGlob = __webpack_require__(596); -const dirGlob = __webpack_require__(662); -const gitignore = __webpack_require__(664); -const {FilterStream, UniqueStream} = __webpack_require__(667); +const dirGlob = __webpack_require__(663); +const gitignore = __webpack_require__(665); +const {FilterStream, UniqueStream} = __webpack_require__(668); const DEFAULT_FILTER = () => false; @@ -69831,10 +69831,10 @@ function childrenIgnored (self, path) { "use strict"; const taskManager = __webpack_require__(597); -const async_1 = __webpack_require__(625); -const stream_1 = __webpack_require__(658); -const sync_1 = __webpack_require__(659); -const settings_1 = __webpack_require__(661); +const async_1 = __webpack_require__(626); +const stream_1 = __webpack_require__(659); +const sync_1 = __webpack_require__(660); +const settings_1 = __webpack_require__(662); const utils = __webpack_require__(598); function FastGlob(source, options) { try { @@ -69846,6 +69846,8 @@ function FastGlob(source, options) { const works = getWorks(source, async_1.default, options); return Promise.all(works).then(utils.array.flatten); } +// https://github.com/typescript-eslint/typescript-eslint/issues/60 +// eslint-disable-next-line no-redeclare (function (FastGlob) { function sync(source, options) { assertPatternsInput(source); @@ -69871,6 +69873,17 @@ function FastGlob(source, options) { return taskManager.generate(patterns, settings); } FastGlob.generateTasks = generateTasks; + function isDynamicPattern(source, options) { + assertPatternsInput(source); + const settings = new settings_1.default(options); + return utils.pattern.isDynamicPattern(source, settings); + } + FastGlob.isDynamicPattern = isDynamicPattern; + function escapePath(source) { + assertPatternsInput(source); + return utils.path.escape(source); + } + FastGlob.escapePath = escapePath; })(FastGlob || (FastGlob = {})); function getWorks(source, _Provider, options) { const patterns = [].concat(source); @@ -69886,7 +69899,6 @@ function assertPatternsInput(source) { 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; @@ -69903,12 +69915,8 @@ const utils = __webpack_require__(598); 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 staticPatterns = positivePatterns.filter((pattern) => utils.pattern.isStaticPattern(pattern, settings)); + const dynamicPatterns = positivePatterns.filter((pattern) => utils.pattern.isDynamicPattern(pattern, settings)); const staticTasks = convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false); const dynamicTasks = convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true); return staticTasks.concat(dynamicTasks); @@ -69936,6 +69944,7 @@ function getNegativePatternsAsPositive(patterns, ignore) { } exports.getNegativePatternsAsPositive = getNegativePatternsAsPositive; function groupPatternsByBaseDirectory(patterns) { + const group = {}; return patterns.reduce((collection, pattern) => { const base = utils.pattern.getBaseDirectory(pattern); if (base in collection) { @@ -69945,7 +69954,7 @@ function groupPatternsByBaseDirectory(patterns) { collection[base] = [pattern]; } return collection; - }, {}); + }, group); } exports.groupPatternsByBaseDirectory = groupPatternsByBaseDirectory; function convertPatternGroupsToTasks(positive, negative, dynamic) { @@ -70046,6 +70055,7 @@ exports.createDirentFromStats = createDirentFromStats; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); +const UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([*?|(){}[\]]|^!|[@+!](?=\())/g; /** * Designed to work only with simple paths: `dir\\file`. */ @@ -70057,6 +70067,10 @@ function makeAbsolute(cwd, filepath) { return path.resolve(cwd, filepath); } exports.makeAbsolute = makeAbsolute; +function escape(pattern) { + return pattern.replace(UNESCAPED_GLOB_SYMBOLS_RE, '\\$2'); +} +exports.escape = escape; /***/ }), @@ -70068,15 +70082,36 @@ exports.makeAbsolute = makeAbsolute; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); const globParent = __webpack_require__(604); -const isGlob = __webpack_require__(605); const micromatch = __webpack_require__(607); const GLOBSTAR = '**'; -function isStaticPattern(pattern) { - return !isDynamicPattern(pattern); +const ESCAPE_SYMBOL = '\\'; +const COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/; +const REGEX_CHARACTER_CLASS_SYMBOLS_RE = /\[.*]/; +const REGEX_GROUP_SYMBOLS_RE = /(?:^|[^@!*?+])\(.*\|.*\)/; +const GLOB_EXTENSION_SYMBOLS_RE = /[@!*?+]\(.*\)/; +const BRACE_EXPANSIONS_SYMBOLS_RE = /{.*(?:,|\.\.).*}/; +function isStaticPattern(pattern, options = {}) { + return !isDynamicPattern(pattern, options); } exports.isStaticPattern = isStaticPattern; -function isDynamicPattern(pattern) { - return isGlob(pattern, { strict: false }); +function isDynamicPattern(pattern, options = {}) { + /** + * When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check + * filepath directly (without read directory). + */ + if (options.caseSensitiveMatch === false || pattern.includes(ESCAPE_SYMBOL)) { + return true; + } + if (COMMON_GLOB_SYMBOLS_RE.test(pattern) || REGEX_CHARACTER_CLASS_SYMBOLS_RE.test(pattern) || REGEX_GROUP_SYMBOLS_RE.test(pattern)) { + return true; + } + if (options.extglob !== false && GLOB_EXTENSION_SYMBOLS_RE.test(pattern)) { + return true; + } + if (options.braceExpansion !== false && BRACE_EXPANSIONS_SYMBOLS_RE.test(pattern)) { + return true; + } + return false; } exports.isDynamicPattern = isDynamicPattern; function convertToPositivePattern(pattern) { @@ -70104,11 +70139,11 @@ function getPositivePatterns(patterns) { } exports.getPositivePatterns = getPositivePatterns; function getBaseDirectory(pattern) { - return globParent(pattern); + return globParent(pattern, { flipBackslashes: false }); } exports.getBaseDirectory = getBaseDirectory; function hasGlobStar(pattern) { - return pattern.indexOf(GLOBSTAR) !== -1; + return pattern.includes(GLOBSTAR); } exports.hasGlobStar = hasGlobStar; function endsWithSlashGlobStar(pattern) { @@ -70151,7 +70186,7 @@ function convertPatternsToRe(patterns, options) { } exports.convertPatternsToRe = convertPatternsToRe; function matchAny(entry, patternsRe) { - const filepath = entry.replace(/^\.[\\\/]/, ''); + const filepath = entry.replace(/^\.[\\/]/, ''); return patternsRe.some((patternRe) => patternRe.test(filepath)); } exports.matchAny = matchAny; @@ -70174,9 +70209,16 @@ var enclosure = /[\{\[].*[\/]*.*[\}\]]$/; var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; var escaped = /\\([\*\?\|\[\]\(\)\{\}])/g; -module.exports = function globParent(str) { +/** + * @param {string} str + * @param {Object} opts + * @param {boolean} [opts.flipBackslashes=true] + */ +module.exports = function globParent(str, opts) { + var options = Object.assign({ flipBackslashes: true }, opts); + // flip windows path separators - if (isWin32 && str.indexOf(slash) < 0) { + if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) { str = str.replace(backslash, slash); } @@ -74070,26 +74112,145 @@ module.exports = parse; "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const merge2 = __webpack_require__(590); +const merge2 = __webpack_require__(625); function merge(streams) { const mergedStream = merge2(streams); streams.forEach((stream) => { - stream.once('error', (err) => mergedStream.emit('error', err)); + stream.once('error', (error) => mergedStream.emit('error', error)); }); + mergedStream.once('close', () => propagateCloseEventToSources(streams)); + mergedStream.once('end', () => propagateCloseEventToSources(streams)); return mergedStream; } exports.merge = merge; +function propagateCloseEventToSources(streams) { + streams.forEach((stream) => stream.emit('close')); +} /***/ }), /* 625 */ /***/ (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__(27) +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 +} + + +/***/ }), +/* 626 */ +/***/ (function(module, exports, __webpack_require__) { + "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(626); -const provider_1 = __webpack_require__(653); +const stream_1 = __webpack_require__(627); +const provider_1 = __webpack_require__(654); class ProviderAsync extends provider_1.default { constructor() { super(...arguments); @@ -74117,16 +74278,16 @@ exports.default = ProviderAsync; /***/ }), -/* 626 */ +/* 627 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const fsStat = __webpack_require__(627); -const fsWalk = __webpack_require__(632); -const reader_1 = __webpack_require__(652); +const fsStat = __webpack_require__(628); +const fsWalk = __webpack_require__(633); +const reader_1 = __webpack_require__(653); class ReaderStream extends reader_1.default { constructor() { super(...arguments); @@ -74170,7 +74331,7 @@ class ReaderStream extends reader_1.default { _getStat(filepath) { return new Promise((resolve, reject) => { this._stat(filepath, this._fsStatSettings, (error, stats) => { - error ? reject(error) : resolve(stats); + return error === null ? resolve(stats) : reject(error); }); }); } @@ -74179,15 +74340,15 @@ exports.default = ReaderStream; /***/ }), -/* 627 */ +/* 628 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(628); -const sync = __webpack_require__(629); -const settings_1 = __webpack_require__(630); +const async = __webpack_require__(629); +const sync = __webpack_require__(630); +const settings_1 = __webpack_require__(631); exports.Settings = settings_1.default; function stat(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -74210,7 +74371,7 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 628 */ +/* 629 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74218,14 +74379,14 @@ function getSettings(settingsOrOptions = {}) { Object.defineProperty(exports, "__esModule", { value: true }); function read(path, settings, callback) { settings.fs.lstat(path, (lstatError, lstat) => { - if (lstatError) { + if (lstatError !== null) { return callFailureCallback(callback, lstatError); } if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { return callSuccessCallback(callback, lstat); } settings.fs.stat(path, (statError, stat) => { - if (statError) { + if (statError !== null) { if (settings.throwErrorOnBrokenSymbolicLink) { return callFailureCallback(callback, statError); } @@ -74248,7 +74409,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 629 */ +/* 630 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74277,13 +74438,13 @@ exports.read = read; /***/ }), -/* 630 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(631); +const fs = __webpack_require__(632); class Settings { constructor(_options = {}) { this._options = _options; @@ -74300,7 +74461,7 @@ exports.default = Settings; /***/ }), -/* 631 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74314,42 +74475,42 @@ exports.FILE_SYSTEM_ADAPTER = { statSync: fs.statSync }; function createFileSystemAdapter(fsMethods) { - if (!fsMethods) { + if (fsMethods === undefined) { return exports.FILE_SYSTEM_ADAPTER; } - return Object.assign({}, exports.FILE_SYSTEM_ADAPTER, fsMethods); + return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods); } exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 632 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(633); -const stream_1 = __webpack_require__(648); -const sync_1 = __webpack_require__(649); -const settings_1 = __webpack_require__(651); +const async_1 = __webpack_require__(634); +const stream_1 = __webpack_require__(649); +const sync_1 = __webpack_require__(650); +const settings_1 = __webpack_require__(652); exports.Settings = settings_1.default; -function walk(dir, optionsOrSettingsOrCallback, callback) { +function walk(directory, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { - return new async_1.default(dir, getSettings()).read(optionsOrSettingsOrCallback); + return new async_1.default(directory, getSettings()).read(optionsOrSettingsOrCallback); } - new async_1.default(dir, getSettings(optionsOrSettingsOrCallback)).read(callback); + new async_1.default(directory, getSettings(optionsOrSettingsOrCallback)).read(callback); } exports.walk = walk; -function walkSync(dir, optionsOrSettings) { +function walkSync(directory, optionsOrSettings) { const settings = getSettings(optionsOrSettings); - const provider = new sync_1.default(dir, settings); + const provider = new sync_1.default(directory, settings); return provider.read(); } exports.walkSync = walkSync; -function walkStream(dir, optionsOrSettings) { +function walkStream(directory, optionsOrSettings) { const settings = getSettings(optionsOrSettings); - const provider = new stream_1.default(dir, settings); + const provider = new stream_1.default(directory, settings); return provider.read(); } exports.walkStream = walkStream; @@ -74362,13 +74523,13 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 633 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(634); +const async_1 = __webpack_require__(635); class AsyncProvider { constructor(_root, _settings) { this._root = _root; @@ -74384,7 +74545,7 @@ class AsyncProvider { this._storage.add(entry); }); this._reader.onEnd(() => { - callSuccessCallback(callback, Array.from(this._storage)); + callSuccessCallback(callback, [...this._storage]); }); this._reader.read(); } @@ -74399,17 +74560,17 @@ function callSuccessCallback(callback, entries) { /***/ }), -/* 634 */ +/* 635 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const events_1 = __webpack_require__(379); -const fsScandir = __webpack_require__(635); -const fastq = __webpack_require__(644); -const common = __webpack_require__(646); -const reader_1 = __webpack_require__(647); +const fsScandir = __webpack_require__(636); +const fastq = __webpack_require__(645); +const common = __webpack_require__(647); +const reader_1 = __webpack_require__(648); class AsyncReader extends reader_1.default { constructor(_root, _settings) { super(_root, _settings); @@ -74449,17 +74610,17 @@ class AsyncReader extends reader_1.default { onEnd(callback) { this._emitter.once('end', callback); } - _pushToQueue(dir, base) { - const queueItem = { dir, base }; + _pushToQueue(directory, base) { + const queueItem = { directory, base }; this._queue.push(queueItem, (error) => { - if (error) { + if (error !== null) { this._handleError(error); } }); } _worker(item, done) { - this._scandir(item.dir, this._settings.fsScandirSettings, (error, entries) => { - if (error) { + this._scandir(item.directory, this._settings.fsScandirSettings, (error, entries) => { + if (error !== null) { return done(error, undefined); } for (const entry of entries) { @@ -74499,15 +74660,15 @@ exports.default = AsyncReader; /***/ }), -/* 635 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(636); -const sync = __webpack_require__(641); -const settings_1 = __webpack_require__(642); +const async = __webpack_require__(637); +const sync = __webpack_require__(642); +const settings_1 = __webpack_require__(643); exports.Settings = settings_1.default; function scandir(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -74530,39 +74691,39 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 636 */ +/* 637 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(627); -const rpl = __webpack_require__(637); -const constants_1 = __webpack_require__(638); -const utils = __webpack_require__(639); -function read(dir, settings, callback) { +const fsStat = __webpack_require__(628); +const rpl = __webpack_require__(638); +const constants_1 = __webpack_require__(639); +const utils = __webpack_require__(640); +function read(directory, settings, callback) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { - return readdirWithFileTypes(dir, settings, callback); + return readdirWithFileTypes(directory, settings, callback); } - return readdir(dir, settings, callback); + return readdir(directory, settings, callback); } exports.read = read; -function readdirWithFileTypes(dir, settings, callback) { - settings.fs.readdir(dir, { withFileTypes: true }, (readdirError, dirents) => { - if (readdirError) { +function readdirWithFileTypes(directory, settings, callback) { + settings.fs.readdir(directory, { withFileTypes: true }, (readdirError, dirents) => { + if (readdirError !== null) { return callFailureCallback(callback, readdirError); } const entries = dirents.map((dirent) => ({ dirent, name: dirent.name, - path: `${dir}${settings.pathSegmentSeparator}${dirent.name}` + path: `${directory}${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) { + if (rplError !== null) { return callFailureCallback(callback, rplError); } callSuccessCallback(callback, rplEntries); @@ -74576,7 +74737,7 @@ function makeRplTaskEntry(entry, settings) { return done(null, entry); } settings.fs.stat(entry.path, (statError, stats) => { - if (statError) { + if (statError !== null) { if (settings.throwErrorOnBrokenSymbolicLink) { return done(statError); } @@ -74587,22 +74748,21 @@ function makeRplTaskEntry(entry, settings) { }); }; } -function readdir(dir, settings, callback) { - settings.fs.readdir(dir, (readdirError, names) => { - if (readdirError) { +function readdir(directory, settings, callback) { + settings.fs.readdir(directory, (readdirError, names) => { + if (readdirError !== null) { return callFailureCallback(callback, readdirError); } - const filepaths = names.map((name) => `${dir}${settings.pathSegmentSeparator}${name}`); + const filepaths = names.map((name) => `${directory}${settings.pathSegmentSeparator}${name}`); const tasks = filepaths.map((filepath) => { return (done) => fsStat.stat(filepath, settings.fsStatSettings, done); }); rpl(tasks, (rplError, results) => { - if (rplError) { + if (rplError !== null) { return callFailureCallback(callback, rplError); } const entries = []; - for (let index = 0; index < names.length; index++) { - const name = names[index]; + names.forEach((name, index) => { const stats = results[index]; const entry = { name, @@ -74613,7 +74773,7 @@ function readdir(dir, settings, callback) { entry.stats = stats; } entries.push(entry); - } + }); callSuccessCallback(callback, entries); }); }); @@ -74628,7 +74788,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 637 */ +/* 638 */ /***/ (function(module, exports) { module.exports = runParallel @@ -74682,7 +74842,7 @@ function runParallel (tasks, cb) { /***/ }), -/* 638 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74691,25 +74851,29 @@ 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); +const SUPPORTED_MAJOR_VERSION = 10; +const SUPPORTED_MINOR_VERSION = 10; +const IS_MATCHED_BY_MAJOR = MAJOR_VERSION > SUPPORTED_MAJOR_VERSION; +const IS_MATCHED_BY_MAJOR_AND_MINOR = MAJOR_VERSION === SUPPORTED_MAJOR_VERSION && MINOR_VERSION >= SUPPORTED_MINOR_VERSION; /** * 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); +exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_BY_MAJOR_AND_MINOR; /***/ }), -/* 639 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(640); +const fs = __webpack_require__(641); exports.fs = fs; /***/ }), -/* 640 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74734,29 +74898,29 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 641 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(627); -const constants_1 = __webpack_require__(638); -const utils = __webpack_require__(639); -function read(dir, settings) { +const fsStat = __webpack_require__(628); +const constants_1 = __webpack_require__(639); +const utils = __webpack_require__(640); +function read(directory, settings) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { - return readdirWithFileTypes(dir, settings); + return readdirWithFileTypes(directory, settings); } - return readdir(dir, settings); + return readdir(directory, settings); } exports.read = read; -function readdirWithFileTypes(dir, settings) { - const dirents = settings.fs.readdirSync(dir, { withFileTypes: true }); +function readdirWithFileTypes(directory, settings) { + const dirents = settings.fs.readdirSync(directory, { withFileTypes: true }); return dirents.map((dirent) => { const entry = { dirent, name: dirent.name, - path: `${dir}${settings.pathSegmentSeparator}${dirent.name}` + path: `${directory}${settings.pathSegmentSeparator}${dirent.name}` }; if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) { try { @@ -74773,10 +74937,10 @@ function readdirWithFileTypes(dir, settings) { }); } exports.readdirWithFileTypes = readdirWithFileTypes; -function readdir(dir, settings) { - const names = settings.fs.readdirSync(dir); +function readdir(directory, settings) { + const names = settings.fs.readdirSync(directory); return names.map((name) => { - const entryPath = `${dir}${settings.pathSegmentSeparator}${name}`; + const entryPath = `${directory}${settings.pathSegmentSeparator}${name}`; const stats = fsStat.statSync(entryPath, settings.fsStatSettings); const entry = { name, @@ -74793,15 +74957,15 @@ exports.readdir = readdir; /***/ }), -/* 642 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsStat = __webpack_require__(627); -const fs = __webpack_require__(643); +const fsStat = __webpack_require__(628); +const fs = __webpack_require__(644); class Settings { constructor(_options = {}) { this._options = _options; @@ -74824,7 +74988,7 @@ exports.default = Settings; /***/ }), -/* 643 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74840,22 +75004,22 @@ exports.FILE_SYSTEM_ADAPTER = { readdirSync: fs.readdirSync }; function createFileSystemAdapter(fsMethods) { - if (!fsMethods) { + if (fsMethods === undefined) { return exports.FILE_SYSTEM_ADAPTER; } - return Object.assign({}, exports.FILE_SYSTEM_ADAPTER, fsMethods); + return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods); } exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 644 */ +/* 645 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var reusify = __webpack_require__(645) +var reusify = __webpack_require__(646) function fastqueue (context, worker, concurrency) { if (typeof context === 'function') { @@ -75029,7 +75193,7 @@ module.exports = fastqueue /***/ }), -/* 645 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75069,7 +75233,7 @@ module.exports = reusify /***/ }), -/* 646 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75087,7 +75251,7 @@ function isAppliedFilter(filter, value) { } exports.isAppliedFilter = isAppliedFilter; function replacePathSegmentSeparator(filepath, separator) { - return filepath.split(/[\\\/]/).join(separator); + return filepath.split(/[\\/]/).join(separator); } exports.replacePathSegmentSeparator = replacePathSegmentSeparator; function joinPathSegments(a, b, separator) { @@ -75100,13 +75264,13 @@ exports.joinPathSegments = joinPathSegments; /***/ }), -/* 647 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const common = __webpack_require__(646); +const common = __webpack_require__(647); class Reader { constructor(_root, _settings) { this._root = _root; @@ -75118,14 +75282,14 @@ exports.default = Reader; /***/ }), -/* 648 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const async_1 = __webpack_require__(634); +const async_1 = __webpack_require__(635); class StreamProvider { constructor(_root, _settings) { this._root = _root; @@ -75155,13 +75319,13 @@ exports.default = StreamProvider; /***/ }), -/* 649 */ +/* 650 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(650); +const sync_1 = __webpack_require__(651); class SyncProvider { constructor(_root, _settings) { this._root = _root; @@ -75176,15 +75340,15 @@ exports.default = SyncProvider; /***/ }), -/* 650 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsScandir = __webpack_require__(635); -const common = __webpack_require__(646); -const reader_1 = __webpack_require__(647); +const fsScandir = __webpack_require__(636); +const common = __webpack_require__(647); +const reader_1 = __webpack_require__(648); class SyncReader extends reader_1.default { constructor() { super(...arguments); @@ -75195,19 +75359,19 @@ class SyncReader extends reader_1.default { read() { this._pushToQueue(this._root, this._settings.basePath); this._handleQueue(); - return Array.from(this._storage); + return [...this._storage]; } - _pushToQueue(dir, base) { - this._queue.add({ dir, base }); + _pushToQueue(directory, base) { + this._queue.add({ directory, base }); } _handleQueue() { for (const item of this._queue.values()) { - this._handleDirectory(item.dir, item.base); + this._handleDirectory(item.directory, item.base); } } - _handleDirectory(dir, base) { + _handleDirectory(directory, base) { try { - const entries = this._scandir(dir, this._settings.fsScandirSettings); + const entries = this._scandir(directory, this._settings.fsScandirSettings); for (const entry of entries) { this._handleEntry(entry, base); } @@ -75242,14 +75406,14 @@ exports.default = SyncReader; /***/ }), -/* 651 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsScandir = __webpack_require__(635); +const fsScandir = __webpack_require__(636); class Settings { constructor(_options = {}) { this._options = _options; @@ -75275,14 +75439,14 @@ exports.default = Settings; /***/ }), -/* 652 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsStat = __webpack_require__(627); +const fsStat = __webpack_require__(628); const utils = __webpack_require__(598); class Reader { constructor(_settings) { @@ -75315,17 +75479,17 @@ exports.default = Reader; /***/ }), -/* 653 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const deep_1 = __webpack_require__(654); -const entry_1 = __webpack_require__(655); -const error_1 = __webpack_require__(656); -const entry_2 = __webpack_require__(657); +const deep_1 = __webpack_require__(655); +const entry_1 = __webpack_require__(656); +const error_1 = __webpack_require__(657); +const entry_2 = __webpack_require__(658); class Provider { constructor(_settings) { this._settings = _settings; @@ -75370,7 +75534,7 @@ exports.default = Provider; /***/ }), -/* 654 */ +/* 655 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75406,9 +75570,6 @@ class DeepFilter { if (this._isSkippedSymbolicLink(entry)) { return false; } - if (this._isSkippedDotDirectory(entry)) { - return false; - } return this._isSkippedByNegativePatterns(entry, negativeRe); } _getEntryDepth(basePath, entryPath) { @@ -75425,9 +75586,6 @@ class DeepFilter { _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); } @@ -75436,7 +75594,7 @@ exports.default = DeepFilter; /***/ }), -/* 655 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75497,7 +75655,7 @@ exports.default = EntryFilter; /***/ }), -/* 656 */ +/* 657 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75519,7 +75677,7 @@ exports.default = ErrorFilter; /***/ }), -/* 657 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75545,22 +75703,22 @@ class EntryTransformer { if (!this._settings.objectMode) { return filepath; } - return Object.assign({}, entry, { path: filepath }); + return Object.assign(Object.assign({}, entry), { path: filepath }); } } exports.default = EntryTransformer; /***/ }), -/* 658 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const stream_2 = __webpack_require__(626); -const provider_1 = __webpack_require__(653); +const stream_2 = __webpack_require__(627); +const provider_1 = __webpack_require__(654); class ProviderStream extends provider_1.default { constructor() { super(...arguments); @@ -75570,12 +75728,14 @@ class ProviderStream extends provider_1.default { 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: () => { } }); + const destination = 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; + .once('error', (error) => destination.emit('error', error)) + .on('data', (entry) => destination.emit('data', options.transform(entry))) + .once('end', () => destination.emit('end')); + destination + .once('close', () => source.destroy()); + return destination; } api(root, task, options) { if (task.dynamic) { @@ -75588,14 +75748,14 @@ exports.default = ProviderStream; /***/ }), -/* 659 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(660); -const provider_1 = __webpack_require__(653); +const sync_1 = __webpack_require__(661); +const provider_1 = __webpack_require__(654); class ProviderSync extends provider_1.default { constructor() { super(...arguments); @@ -75618,15 +75778,15 @@ exports.default = ProviderSync; /***/ }), -/* 660 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(627); -const fsWalk = __webpack_require__(632); -const reader_1 = __webpack_require__(652); +const fsStat = __webpack_require__(628); +const fsWalk = __webpack_require__(633); +const reader_1 = __webpack_require__(653); class ReaderSync extends reader_1.default { constructor() { super(...arguments); @@ -75668,7 +75828,7 @@ exports.default = ReaderSync; /***/ }), -/* 661 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75685,7 +75845,6 @@ exports.DEFAULT_FILE_SYSTEM_ADAPTER = { readdir: fs.readdir, readdirSync: fs.readdirSync }; -// tslint:enable no-redundant-jsdoc class Settings { constructor(_options = {}) { this._options = _options; @@ -75721,20 +75880,20 @@ class Settings { return option === undefined ? value : option; } _getFileSystemMethods(methods = {}) { - return Object.assign({}, exports.DEFAULT_FILE_SYSTEM_ADAPTER, methods); + return Object.assign(Object.assign({}, exports.DEFAULT_FILE_SYSTEM_ADAPTER), methods); } } exports.default = Settings; /***/ }), -/* 662 */ +/* 663 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(663); +const pathType = __webpack_require__(664); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -75810,7 +75969,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 663 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75860,7 +76019,7 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 664 */ +/* 665 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75869,8 +76028,8 @@ const {promisify} = __webpack_require__(29); const fs = __webpack_require__(23); const path = __webpack_require__(16); const fastGlob = __webpack_require__(596); -const gitIgnore = __webpack_require__(665); -const slash = __webpack_require__(666); +const gitIgnore = __webpack_require__(666); +const slash = __webpack_require__(667); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -75984,7 +76143,7 @@ module.exports.sync = options => { /***/ }), -/* 665 */ +/* 666 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -76575,7 +76734,7 @@ if ( /***/ }), -/* 666 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76593,7 +76752,7 @@ module.exports = path => { /***/ }), -/* 667 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76646,7 +76805,7 @@ module.exports = { /***/ }), -/* 668 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76668,7 +76827,7 @@ module.exports = path_ => { /***/ }), -/* 669 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76696,7 +76855,7 @@ module.exports = (childPath, parentPath) => { /***/ }), -/* 670 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { const assert = __webpack_require__(30) @@ -77070,12 +77229,12 @@ rimraf.sync = rimrafSync /***/ }), -/* 671 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const AggregateError = __webpack_require__(672); +const AggregateError = __webpack_require__(673); module.exports = async ( iterable, @@ -77158,13 +77317,13 @@ module.exports = async ( /***/ }), -/* 672 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const indentString = __webpack_require__(673); -const cleanStack = __webpack_require__(674); +const indentString = __webpack_require__(674); +const cleanStack = __webpack_require__(675); const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); @@ -77212,7 +77371,7 @@ module.exports = AggregateError; /***/ }), -/* 673 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77254,7 +77413,7 @@ module.exports = (string, count = 1, options) => { /***/ }), -/* 674 */ +/* 675 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77301,14 +77460,14 @@ module.exports = (stack, options) => { /***/ }), -/* 675 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(676); -const cliCursor = __webpack_require__(680); -const cliSpinners = __webpack_require__(684); +const chalk = __webpack_require__(677); +const cliCursor = __webpack_require__(681); +const cliSpinners = __webpack_require__(685); const logSymbols = __webpack_require__(565); class Ora { @@ -77456,16 +77615,16 @@ module.exports.promise = (action, options) => { /***/ }), -/* 676 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(677); -const stdoutColor = __webpack_require__(678).stdout; +const ansiStyles = __webpack_require__(678); +const stdoutColor = __webpack_require__(679).stdout; -const template = __webpack_require__(679); +const template = __webpack_require__(680); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -77691,7 +77850,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 677 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77864,7 +78023,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 678 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78006,7 +78165,7 @@ module.exports = { /***/ }), -/* 679 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78141,12 +78300,12 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 680 */ +/* 681 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(681); +const restoreCursor = __webpack_require__(682); let hidden = false; @@ -78187,12 +78346,12 @@ exports.toggle = (force, stream) => { /***/ }), -/* 681 */ +/* 682 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(682); +const onetime = __webpack_require__(683); const signalExit = __webpack_require__(377); module.exports = onetime(() => { @@ -78203,12 +78362,12 @@ module.exports = onetime(() => { /***/ }), -/* 682 */ +/* 683 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const mimicFn = __webpack_require__(683); +const mimicFn = __webpack_require__(684); module.exports = (fn, opts) => { // TODO: Remove this in v3 @@ -78249,7 +78408,7 @@ module.exports = (fn, opts) => { /***/ }), -/* 683 */ +/* 684 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78265,22 +78424,22 @@ module.exports = (to, from) => { /***/ }), -/* 684 */ +/* 685 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(685); +module.exports = __webpack_require__(686); /***/ }), -/* 685 */ +/* 686 */ /***/ (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\":[\"🌲\",\"🎄\"]}}"); /***/ }), -/* 686 */ +/* 687 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78340,7 +78499,7 @@ const RunCommand = { }; /***/ }), -/* 687 */ +/* 688 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78351,7 +78510,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(500); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(501); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(688); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(689); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -78435,7 +78594,7 @@ const WatchCommand = { }; /***/ }), -/* 688 */ +/* 689 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78509,7 +78668,7 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 689 */ +/* 690 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78517,15 +78676,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__(690); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(691); /* 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__(691); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(692); /* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(34); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(501); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(698); -/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(699); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(699); +/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(700); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -78613,7 +78772,7 @@ function toArray(value) { } /***/ }), -/* 690 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78647,13 +78806,13 @@ module.exports = (str, count, opts) => { /***/ }), -/* 691 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringWidth = __webpack_require__(692); -const stripAnsi = __webpack_require__(696); +const stringWidth = __webpack_require__(693); +const stripAnsi = __webpack_require__(697); const ESCAPES = new Set([ '\u001B', @@ -78847,13 +79006,13 @@ module.exports = (str, cols, opts) => { /***/ }), -/* 692 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stripAnsi = __webpack_require__(693); -const isFullwidthCodePoint = __webpack_require__(695); +const stripAnsi = __webpack_require__(694); +const isFullwidthCodePoint = __webpack_require__(696); module.exports = str => { if (typeof str !== 'string' || str.length === 0) { @@ -78890,18 +79049,18 @@ module.exports = str => { /***/ }), -/* 693 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(694); +const ansiRegex = __webpack_require__(695); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 694 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78918,7 +79077,7 @@ module.exports = () => { /***/ }), -/* 695 */ +/* 696 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78971,18 +79130,18 @@ module.exports = x => { /***/ }), -/* 696 */ +/* 697 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(697); +const ansiRegex = __webpack_require__(698); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 697 */ +/* 698 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78999,7 +79158,7 @@ module.exports = () => { /***/ }), -/* 698 */ +/* 699 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79152,7 +79311,7 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 699 */ +/* 700 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79160,7 +79319,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Kibana", function() { return Kibana; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(700); +/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(701); /* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(501); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579); @@ -79295,15 +79454,15 @@ class Kibana { } /***/ }), -/* 700 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const minimatch = __webpack_require__(505); -const arrayUnion = __webpack_require__(701); -const arrayDiffer = __webpack_require__(702); -const arrify = __webpack_require__(703); +const arrayUnion = __webpack_require__(702); +const arrayDiffer = __webpack_require__(703); +const arrify = __webpack_require__(704); module.exports = (list, patterns, options = {}) => { list = arrify(list); @@ -79327,7 +79486,7 @@ module.exports = (list, patterns, options = {}) => { /***/ }), -/* 701 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79339,7 +79498,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 702 */ +/* 703 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79353,444 +79512,8 @@ const arrayDiffer = (array, ...values) => { module.exports = arrayDiffer; -/***/ }), -/* 703 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const arrify = value => { - if (value === null || value === undefined) { - return []; - } - - if (Array.isArray(value)) { - return value; - } - - if (typeof value === 'string') { - return [value]; - } - - if (typeof value[Symbol.iterator] === 'function') { - return [...value]; - } - - return [value]; -}; - -module.exports = arrify; - - /***/ }), /* 704 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(705); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); - -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(928); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); - -/* - * 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. - */ - - - -/***/ }), -/* 705 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(706); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(587); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579); -/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); -/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(517); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(501); -/* - * 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. - */ - - - - - - - - -async function buildProductionProjects({ - kibanaRoot, - buildRoot, - onlyOSS -}) { - const projects = await getProductionProjects(kibanaRoot, onlyOSS); - const projectGraph = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["buildProjectGraph"])(projects); - const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["topologicallyBatchProjects"])(projects, projectGraph); - const projectNames = [...projects.values()].map(project => project.name); - _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(`Preparing production build for [${projectNames.join(', ')}]`); - - for (const batch of batchedProjects) { - for (const project of batch) { - await deleteTarget(project); - await buildProject(project); - await copyToBuild(project, kibanaRoot, buildRoot); - } - } -} -/** - * Returns the subset of projects that should be built into the production - * bundle. As we copy these into Kibana's `node_modules` during the build step, - * and let Kibana's build process be responsible for installing dependencies, - * we only include Kibana's transitive _production_ dependencies. If onlyOSS - * is supplied, we omit projects with build.oss in their package.json set to false. - */ - -async function getProductionProjects(rootPath, onlyOSS) { - const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])({ - rootPath - }); - const projects = await Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["getProjects"])(rootPath, projectPaths); - const projectsSubset = [projects.get('kibana')]; - - if (projects.has('x-pack')) { - projectsSubset.push(projects.get('x-pack')); - } - - const productionProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["includeTransitiveProjects"])(projectsSubset, projects, { - onlyProductionDependencies: true - }); // We remove Kibana, as we're already building Kibana - - productionProjects.delete('kibana'); - - if (onlyOSS) { - productionProjects.forEach(project => { - if (project.getBuildConfig().oss === false) { - productionProjects.delete(project.json.name); - } - }); - } - - return productionProjects; -} - -async function deleteTarget(project) { - const targetDir = project.targetLocation; - - if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(targetDir)) { - await del__WEBPACK_IMPORTED_MODULE_1___default()(targetDir, { - force: true - }); - } -} - -async function buildProject(project) { - if (project.hasScript('build')) { - await project.runScript('build'); - } -} -/** - * Copy all the project's files from its "intermediate build directory" and - * into the build. The intermediate directory can either be the root of the - * project or some other location defined in the project's `package.json`. - * - * When copying all the files into the build, we exclude `node_modules` because - * we want the Kibana build to be responsible for actually installing all - * dependencies. The primary reason for allowing the Kibana build process to - * manage dependencies is that it will "dedupe" them, so we don't include - * unnecessary copies of dependencies. - */ - - -async function copyToBuild(project, kibanaRoot, buildRoot) { - // We want the package to have the same relative location within the build - const relativeProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(kibanaRoot, project.path); - const buildProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["resolve"])(buildRoot, relativeProjectPath); - await cpy__WEBPACK_IMPORTED_MODULE_0___default()(['**/*', '!node_modules/**'], buildProjectPath, { - cwd: project.getIntermediateBuildDirectory(), - dot: true, - nodir: true, - parents: true - }); // If a project is using an intermediate build directory, we special-case our - // handling of `package.json`, as the project build process might have copied - // (a potentially modified) `package.json` into the intermediate build - // directory already. If so, we want to use that `package.json` as the basis - // for creating the production-ready `package.json`. If it's not present in - // the intermediate build, we fall back to using the project's already defined - // `package.json`. - - const packageJson = (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isFile"])(Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(buildProjectPath, 'package.json'))) ? await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["readPackageJson"])(buildProjectPath) : project.json; - await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["writePackageJson"])(buildProjectPath, packageJson); -} - -/***/ }), -/* 706 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -const EventEmitter = __webpack_require__(379); -const path = __webpack_require__(16); -const os = __webpack_require__(11); -const pAll = __webpack_require__(707); -const arrify = __webpack_require__(709); -const globby = __webpack_require__(710); -const isGlob = __webpack_require__(605); -const cpFile = __webpack_require__(913); -const junk = __webpack_require__(925); -const CpyError = __webpack_require__(926); - -const defaultOptions = { - ignoreJunk: true -}; - -const preprocessSourcePath = (source, options) => options.cwd ? path.resolve(options.cwd, source) : source; - -const preprocessDestinationPath = (source, destination, options) => { - let basename = path.basename(source); - const dirname = path.dirname(source); - - if (typeof options.rename === 'string') { - basename = options.rename; - } else if (typeof options.rename === 'function') { - basename = options.rename(basename); - } - - if (options.cwd) { - destination = path.resolve(options.cwd, destination); - } - - if (options.parents) { - return path.join(destination, dirname, basename); - } - - return path.join(destination, basename); -}; - -module.exports = (source, destination, { - concurrency = (os.cpus().length || 1) * 2, - ...options -} = {}) => { - const progressEmitter = new EventEmitter(); - - options = { - ...defaultOptions, - ...options - }; - - const promise = (async () => { - source = arrify(source); - - if (source.length === 0 || !destination) { - throw new CpyError('`source` and `destination` required'); - } - - const copyStatus = new Map(); - let completedFiles = 0; - let completedSize = 0; - - let files; - try { - files = await globby(source, options); - - if (options.ignoreJunk) { - files = files.filter(file => junk.not(path.basename(file))); - } - } catch (error) { - throw new CpyError(`Cannot glob \`${source}\`: ${error.message}`, error); - } - - const sourcePaths = source.filter(value => !isGlob(value)); - - if (files.length === 0 || (sourcePaths.length > 0 && !sourcePaths.every(value => files.includes(value)))) { - throw new CpyError(`Cannot copy \`${source}\`: the file doesn't exist`); - } - - const fileProgressHandler = event => { - const fileStatus = copyStatus.get(event.src) || {written: 0, percent: 0}; - - if (fileStatus.written !== event.written || fileStatus.percent !== event.percent) { - completedSize -= fileStatus.written; - completedSize += event.written; - - if (event.percent === 1 && fileStatus.percent !== 1) { - completedFiles++; - } - - copyStatus.set(event.src, { - written: event.written, - percent: event.percent - }); - - progressEmitter.emit('progress', { - totalFiles: files.length, - percent: completedFiles / files.length, - completedFiles, - completedSize - }); - } - }; - - return pAll(files.map(sourcePath => { - return async () => { - const from = preprocessSourcePath(sourcePath, options); - const to = preprocessDestinationPath(sourcePath, destination, options); - - try { - await cpFile(from, to, options).on('progress', fileProgressHandler); - } catch (error) { - throw new CpyError(`Cannot copy from \`${from}\` to \`${to}\`: ${error.message}`, error); - } - - return to; - }; - }), {concurrency}); - })(); - - promise.on = (...arguments_) => { - progressEmitter.on(...arguments_); - return promise; - }; - - return promise; -}; - - -/***/ }), -/* 707 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -const pMap = __webpack_require__(708); - -module.exports = (iterable, options) => pMap(iterable, element => element(), options); -// TODO: Remove this for the next major release -module.exports.default = module.exports; - - -/***/ }), -/* 708 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -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'); - } - - 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})`); - } - - 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 nextItem = iterator.next(); - const i = currentIndex; - currentIndex++; - - if (nextItem.done) { - isIterableDone = true; - - if (resolvingCount === 0) { - resolve(ret); - } - - return; - } - - resolvingCount++; - - Promise.resolve(nextItem.value) - .then(element => mapper(element, i)) - .then( - value => { - ret[i] = value; - resolvingCount--; - next(); - }, - error => { - isRejected = true; - reject(error); - } - ); - }; - - for (let i = 0; i < concurrency; i++) { - next(); - - if (isIterableDone) { - break; - } - } -}); - -module.exports = pMap; -// TODO: Remove this for the next major release -module.exports.default = pMap; - - -/***/ }), -/* 709 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79819,18 +79542,454 @@ const arrify = value => { module.exports = arrify; +/***/ }), +/* 705 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(706); +/* harmony 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__(741); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); + +/* + * 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. + */ + + + +/***/ }), +/* 706 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(707); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(587); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(517); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(501); +/* + * 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. + */ + + + + + + + + +async function buildProductionProjects({ + kibanaRoot, + buildRoot, + onlyOSS +}) { + const projects = await getProductionProjects(kibanaRoot, onlyOSS); + const projectGraph = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["buildProjectGraph"])(projects); + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["topologicallyBatchProjects"])(projects, projectGraph); + const projectNames = [...projects.values()].map(project => project.name); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(`Preparing production build for [${projectNames.join(', ')}]`); + + for (const batch of batchedProjects) { + for (const project of batch) { + await deleteTarget(project); + await buildProject(project); + await copyToBuild(project, kibanaRoot, buildRoot); + } + } +} +/** + * Returns the subset of projects that should be built into the production + * bundle. As we copy these into Kibana's `node_modules` during the build step, + * and let Kibana's build process be responsible for installing dependencies, + * we only include Kibana's transitive _production_ dependencies. If onlyOSS + * is supplied, we omit projects with build.oss in their package.json set to false. + */ + +async function getProductionProjects(rootPath, onlyOSS) { + const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])({ + rootPath + }); + const projects = await Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["getProjects"])(rootPath, projectPaths); + const projectsSubset = [projects.get('kibana')]; + + if (projects.has('x-pack')) { + projectsSubset.push(projects.get('x-pack')); + } + + const productionProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["includeTransitiveProjects"])(projectsSubset, projects, { + onlyProductionDependencies: true + }); // We remove Kibana, as we're already building Kibana + + productionProjects.delete('kibana'); + + if (onlyOSS) { + productionProjects.forEach(project => { + if (project.getBuildConfig().oss === false) { + productionProjects.delete(project.json.name); + } + }); + } + + return productionProjects; +} + +async function deleteTarget(project) { + const targetDir = project.targetLocation; + + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(targetDir)) { + await del__WEBPACK_IMPORTED_MODULE_1___default()(targetDir, { + force: true + }); + } +} + +async function buildProject(project) { + if (project.hasScript('build')) { + await project.runScript('build'); + } +} +/** + * Copy all the project's files from its "intermediate build directory" and + * into the build. The intermediate directory can either be the root of the + * project or some other location defined in the project's `package.json`. + * + * When copying all the files into the build, we exclude `node_modules` because + * we want the Kibana build to be responsible for actually installing all + * dependencies. The primary reason for allowing the Kibana build process to + * manage dependencies is that it will "dedupe" them, so we don't include + * unnecessary copies of dependencies. + */ + + +async function copyToBuild(project, kibanaRoot, buildRoot) { + // We want the package to have the same relative location within the build + const relativeProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(kibanaRoot, project.path); + const buildProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["resolve"])(buildRoot, relativeProjectPath); + await cpy__WEBPACK_IMPORTED_MODULE_0___default()(['**/*', '!node_modules/**'], buildProjectPath, { + cwd: project.getIntermediateBuildDirectory(), + dot: true, + nodir: true, + parents: true + }); // If a project is using an intermediate build directory, we special-case our + // handling of `package.json`, as the project build process might have copied + // (a potentially modified) `package.json` into the intermediate build + // directory already. If so, we want to use that `package.json` as the basis + // for creating the production-ready `package.json`. If it's not present in + // the intermediate build, we fall back to using the project's already defined + // `package.json`. + + const packageJson = (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isFile"])(Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(buildProjectPath, 'package.json'))) ? await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["readPackageJson"])(buildProjectPath) : project.json; + await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["writePackageJson"])(buildProjectPath, packageJson); +} + +/***/ }), +/* 707 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const EventEmitter = __webpack_require__(379); +const path = __webpack_require__(16); +const os = __webpack_require__(11); +const pAll = __webpack_require__(708); +const arrify = __webpack_require__(710); +const globby = __webpack_require__(711); +const isGlob = __webpack_require__(605); +const cpFile = __webpack_require__(726); +const junk = __webpack_require__(738); +const CpyError = __webpack_require__(739); + +const defaultOptions = { + ignoreJunk: true +}; + +const preprocessSourcePath = (source, options) => options.cwd ? path.resolve(options.cwd, source) : source; + +const preprocessDestinationPath = (source, destination, options) => { + let basename = path.basename(source); + const dirname = path.dirname(source); + + if (typeof options.rename === 'string') { + basename = options.rename; + } else if (typeof options.rename === 'function') { + basename = options.rename(basename); + } + + if (options.cwd) { + destination = path.resolve(options.cwd, destination); + } + + if (options.parents) { + return path.join(destination, dirname, basename); + } + + return path.join(destination, basename); +}; + +module.exports = (source, destination, { + concurrency = (os.cpus().length || 1) * 2, + ...options +} = {}) => { + const progressEmitter = new EventEmitter(); + + options = { + ...defaultOptions, + ...options + }; + + const promise = (async () => { + source = arrify(source); + + if (source.length === 0 || !destination) { + throw new CpyError('`source` and `destination` required'); + } + + const copyStatus = new Map(); + let completedFiles = 0; + let completedSize = 0; + + let files; + try { + files = await globby(source, options); + + if (options.ignoreJunk) { + files = files.filter(file => junk.not(path.basename(file))); + } + } catch (error) { + throw new CpyError(`Cannot glob \`${source}\`: ${error.message}`, error); + } + + const sourcePaths = source.filter(value => !isGlob(value)); + + if (files.length === 0 || (sourcePaths.length > 0 && !sourcePaths.every(value => files.includes(value)))) { + throw new CpyError(`Cannot copy \`${source}\`: the file doesn't exist`); + } + + const fileProgressHandler = event => { + const fileStatus = copyStatus.get(event.src) || {written: 0, percent: 0}; + + if (fileStatus.written !== event.written || fileStatus.percent !== event.percent) { + completedSize -= fileStatus.written; + completedSize += event.written; + + if (event.percent === 1 && fileStatus.percent !== 1) { + completedFiles++; + } + + copyStatus.set(event.src, { + written: event.written, + percent: event.percent + }); + + progressEmitter.emit('progress', { + totalFiles: files.length, + percent: completedFiles / files.length, + completedFiles, + completedSize + }); + } + }; + + return pAll(files.map(sourcePath => { + return async () => { + const from = preprocessSourcePath(sourcePath, options); + const to = preprocessDestinationPath(sourcePath, destination, options); + + try { + await cpFile(from, to, options).on('progress', fileProgressHandler); + } catch (error) { + throw new CpyError(`Cannot copy from \`${from}\` to \`${to}\`: ${error.message}`, error); + } + + return to; + }; + }), {concurrency}); + })(); + + promise.on = (...arguments_) => { + progressEmitter.on(...arguments_); + return promise; + }; + + return promise; +}; + + +/***/ }), +/* 708 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const pMap = __webpack_require__(709); + +module.exports = (iterable, options) => pMap(iterable, element => element(), options); +// TODO: Remove this for the next major release +module.exports.default = module.exports; + + +/***/ }), +/* 709 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +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'); + } + + 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})`); + } + + 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 nextItem = iterator.next(); + const i = currentIndex; + currentIndex++; + + if (nextItem.done) { + isIterableDone = true; + + if (resolvingCount === 0) { + resolve(ret); + } + + return; + } + + resolvingCount++; + + Promise.resolve(nextItem.value) + .then(element => mapper(element, i)) + .then( + value => { + ret[i] = value; + resolvingCount--; + next(); + }, + error => { + isRejected = true; + reject(error); + } + ); + }; + + for (let i = 0; i < concurrency; i++) { + next(); + + if (isIterableDone) { + break; + } + } +}); + +module.exports = pMap; +// TODO: Remove this for the next major release +module.exports.default = pMap; + + /***/ }), /* 710 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; + +const arrify = value => { + if (value === null || value === undefined) { + return []; + } + + if (Array.isArray(value)) { + return value; + } + + if (typeof value === 'string') { + return [value]; + } + + if (typeof value[Symbol.iterator] === 'function') { + return [...value]; + } + + return [value]; +}; + +module.exports = arrify; + + +/***/ }), +/* 711 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(711); -const glob = __webpack_require__(713); -const fastGlob = __webpack_require__(718); -const dirGlob = __webpack_require__(906); -const gitignore = __webpack_require__(909); +const arrayUnion = __webpack_require__(712); +const glob = __webpack_require__(714); +const fastGlob = __webpack_require__(596); +const dirGlob = __webpack_require__(719); +const gitignore = __webpack_require__(722); const DEFAULT_FILTER = () => false; @@ -79975,12 +80134,12 @@ module.exports.gitignore = gitignore; /***/ }), -/* 711 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(712); +var arrayUniq = __webpack_require__(713); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -79988,7 +80147,7 @@ module.exports = function () { /***/ }), -/* 712 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80057,7 +80216,7 @@ if ('Set' in global) { /***/ }), -/* 713 */ +/* 714 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -80106,13 +80265,13 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(503) var minimatch = __webpack_require__(505) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(714) +var inherits = __webpack_require__(715) var EE = __webpack_require__(379).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(511) -var globSync = __webpack_require__(716) -var common = __webpack_require__(717) +var globSync = __webpack_require__(717) +var common = __webpack_require__(718) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -80853,7 +81012,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 714 */ +/* 715 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -80863,12 +81022,12 @@ try { module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(715); + module.exports = __webpack_require__(716); } /***/ }), -/* 715 */ +/* 716 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -80901,7 +81060,7 @@ if (typeof Object.create === 'function') { /***/ }), -/* 716 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync @@ -80911,12 +81070,12 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(503) var minimatch = __webpack_require__(505) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(713).Glob +var Glob = __webpack_require__(714).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(511) -var common = __webpack_require__(717) +var common = __webpack_require__(718) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -81342,24464 +81501,310 @@ GlobSync.prototype._stat = function (f) { return false // otherwise we have to stat, because maybe c=true - // if we know it exists, but not what it is. - } - - var exists - var stat = this.statCache[abs] - if (!stat) { - var lstat - try { - lstat = fs.lstatSync(abs) - } catch (er) { - if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { - this.statCache[abs] = false - return false - } - } - - if (lstat && lstat.isSymbolicLink()) { - try { - stat = fs.statSync(abs) - } catch (er) { - stat = lstat - } - } else { - stat = lstat - } - } - - this.statCache[abs] = stat - - var c = true - if (stat) - c = stat.isDirectory() ? 'DIR' : 'FILE' - - this.cache[abs] = this.cache[abs] || c - - if (needDir && c === 'FILE') - return false - - return c -} - -GlobSync.prototype._mark = function (p) { - return common.mark(this, p) -} - -GlobSync.prototype._makeAbs = function (f) { - return common.makeAbs(this, f) -} - - -/***/ }), -/* 717 */ -/***/ (function(module, exports, __webpack_require__) { - -exports.alphasort = alphasort -exports.alphasorti = alphasorti -exports.setopts = setopts -exports.ownProp = ownProp -exports.makeAbs = makeAbs -exports.finish = finish -exports.mark = mark -exports.isIgnored = isIgnored -exports.childrenIgnored = childrenIgnored - -function ownProp (obj, field) { - return Object.prototype.hasOwnProperty.call(obj, field) -} - -var path = __webpack_require__(16) -var minimatch = __webpack_require__(505) -var isAbsolute = __webpack_require__(511) -var Minimatch = minimatch.Minimatch - -function alphasorti (a, b) { - return a.toLowerCase().localeCompare(b.toLowerCase()) -} - -function alphasort (a, b) { - return a.localeCompare(b) -} - -function setupIgnores (self, options) { - self.ignore = options.ignore || [] - - if (!Array.isArray(self.ignore)) - self.ignore = [self.ignore] - - if (self.ignore.length) { - self.ignore = self.ignore.map(ignoreMap) - } -} - -// ignore patterns are always in dot:true mode. -function ignoreMap (pattern) { - var gmatcher = null - if (pattern.slice(-3) === '/**') { - var gpattern = pattern.replace(/(\/\*\*)+$/, '') - gmatcher = new Minimatch(gpattern, { dot: true }) - } - - return { - matcher: new Minimatch(pattern, { dot: true }), - gmatcher: gmatcher - } -} - -function setopts (self, pattern, options) { - if (!options) - options = {} - - // base-matching: just use globstar for that. - if (options.matchBase && -1 === pattern.indexOf("/")) { - if (options.noglobstar) { - throw new Error("base matching requires globstar") - } - pattern = "**/" + pattern - } - - self.silent = !!options.silent - self.pattern = pattern - self.strict = options.strict !== false - self.realpath = !!options.realpath - self.realpathCache = options.realpathCache || Object.create(null) - self.follow = !!options.follow - self.dot = !!options.dot - self.mark = !!options.mark - self.nodir = !!options.nodir - if (self.nodir) - self.mark = true - self.sync = !!options.sync - self.nounique = !!options.nounique - self.nonull = !!options.nonull - self.nosort = !!options.nosort - self.nocase = !!options.nocase - self.stat = !!options.stat - self.noprocess = !!options.noprocess - self.absolute = !!options.absolute - - self.maxLength = options.maxLength || Infinity - self.cache = options.cache || Object.create(null) - self.statCache = options.statCache || Object.create(null) - self.symlinks = options.symlinks || Object.create(null) - - setupIgnores(self, options) - - self.changedCwd = false - var cwd = process.cwd() - if (!ownProp(options, "cwd")) - self.cwd = cwd - else { - self.cwd = path.resolve(options.cwd) - self.changedCwd = self.cwd !== cwd - } - - self.root = options.root || path.resolve(self.cwd, "/") - self.root = path.resolve(self.root) - if (process.platform === "win32") - self.root = self.root.replace(/\\/g, "/") - - // TODO: is an absolute `cwd` supposed to be resolved against `root`? - // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test') - self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd) - if (process.platform === "win32") - self.cwdAbs = self.cwdAbs.replace(/\\/g, "/") - self.nomount = !!options.nomount - - // disable comments and negation in Minimatch. - // Note that they are not supported in Glob itself anyway. - options.nonegate = true - options.nocomment = true - - self.minimatch = new Minimatch(pattern, options) - self.options = self.minimatch.options -} - -function finish (self) { - var nou = self.nounique - var all = nou ? [] : Object.create(null) - - for (var i = 0, l = self.matches.length; i < l; i ++) { - var matches = self.matches[i] - if (!matches || Object.keys(matches).length === 0) { - if (self.nonull) { - // do like the shell, and spit out the literal glob - var literal = self.minimatch.globSet[i] - if (nou) - all.push(literal) - else - all[literal] = true - } - } else { - // had matches - var m = Object.keys(matches) - if (nou) - all.push.apply(all, m) - else - m.forEach(function (m) { - all[m] = true - }) - } - } - - if (!nou) - all = Object.keys(all) - - if (!self.nosort) - all = all.sort(self.nocase ? alphasorti : alphasort) - - // at *some* point we statted all of these - if (self.mark) { - for (var i = 0; i < all.length; i++) { - all[i] = self._mark(all[i]) - } - if (self.nodir) { - all = all.filter(function (e) { - var notDir = !(/\/$/.test(e)) - var c = self.cache[e] || self.cache[makeAbs(self, e)] - if (notDir && c) - notDir = c !== 'DIR' && !Array.isArray(c) - return notDir - }) - } - } - - if (self.ignore.length) - all = all.filter(function(m) { - return !isIgnored(self, m) - }) - - self.found = all -} - -function mark (self, p) { - var abs = makeAbs(self, p) - var c = self.cache[abs] - var m = p - if (c) { - var isDir = c === 'DIR' || Array.isArray(c) - var slash = p.slice(-1) === '/' - - if (isDir && !slash) - m += '/' - else if (!isDir && slash) - m = m.slice(0, -1) - - if (m !== p) { - var mabs = makeAbs(self, m) - self.statCache[mabs] = self.statCache[abs] - self.cache[mabs] = self.cache[abs] - } - } - - return m -} - -// lotta situps... -function makeAbs (self, f) { - var abs = f - if (f.charAt(0) === '/') { - abs = path.join(self.root, f) - } else if (isAbsolute(f) || f === '') { - abs = f - } else if (self.changedCwd) { - abs = path.resolve(self.cwd, f) - } else { - abs = path.resolve(f) - } - - if (process.platform === 'win32') - abs = abs.replace(/\\/g, '/') - - return abs -} - - -// Return true, if pattern ends with globstar '**', for the accompanying parent directory. -// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents -function isIgnored (self, path) { - if (!self.ignore.length) - return false - - return self.ignore.some(function(item) { - return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) - }) -} - -function childrenIgnored (self, path) { - if (!self.ignore.length) - return false - - return self.ignore.some(function(item) { - return !!(item.gmatcher && item.gmatcher.match(path)) - }) -} - - -/***/ }), -/* 718 */ -/***/ (function(module, exports, __webpack_require__) { - -const pkg = __webpack_require__(719); - -module.exports = pkg.async; -module.exports.default = pkg.async; - -module.exports.async = pkg.async; -module.exports.sync = pkg.sync; -module.exports.stream = pkg.stream; - -module.exports.generateTasks = pkg.generateTasks; - - -/***/ }), -/* 719 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(720); -var taskManager = __webpack_require__(721); -var reader_async_1 = __webpack_require__(877); -var reader_stream_1 = __webpack_require__(901); -var reader_sync_1 = __webpack_require__(902); -var arrayUtils = __webpack_require__(904); -var streamUtils = __webpack_require__(905); -/** - * Synchronous API. - */ -function sync(source, opts) { - assertPatternsInput(source); - var works = getWorks(source, reader_sync_1.default, opts); - return arrayUtils.flatten(works); -} -exports.sync = sync; -/** - * Asynchronous API. - */ -function async(source, opts) { - try { - assertPatternsInput(source); - } - catch (error) { - return Promise.reject(error); - } - var works = getWorks(source, reader_async_1.default, opts); - return Promise.all(works).then(arrayUtils.flatten); -} -exports.async = async; -/** - * Stream API. - */ -function stream(source, opts) { - assertPatternsInput(source); - var works = getWorks(source, reader_stream_1.default, opts); - return streamUtils.merge(works); -} -exports.stream = stream; -/** - * Return a set of tasks based on provided patterns. - */ -function generateTasks(source, opts) { - assertPatternsInput(source); - var patterns = [].concat(source); - var options = optionsManager.prepare(opts); - return taskManager.generate(patterns, options); -} -exports.generateTasks = generateTasks; -/** - * Returns a set of works based on provided tasks and class of the reader. - */ -function getWorks(source, _Reader, opts) { - var patterns = [].concat(source); - var options = optionsManager.prepare(opts); - var tasks = taskManager.generate(patterns, options); - var reader = new _Reader(options); - return tasks.map(reader.read, reader); -} -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'; -} - - -/***/ }), -/* 720 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -function prepare(options) { - var opts = __assign({ cwd: process.cwd(), deep: true, ignore: [], dot: false, stats: false, onlyFiles: true, onlyDirectories: false, followSymlinkedDirectories: true, unique: true, markDirectories: false, absolute: false, nobrace: false, brace: true, noglobstar: false, globstar: true, noext: false, extension: true, nocase: false, case: true, matchBase: false, transform: null }, options); - if (opts.onlyDirectories) { - opts.onlyFiles = false; - } - opts.brace = !opts.nobrace; - opts.globstar = !opts.noglobstar; - opts.extension = !opts.noext; - opts.case = !opts.nocase; - if (options) { - opts.brace = ('brace' in options ? options.brace : opts.brace); - opts.globstar = ('globstar' in options ? options.globstar : opts.globstar); - opts.extension = ('extension' in options ? options.extension : opts.extension); - opts.case = ('case' in options ? options.case : opts.case); - } - return opts; -} -exports.prepare = prepare; - - -/***/ }), -/* 721 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(722); -/** - * Generate tasks based on parent directory of each pattern. - */ -function generate(patterns, options) { - var unixPatterns = patterns.map(patternUtils.unixifyPattern); - var unixIgnore = options.ignore.map(patternUtils.unixifyPattern); - var positivePatterns = getPositivePatterns(unixPatterns); - var negativePatterns = getNegativePatternsAsPositive(unixPatterns, unixIgnore); - /** - * When the `case` option is disabled, all patterns must be marked as dynamic, because we cannot check filepath - * directly (without read directory). - */ - var staticPatterns = !options.case ? [] : positivePatterns.filter(patternUtils.isStaticPattern); - var dynamicPatterns = !options.case ? positivePatterns : positivePatterns.filter(patternUtils.isDynamicPattern); - var staticTasks = convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false); - var dynamicTasks = convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true); - return staticTasks.concat(dynamicTasks); -} -exports.generate = generate; -/** - * Convert patterns to tasks based on parent directory of each pattern. - */ -function convertPatternsToTasks(positive, negative, dynamic) { - var 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) { - var task = convertPatternGroupToTask('.', positive, negative, dynamic); - return [task]; - } - return convertPatternGroupsToTasks(positivePatternsGroup, negative, dynamic); -} -exports.convertPatternsToTasks = convertPatternsToTasks; -/** - * Return only positive patterns. - */ -function getPositivePatterns(patterns) { - return patternUtils.getPositivePatterns(patterns); -} -exports.getPositivePatterns = getPositivePatterns; -/** - * Return only negative patterns. - */ -function getNegativePatternsAsPositive(patterns, ignore) { - var negative = patternUtils.getNegativePatterns(patterns).concat(ignore); - var positive = negative.map(patternUtils.convertToPositivePattern); - return positive; -} -exports.getNegativePatternsAsPositive = getNegativePatternsAsPositive; -/** - * Group patterns by base directory of each pattern. - */ -function groupPatternsByBaseDirectory(patterns) { - return patterns.reduce(function (collection, pattern) { - var base = patternUtils.getBaseDirectory(pattern); - if (base in collection) { - collection[base].push(pattern); - } - else { - collection[base] = [pattern]; - } - return collection; - }, {}); -} -exports.groupPatternsByBaseDirectory = groupPatternsByBaseDirectory; -/** - * Convert group of patterns to tasks. - */ -function convertPatternGroupsToTasks(positive, negative, dynamic) { - return Object.keys(positive).map(function (base) { - return convertPatternGroupToTask(base, positive[base], negative, dynamic); - }); -} -exports.convertPatternGroupsToTasks = convertPatternGroupsToTasks; -/** - * Create a task for positive and negative patterns. - */ -function convertPatternGroupToTask(base, positive, negative, dynamic) { - return { - base: base, - dynamic: dynamic, - positive: positive, - negative: negative, - patterns: [].concat(positive, negative.map(patternUtils.convertToNegativePattern)) - }; -} -exports.convertPatternGroupToTask = convertPatternGroupToTask; - - -/***/ }), -/* 722 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var path = __webpack_require__(16); -var globParent = __webpack_require__(723); -var isGlob = __webpack_require__(726); -var micromatch = __webpack_require__(727); -var GLOBSTAR = '**'; -/** - * Return true for static pattern. - */ -function isStaticPattern(pattern) { - return !isDynamicPattern(pattern); -} -exports.isStaticPattern = isStaticPattern; -/** - * Return true for pattern that looks like glob. - */ -function isDynamicPattern(pattern) { - return isGlob(pattern, { strict: false }); -} -exports.isDynamicPattern = isDynamicPattern; -/** - * Convert a windows «path» to a unix-style «path». - */ -function unixifyPattern(pattern) { - return pattern.replace(/\\/g, '/'); -} -exports.unixifyPattern = unixifyPattern; -/** - * Returns negative pattern as positive pattern. - */ -function convertToPositivePattern(pattern) { - return isNegativePattern(pattern) ? pattern.slice(1) : pattern; -} -exports.convertToPositivePattern = convertToPositivePattern; -/** - * Returns positive pattern as negative pattern. - */ -function convertToNegativePattern(pattern) { - return '!' + pattern; -} -exports.convertToNegativePattern = convertToNegativePattern; -/** - * Return true if provided pattern is negative pattern. - */ -function isNegativePattern(pattern) { - return pattern.startsWith('!') && pattern[1] !== '('; -} -exports.isNegativePattern = isNegativePattern; -/** - * Return true if provided pattern is positive pattern. - */ -function isPositivePattern(pattern) { - return !isNegativePattern(pattern); -} -exports.isPositivePattern = isPositivePattern; -/** - * Extracts negative patterns from array of patterns. - */ -function getNegativePatterns(patterns) { - return patterns.filter(isNegativePattern); -} -exports.getNegativePatterns = getNegativePatterns; -/** - * Extracts positive patterns from array of patterns. - */ -function getPositivePatterns(patterns) { - return patterns.filter(isPositivePattern); -} -exports.getPositivePatterns = getPositivePatterns; -/** - * Extract base directory from provided pattern. - */ -function getBaseDirectory(pattern) { - return globParent(pattern); -} -exports.getBaseDirectory = getBaseDirectory; -/** - * Return true if provided pattern has globstar. - */ -function hasGlobStar(pattern) { - return pattern.indexOf(GLOBSTAR) !== -1; -} -exports.hasGlobStar = hasGlobStar; -/** - * Return true if provided pattern ends with slash and globstar. - */ -function endsWithSlashGlobStar(pattern) { - return pattern.endsWith('/' + GLOBSTAR); -} -exports.endsWithSlashGlobStar = endsWithSlashGlobStar; -/** - * Returns «true» when pattern ends with a slash and globstar or the last partial of the pattern is static pattern. - */ -function isAffectDepthOfReadingPattern(pattern) { - var basename = path.basename(pattern); - return endsWithSlashGlobStar(pattern) || isStaticPattern(basename); -} -exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern; -/** - * Return naive depth of provided pattern without depth of the base directory. - */ -function getNaiveDepth(pattern) { - var base = getBaseDirectory(pattern); - var patternDepth = pattern.split('/').length; - var 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; -/** - * Return max naive depth of provided patterns without depth of the base directory. - */ -function getMaxNaivePatternsDepth(patterns) { - return patterns.reduce(function (max, pattern) { - var depth = getNaiveDepth(pattern); - return depth > max ? depth : max; - }, 0); -} -exports.getMaxNaivePatternsDepth = getMaxNaivePatternsDepth; -/** - * Make RegExp for provided pattern. - */ -function makeRe(pattern, options) { - return micromatch.makeRe(pattern, options); -} -exports.makeRe = makeRe; -/** - * Convert patterns to regexps. - */ -function convertPatternsToRe(patterns, options) { - return patterns.map(function (pattern) { return makeRe(pattern, options); }); -} -exports.convertPatternsToRe = convertPatternsToRe; -/** - * Returns true if the entry match any of the given RegExp's. - */ -function matchAny(entry, patternsRe) { - return patternsRe.some(function (patternRe) { return patternRe.test(entry); }); -} -exports.matchAny = matchAny; - - -/***/ }), -/* 723 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var path = __webpack_require__(16); -var isglob = __webpack_require__(724); -var pathDirname = __webpack_require__(725); -var isWin32 = __webpack_require__(11).platform() === 'win32'; - -module.exports = function globParent(str) { - // flip windows path separators - if (isWin32 && str.indexOf('/') < 0) str = str.split('\\').join('/'); - - // special case for strings ending in enclosure containing path separator - if (/[\{\[].*[\/]*.*[\}\]]$/.test(str)) str += '/'; - - // preserves full path in case of trailing path separator - str += 'a'; - - // remove path parts that are globby - do {str = pathDirname.posix(str)} - while (isglob(str) || /(^|[^\\])([\{\[]|\([^\)]+$)/.test(str)); - - // remove escape chars and return result - return str.replace(/\\([\*\?\|\[\]\(\)\{\}])/g, '$1'); -}; - - -/***/ }), -/* 724 */ -/***/ (function(module, exports, __webpack_require__) { - -/*! - * is-glob - * - * Copyright (c) 2014-2016, Jon Schlinkert. - * Licensed under the MIT License. - */ - -var isExtglob = __webpack_require__(606); - -module.exports = function isGlob(str) { - if (typeof str !== 'string' || str === '') { - return false; - } - - if (isExtglob(str)) return true; - - var regex = /(\\).|([*?]|\[.*\]|\{.*\}|\(.*\|.*\)|^!)/; - var match; - - while ((match = regex.exec(str))) { - if (match[2]) return true; - str = str.slice(match.index + match[0].length); - } - return false; -}; - - -/***/ }), -/* 725 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var path = __webpack_require__(16); -var inspect = __webpack_require__(29).inspect; - -function assertPath(path) { - if (typeof path !== 'string') { - throw new TypeError('Path must be a string. Received ' + inspect(path)); - } -} - -function posix(path) { - assertPath(path); - if (path.length === 0) - return '.'; - var code = path.charCodeAt(0); - var hasRoot = (code === 47/*/*/); - var end = -1; - var matchedSlash = true; - for (var i = path.length - 1; i >= 1; --i) { - code = path.charCodeAt(i); - if (code === 47/*/*/) { - if (!matchedSlash) { - end = i; - break; - } - } else { - // We saw the first non-path separator - matchedSlash = false; - } - } - - if (end === -1) - return hasRoot ? '/' : '.'; - if (hasRoot && end === 1) - return '//'; - return path.slice(0, end); -} - -function win32(path) { - assertPath(path); - var len = path.length; - if (len === 0) - return '.'; - var rootEnd = -1; - var end = -1; - var matchedSlash = true; - var offset = 0; - var code = path.charCodeAt(0); - - // Try to match a root - if (len > 1) { - if (code === 47/*/*/ || code === 92/*\*/) { - // Possible UNC root - - rootEnd = offset = 1; - - code = path.charCodeAt(1); - if (code === 47/*/*/ || code === 92/*\*/) { - // Matched double path separator at beginning - var j = 2; - var last = j; - // Match 1 or more non-path separators - for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code === 47/*/*/ || code === 92/*\*/) - break; - } - if (j < len && j !== last) { - // Matched! - last = j; - // Match 1 or more path separators - for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code !== 47/*/*/ && code !== 92/*\*/) - break; - } - if (j < len && j !== last) { - // Matched! - last = j; - // Match 1 or more non-path separators - for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code === 47/*/*/ || code === 92/*\*/) - break; - } - if (j === len) { - // We matched a UNC root only - return path; - } - if (j !== last) { - // We matched a UNC root with leftovers - - // Offset by 1 to include the separator after the UNC root to - // treat it as a "normal root" on top of a (UNC) root - rootEnd = offset = j + 1; - } - } - } - } - } else if ((code >= 65/*A*/ && code <= 90/*Z*/) || - (code >= 97/*a*/ && code <= 122/*z*/)) { - // Possible device root - - code = path.charCodeAt(1); - if (path.charCodeAt(1) === 58/*:*/) { - rootEnd = offset = 2; - if (len > 2) { - code = path.charCodeAt(2); - if (code === 47/*/*/ || code === 92/*\*/) - rootEnd = offset = 3; - } - } - } - } else if (code === 47/*/*/ || code === 92/*\*/) { - return path[0]; - } - - for (var i = len - 1; i >= offset; --i) { - code = path.charCodeAt(i); - if (code === 47/*/*/ || code === 92/*\*/) { - if (!matchedSlash) { - end = i; - break; - } - } else { - // We saw the first non-path separator - matchedSlash = false; - } - } - - if (end === -1) { - if (rootEnd === -1) - return '.'; - else - end = rootEnd; - } - return path.slice(0, end); -} - -module.exports = process.platform === 'win32' ? win32 : posix; -module.exports.posix = posix; -module.exports.win32 = win32; - - -/***/ }), -/* 726 */ -/***/ (function(module, exports, __webpack_require__) { - -/*! - * is-glob - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - -var isExtglob = __webpack_require__(606); -var chars = { '{': '}', '(': ')', '[': ']'}; - -module.exports = function isGlob(str, options) { - if (typeof str !== 'string' || str === '') { - return false; - } - - if (isExtglob(str)) { - return true; - } - - var regex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; - var match; - - // optionally relax regex - if (options && options.strict === false) { - regex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; - } - - 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; -}; - - -/***/ }), -/* 727 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Module dependencies - */ - -var util = __webpack_require__(29); -var braces = __webpack_require__(728); -var toRegex = __webpack_require__(830); -var extend = __webpack_require__(838); - -/** - * Local dependencies - */ - -var compilers = __webpack_require__(841); -var parsers = __webpack_require__(873); -var cache = __webpack_require__(874); -var utils = __webpack_require__(875); -var MAX_LENGTH = 1024 * 64; - -/** - * The main function takes a list of strings and one or more - * glob patterns to use for matching. - * - * ```js - * var mm = require('micromatch'); - * mm(list, patterns[, options]); - * - * console.log(mm(['a.js', 'a.txt'], ['*.js'])); - * //=> [ 'a.js' ] - * ``` - * @param {Array} `list` A 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) for changing how matches are performed - * @return {Array} Returns an array of matches - * @summary false - * @api public - */ - -function micromatch(list, patterns, options) { - patterns = utils.arrayify(patterns); - list = utils.arrayify(list); - - var len = patterns.length; - if (list.length === 0 || len === 0) { - return []; - } - - if (len === 1) { - return micromatch.match(list, patterns[0], options); - } - - var omit = []; - var keep = []; - var idx = -1; - - while (++idx < len) { - var pattern = patterns[idx]; - - if (typeof pattern === 'string' && pattern.charCodeAt(0) === 33 /* ! */) { - omit.push.apply(omit, micromatch.match(list, pattern.slice(1), options)); - } else { - keep.push.apply(keep, micromatch.match(list, pattern, options)); - } - } - - var matches = utils.diff(keep, omit); - if (!options || options.nodupes !== false) { - return utils.unique(matches); - } - - return matches; -} - -/** - * Similar to the main function, but `pattern` must be a string. - * - * ```js - * var mm = require('micromatch'); - * mm.match(list, pattern[, options]); - * - * console.log(mm.match(['a.a', 'a.aa', 'a.b', 'a.c'], '*.a')); - * //=> ['a.a', 'a.aa'] - * ``` - * @param {Array} `list` Array of strings to match - * @param {String} `pattern` 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 matches - * @api public - */ - -micromatch.match = function(list, pattern, options) { - if (Array.isArray(pattern)) { - throw new TypeError('expected pattern to be a string'); - } - - var unixify = utils.unixify(options); - var isMatch = memoize('match', pattern, options, micromatch.matcher); - var matches = []; - - list = utils.arrayify(list); - var len = list.length; - var idx = -1; - - while (++idx < len) { - var ele = list[idx]; - if (ele === pattern || isMatch(ele)) { - matches.push(utils.value(ele, unixify, options)); - } - } - - // if no options were passed, uniquify results and return - if (typeof options === 'undefined') { - return utils.unique(matches); - } - - if (matches.length === 0) { - if (options.failglob === true) { - throw new Error('no matches found for "' + pattern + '"'); - } - if (options.nonull === true || options.nullglob === true) { - return [options.unescape ? utils.unescape(pattern) : pattern]; - } - } - - // if `opts.ignore` was defined, diff ignored list - if (options.ignore) { - matches = micromatch.not(matches, options.ignore, options); - } - - return options.nodupes !== false ? utils.unique(matches) : matches; -}; - -/** - * Returns true if the specified `string` matches the given glob `pattern`. - * - * ```js - * var mm = require('micromatch'); - * mm.isMatch(string, pattern[, options]); - * - * console.log(mm.isMatch('a.a', '*.a')); - * //=> true - * console.log(mm.isMatch('a.b', '*.a')); - * //=> false - * ``` - * @param {String} `string` String to match - * @param {String} `pattern` 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 string matches the glob pattern. - * @api public - */ - -micromatch.isMatch = function(str, pattern, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string: "' + util.inspect(str) + '"'); - } - - if (isEmptyString(str) || isEmptyString(pattern)) { - return false; - } - - var equals = utils.equalsPattern(options); - if (equals(str)) { - return true; - } - - var isMatch = memoize('isMatch', pattern, options, micromatch.matcher); - return isMatch(str); -}; - -/** - * Returns true if some of the strings in the given `list` match any of the - * given glob `patterns`. - * - * ```js - * var 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 = function(list, patterns, options) { - if (typeof list === 'string') { - list = [list]; - } - for (var i = 0; i < list.length; i++) { - if (micromatch(list[i], patterns, options).length === 1) { - return true; - } - } - return false; -}; - -/** - * Returns true if every string in the given `list` matches - * any of the given glob `patterns`. - * - * ```js - * var 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 = function(list, patterns, options) { - if (typeof list === 'string') { - list = [list]; - } - for (var i = 0; i < list.length; i++) { - if (micromatch(list[i], patterns, options).length !== 1) { - return false; - } - } - return true; -}; - -/** - * Returns true if **any** of the given glob `patterns` - * match the specified `string`. - * - * ```js - * var mm = require('micromatch'); - * mm.any(string, patterns[, options]); - * - * console.log(mm.any('a.a', ['b.*', '*.a'])); - * //=> true - * console.log(mm.any('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) for changing how matches are performed - * @return {Boolean} Returns true if any patterns match `str` - * @api public - */ - -micromatch.any = function(str, patterns, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string: "' + util.inspect(str) + '"'); - } - - if (isEmptyString(str) || isEmptyString(patterns)) { - return false; - } - - if (typeof patterns === 'string') { - patterns = [patterns]; - } - - for (var i = 0; i < patterns.length; i++) { - if (micromatch.isMatch(str, patterns[i], options)) { - return true; - } - } - return false; -}; - -/** - * Returns true if **all** of the given `patterns` match - * the specified string. - * - * ```js - * var 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 = function(str, patterns, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string: "' + util.inspect(str) + '"'); - } - if (typeof patterns === 'string') { - patterns = [patterns]; - } - for (var i = 0; i < patterns.length; i++) { - if (!micromatch.isMatch(str, patterns[i], options)) { - return false; - } - } - return true; -}; - -/** - * Returns a list of strings that _**do not match any**_ of the given `patterns`. - * - * ```js - * var 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 = function(list, patterns, options) { - var opts = extend({}, options); - var ignore = opts.ignore; - delete opts.ignore; - - var unixify = utils.unixify(opts); - list = utils.arrayify(list).map(unixify); - - var matches = utils.diff(list, micromatch(list, patterns, opts)); - if (ignore) { - matches = utils.diff(matches, micromatch(list, ignore)); - } - - return opts.nodupes !== false ? utils.unique(matches) : matches; -}; - -/** - * 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 = function(str, patterns, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string: "' + util.inspect(str) + '"'); - } - - if (typeof patterns === 'string') { - if (isEmptyString(str) || isEmptyString(patterns)) { - return false; - } - - var equals = utils.equalsPattern(patterns, options); - if (equals(str)) { - return true; - } - var contains = utils.containsPattern(patterns, options); - if (contains(str)) { - return true; - } - } - - var opts = extend({}, options, {contains: true}); - return micromatch.any(str, patterns, opts); -}; - -/** - * Returns true if the given pattern and options should enable - * the `matchBase` option. - * @return {Boolean} - * @api private - */ - -micromatch.matchBase = function(pattern, options) { - if (pattern && pattern.indexOf('/') !== -1 || !options) return false; - return options.basename === true || options.matchBase === 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 - * var mm = require('micromatch'); - * mm.matchKeys(object, patterns[, options]); - * - * var 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 = function(obj, patterns, options) { - if (!utils.isObject(obj)) { - throw new TypeError('expected the first argument to be an object'); - } - var keys = micromatch(Object.keys(obj), patterns, options); - return utils.pick(obj, keys); -}; - -/** - * Returns a memoized 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 - * var mm = require('micromatch'); - * mm.matcher(pattern[, options]); - * - * var isMatch = mm.matcher('*.!(*a)'); - * console.log(isMatch('a.a')); - * //=> false - * console.log(isMatch('a.b')); - * //=> true - * ``` - * @param {String} `pattern` Glob pattern - * @param {Object} `options` See available [options](#options) for changing how matches are performed. - * @return {Function} Returns a matcher function. - * @api public - */ - -micromatch.matcher = function matcher(pattern, options) { - if (Array.isArray(pattern)) { - return compose(pattern, options, matcher); - } - - // if pattern is a regex - if (pattern instanceof RegExp) { - return test(pattern); - } - - // if pattern is invalid - if (!utils.isString(pattern)) { - throw new TypeError('expected pattern to be an array, string or regex'); - } - - // if pattern is a non-glob string - if (!utils.hasSpecialChars(pattern)) { - if (options && options.nocase === true) { - pattern = pattern.toLowerCase(); - } - return utils.matchPath(pattern, options); - } - - // if pattern is a glob string - var re = micromatch.makeRe(pattern, options); - - // if `options.matchBase` or `options.basename` is defined - if (micromatch.matchBase(pattern, options)) { - return utils.matchBasename(re, options); - } - - function test(regex) { - var equals = utils.equalsPattern(options); - var unixify = utils.unixify(options); - - return function(str) { - if (equals(str)) { - return true; - } - - if (regex.test(unixify(str))) { - return true; - } - return false; - }; - } - - var fn = test(re); - Object.defineProperty(fn, 'result', { - configurable: true, - enumerable: false, - value: re.result - }); - return fn; -}; - -/** - * Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match. - * - * ```js - * var 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} `pattern` Glob pattern to use for matching. - * @param {String} `string` 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 string matches the glob pattern, otherwise `null`. - * @api public - */ - -micromatch.capture = function(pattern, str, options) { - var re = micromatch.makeRe(pattern, extend({capture: true}, options)); - var unixify = utils.unixify(options); - - function match() { - return function(string) { - var match = re.exec(unixify(string)); - if (!match) { - return null; - } - - return match.slice(1); - }; - } - - var capture = memoize('capture', pattern, options, match); - return capture(str); -}; - -/** - * Create a regular expression from the given glob `pattern`. - * - * ```js - * var 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` See available [options](#options) for changing how matches are performed. - * @return {RegExp} Returns a regex created from the given pattern. - * @api public - */ - -micromatch.makeRe = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected pattern to be a string'); - } - - if (pattern.length > MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); - } - - function makeRe() { - var result = micromatch.create(pattern, options); - var ast_array = []; - var output = result.map(function(obj) { - obj.ast.state = obj.state; - ast_array.push(obj.ast); - return obj.output; - }); - - var regex = toRegex(output.join('|'), options); - Object.defineProperty(regex, 'result', { - configurable: true, - enumerable: false, - value: ast_array - }); - return regex; - } - - return memoize('makeRe', pattern, options, makeRe); -}; - -/** - * Expand the given brace `pattern`. - * - * ```js - * var mm = require('micromatch'); - * console.log(mm.braces('foo/{a,b}/bar')); - * //=> ['foo/(a|b)/bar'] - * - * console.log(mm.braces('foo/{a,b}/bar', {expand: true})); - * //=> ['foo/(a|b)/bar'] - * ``` - * @param {String} `pattern` String with brace pattern to expand. - * @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 = function(pattern, options) { - if (typeof pattern !== 'string' && !Array.isArray(pattern)) { - throw new TypeError('expected pattern to be an array or string'); - } - - function expand() { - if (options && options.nobrace === true || !/\{.*\}/.test(pattern)) { - return utils.arrayify(pattern); - } - return braces(pattern, options); - } - - return memoize('braces', pattern, options, expand); -}; - -/** - * Proxy to the [micromatch.braces](#method), for parity with - * minimatch. - */ - -micromatch.braceExpand = function(pattern, options) { - var opts = extend({}, options, {expand: true}); - return micromatch.braces(pattern, opts); -}; - -/** - * Parses the given glob `pattern` and returns an array of abstract syntax - * trees (ASTs), with the compiled `output` and optional source `map` on - * each AST. - * - * ```js - * var mm = require('micromatch'); - * mm.create(pattern[, options]); - * - * console.log(mm.create('abc/*.js')); - * // [{ options: { source: 'string', sourcemap: true }, - * // state: {}, - * // compilers: - * // { ... }, - * // output: '(\\.[\\\\\\/])?abc\\/(?!\\.)(?=.)[^\\/]*?\\.js', - * // ast: - * // { type: 'root', - * // errors: [], - * // nodes: - * // [ ... ], - * // dot: false, - * // input: 'abc/*.js' }, - * // parsingErrors: [], - * // map: - * // { version: 3, - * // sources: [ 'string' ], - * // names: [], - * // mappings: 'AAAA,GAAG,EAAC,kBAAC,EAAC,EAAE', - * // sourcesContent: [ 'abc/*.js' ] }, - * // position: { line: 1, column: 28 }, - * // content: {}, - * // files: {}, - * // idx: 6 }] - * ``` - * @param {String} `pattern` Glob pattern to parse and compile. - * @param {Object} `options` Any [options](#options) to change how parsing and compiling is performed. - * @return {Object} Returns an object with the parsed AST, compiled string and optional source map. - * @api public - */ - -micromatch.create = function(pattern, options) { - return memoize('create', pattern, options, function() { - function create(str, opts) { - return micromatch.compile(micromatch.parse(str, opts), opts); - } - - pattern = micromatch.braces(pattern, options); - var len = pattern.length; - var idx = -1; - var res = []; - - while (++idx < len) { - res.push(create(pattern[idx], options)); - } - return res; - }); -}; - -/** - * Parse the given `str` with the given `options`. - * - * ```js - * var mm = require('micromatch'); - * mm.parse(pattern[, options]); - * - * var ast = mm.parse('a/{b,c}/d'); - * console.log(ast); - * // { type: 'root', - * // errors: [], - * // input: 'a/{b,c}/d', - * // nodes: - * // [ { type: 'bos', val: '' }, - * // { type: 'text', val: 'a/' }, - * // { type: 'brace', - * // nodes: - * // [ { type: 'brace.open', val: '{' }, - * // { type: 'text', val: 'b,c' }, - * // { type: 'brace.close', val: '}' } ] }, - * // { type: 'text', val: '/d' }, - * // { type: 'eos', val: '' } ] } - * ``` - * @param {String} `str` - * @param {Object} `options` - * @return {Object} Returns an AST - * @api public - */ - -micromatch.parse = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - function parse() { - var snapdragon = utils.instantiate(null, options); - parsers(snapdragon, options); - - var ast = snapdragon.parse(pattern, options); - utils.define(ast, 'snapdragon', snapdragon); - ast.input = pattern; - return ast; - } - - return memoize('parse', pattern, options, parse); -}; - -/** - * Compile the given `ast` or string with the given `options`. - * - * ```js - * var mm = require('micromatch'); - * mm.compile(ast[, options]); - * - * var ast = mm.parse('a/{b,c}/d'); - * console.log(mm.compile(ast)); - * // { options: { source: 'string' }, - * // state: {}, - * // compilers: - * // { eos: [Function], - * // noop: [Function], - * // bos: [Function], - * // brace: [Function], - * // 'brace.open': [Function], - * // text: [Function], - * // 'brace.close': [Function] }, - * // output: [ 'a/(b|c)/d' ], - * // ast: - * // { ... }, - * // parsingErrors: [] } - * ``` - * @param {Object|String} `ast` - * @param {Object} `options` - * @return {Object} Returns an object that has an `output` property with the compiled string. - * @api public - */ - -micromatch.compile = function(ast, options) { - if (typeof ast === 'string') { - ast = micromatch.parse(ast, options); - } - - return memoize('compile', ast.input, options, function() { - var snapdragon = utils.instantiate(ast, options); - compilers(snapdragon, options); - return snapdragon.compile(ast, options); - }); -}; - -/** - * Clear the regex cache. - * - * ```js - * mm.clearCache(); - * ``` - * @api public - */ - -micromatch.clearCache = function() { - micromatch.cache.caches = {}; -}; - -/** - * Returns true if the given value is effectively an empty string - */ - -function isEmptyString(val) { - return String(val) === '' || String(val) === './'; -} - -/** - * Compose a matcher function with the given patterns. - * This allows matcher functions to be compiled once and - * called multiple times. - */ - -function compose(patterns, options, matcher) { - var matchers; - - return memoize('compose', String(patterns), options, function() { - return function(file) { - // delay composition until it's invoked the first time, - // after that it won't be called again - if (!matchers) { - matchers = []; - for (var i = 0; i < patterns.length; i++) { - matchers.push(matcher(patterns[i], options)); - } - } - - var len = matchers.length; - while (len--) { - if (matchers[len](file) === true) { - return true; - } - } - return false; - }; - }); -} - -/** - * Memoize a generated regex or function. A unique key is generated - * from the `type` (usually method name), the `pattern`, and - * user-defined options. - */ - -function memoize(type, pattern, options, fn) { - var key = utils.createKey(type + '=' + pattern, options); - - if (options && options.cache === false) { - return fn(pattern, options); - } - - if (cache.has(type, key)) { - return cache.get(type, key); - } - - var val = fn(pattern, options); - cache.set(type, key, val); - return val; -} - -/** - * Expose compiler, parser and cache on `micromatch` - */ - -micromatch.compilers = compilers; -micromatch.parsers = parsers; -micromatch.caches = cache.caches; - -/** - * Expose `micromatch` - * @type {Function} - */ - -module.exports = micromatch; - - -/***/ }), -/* 728 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Module dependencies - */ - -var toRegex = __webpack_require__(729); -var unique = __webpack_require__(741); -var extend = __webpack_require__(738); - -/** - * Local dependencies - */ - -var compilers = __webpack_require__(742); -var parsers = __webpack_require__(757); -var Braces = __webpack_require__(767); -var utils = __webpack_require__(743); -var MAX_LENGTH = 1024 * 64; -var cache = {}; - -/** - * Convert the given `braces` pattern into a regex-compatible string. By default, only one string is generated for every input string. Set `options.expand` to true to return an array of patterns (similar to Bash or minimatch. Before using `options.expand`, it's recommended that you read the [performance notes](#performance)). - * - * ```js - * var braces = require('braces'); - * console.log(braces('{a,b,c}')); - * //=> ['(a|b|c)'] - * - * console.log(braces('{a,b,c}', {expand: true})); - * //=> ['a', 'b', 'c'] - * ``` - * @param {String} `str` - * @param {Object} `options` - * @return {String} - * @api public - */ - -function braces(pattern, options) { - var key = utils.createKey(String(pattern), options); - var arr = []; - - var disabled = options && options.cache === false; - if (!disabled && cache.hasOwnProperty(key)) { - return cache[key]; - } - - if (Array.isArray(pattern)) { - for (var i = 0; i < pattern.length; i++) { - arr.push.apply(arr, braces.create(pattern[i], options)); - } - } else { - arr = braces.create(pattern, options); - } - - if (options && options.nodupes === true) { - arr = unique(arr); - } - - if (!disabled) { - cache[key] = arr; - } - return arr; -} - -/** - * 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 [.optimize](#optimize) instead. - * - * ```js - * var 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 = function(pattern, options) { - return braces.create(pattern, extend({}, options, {expand: true})); -}; - -/** - * Expands a brace pattern into a regex-compatible, optimized string. This method is called by the main [braces](#braces) function by default. - * - * ```js - * var braces = require('braces'); - * console.log(braces.expand('a/{b,c}/d')); - * //=> ['a/(b|c)/d'] - * ``` - * @param {String} `pattern` Brace pattern - * @param {Object} `options` - * @return {Array} Returns an array of expanded values. - * @api public - */ - -braces.optimize = function(pattern, options) { - return braces.create(pattern, options); -}; - -/** - * 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 - * var 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 = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - var maxLength = (options && options.maxLength) || MAX_LENGTH; - if (pattern.length >= maxLength) { - throw new Error('expected pattern to be less than ' + maxLength + ' characters'); - } - - function create() { - if (pattern === '' || pattern.length < 3) { - return [pattern]; - } - - if (utils.isEmptySets(pattern)) { - return []; - } - - if (utils.isQuotedString(pattern)) { - return [pattern.slice(1, -1)]; - } - - var proto = new Braces(options); - var result = !options || options.expand !== true - ? proto.optimize(pattern, options) - : proto.expand(pattern, options); - - // get the generated pattern(s) - var arr = result.output; - - // filter out empty strings if specified - if (options && options.noempty === true) { - arr = arr.filter(Boolean); - } - - // filter out duplicates if specified - if (options && options.nodupes === true) { - arr = unique(arr); - } - - Object.defineProperty(arr, 'result', { - enumerable: false, - value: result - }); - - return arr; - } - - return memoize('create', pattern, options, create); -}; - -/** - * Create a regular expression from the given string `pattern`. - * - * ```js - * var braces = require('braces'); - * - * console.log(braces.makeRe('id-{200..300}')); - * //=> /^(?:id-(20[0-9]|2[1-9][0-9]|300))$/ - * ``` - * @param {String} `pattern` The pattern to convert to regex. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ - -braces.makeRe = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - var maxLength = (options && options.maxLength) || MAX_LENGTH; - if (pattern.length >= maxLength) { - throw new Error('expected pattern to be less than ' + maxLength + ' characters'); - } - - function makeRe() { - var arr = braces(pattern, options); - var opts = extend({strictErrors: false}, options); - return toRegex(arr, opts); - } - - return memoize('makeRe', pattern, options, makeRe); -}; - -/** - * Parse the given `str` with the given `options`. - * - * ```js - * var braces = require('braces'); - * var ast = braces.parse('a/{b,c}/d'); - * console.log(ast); - * // { type: 'root', - * // errors: [], - * // input: 'a/{b,c}/d', - * // nodes: - * // [ { type: 'bos', val: '' }, - * // { type: 'text', val: 'a/' }, - * // { type: 'brace', - * // nodes: - * // [ { type: 'brace.open', val: '{' }, - * // { type: 'text', val: 'b,c' }, - * // { type: 'brace.close', val: '}' } ] }, - * // { type: 'text', val: '/d' }, - * // { type: 'eos', val: '' } ] } - * ``` - * @param {String} `pattern` Brace pattern to parse - * @param {Object} `options` - * @return {Object} Returns an AST - * @api public - */ - -braces.parse = function(pattern, options) { - var proto = new Braces(options); - return proto.parse(pattern, options); -}; - -/** - * Compile the given `ast` or string with the given `options`. - * - * ```js - * var braces = require('braces'); - * var ast = braces.parse('a/{b,c}/d'); - * console.log(braces.compile(ast)); - * // { options: { source: 'string' }, - * // state: {}, - * // compilers: - * // { eos: [Function], - * // noop: [Function], - * // bos: [Function], - * // brace: [Function], - * // 'brace.open': [Function], - * // text: [Function], - * // 'brace.close': [Function] }, - * // output: [ 'a/(b|c)/d' ], - * // ast: - * // { ... }, - * // parsingErrors: [] } - * ``` - * @param {Object|String} `ast` AST from [.parse](#parse). If a string is passed it will be parsed first. - * @param {Object} `options` - * @return {Object} Returns an object that has an `output` property with the compiled string. - * @api public - */ - -braces.compile = function(ast, options) { - var proto = new Braces(options); - return proto.compile(ast, options); -}; - -/** - * Clear the regex cache. - * - * ```js - * braces.clearCache(); - * ``` - * @api public - */ - -braces.clearCache = function() { - cache = braces.cache = {}; -}; - -/** - * Memoize a generated regex or function. A unique key is generated - * from the method name, pattern, and user-defined options. Set - * options.memoize to false to disable. - */ - -function memoize(type, pattern, options, fn) { - var key = utils.createKey(type + ':' + pattern, options); - var disabled = options && options.cache === false; - if (disabled) { - braces.clearCache(); - return fn(pattern, options); - } - - if (cache.hasOwnProperty(key)) { - return cache[key]; - } - - var res = fn(pattern, options); - cache[key] = res; - return res; -} - -/** - * Expose `Braces` constructor and methods - * @type {Function} - */ - -braces.Braces = Braces; -braces.compilers = compilers; -braces.parsers = parsers; -braces.cache = cache; - -/** - * Expose `braces` - * @type {Function} - */ - -module.exports = braces; - - -/***/ }), -/* 729 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var define = __webpack_require__(730); -var extend = __webpack_require__(738); -var not = __webpack_require__(740); -var MAX_LENGTH = 1024 * 64; - -/** - * Session cache - */ - -var cache = {}; - -/** - * Create a regular expression from the given `pattern` string. - * - * @param {String|RegExp} `pattern` Pattern can be a string or regular expression. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ - -module.exports = function(patterns, options) { - if (!Array.isArray(patterns)) { - return makeRe(patterns, options); - } - return makeRe(patterns.join('|'), options); -}; - -/** - * Create a regular expression from the given `pattern` string. - * - * @param {String|RegExp} `pattern` Pattern can be a string or regular expression. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ - -function makeRe(pattern, options) { - if (pattern instanceof RegExp) { - return pattern; - } - - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - if (pattern.length > MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); - } - - var key = pattern; - // do this before shallow cloning options, it's a lot faster - if (!options || (options && options.cache !== false)) { - key = createKey(pattern, options); - - if (cache.hasOwnProperty(key)) { - return cache[key]; - } - } - - var opts = extend({}, options); - if (opts.contains === true) { - if (opts.negate === true) { - opts.strictNegate = false; - } else { - opts.strict = false; - } - } - - if (opts.strict === false) { - opts.strictOpen = false; - opts.strictClose = false; - } - - var open = opts.strictOpen !== false ? '^' : ''; - var close = opts.strictClose !== false ? '$' : ''; - var flags = opts.flags || ''; - var regex; - - if (opts.nocase === true && !/i/.test(flags)) { - flags += 'i'; - } - - try { - if (opts.negate || typeof opts.strictNegate === 'boolean') { - pattern = not.create(pattern, opts); - } - var str = open + '(?:' + pattern + ')' + close; - regex = new RegExp(str, flags); - } catch (err) { - if (opts.strictErrors === true) { - err.key = key; - err.pattern = pattern; - err.originalOptions = options; - err.createdOptions = opts; - throw err; - } - - try { - regex = new RegExp('^' + pattern.replace(/(\W)/g, '\\$1') + '$'); - } catch (err) { - regex = /.^/; //<= match nothing - } - } - - if (opts.cache !== false) { - cacheRegex(regex, key, pattern, opts); - } - return regex; -} - -/** - * Cache generated regex. This can result in dramatic speed improvements - * and simplify debugging by adding options and pattern to the regex. It can be - * disabled by passing setting `options.cache` to false. - */ - -function cacheRegex(regex, key, pattern, options) { - define(regex, 'cached', true); - define(regex, 'pattern', pattern); - define(regex, 'options', options); - define(regex, 'key', key); - cache[key] = regex; -} - -/** - * Create the key to use for memoization. The key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. - */ - -function createKey(pattern, options) { - if (!options) return pattern; - var key = pattern; - for (var prop in options) { - if (options.hasOwnProperty(prop)) { - key += ';' + prop + '=' + String(options[prop]); - } - } - return key; -} - -/** - * Expose `makeRe` - */ - -module.exports.makeRe = makeRe; - - -/***/ }), -/* 730 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isDescriptor = __webpack_require__(731); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } - - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } - - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; - - -/***/ }), -/* 731 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(732); -var isAccessor = __webpack_require__(733); -var isData = __webpack_require__(736); - -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; - } - if ('get' in obj) { - return isAccessor(obj, key); - } - return isData(obj, key); -}; - - -/***/ }), -/* 732 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - var type = typeof val; - - // primitivies - if (type === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (type === 'string' || val instanceof String) { - return 'string'; - } - if (type === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (type === 'function' || val instanceof Function) { - if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') { - return 'generatorfunction'; - } - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - if (type === '[object Map Iterator]') { - return 'mapiterator'; - } - if (type === '[object Set Iterator]') { - return 'setiterator'; - } - if (type === '[object String Iterator]') { - return 'stringiterator'; - } - if (type === '[object Array Iterator]') { - return 'arrayiterator'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - return val.constructor - && typeof val.constructor.isBuffer === 'function' - && val.constructor.isBuffer(val); -} - - -/***/ }), -/* 733 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-accessor-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var typeOf = __webpack_require__(734); - -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; - -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (typeOf(obj) !== 'object') { - return false; - } - - if (has(obj, 'value') || has(obj, 'writable')) { - return false; - } - - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; - } - - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; - } - - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === accessor[key]) { - continue; - } - - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -} - -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} - -/** - * Expose `isAccessorDescriptor` - */ - -module.exports = isAccessorDescriptor; - - -/***/ }), -/* 734 */ -/***/ (function(module, exports, __webpack_require__) { - -var isBuffer = __webpack_require__(735); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - var type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - - -/***/ }), -/* 735 */ -/***/ (function(module, exports) { - -/*! - * Determine if an object is a Buffer - * - * @author Feross Aboukhadijeh - * @license MIT - */ - -// The _isBuffer check is for Safari 5-7 support, because it's missing -// Object.prototype.constructor. Remove this eventually -module.exports = function (obj) { - return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) -} - -function isBuffer (obj) { - return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) -} - -// For Node v0.10 support. Remove this eventually. -function isSlowBuffer (obj) { - return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) -} - - -/***/ }), -/* 736 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-data-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var typeOf = __webpack_require__(737); - -// data descriptor properties -var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' -}; - -function isDataDescriptor(obj, prop) { - if (typeOf(obj) !== 'object') { - return false; - } - - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (!('value' in obj) && !('writable' in obj)) { - return false; - } - - for (var key in obj) { - if (key === 'value') continue; - - if (!data.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === data[key]) { - continue; - } - - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -} - -/** - * Expose `isDataDescriptor` - */ - -module.exports = isDataDescriptor; - - -/***/ }), -/* 737 */ -/***/ (function(module, exports, __webpack_require__) { - -var isBuffer = __webpack_require__(735); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - var type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - - -/***/ }), -/* 738 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isObject = __webpack_require__(739); - -module.exports = function extend(o/*, objects*/) { - if (!isObject(o)) { o = {}; } - - var len = arguments.length; - for (var i = 1; i < len; i++) { - var obj = arguments[i]; - - if (isObject(obj)) { - assign(o, obj); - } - } - return o; -}; - -function assign(a, b) { - for (var key in b) { - if (hasOwn(b, key)) { - a[key] = b[key]; - } - } -} - -/** - * Returns true if the given `key` is an own property of `obj`. - */ - -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - - -/***/ }), -/* 739 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-extendable - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -module.exports = function isExtendable(val) { - return typeof val !== 'undefined' && val !== null - && (typeof val === 'object' || typeof val === 'function'); -}; - - -/***/ }), -/* 740 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var extend = __webpack_require__(738); - -/** - * The main export is a function that takes a `pattern` string and an `options` object. - * - * ```js - & var not = require('regex-not'); - & console.log(not('foo')); - & //=> /^(?:(?!^(?:foo)$).)*$/ - * ``` - * - * @param {String} `pattern` - * @param {Object} `options` - * @return {RegExp} Converts the given `pattern` to a regex using the specified `options`. - * @api public - */ - -function toRegex(pattern, options) { - return new RegExp(toRegex.create(pattern, options)); -} - -/** - * Create a regex-compatible string from the given `pattern` and `options`. - * - * ```js - & var not = require('regex-not'); - & console.log(not.create('foo')); - & //=> '^(?:(?!^(?:foo)$).)*$' - * ``` - * @param {String} `pattern` - * @param {Object} `options` - * @return {String} - * @api public - */ - -toRegex.create = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - var opts = extend({}, options); - if (opts && opts.contains === true) { - opts.strictNegate = false; - } - - var open = opts.strictOpen !== false ? '^' : ''; - var close = opts.strictClose !== false ? '$' : ''; - var endChar = opts.endChar ? opts.endChar : '+'; - var str = pattern; - - if (opts && opts.strictNegate === false) { - str = '(?:(?!(?:' + pattern + ')).)' + endChar; - } else { - str = '(?:(?!^(?:' + pattern + ')$).)' + endChar; - } - - return open + str + close; -}; - -/** - * Expose `toRegex` - */ - -module.exports = toRegex; - - -/***/ }), -/* 741 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * array-unique - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -module.exports = function unique(arr) { - if (!Array.isArray(arr)) { - throw new TypeError('array-unique expects an array.'); - } - - var len = arr.length; - var i = -1; - - while (i++ < len) { - var j = i + 1; - - for (; j < arr.length; ++j) { - if (arr[i] === arr[j]) { - arr.splice(j--, 1); - } - } - } - return arr; -}; - -module.exports.immutable = function uniqueImmutable(arr) { - if (!Array.isArray(arr)) { - throw new TypeError('array-unique expects an array.'); - } - - var arrLen = arr.length; - var newArr = new Array(arrLen); - - for (var i = 0; i < arrLen; i++) { - newArr[i] = arr[i]; - } - - return module.exports(newArr); -}; - - -/***/ }), -/* 742 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var utils = __webpack_require__(743); - -module.exports = function(braces, options) { - braces.compiler - - /** - * bos - */ - - .set('bos', function() { - if (this.output) return; - this.ast.queue = isEscaped(this.ast) ? [this.ast.val] : []; - this.ast.count = 1; - }) - - /** - * Square brackets - */ - - .set('bracket', function(node) { - var close = node.close; - var open = !node.escaped ? '[' : '\\['; - var negated = node.negated; - var inner = node.inner; - - inner = inner.replace(/\\(?=[\\\w]|$)/g, '\\\\'); - if (inner === ']-') { - inner = '\\]\\-'; - } - - if (negated && inner.indexOf('.') === -1) { - inner += '.'; - } - if (negated && inner.indexOf('/') === -1) { - inner += '/'; - } - - var val = open + negated + inner + close; - var queue = node.parent.queue; - var last = utils.arrayify(queue.pop()); - - queue.push(utils.join(last, val)); - queue.push.apply(queue, []); - }) - - /** - * Brace - */ - - .set('brace', function(node) { - node.queue = isEscaped(node) ? [node.val] : []; - node.count = 1; - return this.mapVisit(node.nodes); - }) - - /** - * Open - */ - - .set('brace.open', function(node) { - node.parent.open = node.val; - }) - - /** - * Inner - */ - - .set('text', function(node) { - var queue = node.parent.queue; - var escaped = node.escaped; - var segs = [node.val]; - - if (node.optimize === false) { - options = utils.extend({}, options, {optimize: false}); - } - - if (node.multiplier > 1) { - node.parent.count *= node.multiplier; - } - - if (options.quantifiers === true && utils.isQuantifier(node.val)) { - escaped = true; - - } else if (node.val.length > 1) { - if (isType(node.parent, 'brace') && !isEscaped(node)) { - var expanded = utils.expand(node.val, options); - segs = expanded.segs; - - if (expanded.isOptimized) { - node.parent.isOptimized = true; - } - - // if nothing was expanded, we probably have a literal brace - if (!segs.length) { - var val = (expanded.val || node.val); - if (options.unescape !== false) { - // unescape unexpanded brace sequence/set separators - val = val.replace(/\\([,.])/g, '$1'); - // strip quotes - val = val.replace(/["'`]/g, ''); - } - - segs = [val]; - escaped = true; - } - } - - } else if (node.val === ',') { - if (options.expand) { - node.parent.queue.push(['']); - segs = ['']; - } else { - segs = ['|']; - } - } else { - escaped = true; - } - - if (escaped && isType(node.parent, 'brace')) { - if (node.parent.nodes.length <= 4 && node.parent.count === 1) { - node.parent.escaped = true; - } else if (node.parent.length <= 3) { - node.parent.escaped = true; - } - } - - if (!hasQueue(node.parent)) { - node.parent.queue = segs; - return; - } - - var last = utils.arrayify(queue.pop()); - if (node.parent.count > 1 && options.expand) { - last = multiply(last, node.parent.count); - node.parent.count = 1; - } - - queue.push(utils.join(utils.flatten(last), segs.shift())); - queue.push.apply(queue, segs); - }) - - /** - * Close - */ - - .set('brace.close', function(node) { - var queue = node.parent.queue; - var prev = node.parent.parent; - var last = prev.queue.pop(); - var open = node.parent.open; - var close = node.val; - - if (open && close && isOptimized(node, options)) { - open = '('; - close = ')'; - } - - // if a close brace exists, and the previous segment is one character - // don't wrap the result in braces or parens - var ele = utils.last(queue); - if (node.parent.count > 1 && options.expand) { - ele = multiply(queue.pop(), node.parent.count); - node.parent.count = 1; - queue.push(ele); - } - - if (close && typeof ele === 'string' && ele.length === 1) { - open = ''; - close = ''; - } - - if ((isLiteralBrace(node, options) || noInner(node)) && !node.parent.hasEmpty) { - queue.push(utils.join(open, queue.pop() || '')); - queue = utils.flatten(utils.join(queue, close)); - } - - if (typeof last === 'undefined') { - prev.queue = [queue]; - } else { - prev.queue.push(utils.flatten(utils.join(last, queue))); - } - }) - - /** - * eos - */ - - .set('eos', function(node) { - if (this.input) return; - - if (options.optimize !== false) { - this.output = utils.last(utils.flatten(this.ast.queue)); - } else if (Array.isArray(utils.last(this.ast.queue))) { - this.output = utils.flatten(this.ast.queue.pop()); - } else { - this.output = utils.flatten(this.ast.queue); - } - - if (node.parent.count > 1 && options.expand) { - this.output = multiply(this.output, node.parent.count); - } - - this.output = utils.arrayify(this.output); - this.ast.queue = []; - }); - -}; - -/** - * Multiply the segments in the current brace level - */ - -function multiply(queue, n, options) { - return utils.flatten(utils.repeat(utils.arrayify(queue), n)); -} - -/** - * Return true if `node` is escaped - */ - -function isEscaped(node) { - return node.escaped === true; -} - -/** - * Returns true if regex parens should be used for sets. If the parent `type` - * is not `brace`, then we're on a root node, which means we should never - * expand segments and open/close braces should be `{}` (since this indicates - * a brace is missing from the set) - */ - -function isOptimized(node, options) { - if (node.parent.isOptimized) return true; - return isType(node.parent, 'brace') - && !isEscaped(node.parent) - && options.expand !== true; -} - -/** - * Returns true if the value in `node` should be wrapped in a literal brace. - * @return {Boolean} - */ - -function isLiteralBrace(node, options) { - return isEscaped(node.parent) || options.optimize !== false; -} - -/** - * Returns true if the given `node` does not have an inner value. - * @return {Boolean} - */ - -function noInner(node, type) { - if (node.parent.queue.length === 1) { - return true; - } - var nodes = node.parent.nodes; - return nodes.length === 3 - && isType(nodes[0], 'brace.open') - && !isType(nodes[1], 'text') - && isType(nodes[2], 'brace.close'); -} - -/** - * Returns true if the given `node` is the given `type` - * @return {Boolean} - */ - -function isType(node, type) { - return typeof node !== 'undefined' && node.type === type; -} - -/** - * Returns true if the given `node` has a non-empty queue. - * @return {Boolean} - */ - -function hasQueue(node) { - return Array.isArray(node.queue) && node.queue.length; -} - - -/***/ }), -/* 743 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var splitString = __webpack_require__(744); -var utils = module.exports; - -/** - * Module dependencies - */ - -utils.extend = __webpack_require__(738); -utils.flatten = __webpack_require__(750); -utils.isObject = __webpack_require__(748); -utils.fillRange = __webpack_require__(751); -utils.repeat = __webpack_require__(756); -utils.unique = __webpack_require__(741); - -utils.define = function(obj, key, val) { - Object.defineProperty(obj, key, { - writable: true, - configurable: true, - enumerable: false, - value: val - }); -}; - -/** - * Returns true if the given string contains only empty brace sets. - */ - -utils.isEmptySets = function(str) { - return /^(?:\{,\})+$/.test(str); -}; - -/** - * Returns true if the given string contains only empty brace sets. - */ - -utils.isQuotedString = function(str) { - var open = str.charAt(0); - if (open === '\'' || open === '"' || open === '`') { - return str.slice(-1) === open; - } - return false; -}; - -/** - * Create the key to use for memoization. The unique key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. - */ - -utils.createKey = function(pattern, options) { - var id = pattern; - if (typeof options === 'undefined') { - return id; - } - var keys = Object.keys(options); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - id += ';' + key + '=' + String(options[key]); - } - return id; -}; - -/** - * Normalize options - */ - -utils.createOptions = function(options) { - var opts = utils.extend.apply(null, arguments); - if (typeof opts.expand === 'boolean') { - opts.optimize = !opts.expand; - } - if (typeof opts.optimize === 'boolean') { - opts.expand = !opts.optimize; - } - if (opts.optimize === true) { - opts.makeRe = true; - } - return opts; -}; - -/** - * Join patterns in `a` to patterns in `b` - */ - -utils.join = function(a, b, options) { - options = options || {}; - a = utils.arrayify(a); - b = utils.arrayify(b); - - if (!a.length) return b; - if (!b.length) return a; - - var len = a.length; - var idx = -1; - var arr = []; - - while (++idx < len) { - var val = a[idx]; - if (Array.isArray(val)) { - for (var i = 0; i < val.length; i++) { - val[i] = utils.join(val[i], b, options); - } - arr.push(val); - continue; - } - - for (var j = 0; j < b.length; j++) { - var bval = b[j]; - - if (Array.isArray(bval)) { - arr.push(utils.join(val, bval, options)); - } else { - arr.push(val + bval); - } - } - } - return arr; -}; - -/** - * Split the given string on `,` if not escaped. - */ - -utils.split = function(str, options) { - var opts = utils.extend({sep: ','}, options); - if (typeof opts.keepQuotes !== 'boolean') { - opts.keepQuotes = true; - } - if (opts.unescape === false) { - opts.keepEscaping = true; - } - return splitString(str, opts, utils.escapeBrackets(opts)); -}; - -/** - * Expand ranges or sets in the given `pattern`. - * - * @param {String} `str` - * @param {Object} `options` - * @return {Object} - */ - -utils.expand = function(str, options) { - var opts = utils.extend({rangeLimit: 10000}, options); - var segs = utils.split(str, opts); - var tok = { segs: segs }; - - if (utils.isQuotedString(str)) { - return tok; - } - - if (opts.rangeLimit === true) { - opts.rangeLimit = 10000; - } - - if (segs.length > 1) { - if (opts.optimize === false) { - tok.val = segs[0]; - return tok; - } - - tok.segs = utils.stringifyArray(tok.segs); - } else if (segs.length === 1) { - var arr = str.split('..'); - - if (arr.length === 1) { - tok.val = tok.segs[tok.segs.length - 1] || tok.val || str; - tok.segs = []; - return tok; - } - - if (arr.length === 2 && arr[0] === arr[1]) { - tok.escaped = true; - tok.val = arr[0]; - tok.segs = []; - return tok; - } - - if (arr.length > 1) { - if (opts.optimize !== false) { - opts.optimize = true; - delete opts.expand; - } - - if (opts.optimize !== true) { - var min = Math.min(arr[0], arr[1]); - var max = Math.max(arr[0], arr[1]); - var step = arr[2] || 1; - - if (opts.rangeLimit !== false && ((max - min) / step >= opts.rangeLimit)) { - throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); - } - } - - arr.push(opts); - tok.segs = utils.fillRange.apply(null, arr); - - if (!tok.segs.length) { - tok.escaped = true; - tok.val = str; - return tok; - } - - if (opts.optimize === true) { - tok.segs = utils.stringifyArray(tok.segs); - } - - if (tok.segs === '') { - tok.val = str; - } else { - tok.val = tok.segs[0]; - } - return tok; - } - } else { - tok.val = str; - } - return tok; -}; - -/** - * Ensure commas inside brackets and parens are not split. - * @param {Object} `tok` Token from the `split-string` module - * @return {undefined} - */ - -utils.escapeBrackets = function(options) { - return function(tok) { - if (tok.escaped && tok.val === 'b') { - tok.val = '\\b'; - return; - } - - if (tok.val !== '(' && tok.val !== '[') return; - var opts = utils.extend({}, options); - var brackets = []; - var parens = []; - var stack = []; - var val = tok.val; - var str = tok.str; - var i = tok.idx - 1; - - while (++i < str.length) { - var ch = str[i]; - - if (ch === '\\') { - val += (opts.keepEscaping === false ? '' : ch) + str[++i]; - continue; - } - - if (ch === '(') { - parens.push(ch); - stack.push(ch); - } - - if (ch === '[') { - brackets.push(ch); - stack.push(ch); - } - - if (ch === ')') { - parens.pop(); - stack.pop(); - if (!stack.length) { - val += ch; - break; - } - } - - if (ch === ']') { - brackets.pop(); - stack.pop(); - if (!stack.length) { - val += ch; - break; - } - } - val += ch; - } - - tok.split = false; - tok.val = val.slice(1); - tok.idx = i; - }; -}; - -/** - * Returns true if the given string looks like a regex quantifier - * @return {Boolean} - */ - -utils.isQuantifier = function(str) { - return /^(?:[0-9]?,[0-9]|[0-9],)$/.test(str); -}; - -/** - * Cast `val` to an array. - * @param {*} `val` - */ - -utils.stringifyArray = function(arr) { - return [utils.arrayify(arr).join('|')]; -}; - -/** - * Cast `val` to an array. - * @param {*} `val` - */ - -utils.arrayify = function(arr) { - if (typeof arr === 'undefined') { - return []; - } - if (typeof arr === 'string') { - return [arr]; - } - return arr; -}; - -/** - * Returns true if the given `str` is a non-empty string - * @return {Boolean} - */ - -utils.isString = function(str) { - return str != null && typeof str === 'string'; -}; - -/** - * Get the last element from `array` - * @param {Array} `array` - * @return {*} - */ - -utils.last = function(arr, n) { - return arr[arr.length - (n || 1)]; -}; - -utils.escapeRegex = function(str) { - return str.replace(/\\?([!^*?()[\]{}+?/])/g, '\\$1'); -}; - - -/***/ }), -/* 744 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * split-string - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var extend = __webpack_require__(745); - -module.exports = function(str, options, fn) { - if (typeof str !== 'string') { - throw new TypeError('expected a string'); - } - - if (typeof options === 'function') { - fn = options; - options = null; - } - - // allow separator to be defined as a string - if (typeof options === 'string') { - options = { sep: options }; - } - - var opts = extend({sep: '.'}, options); - var quotes = opts.quotes || ['"', "'", '`']; - var brackets; - - if (opts.brackets === true) { - brackets = { - '<': '>', - '(': ')', - '[': ']', - '{': '}' - }; - } else if (opts.brackets) { - brackets = opts.brackets; - } - - var tokens = []; - var stack = []; - var arr = ['']; - var sep = opts.sep; - var len = str.length; - var idx = -1; - var closeIdx; - - function expected() { - if (brackets && stack.length) { - return brackets[stack[stack.length - 1]]; - } - } - - while (++idx < len) { - var ch = str[idx]; - var next = str[idx + 1]; - var tok = { val: ch, idx: idx, arr: arr, str: str }; - tokens.push(tok); - - if (ch === '\\') { - tok.val = keepEscaping(opts, str, idx) === true ? (ch + next) : next; - tok.escaped = true; - if (typeof fn === 'function') { - fn(tok); - } - arr[arr.length - 1] += tok.val; - idx++; - continue; - } - - if (brackets && brackets[ch]) { - stack.push(ch); - var e = expected(); - var i = idx + 1; - - if (str.indexOf(e, i + 1) !== -1) { - while (stack.length && i < len) { - var s = str[++i]; - if (s === '\\') { - s++; - continue; - } - - if (quotes.indexOf(s) !== -1) { - i = getClosingQuote(str, s, i + 1); - continue; - } - - e = expected(); - if (stack.length && str.indexOf(e, i + 1) === -1) { - break; - } - - if (brackets[s]) { - stack.push(s); - continue; - } - - if (e === s) { - stack.pop(); - } - } - } - - closeIdx = i; - if (closeIdx === -1) { - arr[arr.length - 1] += ch; - continue; - } - - ch = str.slice(idx, closeIdx + 1); - tok.val = ch; - tok.idx = idx = closeIdx; - } - - if (quotes.indexOf(ch) !== -1) { - closeIdx = getClosingQuote(str, ch, idx + 1); - if (closeIdx === -1) { - arr[arr.length - 1] += ch; - continue; - } - - if (keepQuotes(ch, opts) === true) { - ch = str.slice(idx, closeIdx + 1); - } else { - ch = str.slice(idx + 1, closeIdx); - } - - tok.val = ch; - tok.idx = idx = closeIdx; - } - - if (typeof fn === 'function') { - fn(tok, tokens); - ch = tok.val; - idx = tok.idx; - } - - if (tok.val === sep && tok.split !== false) { - arr.push(''); - continue; - } - - arr[arr.length - 1] += tok.val; - } - - return arr; -}; - -function getClosingQuote(str, ch, i, brackets) { - var idx = str.indexOf(ch, i); - if (str.charAt(idx - 1) === '\\') { - return getClosingQuote(str, ch, idx + 1); - } - return idx; -} - -function keepQuotes(ch, opts) { - if (opts.keepDoubleQuotes === true && ch === '"') return true; - if (opts.keepSingleQuotes === true && ch === "'") return true; - return opts.keepQuotes; -} - -function keepEscaping(opts, str, idx) { - if (typeof opts.keepEscaping === 'function') { - return opts.keepEscaping(str, idx); - } - return opts.keepEscaping === true || str[idx + 1] === '\\'; -} - - -/***/ }), -/* 745 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isExtendable = __webpack_require__(746); -var assignSymbols = __webpack_require__(749); - -module.exports = Object.assign || function(obj/*, objects*/) { - if (obj === null || typeof obj === 'undefined') { - throw new TypeError('Cannot convert undefined or null to object'); - } - if (!isObject(obj)) { - obj = {}; - } - for (var i = 1; i < arguments.length; i++) { - var val = arguments[i]; - if (isString(val)) { - val = toObject(val); - } - if (isObject(val)) { - assign(obj, val); - assignSymbols(obj, val); - } - } - return obj; -}; - -function assign(a, b) { - for (var key in b) { - if (hasOwn(b, key)) { - a[key] = b[key]; - } - } -} - -function isString(val) { - return (val && typeof val === 'string'); -} - -function toObject(str) { - var obj = {}; - for (var i in str) { - obj[i] = str[i]; - } - return obj; -} - -function isObject(val) { - return (val && typeof val === 'object') || isExtendable(val); -} - -/** - * Returns true if the given `key` is an own property of `obj`. - */ - -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - -function isEnum(obj, key) { - return Object.prototype.propertyIsEnumerable.call(obj, key); -} - - -/***/ }), -/* 746 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-extendable - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isPlainObject = __webpack_require__(747); - -module.exports = function isExtendable(val) { - return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); -}; - - -/***/ }), -/* 747 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-plain-object - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isObject = __webpack_require__(748); - -function isObjectObject(o) { - return isObject(o) === true - && Object.prototype.toString.call(o) === '[object Object]'; -} - -module.exports = function isPlainObject(o) { - var ctor,prot; - - if (isObjectObject(o) === false) return false; - - // If has modified constructor - ctor = o.constructor; - if (typeof ctor !== 'function') return false; - - // If has modified prototype - prot = ctor.prototype; - if (isObjectObject(prot) === false) return false; - - // If constructor does not have an Object-specific method - if (prot.hasOwnProperty('isPrototypeOf') === false) { - return false; - } - - // Most likely a plain Object - return true; -}; - - -/***/ }), -/* 748 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * isobject - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -module.exports = function isObject(val) { - return val != null && typeof val === 'object' && Array.isArray(val) === false; -}; - - -/***/ }), -/* 749 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * assign-symbols - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -module.exports = function(receiver, objects) { - if (receiver === null || typeof receiver === 'undefined') { - throw new TypeError('expected first argument to be an object.'); - } - - if (typeof objects === 'undefined' || typeof Symbol === 'undefined') { - return receiver; - } - - if (typeof Object.getOwnPropertySymbols !== 'function') { - return receiver; - } - - var isEnumerable = Object.prototype.propertyIsEnumerable; - var target = Object(receiver); - var len = arguments.length, i = 0; - - while (++i < len) { - var provider = Object(arguments[i]); - var names = Object.getOwnPropertySymbols(provider); - - for (var j = 0; j < names.length; j++) { - var key = names[j]; - - if (isEnumerable.call(provider, key)) { - target[key] = provider[key]; - } - } - } - return target; -}; - - -/***/ }), -/* 750 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * arr-flatten - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -module.exports = function (arr) { - return flat(arr, []); -}; - -function flat(arr, res) { - var i = 0, cur; - var len = arr.length; - for (; i < len; i++) { - cur = arr[i]; - Array.isArray(cur) ? flat(cur, res) : res.push(cur); - } - return res; -} - - -/***/ }), -/* 751 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * fill-range - * - * Copyright (c) 2014-2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var util = __webpack_require__(29); -var isNumber = __webpack_require__(752); -var extend = __webpack_require__(738); -var repeat = __webpack_require__(754); -var toRegex = __webpack_require__(755); - -/** - * Return a range of numbers or letters. - * - * @param {String} `start` Start of the range - * @param {String} `stop` End of the range - * @param {String} `step` Increment or decrement to use. - * @param {Function} `fn` Custom function to modify each element in the range. - * @return {Array} - */ - -function fillRange(start, stop, step, options) { - if (typeof start === 'undefined') { - return []; - } - - if (typeof stop === 'undefined' || start === stop) { - // special case, for handling negative zero - var isString = typeof start === 'string'; - if (isNumber(start) && !toNumber(start)) { - return [isString ? '0' : 0]; - } - return [start]; - } - - if (typeof step !== 'number' && typeof step !== 'string') { - options = step; - step = undefined; - } - - if (typeof options === 'function') { - options = { transform: options }; - } - - var opts = extend({step: step}, options); - if (opts.step && !isValidNumber(opts.step)) { - if (opts.strictRanges === true) { - throw new TypeError('expected options.step to be a number'); - } - return []; - } - - opts.isNumber = isValidNumber(start) && isValidNumber(stop); - if (!opts.isNumber && !isValid(start, stop)) { - if (opts.strictRanges === true) { - throw new RangeError('invalid range arguments: ' + util.inspect([start, stop])); - } - return []; - } - - opts.isPadded = isPadded(start) || isPadded(stop); - opts.toString = opts.stringify - || typeof opts.step === 'string' - || typeof start === 'string' - || typeof stop === 'string' - || !opts.isNumber; - - if (opts.isPadded) { - opts.maxLength = Math.max(String(start).length, String(stop).length); - } - - // support legacy minimatch/fill-range options - if (typeof opts.optimize === 'boolean') opts.toRegex = opts.optimize; - if (typeof opts.makeRe === 'boolean') opts.toRegex = opts.makeRe; - return expand(start, stop, opts); -} - -function expand(start, stop, options) { - var a = options.isNumber ? toNumber(start) : start.charCodeAt(0); - var b = options.isNumber ? toNumber(stop) : stop.charCodeAt(0); - - var step = Math.abs(toNumber(options.step)) || 1; - if (options.toRegex && step === 1) { - return toRange(a, b, start, stop, options); - } - - var zero = {greater: [], lesser: []}; - var asc = a < b; - var arr = new Array(Math.round((asc ? b - a : a - b) / step)); - var idx = 0; - - while (asc ? a <= b : a >= b) { - var val = options.isNumber ? a : String.fromCharCode(a); - if (options.toRegex && (val >= 0 || !options.isNumber)) { - zero.greater.push(val); - } else { - zero.lesser.push(Math.abs(val)); - } - - if (options.isPadded) { - val = zeros(val, options); - } - - if (options.toString) { - val = String(val); - } - - if (typeof options.transform === 'function') { - arr[idx++] = options.transform(val, a, b, step, idx, arr, options); - } else { - arr[idx++] = val; - } - - if (asc) { - a += step; - } else { - a -= step; - } - } - - if (options.toRegex === true) { - return toSequence(arr, zero, options); - } - return arr; -} - -function toRange(a, b, start, stop, options) { - if (options.isPadded) { - return toRegex(start, stop, options); - } - - if (options.isNumber) { - return toRegex(Math.min(a, b), Math.max(a, b), options); - } - - var start = String.fromCharCode(Math.min(a, b)); - var stop = String.fromCharCode(Math.max(a, b)); - return '[' + start + '-' + stop + ']'; -} - -function toSequence(arr, zeros, options) { - var greater = '', lesser = ''; - if (zeros.greater.length) { - greater = zeros.greater.join('|'); - } - if (zeros.lesser.length) { - lesser = '-(' + zeros.lesser.join('|') + ')'; - } - var res = greater && lesser - ? greater + '|' + lesser - : greater || lesser; - - if (options.capture) { - return '(' + res + ')'; - } - return res; -} - -function zeros(val, options) { - if (options.isPadded) { - var str = String(val); - var len = str.length; - var dash = ''; - if (str.charAt(0) === '-') { - dash = '-'; - str = str.slice(1); - } - var diff = options.maxLength - len; - var pad = repeat('0', diff); - val = (dash + pad + str); - } - if (options.stringify) { - return String(val); - } - return val; -} - -function toNumber(val) { - return Number(val) || 0; -} - -function isPadded(str) { - return /^-?0\d/.test(str); -} - -function isValid(min, max) { - return (isValidNumber(min) || isValidLetter(min)) - && (isValidNumber(max) || isValidLetter(max)); -} - -function isValidLetter(ch) { - return typeof ch === 'string' && ch.length === 1 && /^\w+$/.test(ch); -} - -function isValidNumber(n) { - return isNumber(n) && !/\./.test(n); -} - -/** - * Expose `fillRange` - * @type {Function} - */ - -module.exports = fillRange; - - -/***/ }), -/* 752 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-number - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var typeOf = __webpack_require__(753); - -module.exports = function isNumber(num) { - var type = typeOf(num); - - if (type === 'string') { - if (!num.trim()) return false; - } else if (type !== 'number') { - return false; - } - - return (num - num + 1) >= 0; -}; - - -/***/ }), -/* 753 */ -/***/ (function(module, exports, __webpack_require__) { - -var isBuffer = __webpack_require__(735); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - var type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - - -/***/ }), -/* 754 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * repeat-string - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -/** - * Results cache - */ - -var res = ''; -var cache; - -/** - * Expose `repeat` - */ - -module.exports = repeat; - -/** - * Repeat the given `string` the specified `number` - * of times. - * - * **Example:** - * - * ```js - * var repeat = require('repeat-string'); - * repeat('A', 5); - * //=> AAAAA - * ``` - * - * @param {String} `string` The string to repeat - * @param {Number} `number` The number of times to repeat the string - * @return {String} Repeated string - * @api public - */ - -function repeat(str, num) { - if (typeof str !== 'string') { - throw new TypeError('expected a string'); - } - - // cover common, quick use cases - if (num === 1) return str; - if (num === 2) return str + str; - - var max = str.length * num; - if (cache !== str || typeof cache === 'undefined') { - cache = str; - res = ''; - } else if (res.length >= max) { - return res.substr(0, max); - } - - while (max > res.length && num > 1) { - if (num & 1) { - res += str; - } - - num >>= 1; - str += str; - } - - res += str; - res = res.substr(0, max); - return res; -} - - -/***/ }), -/* 755 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * to-regex-range - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var repeat = __webpack_require__(754); -var isNumber = __webpack_require__(752); -var cache = {}; - -function toRegexRange(min, max, options) { - if (isNumber(min) === false) { - throw new RangeError('toRegexRange: first argument is invalid.'); - } - - if (typeof max === 'undefined' || min === max) { - return String(min); - } - - if (isNumber(max) === false) { - throw new RangeError('toRegexRange: second argument is invalid.'); - } - - options = options || {}; - var relax = String(options.relaxZeros); - var shorthand = String(options.shorthand); - var capture = String(options.capture); - var key = min + ':' + max + '=' + relax + shorthand + capture; - if (cache.hasOwnProperty(key)) { - return cache[key].result; - } - - var a = Math.min(min, max); - var b = Math.max(min, max); - - if (Math.abs(a - b) === 1) { - var result = min + '|' + max; - if (options.capture) { - return '(' + result + ')'; - } - return result; - } - - var isPadded = padding(min) || padding(max); - var positives = []; - var negatives = []; - - var tok = {min: min, max: max, a: a, b: b}; - if (isPadded) { - tok.isPadded = isPadded; - tok.maxLen = String(tok.max).length; - } - - if (a < 0) { - var newMin = b < 0 ? Math.abs(b) : 1; - var newMax = Math.abs(a); - negatives = splitToPatterns(newMin, newMax, tok, options); - a = tok.a = 0; - } - - if (b >= 0) { - positives = splitToPatterns(a, b, tok, options); - } - - tok.negatives = negatives; - tok.positives = positives; - tok.result = siftPatterns(negatives, positives, options); - - if (options.capture && (positives.length + negatives.length) > 1) { - tok.result = '(' + tok.result + ')'; - } - - cache[key] = tok; - return tok.result; -} - -function siftPatterns(neg, pos, options) { - var onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; - var onlyPositive = filterPatterns(pos, neg, '', false, options) || []; - var intersected = filterPatterns(neg, pos, '-?', true, options) || []; - var subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); - return subpatterns.join('|'); -} - -function splitToRanges(min, max) { - min = Number(min); - max = Number(max); - - var nines = 1; - var stops = [max]; - var stop = +countNines(min, nines); - - while (min <= stop && stop <= max) { - stops = push(stops, stop); - nines += 1; - stop = +countNines(min, nines); - } - - var zeros = 1; - stop = countZeros(max + 1, zeros) - 1; - - while (min < stop && stop <= max) { - stops = push(stops, stop); - zeros += 1; - stop = countZeros(max + 1, zeros) - 1; - } - - 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: String(start), digits: []}; - } - - var zipped = zip(String(start), String(stop)); - var len = zipped.length, i = -1; - - var pattern = ''; - var digits = 0; - - while (++i < len) { - var numbers = zipped[i]; - var startDigit = numbers[0]; - var stopDigit = numbers[1]; - - if (startDigit === stopDigit) { - pattern += startDigit; - - } else if (startDigit !== '0' || stopDigit !== '9') { - pattern += toCharacterClass(startDigit, stopDigit); - - } else { - digits += 1; - } - } - - if (digits) { - pattern += options.shorthand ? '\\d' : '[0-9]'; - } - - return { pattern: pattern, digits: [digits] }; -} - -function splitToPatterns(min, max, tok, options) { - var ranges = splitToRanges(min, max); - var len = ranges.length; - var idx = -1; - - var tokens = []; - var start = min; - var prev; - - while (++idx < len) { - var range = ranges[idx]; - var obj = rangeToPattern(start, range, options); - var zeros = ''; - - if (!tok.isPadded && prev && prev.pattern === obj.pattern) { - if (prev.digits.length > 1) { - prev.digits.pop(); - } - prev.digits.push(obj.digits[0]); - prev.string = prev.pattern + toQuantifier(prev.digits); - start = range + 1; - continue; - } - - if (tok.isPadded) { - zeros = padZeros(range, tok); - } - - obj.string = zeros + obj.pattern + toQuantifier(obj.digits); - tokens.push(obj); - start = range + 1; - prev = obj; - } - - return tokens; -} - -function filterPatterns(arr, comparison, prefix, intersection, options) { - var res = []; - - for (var i = 0; i < arr.length; i++) { - var tok = arr[i]; - var ele = tok.string; - - if (options.relaxZeros !== false) { - if (prefix === '-' && ele.charAt(0) === '0') { - if (ele.charAt(1) === '{') { - ele = '0*' + ele.replace(/^0\{\d+\}/, ''); - } else { - ele = '0*' + ele.slice(1); - } - } - } - - if (!intersection && !contains(comparison, 'string', ele)) { - res.push(prefix + ele); - } - - if (intersection && contains(comparison, 'string', ele)) { - res.push(prefix + ele); - } - } - return res; -} - -/** - * Zip strings (`for in` can be used on string characters) - */ - -function zip(a, b) { - var arr = []; - for (var ch in a) arr.push([a[ch], b[ch]]); - return arr; -} - -function compare(a, b) { - return a > b ? 1 : b > a ? -1 : 0; -} - -function push(arr, ele) { - if (arr.indexOf(ele) === -1) arr.push(ele); - return arr; -} - -function contains(arr, key, val) { - for (var i = 0; i < arr.length; i++) { - if (arr[i][key] === val) { - return true; - } - } - return false; -} - -function countNines(min, len) { - return String(min).slice(0, -len) + repeat('9', len); -} - -function countZeros(integer, zeros) { - return integer - (integer % Math.pow(10, zeros)); -} - -function toQuantifier(digits) { - var start = digits[0]; - var stop = digits[1] ? (',' + digits[1]) : ''; - if (!stop && (!start || start === 1)) { - return ''; - } - return '{' + start + stop + '}'; -} - -function toCharacterClass(a, b) { - return '[' + a + ((b - a === 1) ? '' : '-') + b + ']'; -} - -function padding(str) { - return /^-?(0+)\d/.exec(str); -} - -function padZeros(val, tok) { - if (tok.isPadded) { - var diff = Math.abs(tok.maxLen - String(val).length); - switch (diff) { - case 0: - return ''; - case 1: - return '0'; - default: { - return '0{' + diff + '}'; - } - } - } - return val; -} - -/** - * Expose `toRegexRange` - */ - -module.exports = toRegexRange; - - -/***/ }), -/* 756 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * repeat-element - * - * Copyright (c) 2015 Jon Schlinkert. - * Licensed under the MIT license. - */ - - - -module.exports = function repeat(ele, num) { - var arr = new Array(num); - - for (var i = 0; i < num; i++) { - arr[i] = ele; - } - - return arr; -}; - - -/***/ }), -/* 757 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var Node = __webpack_require__(758); -var utils = __webpack_require__(743); - -/** - * Braces parsers - */ - -module.exports = function(braces, options) { - braces.parser - .set('bos', function() { - if (!this.parsed) { - this.ast = this.nodes[0] = new Node(this.ast); - } - }) - - /** - * Character parsers - */ - - .set('escape', function() { - var pos = this.position(); - var m = this.match(/^(?:\\(.)|\$\{)/); - if (!m) return; - - var prev = this.prev(); - var last = utils.last(prev.nodes); - - var node = pos(new Node({ - type: 'text', - multiplier: 1, - val: m[0] - })); - - if (node.val === '\\\\') { - return node; - } - - if (node.val === '${') { - var str = this.input; - var idx = -1; - var ch; - - while ((ch = str[++idx])) { - this.consume(1); - node.val += ch; - if (ch === '\\') { - node.val += str[++idx]; - continue; - } - if (ch === '}') { - break; - } - } - } - - if (this.options.unescape !== false) { - node.val = node.val.replace(/\\([{}])/g, '$1'); - } - - if (last.val === '"' && this.input.charAt(0) === '"') { - last.val = node.val; - this.consume(1); - return; - } - - return concatNodes.call(this, pos, node, prev, options); - }) - - /** - * Brackets: "[...]" (basic, this is overridden by - * other parsers in more advanced implementations) - */ - - .set('bracket', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^(?:\[([!^]?)([^\]]{2,}|\]-)(\]|[^*+?]+)|\[)/); - if (!m) return; - - var prev = this.prev(); - var val = m[0]; - var negated = m[1] ? '^' : ''; - var inner = m[2] || ''; - var close = m[3] || ''; - - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } - - var esc = this.input.slice(0, 2); - if (inner === '' && esc === '\\]') { - inner += esc; - this.consume(2); - - var str = this.input; - var idx = -1; - var ch; - - while ((ch = str[++idx])) { - this.consume(1); - if (ch === ']') { - close = ch; - break; - } - inner += ch; - } - } - - return pos(new Node({ - type: 'bracket', - val: val, - escaped: close !== ']', - negated: negated, - inner: inner, - close: close - })); - }) - - /** - * Empty braces (we capture these early to - * speed up processing in the compiler) - */ - - .set('multiplier', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^\{((?:,|\{,+\})+)\}/); - if (!m) return; - - this.multiplier = true; - var prev = this.prev(); - var val = m[0]; - - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } - - var node = pos(new Node({ - type: 'text', - multiplier: 1, - match: m, - val: val - })); - - return concatNodes.call(this, pos, node, prev, options); - }) - - /** - * Open - */ - - .set('brace.open', function() { - var pos = this.position(); - var m = this.match(/^\{(?!(?:[^\\}]?|,+)\})/); - if (!m) return; - - var prev = this.prev(); - var last = utils.last(prev.nodes); - - // if the last parsed character was an extglob character - // we need to _not optimize_ the brace pattern because - // it might be mistaken for an extglob by a downstream parser - if (last && last.val && isExtglobChar(last.val.slice(-1))) { - last.optimize = false; - } - - var open = pos(new Node({ - type: 'brace.open', - val: m[0] - })); - - var node = pos(new Node({ - type: 'brace', - nodes: [] - })); - - node.push(open); - prev.push(node); - this.push('brace', node); - }) - - /** - * Close - */ - - .set('brace.close', function() { - var pos = this.position(); - var m = this.match(/^\}/); - if (!m || !m[0]) return; - - var brace = this.pop('brace'); - var node = pos(new Node({ - type: 'brace.close', - val: m[0] - })); - - if (!this.isType(brace, 'brace')) { - if (this.options.strict) { - throw new Error('missing opening "{"'); - } - node.type = 'text'; - node.multiplier = 0; - node.escaped = true; - return node; - } - - var prev = this.prev(); - var last = utils.last(prev.nodes); - if (last.text) { - var lastNode = utils.last(last.nodes); - if (lastNode.val === ')' && /[!@*?+]\(/.test(last.text)) { - var open = last.nodes[0]; - var text = last.nodes[1]; - if (open.type === 'brace.open' && text && text.type === 'text') { - text.optimize = false; - } - } - } - - if (brace.nodes.length > 2) { - var first = brace.nodes[1]; - if (first.type === 'text' && first.val === ',') { - brace.nodes.splice(1, 1); - brace.nodes.push(first); - } - } - - brace.push(node); - }) - - /** - * Capture boundary characters - */ - - .set('boundary', function() { - var pos = this.position(); - var m = this.match(/^[$^](?!\{)/); - if (!m) return; - return pos(new Node({ - type: 'text', - val: m[0] - })); - }) - - /** - * One or zero, non-comma characters wrapped in braces - */ - - .set('nobrace', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^\{[^,]?\}/); - if (!m) return; - - var prev = this.prev(); - var val = m[0]; - - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } - - return pos(new Node({ - type: 'text', - multiplier: 0, - val: val - })); - }) - - /** - * Text - */ - - .set('text', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^((?!\\)[^${}[\]])+/); - if (!m) return; - - var prev = this.prev(); - var val = m[0]; - - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } - - var node = pos(new Node({ - type: 'text', - multiplier: 1, - val: val - })); - - return concatNodes.call(this, pos, node, prev, options); - }); -}; - -/** - * Returns true if the character is an extglob character. - */ - -function isExtglobChar(ch) { - return ch === '!' || ch === '@' || ch === '*' || ch === '?' || ch === '+'; -} - -/** - * Combine text nodes, and calculate empty sets (`{,,}`) - * @param {Function} `pos` Function to calculate node position - * @param {Object} `node` AST node - * @return {Object} - */ - -function concatNodes(pos, node, parent, options) { - node.orig = node.val; - var prev = this.prev(); - var last = utils.last(prev.nodes); - var isEscaped = false; - - if (node.val.length > 1) { - var a = node.val.charAt(0); - var b = node.val.slice(-1); - - isEscaped = (a === '"' && b === '"') - || (a === "'" && b === "'") - || (a === '`' && b === '`'); - } - - if (isEscaped && options.unescape !== false) { - node.val = node.val.slice(1, node.val.length - 1); - node.escaped = true; - } - - if (node.match) { - var match = node.match[1]; - if (!match || match.indexOf('}') === -1) { - match = node.match[0]; - } - - // replace each set with a single "," - var val = match.replace(/\{/g, ',').replace(/\}/g, ''); - node.multiplier *= val.length; - node.val = ''; - } - - var simpleText = last.type === 'text' - && last.multiplier === 1 - && node.multiplier === 1 - && node.val; - - if (simpleText) { - last.val += node.val; - return; - } - - prev.push(node); -} - - -/***/ }), -/* 758 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isObject = __webpack_require__(748); -var define = __webpack_require__(759); -var utils = __webpack_require__(766); -var ownNames; - -/** - * Create a new AST `Node` with the given `val` and `type`. - * - * ```js - * var node = new Node('*', 'Star'); - * var node = new Node({type: 'star', val: '*'}); - * ``` - * @name Node - * @param {String|Object} `val` Pass a matched substring, or an object to merge onto the node. - * @param {String} `type` The node type to use when `val` is a string. - * @return {Object} node instance - * @api public - */ - -function Node(val, type, parent) { - if (typeof type !== 'string') { - parent = type; - type = null; - } - - define(this, 'parent', parent); - define(this, 'isNode', true); - define(this, 'expect', null); - - if (typeof type !== 'string' && isObject(val)) { - lazyKeys(); - var keys = Object.keys(val); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - if (ownNames.indexOf(key) === -1) { - this[key] = val[key]; - } - } - } else { - this.type = type; - this.val = val; - } -} - -/** - * Returns true if the given value is a node. - * - * ```js - * var Node = require('snapdragon-node'); - * var node = new Node({type: 'foo'}); - * console.log(Node.isNode(node)); //=> true - * console.log(Node.isNode({})); //=> false - * ``` - * @param {Object} `node` - * @returns {Boolean} - * @api public - */ - -Node.isNode = function(node) { - return utils.isNode(node); -}; - -/** - * Define a non-enumberable property on the node instance. - * Useful for adding properties that shouldn't be extended - * or visible during debugging. - * - * ```js - * var node = new Node(); - * node.define('foo', 'something non-enumerable'); - * ``` - * @param {String} `name` - * @param {any} `val` - * @return {Object} returns the node instance - * @api public - */ - -Node.prototype.define = function(name, val) { - define(this, name, val); - return this; -}; - -/** - * Returns true if `node.val` is an empty string, or `node.nodes` does - * not contain any non-empty text nodes. - * - * ```js - * var node = new Node({type: 'text'}); - * node.isEmpty(); //=> true - * node.val = 'foo'; - * node.isEmpty(); //=> false - * ``` - * @param {Function} `fn` (optional) Filter function that is called on `node` and/or child nodes. `isEmpty` will return false immediately when the filter function returns false on any nodes. - * @return {Boolean} - * @api public - */ - -Node.prototype.isEmpty = function(fn) { - return utils.isEmpty(this, fn); -}; - -/** - * Given node `foo` and node `bar`, push node `bar` onto `foo.nodes`, and - * set `foo` as `bar.parent`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * foo.push(bar); - * ``` - * @param {Object} `node` - * @return {Number} Returns the length of `node.nodes` - * @api public - */ - -Node.prototype.push = function(node) { - assert(Node.isNode(node), 'expected node to be an instance of Node'); - define(node, 'parent', this); - - this.nodes = this.nodes || []; - return this.nodes.push(node); -}; - -/** - * Given node `foo` and node `bar`, unshift node `bar` onto `foo.nodes`, and - * set `foo` as `bar.parent`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * foo.unshift(bar); - * ``` - * @param {Object} `node` - * @return {Number} Returns the length of `node.nodes` - * @api public - */ - -Node.prototype.unshift = function(node) { - assert(Node.isNode(node), 'expected node to be an instance of Node'); - define(node, 'parent', this); - - this.nodes = this.nodes || []; - return this.nodes.unshift(node); -}; - -/** - * Pop a node from `node.nodes`. - * - * ```js - * var node = new Node({type: 'foo'}); - * node.push(new Node({type: 'a'})); - * node.push(new Node({type: 'b'})); - * node.push(new Node({type: 'c'})); - * node.push(new Node({type: 'd'})); - * console.log(node.nodes.length); - * //=> 4 - * node.pop(); - * console.log(node.nodes.length); - * //=> 3 - * ``` - * @return {Number} Returns the popped `node` - * @api public - */ - -Node.prototype.pop = function() { - return this.nodes && this.nodes.pop(); -}; - -/** - * Shift a node from `node.nodes`. - * - * ```js - * var node = new Node({type: 'foo'}); - * node.push(new Node({type: 'a'})); - * node.push(new Node({type: 'b'})); - * node.push(new Node({type: 'c'})); - * node.push(new Node({type: 'd'})); - * console.log(node.nodes.length); - * //=> 4 - * node.shift(); - * console.log(node.nodes.length); - * //=> 3 - * ``` - * @return {Object} Returns the shifted `node` - * @api public - */ - -Node.prototype.shift = function() { - return this.nodes && this.nodes.shift(); -}; - -/** - * Remove `node` from `node.nodes`. - * - * ```js - * node.remove(childNode); - * ``` - * @param {Object} `node` - * @return {Object} Returns the removed node. - * @api public - */ - -Node.prototype.remove = function(node) { - assert(Node.isNode(node), 'expected node to be an instance of Node'); - this.nodes = this.nodes || []; - var idx = node.index; - if (idx !== -1) { - node.index = -1; - return this.nodes.splice(idx, 1); - } - return null; -}; - -/** - * Get the first child node from `node.nodes` that matches the given `type`. - * If `type` is a number, the child node at that index is returned. - * - * ```js - * var child = node.find(1); //<= index of the node to get - * var child = node.find('foo'); //<= node.type of a child node - * var child = node.find(/^(foo|bar)$/); //<= regex to match node.type - * var child = node.find(['foo', 'bar']); //<= array of node.type(s) - * ``` - * @param {String} `type` - * @return {Object} Returns a child node or undefined. - * @api public - */ - -Node.prototype.find = function(type) { - return utils.findNode(this.nodes, type); -}; - -/** - * Return true if the node is the given `type`. - * - * ```js - * var node = new Node({type: 'bar'}); - * cosole.log(node.isType('foo')); // false - * cosole.log(node.isType(/^(foo|bar)$/)); // true - * cosole.log(node.isType(['foo', 'bar'])); // true - * ``` - * @param {String} `type` - * @return {Boolean} - * @api public - */ - -Node.prototype.isType = function(type) { - return utils.isType(this, type); -}; - -/** - * Return true if the `node.nodes` has the given `type`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * foo.push(bar); - * - * cosole.log(foo.hasType('qux')); // false - * cosole.log(foo.hasType(/^(qux|bar)$/)); // true - * cosole.log(foo.hasType(['qux', 'bar'])); // true - * ``` - * @param {String} `type` - * @return {Boolean} - * @api public - */ - -Node.prototype.hasType = function(type) { - return utils.hasType(this, type); -}; - -/** - * Get the siblings array, or `null` if it doesn't exist. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * foo.push(bar); - * foo.push(baz); - * - * console.log(bar.siblings.length) // 2 - * console.log(baz.siblings.length) // 2 - * ``` - * @return {Array} - * @api public - */ - -Object.defineProperty(Node.prototype, 'siblings', { - set: function() { - throw new Error('node.siblings is a getter and cannot be defined'); - }, - get: function() { - return this.parent ? this.parent.nodes : null; - } -}); - -/** - * Get the node's current index from `node.parent.nodes`. - * This should always be correct, even when the parent adds nodes. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.unshift(qux); - * - * console.log(bar.index) // 1 - * console.log(baz.index) // 2 - * console.log(qux.index) // 0 - * ``` - * @return {Number} - * @api public - */ - -Object.defineProperty(Node.prototype, 'index', { - set: function(index) { - define(this, 'idx', index); - }, - get: function() { - if (!Array.isArray(this.siblings)) { - return -1; - } - var tok = this.idx !== -1 ? this.siblings[this.idx] : null; - if (tok !== this) { - this.idx = this.siblings.indexOf(this); - } - return this.idx; - } -}); - -/** - * Get the previous node from the siblings array or `null`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * foo.push(bar); - * foo.push(baz); - * - * console.log(baz.prev.type) // 'bar' - * ``` - * @return {Object} - * @api public - */ - -Object.defineProperty(Node.prototype, 'prev', { - set: function() { - throw new Error('node.prev is a getter and cannot be defined'); - }, - get: function() { - if (Array.isArray(this.siblings)) { - return this.siblings[this.index - 1] || this.parent.prev; - } - return null; - } -}); - -/** - * Get the siblings array, or `null` if it doesn't exist. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * foo.push(bar); - * foo.push(baz); - * - * console.log(bar.siblings.length) // 2 - * console.log(baz.siblings.length) // 2 - * ``` - * @return {Object} - * @api public - */ - -Object.defineProperty(Node.prototype, 'next', { - set: function() { - throw new Error('node.next is a getter and cannot be defined'); - }, - get: function() { - if (Array.isArray(this.siblings)) { - return this.siblings[this.index + 1] || this.parent.next; - } - return null; - } -}); - -/** - * Get the first node from `node.nodes`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.push(qux); - * - * console.log(foo.first.type) // 'bar' - * ``` - * @return {Object} The first node, or undefiend - * @api public - */ - -Object.defineProperty(Node.prototype, 'first', { - get: function() { - return this.nodes ? this.nodes[0] : null; - } -}); - -/** - * Get the last node from `node.nodes`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.push(qux); - * - * console.log(foo.last.type) // 'qux' - * ``` - * @return {Object} The last node, or undefiend - * @api public - */ - -Object.defineProperty(Node.prototype, 'last', { - get: function() { - return this.nodes ? utils.last(this.nodes) : null; - } -}); - -/** - * Get the last node from `node.nodes`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.push(qux); - * - * console.log(foo.last.type) // 'qux' - * ``` - * @return {Object} The last node, or undefiend - * @api public - */ - -Object.defineProperty(Node.prototype, 'scope', { - get: function() { - if (this.isScope !== true) { - return this.parent ? this.parent.scope : this; - } - return this; - } -}); - -/** - * Get own property names from Node prototype, but only the - * first time `Node` is instantiated - */ - -function lazyKeys() { - if (!ownNames) { - ownNames = Object.getOwnPropertyNames(Node.prototype); - } -} - -/** - * Simplified assertion. Throws an error is `val` is falsey. - */ - -function assert(val, message) { - if (!val) throw new Error(message); -} - -/** - * Expose `Node` - */ - -exports = module.exports = Node; - - -/***/ }), -/* 759 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isDescriptor = __webpack_require__(760); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } - - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } - - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; - - -/***/ }), -/* 760 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(761); -var isAccessor = __webpack_require__(762); -var isData = __webpack_require__(764); - -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; - } - if ('get' in obj) { - return isAccessor(obj, key); - } - return isData(obj, key); -}; - - -/***/ }), -/* 761 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } - - if (isGeneratorObj(val)) { - return 'generator'; - } - - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } - - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} - -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } - } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; -} - - -/***/ }), -/* 762 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-accessor-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(763); - -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; - -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (typeOf(obj) !== 'object') { - return false; - } - - if (has(obj, 'value') || has(obj, 'writable')) { - return false; - } - - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; - } - - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; - } - - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === accessor[key]) { - continue; - } - - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -} - -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} - -/** - * Expose `isAccessorDescriptor` - */ - -module.exports = isAccessorDescriptor; - - -/***/ }), -/* 763 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } - - if (isGeneratorObj(val)) { - return 'generator'; - } - - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } - - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} - -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } - } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; -} - - -/***/ }), -/* 764 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-data-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(765); - -module.exports = function isDataDescriptor(obj, prop) { - // data descriptor properties - var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' - }; - - if (typeOf(obj) !== 'object') { - return false; - } - - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (!('value' in obj) && !('writable' in obj)) { - return false; - } - - for (var key in obj) { - if (key === 'value') continue; - - if (!data.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === data[key]) { - continue; - } - - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -}; - - -/***/ }), -/* 765 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } - - if (isGeneratorObj(val)) { - return 'generator'; - } - - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } - - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} - -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } - } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; -} - - -/***/ }), -/* 766 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var typeOf = __webpack_require__(753); -var utils = module.exports; - -/** - * Returns true if the given value is a node. - * - * ```js - * var Node = require('snapdragon-node'); - * var node = new Node({type: 'foo'}); - * console.log(utils.isNode(node)); //=> true - * console.log(utils.isNode({})); //=> false - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @returns {Boolean} - * @api public - */ - -utils.isNode = function(node) { - return typeOf(node) === 'object' && node.isNode === true; -}; - -/** - * Emit an empty string for the given `node`. - * - * ```js - * // do nothing for beginning-of-string - * snapdragon.compiler.set('bos', utils.noop); - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @returns {undefined} - * @api public - */ - -utils.noop = function(node) { - append(this, '', node); -}; - -/** - * Appdend `node.val` to `compiler.output`, exactly as it was created - * by the parser. - * - * ```js - * snapdragon.compiler.set('text', utils.identity); - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @returns {undefined} - * @api public - */ - -utils.identity = function(node) { - append(this, node.val, node); -}; - -/** - * Previously named `.emit`, this method appends the given `val` - * to `compiler.output` for the given node. Useful when you know - * what value should be appended advance, regardless of the actual - * value of `node.val`. - * - * ```js - * snapdragon.compiler - * .set('i', function(node) { - * this.mapVisit(node); - * }) - * .set('i.open', utils.append('')) - * .set('i.close', utils.append('')) - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @returns {Function} Returns a compiler middleware function. - * @api public - */ - -utils.append = function(val) { - return function(node) { - append(this, val, node); - }; -}; - -/** - * Used in compiler middleware, this onverts an AST node into - * an empty `text` node and deletes `node.nodes` if it exists. - * The advantage of this method is that, as opposed to completely - * removing the node, indices will not need to be re-calculated - * in sibling nodes, and nothing is appended to the output. - * - * ```js - * utils.toNoop(node); - * // convert `node.nodes` to the given value instead of deleting it - * utils.toNoop(node, []); - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {Array} `nodes` Optionally pass a new `nodes` value, to replace the existing `node.nodes` array. - * @api public - */ - -utils.toNoop = function(node, nodes) { - if (nodes) { - node.nodes = nodes; - } else { - delete node.nodes; - node.type = 'text'; - node.val = ''; - } -}; - -/** - * Visit `node` with the given `fn`. The built-in `.visit` method in snapdragon - * automatically calls registered compilers, this allows you to pass a visitor - * function. - * - * ```js - * snapdragon.compiler.set('i', function(node) { - * utils.visit(node, function(childNode) { - * // do stuff with "childNode" - * return childNode; - * }); - * }); - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {Function} `fn` - * @return {Object} returns the node after recursively visiting all child nodes. - * @api public - */ - -utils.visit = function(node, fn) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isFunction(fn), 'expected a visitor function'); - fn(node); - return node.nodes ? utils.mapVisit(node, fn) : node; -}; - -/** - * Map [visit](#visit) the given `fn` over `node.nodes`. This is called by - * [visit](#visit), use this method if you do not want `fn` to be called on - * the first node. - * - * ```js - * snapdragon.compiler.set('i', function(node) { - * utils.mapVisit(node, function(childNode) { - * // do stuff with "childNode" - * return childNode; - * }); - * }); - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {Object} `options` - * @param {Function} `fn` - * @return {Object} returns the node - * @api public - */ - -utils.mapVisit = function(node, fn) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isArray(node.nodes), 'expected node.nodes to be an array'); - assert(isFunction(fn), 'expected a visitor function'); - - for (var i = 0; i < node.nodes.length; i++) { - utils.visit(node.nodes[i], fn); - } - return node; -}; - -/** - * Unshift an `*.open` node onto `node.nodes`. - * - * ```js - * var Node = require('snapdragon-node'); - * snapdragon.parser.set('brace', function(node) { - * var match = this.match(/^{/); - * if (match) { - * var parent = new Node({type: 'brace'}); - * utils.addOpen(parent, Node); - * console.log(parent.nodes[0]): - * // { type: 'brace.open', val: '' }; - * - * // push the parent "brace" node onto the stack - * this.push(parent); - * - * // return the parent node, so it's also added to the AST - * return brace; - * } - * }); - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {Function} `Node` (required) Node constructor function from [snapdragon-node][]. - * @param {Function} `filter` Optionaly specify a filter function to exclude the node. - * @return {Object} Returns the created opening node. - * @api public - */ - -utils.addOpen = function(node, Node, val, filter) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isFunction(Node), 'expected Node to be a constructor function'); - - if (typeof val === 'function') { - filter = val; - val = ''; - } - - if (typeof filter === 'function' && !filter(node)) return; - var open = new Node({ type: node.type + '.open', val: val}); - var unshift = node.unshift || node.unshiftNode; - if (typeof unshift === 'function') { - unshift.call(node, open); - } else { - utils.unshiftNode(node, open); - } - return open; -}; - -/** - * Push a `*.close` node onto `node.nodes`. - * - * ```js - * var Node = require('snapdragon-node'); - * snapdragon.parser.set('brace', function(node) { - * var match = this.match(/^}/); - * if (match) { - * var parent = this.parent(); - * if (parent.type !== 'brace') { - * throw new Error('missing opening: ' + '}'); - * } - * - * utils.addClose(parent, Node); - * console.log(parent.nodes[parent.nodes.length - 1]): - * // { type: 'brace.close', val: '' }; - * - * // no need to return a node, since the parent - * // was already added to the AST - * return; - * } - * }); - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {Function} `Node` (required) Node constructor function from [snapdragon-node][]. - * @param {Function} `filter` Optionaly specify a filter function to exclude the node. - * @return {Object} Returns the created closing node. - * @api public - */ - -utils.addClose = function(node, Node, val, filter) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isFunction(Node), 'expected Node to be a constructor function'); - - if (typeof val === 'function') { - filter = val; - val = ''; - } - - if (typeof filter === 'function' && !filter(node)) return; - var close = new Node({ type: node.type + '.close', val: val}); - var push = node.push || node.pushNode; - if (typeof push === 'function') { - push.call(node, close); - } else { - utils.pushNode(node, close); - } - return close; -}; - -/** - * Wraps the given `node` with `*.open` and `*.close` nodes. - * - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {Function} `Node` (required) Node constructor function from [snapdragon-node][]. - * @param {Function} `filter` Optionaly specify a filter function to exclude the node. - * @return {Object} Returns the node - * @api public - */ - -utils.wrapNodes = function(node, Node, filter) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isFunction(Node), 'expected Node to be a constructor function'); - - utils.addOpen(node, Node, filter); - utils.addClose(node, Node, filter); - return node; -}; - -/** - * Push the given `node` onto `parent.nodes`, and set `parent` as `node.parent. - * - * ```js - * var parent = new Node({type: 'foo'}); - * var node = new Node({type: 'bar'}); - * utils.pushNode(parent, node); - * console.log(parent.nodes[0].type) // 'bar' - * console.log(node.parent.type) // 'foo' - * ``` - * @param {Object} `parent` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Object} Returns the child node - * @api public - */ - -utils.pushNode = function(parent, node) { - assert(utils.isNode(parent), 'expected parent node to be an instance of Node'); - assert(utils.isNode(node), 'expected node to be an instance of Node'); - - node.define('parent', parent); - parent.nodes = parent.nodes || []; - parent.nodes.push(node); - return node; -}; - -/** - * Unshift `node` onto `parent.nodes`, and set `parent` as `node.parent. - * - * ```js - * var parent = new Node({type: 'foo'}); - * var node = new Node({type: 'bar'}); - * utils.unshiftNode(parent, node); - * console.log(parent.nodes[0].type) // 'bar' - * console.log(node.parent.type) // 'foo' - * ``` - * @param {Object} `parent` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {undefined} - * @api public - */ - -utils.unshiftNode = function(parent, node) { - assert(utils.isNode(parent), 'expected parent node to be an instance of Node'); - assert(utils.isNode(node), 'expected node to be an instance of Node'); - - node.define('parent', parent); - parent.nodes = parent.nodes || []; - parent.nodes.unshift(node); -}; - -/** - * Pop the last `node` off of `parent.nodes`. The advantage of - * using this method is that it checks for `node.nodes` and works - * with any version of `snapdragon-node`. - * - * ```js - * var parent = new Node({type: 'foo'}); - * utils.pushNode(parent, new Node({type: 'foo'})); - * utils.pushNode(parent, new Node({type: 'bar'})); - * utils.pushNode(parent, new Node({type: 'baz'})); - * console.log(parent.nodes.length); //=> 3 - * utils.popNode(parent); - * console.log(parent.nodes.length); //=> 2 - * ``` - * @param {Object} `parent` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Number|Undefined} Returns the length of `node.nodes` or undefined. - * @api public - */ - -utils.popNode = function(node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - if (typeof node.pop === 'function') { - return node.pop(); - } - return node.nodes && node.nodes.pop(); -}; - -/** - * Shift the first `node` off of `parent.nodes`. The advantage of - * using this method is that it checks for `node.nodes` and works - * with any version of `snapdragon-node`. - * - * ```js - * var parent = new Node({type: 'foo'}); - * utils.pushNode(parent, new Node({type: 'foo'})); - * utils.pushNode(parent, new Node({type: 'bar'})); - * utils.pushNode(parent, new Node({type: 'baz'})); - * console.log(parent.nodes.length); //=> 3 - * utils.shiftNode(parent); - * console.log(parent.nodes.length); //=> 2 - * ``` - * @param {Object} `parent` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Number|Undefined} Returns the length of `node.nodes` or undefined. - * @api public - */ - -utils.shiftNode = function(node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - if (typeof node.shift === 'function') { - return node.shift(); - } - return node.nodes && node.nodes.shift(); -}; - -/** - * Remove the specified `node` from `parent.nodes`. - * - * ```js - * var parent = new Node({type: 'abc'}); - * var foo = new Node({type: 'foo'}); - * utils.pushNode(parent, foo); - * utils.pushNode(parent, new Node({type: 'bar'})); - * utils.pushNode(parent, new Node({type: 'baz'})); - * console.log(parent.nodes.length); //=> 3 - * utils.removeNode(parent, foo); - * console.log(parent.nodes.length); //=> 2 - * ``` - * @param {Object} `parent` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Object|undefined} Returns the removed node, if successful, or undefined if it does not exist on `parent.nodes`. - * @api public - */ - -utils.removeNode = function(parent, node) { - assert(utils.isNode(parent), 'expected parent.node to be an instance of Node'); - assert(utils.isNode(node), 'expected node to be an instance of Node'); - - if (!parent.nodes) { - return null; - } - - if (typeof parent.remove === 'function') { - return parent.remove(node); - } - - var idx = parent.nodes.indexOf(node); - if (idx !== -1) { - return parent.nodes.splice(idx, 1); - } -}; - -/** - * Returns true if `node.type` matches the given `type`. Throws a - * `TypeError` if `node` is not an instance of `Node`. - * - * ```js - * var Node = require('snapdragon-node'); - * var node = new Node({type: 'foo'}); - * console.log(utils.isType(node, 'foo')); // false - * console.log(utils.isType(node, 'bar')); // true - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {String} `type` - * @return {Boolean} - * @api public - */ - -utils.isType = function(node, type) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - switch (typeOf(type)) { - case 'array': - var types = type.slice(); - for (var i = 0; i < types.length; i++) { - if (utils.isType(node, types[i])) { - return true; - } - } - return false; - case 'string': - return node.type === type; - case 'regexp': - return type.test(node.type); - default: { - throw new TypeError('expected "type" to be an array, string or regexp'); - } - } -}; - -/** - * Returns true if the given `node` has the given `type` in `node.nodes`. - * Throws a `TypeError` if `node` is not an instance of `Node`. - * - * ```js - * var Node = require('snapdragon-node'); - * var node = new Node({ - * type: 'foo', - * nodes: [ - * new Node({type: 'bar'}), - * new Node({type: 'baz'}) - * ] - * }); - * console.log(utils.hasType(node, 'xyz')); // false - * console.log(utils.hasType(node, 'baz')); // true - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {String} `type` - * @return {Boolean} - * @api public - */ - -utils.hasType = function(node, type) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - if (!Array.isArray(node.nodes)) return false; - for (var i = 0; i < node.nodes.length; i++) { - if (utils.isType(node.nodes[i], type)) { - return true; - } - } - return false; -}; - -/** - * Returns the first node from `node.nodes` of the given `type` - * - * ```js - * var node = new Node({ - * type: 'foo', - * nodes: [ - * new Node({type: 'text', val: 'abc'}), - * new Node({type: 'text', val: 'xyz'}) - * ] - * }); - * - * var textNode = utils.firstOfType(node.nodes, 'text'); - * console.log(textNode.val); - * //=> 'abc' - * ``` - * @param {Array} `nodes` - * @param {String} `type` - * @return {Object|undefined} Returns the first matching node or undefined. - * @api public - */ - -utils.firstOfType = function(nodes, type) { - for (var i = 0; i < nodes.length; i++) { - var node = nodes[i]; - if (utils.isType(node, type)) { - return node; - } - } -}; - -/** - * Returns the node at the specified index, or the first node of the - * given `type` from `node.nodes`. - * - * ```js - * var node = new Node({ - * type: 'foo', - * nodes: [ - * new Node({type: 'text', val: 'abc'}), - * new Node({type: 'text', val: 'xyz'}) - * ] - * }); - * - * var nodeOne = utils.findNode(node.nodes, 'text'); - * console.log(nodeOne.val); - * //=> 'abc' - * - * var nodeTwo = utils.findNode(node.nodes, 1); - * console.log(nodeTwo.val); - * //=> 'xyz' - * ``` - * - * @param {Array} `nodes` - * @param {String|Number} `type` Node type or index. - * @return {Object} Returns a node or undefined. - * @api public - */ - -utils.findNode = function(nodes, type) { - if (!Array.isArray(nodes)) { - return null; - } - if (typeof type === 'number') { - return nodes[type]; - } - return utils.firstOfType(nodes, type); -}; - -/** - * Returns true if the given node is an "*.open" node. - * - * ```js - * var Node = require('snapdragon-node'); - * var brace = new Node({type: 'brace'}); - * var open = new Node({type: 'brace.open'}); - * var close = new Node({type: 'brace.close'}); - * - * console.log(utils.isOpen(brace)); // false - * console.log(utils.isOpen(open)); // true - * console.log(utils.isOpen(close)); // false - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Boolean} - * @api public - */ - -utils.isOpen = function(node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - return node.type.slice(-5) === '.open'; -}; - -/** - * Returns true if the given node is a "*.close" node. - * - * ```js - * var Node = require('snapdragon-node'); - * var brace = new Node({type: 'brace'}); - * var open = new Node({type: 'brace.open'}); - * var close = new Node({type: 'brace.close'}); - * - * console.log(utils.isClose(brace)); // false - * console.log(utils.isClose(open)); // false - * console.log(utils.isClose(close)); // true - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Boolean} - * @api public - */ - -utils.isClose = function(node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - return node.type.slice(-6) === '.close'; -}; - -/** - * Returns true if `node.nodes` **has** an `.open` node - * - * ```js - * var Node = require('snapdragon-node'); - * var brace = new Node({ - * type: 'brace', - * nodes: [] - * }); - * - * var open = new Node({type: 'brace.open'}); - * console.log(utils.hasOpen(brace)); // false - * - * brace.pushNode(open); - * console.log(utils.hasOpen(brace)); // true - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Boolean} - * @api public - */ - -utils.hasOpen = function(node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - var first = node.first || node.nodes ? node.nodes[0] : null; - if (utils.isNode(first)) { - return first.type === node.type + '.open'; - } - return false; -}; - -/** - * Returns true if `node.nodes` **has** a `.close` node - * - * ```js - * var Node = require('snapdragon-node'); - * var brace = new Node({ - * type: 'brace', - * nodes: [] - * }); - * - * var close = new Node({type: 'brace.close'}); - * console.log(utils.hasClose(brace)); // false - * - * brace.pushNode(close); - * console.log(utils.hasClose(brace)); // true - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Boolean} - * @api public - */ - -utils.hasClose = function(node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - var last = node.last || node.nodes ? node.nodes[node.nodes.length - 1] : null; - if (utils.isNode(last)) { - return last.type === node.type + '.close'; - } - return false; -}; - -/** - * Returns true if `node.nodes` has both `.open` and `.close` nodes - * - * ```js - * var Node = require('snapdragon-node'); - * var brace = new Node({ - * type: 'brace', - * nodes: [] - * }); - * - * var open = new Node({type: 'brace.open'}); - * var close = new Node({type: 'brace.close'}); - * console.log(utils.hasOpen(brace)); // false - * console.log(utils.hasClose(brace)); // false - * - * brace.pushNode(open); - * brace.pushNode(close); - * console.log(utils.hasOpen(brace)); // true - * console.log(utils.hasClose(brace)); // true - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Boolean} - * @api public - */ - -utils.hasOpenAndClose = function(node) { - return utils.hasOpen(node) && utils.hasClose(node); -}; - -/** - * Push the given `node` onto the `state.inside` array for the - * given type. This array is used as a specialized "stack" for - * only the given `node.type`. - * - * ```js - * var state = { inside: {}}; - * var node = new Node({type: 'brace'}); - * utils.addType(state, node); - * console.log(state.inside); - * //=> { brace: [{type: 'brace'}] } - * ``` - * @param {Object} `state` The `compiler.state` object or custom state object. - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Array} Returns the `state.inside` stack for the given type. - * @api public - */ - -utils.addType = function(state, node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isObject(state), 'expected state to be an object'); - - var type = node.parent - ? node.parent.type - : node.type.replace(/\.open$/, ''); - - if (!state.hasOwnProperty('inside')) { - state.inside = {}; - } - if (!state.inside.hasOwnProperty(type)) { - state.inside[type] = []; - } - - var arr = state.inside[type]; - arr.push(node); - return arr; -}; - -/** - * Remove the given `node` from the `state.inside` array for the - * given type. This array is used as a specialized "stack" for - * only the given `node.type`. - * - * ```js - * var state = { inside: {}}; - * var node = new Node({type: 'brace'}); - * utils.addType(state, node); - * console.log(state.inside); - * //=> { brace: [{type: 'brace'}] } - * utils.removeType(state, node); - * //=> { brace: [] } - * ``` - * @param {Object} `state` The `compiler.state` object or custom state object. - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Array} Returns the `state.inside` stack for the given type. - * @api public - */ - -utils.removeType = function(state, node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isObject(state), 'expected state to be an object'); - - var type = node.parent - ? node.parent.type - : node.type.replace(/\.close$/, ''); - - if (state.inside.hasOwnProperty(type)) { - return state.inside[type].pop(); - } -}; - -/** - * Returns true if `node.val` is an empty string, or `node.nodes` does - * not contain any non-empty text nodes. - * - * ```js - * var node = new Node({type: 'text'}); - * utils.isEmpty(node); //=> true - * node.val = 'foo'; - * utils.isEmpty(node); //=> false - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {Function} `fn` - * @return {Boolean} - * @api public - */ - -utils.isEmpty = function(node, fn) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - - if (!Array.isArray(node.nodes)) { - if (node.type !== 'text') { - return true; - } - if (typeof fn === 'function') { - return fn(node, node.parent); - } - return !utils.trim(node.val); - } - - for (var i = 0; i < node.nodes.length; i++) { - var child = node.nodes[i]; - if (utils.isOpen(child) || utils.isClose(child)) { - continue; - } - if (!utils.isEmpty(child, fn)) { - return false; - } - } - - return true; -}; - -/** - * Returns true if the `state.inside` stack for the given type exists - * and has one or more nodes on it. - * - * ```js - * var state = { inside: {}}; - * var node = new Node({type: 'brace'}); - * console.log(utils.isInsideType(state, 'brace')); //=> false - * utils.addType(state, node); - * console.log(utils.isInsideType(state, 'brace')); //=> true - * utils.removeType(state, node); - * console.log(utils.isInsideType(state, 'brace')); //=> false - * ``` - * @param {Object} `state` - * @param {String} `type` - * @return {Boolean} - * @api public - */ - -utils.isInsideType = function(state, type) { - assert(isObject(state), 'expected state to be an object'); - assert(isString(type), 'expected type to be a string'); - - if (!state.hasOwnProperty('inside')) { - return false; - } - - if (!state.inside.hasOwnProperty(type)) { - return false; - } - - return state.inside[type].length > 0; -}; - -/** - * Returns true if `node` is either a child or grand-child of the given `type`, - * or `state.inside[type]` is a non-empty array. - * - * ```js - * var state = { inside: {}}; - * var node = new Node({type: 'brace'}); - * var open = new Node({type: 'brace.open'}); - * console.log(utils.isInside(state, open, 'brace')); //=> false - * utils.pushNode(node, open); - * console.log(utils.isInside(state, open, 'brace')); //=> true - * ``` - * @param {Object} `state` Either the `compiler.state` object, if it exists, or a user-supplied state object. - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {String} `type` The `node.type` to check for. - * @return {Boolean} - * @api public - */ - -utils.isInside = function(state, node, type) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isObject(state), 'expected state to be an object'); - - if (Array.isArray(type)) { - for (var i = 0; i < type.length; i++) { - if (utils.isInside(state, node, type[i])) { - return true; - } - } - return false; - } - - var parent = node.parent; - if (typeof type === 'string') { - return (parent && parent.type === type) || utils.isInsideType(state, type); - } - - if (typeOf(type) === 'regexp') { - if (parent && parent.type && type.test(parent.type)) { - return true; - } - - var keys = Object.keys(state.inside); - var len = keys.length; - var idx = -1; - while (++idx < len) { - var key = keys[idx]; - var val = state.inside[key]; - - if (Array.isArray(val) && val.length !== 0 && type.test(key)) { - return true; - } - } - } - return false; -}; - -/** - * Get the last `n` element from the given `array`. Used for getting - * a node from `node.nodes.` - * - * @param {Array} `array` - * @param {Number} `n` - * @return {undefined} - * @api public - */ - -utils.last = function(arr, n) { - return arr[arr.length - (n || 1)]; -}; - -/** - * Cast the given `val` to an array. - * - * ```js - * console.log(utils.arrayify('')); - * //=> [] - * console.log(utils.arrayify('foo')); - * //=> ['foo'] - * console.log(utils.arrayify(['foo'])); - * //=> ['foo'] - * ``` - * @param {any} `val` - * @return {Array} - * @api public - */ - -utils.arrayify = function(val) { - if (typeof val === 'string' && val !== '') { - return [val]; - } - if (!Array.isArray(val)) { - return []; - } - return val; -}; - -/** - * Convert the given `val` to a string by joining with `,`. Useful - * for creating a cheerio/CSS/DOM-style selector from a list of strings. - * - * @param {any} `val` - * @return {Array} - * @api public - */ - -utils.stringify = function(val) { - return utils.arrayify(val).join(','); -}; - -/** - * Ensure that the given value is a string and call `.trim()` on it, - * or return an empty string. - * - * @param {String} `str` - * @return {String} - * @api public - */ - -utils.trim = function(str) { - return typeof str === 'string' ? str.trim() : ''; -}; - -/** - * Return true if val is an object - */ - -function isObject(val) { - return typeOf(val) === 'object'; -} - -/** - * Return true if val is a string - */ - -function isString(val) { - return typeof val === 'string'; -} - -/** - * Return true if val is a function - */ - -function isFunction(val) { - return typeof val === 'function'; -} - -/** - * Return true if val is an array - */ - -function isArray(val) { - return Array.isArray(val); -} - -/** - * Shim to ensure the `.append` methods work with any version of snapdragon - */ - -function append(compiler, val, node) { - if (typeof compiler.append !== 'function') { - return compiler.emit(val, node); - } - return compiler.append(val, node); -} - -/** - * Simplified assertion. Throws an error is `val` is falsey. - */ - -function assert(val, message) { - if (!val) throw new Error(message); -} - - -/***/ }), -/* 767 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var extend = __webpack_require__(738); -var Snapdragon = __webpack_require__(768); -var compilers = __webpack_require__(742); -var parsers = __webpack_require__(757); -var utils = __webpack_require__(743); - -/** - * Customize Snapdragon parser and renderer - */ - -function Braces(options) { - this.options = extend({}, options); -} - -/** - * Initialize braces - */ - -Braces.prototype.init = function(options) { - if (this.isInitialized) return; - this.isInitialized = true; - var opts = utils.createOptions({}, this.options, options); - this.snapdragon = this.options.snapdragon || new Snapdragon(opts); - this.compiler = this.snapdragon.compiler; - this.parser = this.snapdragon.parser; - - compilers(this.snapdragon, opts); - parsers(this.snapdragon, opts); - - /** - * Call Snapdragon `.parse` method. When AST is returned, we check to - * see if any unclosed braces are left on the stack and, if so, we iterate - * over the stack and correct the AST so that compilers are called in the correct - * order and unbalance braces are properly escaped. - */ - - utils.define(this.snapdragon, 'parse', function(pattern, options) { - var parsed = Snapdragon.prototype.parse.apply(this, arguments); - this.parser.ast.input = pattern; - - var stack = this.parser.stack; - while (stack.length) { - addParent({type: 'brace.close', val: ''}, stack.pop()); - } - - function addParent(node, parent) { - utils.define(node, 'parent', parent); - parent.nodes.push(node); - } - - // add non-enumerable parser reference - utils.define(parsed, 'parser', this.parser); - return parsed; - }); -}; - -/** - * Decorate `.parse` method - */ - -Braces.prototype.parse = function(ast, options) { - if (ast && typeof ast === 'object' && ast.nodes) return ast; - this.init(options); - return this.snapdragon.parse(ast, options); -}; - -/** - * Decorate `.compile` method - */ - -Braces.prototype.compile = function(ast, options) { - if (typeof ast === 'string') { - ast = this.parse(ast, options); - } else { - this.init(options); - } - return this.snapdragon.compile(ast, options); -}; - -/** - * Expand - */ - -Braces.prototype.expand = function(pattern) { - var ast = this.parse(pattern, {expand: true}); - return this.compile(ast, {expand: true}); -}; - -/** - * Optimize - */ - -Braces.prototype.optimize = function(pattern) { - var ast = this.parse(pattern, {optimize: true}); - return this.compile(ast, {optimize: true}); -}; - -/** - * Expose `Braces` - */ - -module.exports = Braces; - - -/***/ }), -/* 768 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var Base = __webpack_require__(769); -var define = __webpack_require__(730); -var Compiler = __webpack_require__(798); -var Parser = __webpack_require__(827); -var utils = __webpack_require__(807); -var regexCache = {}; -var cache = {}; - -/** - * Create a new instance of `Snapdragon` with the given `options`. - * - * ```js - * var snapdragon = new Snapdragon(); - * ``` - * - * @param {Object} `options` - * @api public - */ - -function Snapdragon(options) { - Base.call(this, null, options); - this.options = utils.extend({source: 'string'}, this.options); - this.compiler = new Compiler(this.options); - this.parser = new Parser(this.options); - - Object.defineProperty(this, 'compilers', { - get: function() { - return this.compiler.compilers; - } - }); - - Object.defineProperty(this, 'parsers', { - get: function() { - return this.parser.parsers; - } - }); - - Object.defineProperty(this, 'regex', { - get: function() { - return this.parser.regex; - } - }); -} - -/** - * Inherit Base - */ - -Base.extend(Snapdragon); - -/** - * Add a parser to `snapdragon.parsers` for capturing the given `type` using - * the specified regex or parser function. A function is useful if you need - * to customize how the token is created and/or have access to the parser - * instance to check options, etc. - * - * ```js - * snapdragon - * .capture('slash', /^\//) - * .capture('dot', function() { - * var pos = this.position(); - * var m = this.match(/^\./); - * if (!m) return; - * return pos({ - * type: 'dot', - * val: m[0] - * }); - * }); - * ``` - * @param {String} `type` - * @param {RegExp|Function} `regex` - * @return {Object} Returns the parser instance for chaining - * @api public - */ - -Snapdragon.prototype.capture = function() { - return this.parser.capture.apply(this.parser, arguments); -}; - -/** - * Register a plugin `fn`. - * - * ```js - * var snapdragon = new Snapdgragon([options]); - * snapdragon.use(function() { - * console.log(this); //<= snapdragon instance - * console.log(this.parser); //<= parser instance - * console.log(this.compiler); //<= compiler instance - * }); - * ``` - * @param {Object} `fn` - * @api public - */ - -Snapdragon.prototype.use = function(fn) { - fn.call(this, this); - return this; -}; - -/** - * Parse the given `str`. - * - * ```js - * var snapdragon = new Snapdgragon([options]); - * // register parsers - * snapdragon.parser.use(function() {}); - * - * // parse - * var ast = snapdragon.parse('foo/bar'); - * console.log(ast); - * ``` - * @param {String} `str` - * @param {Object} `options` Set `options.sourcemap` to true to enable source maps. - * @return {Object} Returns an AST. - * @api public - */ - -Snapdragon.prototype.parse = function(str, options) { - this.options = utils.extend({}, this.options, options); - var parsed = this.parser.parse(str, this.options); - - // add non-enumerable parser reference - define(parsed, 'parser', this.parser); - return parsed; -}; - -/** - * Compile the given `AST`. - * - * ```js - * var snapdragon = new Snapdgragon([options]); - * // register plugins - * snapdragon.use(function() {}); - * // register parser plugins - * snapdragon.parser.use(function() {}); - * // register compiler plugins - * snapdragon.compiler.use(function() {}); - * - * // parse - * var ast = snapdragon.parse('foo/bar'); - * - * // compile - * var res = snapdragon.compile(ast); - * console.log(res.output); - * ``` - * @param {Object} `ast` - * @param {Object} `options` - * @return {Object} Returns an object with an `output` property with the rendered string. - * @api public - */ - -Snapdragon.prototype.compile = function(ast, options) { - this.options = utils.extend({}, this.options, options); - var compiled = this.compiler.compile(ast, this.options); - - // add non-enumerable compiler reference - define(compiled, 'compiler', this.compiler); - return compiled; -}; - -/** - * Expose `Snapdragon` - */ - -module.exports = Snapdragon; - -/** - * Expose `Parser` and `Compiler` - */ - -module.exports.Compiler = Compiler; -module.exports.Parser = Parser; - - -/***/ }), -/* 769 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var util = __webpack_require__(29); -var define = __webpack_require__(770); -var CacheBase = __webpack_require__(771); -var Emitter = __webpack_require__(772); -var isObject = __webpack_require__(748); -var merge = __webpack_require__(789); -var pascal = __webpack_require__(792); -var cu = __webpack_require__(793); - -/** - * Optionally define a custom `cache` namespace to use. - */ - -function namespace(name) { - var Cache = name ? CacheBase.namespace(name) : CacheBase; - var fns = []; - - /** - * Create an instance of `Base` with the given `config` and `options`. - * - * ```js - * // initialize with `config` and `options` - * var app = new Base({isApp: true}, {abc: true}); - * app.set('foo', 'bar'); - * - * // values defined with the given `config` object will be on the root of the instance - * console.log(app.baz); //=> undefined - * console.log(app.foo); //=> 'bar' - * // or use `.get` - * console.log(app.get('isApp')); //=> true - * console.log(app.get('foo')); //=> 'bar' - * - * // values defined with the given `options` object will be on `app.options - * console.log(app.options.abc); //=> true - * ``` - * - * @param {Object} `config` If supplied, this object is passed to [cache-base][] to merge onto the the instance upon instantiation. - * @param {Object} `options` If supplied, this object is used to initialize the `base.options` object. - * @api public - */ - - function Base(config, options) { - if (!(this instanceof Base)) { - return new Base(config, options); - } - Cache.call(this, config); - this.is('base'); - this.initBase(config, options); - } - - /** - * Inherit cache-base - */ - - util.inherits(Base, Cache); - - /** - * Add static emitter methods - */ - - Emitter(Base); - - /** - * Initialize `Base` defaults with the given `config` object - */ - - Base.prototype.initBase = function(config, options) { - this.options = merge({}, this.options, options); - this.cache = this.cache || {}; - this.define('registered', {}); - if (name) this[name] = {}; - - // make `app._callbacks` non-enumerable - this.define('_callbacks', this._callbacks); - if (isObject(config)) { - this.visit('set', config); - } - Base.run(this, 'use', fns); - }; - - /** - * Set the given `name` on `app._name` and `app.is*` properties. Used for doing - * lookups in plugins. - * - * ```js - * app.is('foo'); - * console.log(app._name); - * //=> 'foo' - * console.log(app.isFoo); - * //=> true - * app.is('bar'); - * console.log(app.isFoo); - * //=> true - * console.log(app.isBar); - * //=> true - * console.log(app._name); - * //=> 'bar' - * ``` - * @name .is - * @param {String} `name` - * @return {Boolean} - * @api public - */ - - Base.prototype.is = function(name) { - if (typeof name !== 'string') { - throw new TypeError('expected name to be a string'); - } - this.define('is' + pascal(name), true); - this.define('_name', name); - this.define('_appname', name); - return this; - }; - - /** - * Returns true if a plugin has already been registered on an instance. - * - * Plugin implementors are encouraged to use this first thing in a plugin - * to prevent the plugin from being called more than once on the same - * instance. - * - * ```js - * var base = new Base(); - * base.use(function(app) { - * if (app.isRegistered('myPlugin')) return; - * // do stuff to `app` - * }); - * - * // to also record the plugin as being registered - * base.use(function(app) { - * if (app.isRegistered('myPlugin', true)) return; - * // do stuff to `app` - * }); - * ``` - * @name .isRegistered - * @emits `plugin` Emits the name of the plugin being registered. Useful for unit tests, to ensure plugins are only registered once. - * @param {String} `name` The plugin name. - * @param {Boolean} `register` If the plugin if not already registered, to record it as being registered pass `true` as the second argument. - * @return {Boolean} Returns true if a plugin is already registered. - * @api public - */ - - Base.prototype.isRegistered = function(name, register) { - if (this.registered.hasOwnProperty(name)) { - return true; - } - if (register !== false) { - this.registered[name] = true; - this.emit('plugin', name); - } - return false; - }; - - /** - * Define a plugin function to be called immediately upon init. Plugins are chainable - * and expose the following arguments to the plugin function: - * - * - `app`: the current instance of `Base` - * - `base`: the [first ancestor instance](#base) of `Base` - * - * ```js - * var app = new Base() - * .use(foo) - * .use(bar) - * .use(baz) - * ``` - * @name .use - * @param {Function} `fn` plugin function to call - * @return {Object} Returns the item instance for chaining. - * @api public - */ - - Base.prototype.use = function(fn) { - fn.call(this, this); - return this; - }; - - /** - * The `.define` method is used for adding non-enumerable property on the instance. - * Dot-notation is **not supported** with `define`. - * - * ```js - * // arbitrary `render` function using lodash `template` - * app.define('render', function(str, locals) { - * return _.template(str)(locals); - * }); - * ``` - * @name .define - * @param {String} `key` The name of the property to define. - * @param {any} `value` - * @return {Object} Returns the instance for chaining. - * @api public - */ - - Base.prototype.define = function(key, val) { - if (isObject(key)) { - return this.visit('define', key); - } - define(this, key, val); - return this; - }; - - /** - * Mix property `key` onto the Base prototype. If base is inherited using - * `Base.extend` this method will be overridden by a new `mixin` method that will - * only add properties to the prototype of the inheriting application. - * - * ```js - * app.mixin('foo', function() { - * // do stuff - * }); - * ``` - * @name .mixin - * @param {String} `key` - * @param {Object|Array} `val` - * @return {Object} Returns the `base` instance for chaining. - * @api public - */ - - Base.prototype.mixin = function(key, val) { - Base.prototype[key] = val; - return this; - }; - - /** - * Non-enumberable mixin array, used by the static [Base.mixin]() method. - */ - - Base.prototype.mixins = Base.prototype.mixins || []; - - /** - * Getter/setter used when creating nested instances of `Base`, for storing a reference - * to the first ancestor instance. This works by setting an instance of `Base` on the `parent` - * property of a "child" instance. The `base` property defaults to the current instance if - * no `parent` property is defined. - * - * ```js - * // create an instance of `Base`, this is our first ("base") instance - * var first = new Base(); - * first.foo = 'bar'; // arbitrary property, to make it easier to see what's happening later - * - * // create another instance - * var second = new Base(); - * // create a reference to the first instance (`first`) - * second.parent = first; - * - * // create another instance - * var third = new Base(); - * // create a reference to the previous instance (`second`) - * // repeat this pattern every time a "child" instance is created - * third.parent = second; - * - * // we can always access the first instance using the `base` property - * console.log(first.base.foo); - * //=> 'bar' - * console.log(second.base.foo); - * //=> 'bar' - * console.log(third.base.foo); - * //=> 'bar' - * // and now you know how to get to third base ;) - * ``` - * @name .base - * @api public - */ - - Object.defineProperty(Base.prototype, 'base', { - configurable: true, - get: function() { - return this.parent ? this.parent.base : this; - } - }); - - /** - * Static method for adding global plugin functions that will - * be added to an instance when created. - * - * ```js - * Base.use(function(app) { - * app.foo = 'bar'; - * }); - * var app = new Base(); - * console.log(app.foo); - * //=> 'bar' - * ``` - * @name #use - * @param {Function} `fn` Plugin function to use on each instance. - * @return {Object} Returns the `Base` constructor for chaining - * @api public - */ - - define(Base, 'use', function(fn) { - fns.push(fn); - return Base; - }); - - /** - * Run an array of functions by passing each function - * to a method on the given object specified by the given property. - * - * @param {Object} `obj` Object containing method to use. - * @param {String} `prop` Name of the method on the object to use. - * @param {Array} `arr` Array of functions to pass to the method. - */ - - define(Base, 'run', function(obj, prop, arr) { - var len = arr.length, i = 0; - while (len--) { - obj[prop](arr[i++]); - } - return Base; - }); - - /** - * Static method for inheriting the prototype and static methods of the `Base` class. - * This method greatly simplifies the process of creating inheritance-based applications. - * See [static-extend][] for more details. - * - * ```js - * var extend = cu.extend(Parent); - * Parent.extend(Child); - * - * // optional methods - * Parent.extend(Child, { - * foo: function() {}, - * bar: function() {} - * }); - * ``` - * @name #extend - * @param {Function} `Ctor` constructor to extend - * @param {Object} `methods` Optional prototype properties to mix in. - * @return {Object} Returns the `Base` constructor for chaining - * @api public - */ - - define(Base, 'extend', cu.extend(Base, function(Ctor, Parent) { - Ctor.prototype.mixins = Ctor.prototype.mixins || []; - - define(Ctor, 'mixin', function(fn) { - var mixin = fn(Ctor.prototype, Ctor); - if (typeof mixin === 'function') { - Ctor.prototype.mixins.push(mixin); - } - return Ctor; - }); - - define(Ctor, 'mixins', function(Child) { - Base.run(Child, 'mixin', Ctor.prototype.mixins); - return Ctor; - }); - - Ctor.prototype.mixin = function(key, value) { - Ctor.prototype[key] = value; - return this; - }; - return Base; - })); - - /** - * Used for adding methods to the `Base` prototype, and/or to the prototype of child instances. - * When a mixin function returns a function, the returned function is pushed onto the `.mixins` - * array, making it available to be used on inheriting classes whenever `Base.mixins()` is - * called (e.g. `Base.mixins(Child)`). - * - * ```js - * Base.mixin(function(proto) { - * proto.foo = function(msg) { - * return 'foo ' + msg; - * }; - * }); - * ``` - * @name #mixin - * @param {Function} `fn` Function to call - * @return {Object} Returns the `Base` constructor for chaining - * @api public - */ - - define(Base, 'mixin', function(fn) { - var mixin = fn(Base.prototype, Base); - if (typeof mixin === 'function') { - Base.prototype.mixins.push(mixin); - } - return Base; - }); - - /** - * Static method for running global mixin functions against a child constructor. - * Mixins must be registered before calling this method. - * - * ```js - * Base.extend(Child); - * Base.mixins(Child); - * ``` - * @name #mixins - * @param {Function} `Child` Constructor function of a child class - * @return {Object} Returns the `Base` constructor for chaining - * @api public - */ - - define(Base, 'mixins', function(Child) { - Base.run(Child, 'mixin', Base.prototype.mixins); - return Base; - }); - - /** - * Similar to `util.inherit`, but copies all static properties, prototype properties, and - * getters/setters from `Provider` to `Receiver`. See [class-utils][]{#inherit} for more details. - * - * ```js - * Base.inherit(Foo, Bar); - * ``` - * @name #inherit - * @param {Function} `Receiver` Receiving (child) constructor - * @param {Function} `Provider` Providing (parent) constructor - * @return {Object} Returns the `Base` constructor for chaining - * @api public - */ - - define(Base, 'inherit', cu.inherit); - define(Base, 'bubble', cu.bubble); - return Base; -} - -/** - * Expose `Base` with default settings - */ - -module.exports = namespace(); - -/** - * Allow users to define a namespace - */ - -module.exports.namespace = namespace; - - -/***/ }), -/* 770 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isDescriptor = __webpack_require__(760); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } - - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } - - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; - - -/***/ }), -/* 771 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isObject = __webpack_require__(748); -var Emitter = __webpack_require__(772); -var visit = __webpack_require__(773); -var toPath = __webpack_require__(776); -var union = __webpack_require__(777); -var del = __webpack_require__(781); -var get = __webpack_require__(779); -var has = __webpack_require__(786); -var set = __webpack_require__(780); - -/** - * Create a `Cache` constructor that when instantiated will - * store values on the given `prop`. - * - * ```js - * var Cache = require('cache-base').namespace('data'); - * var cache = new Cache(); - * - * cache.set('foo', 'bar'); - * //=> {data: {foo: 'bar'}} - * ``` - * @param {String} `prop` The property name to use for storing values. - * @return {Function} Returns a custom `Cache` constructor - * @api public - */ - -function namespace(prop) { - - /** - * Create a new `Cache`. Internally the `Cache` constructor is created using - * the `namespace` function, with `cache` defined as the storage object. - * - * ```js - * var app = new Cache(); - * ``` - * @param {Object} `cache` Optionally pass an object to initialize with. - * @constructor - * @api public - */ - - function Cache(cache) { - if (prop) { - this[prop] = {}; - } - if (cache) { - this.set(cache); - } - } - - /** - * Inherit Emitter - */ - - Emitter(Cache.prototype); - - /** - * Assign `value` to `key`. Also emits `set` with - * the key and value. - * - * ```js - * app.on('set', function(key, val) { - * // do something when `set` is emitted - * }); - * - * app.set(key, value); - * - * // also takes an object or array - * app.set({name: 'Halle'}); - * app.set([{foo: 'bar'}, {baz: 'quux'}]); - * console.log(app); - * //=> {name: 'Halle', foo: 'bar', baz: 'quux'} - * ``` - * - * @name .set - * @emits `set` with `key` and `value` as arguments. - * @param {String} `key` - * @param {any} `value` - * @return {Object} Returns the instance for chaining. - * @api public - */ - - Cache.prototype.set = function(key, val) { - if (Array.isArray(key) && arguments.length === 2) { - key = toPath(key); - } - if (isObject(key) || Array.isArray(key)) { - this.visit('set', key); - } else { - set(prop ? this[prop] : this, key, val); - this.emit('set', key, val); - } - return this; - }; - - /** - * Union `array` to `key`. Also emits `set` with - * the key and value. - * - * ```js - * app.union('a.b', ['foo']); - * app.union('a.b', ['bar']); - * console.log(app.get('a')); - * //=> {b: ['foo', 'bar']} - * ``` - * @name .union - * @param {String} `key` - * @param {any} `value` - * @return {Object} Returns the instance for chaining. - * @api public - */ - - Cache.prototype.union = function(key, val) { - if (Array.isArray(key) && arguments.length === 2) { - key = toPath(key); - } - var ctx = prop ? this[prop] : this; - union(ctx, key, arrayify(val)); - this.emit('union', val); - return this; - }; - - /** - * Return the value of `key`. Dot notation may be used - * to get [nested property values][get-value]. - * - * ```js - * app.set('a.b.c', 'd'); - * app.get('a.b'); - * //=> {c: 'd'} - * - * app.get(['a', 'b']); - * //=> {c: 'd'} - * ``` - * - * @name .get - * @emits `get` with `key` and `value` as arguments. - * @param {String} `key` The name of the property to get. Dot-notation may be used. - * @return {any} Returns the value of `key` - * @api public - */ - - Cache.prototype.get = function(key) { - key = toPath(arguments); - - var ctx = prop ? this[prop] : this; - var val = get(ctx, key); - - this.emit('get', key, val); - return val; - }; - - /** - * Return true if app has a stored value for `key`, - * false only if value is `undefined`. - * - * ```js - * app.set('foo', 'bar'); - * app.has('foo'); - * //=> true - * ``` - * - * @name .has - * @emits `has` with `key` and true or false as arguments. - * @param {String} `key` - * @return {Boolean} - * @api public - */ - - Cache.prototype.has = function(key) { - key = toPath(arguments); - - var ctx = prop ? this[prop] : this; - var val = get(ctx, key); - - var has = typeof val !== 'undefined'; - this.emit('has', key, has); - return has; - }; - - /** - * Delete one or more properties from the instance. - * - * ```js - * app.del(); // delete all - * // or - * app.del('foo'); - * // or - * app.del(['foo', 'bar']); - * ``` - * @name .del - * @emits `del` with the `key` as the only argument. - * @param {String|Array} `key` Property name or array of property names. - * @return {Object} Returns the instance for chaining. - * @api public - */ - - Cache.prototype.del = function(key) { - if (Array.isArray(key)) { - this.visit('del', key); - } else { - del(prop ? this[prop] : this, key); - this.emit('del', key); - } - return this; - }; - - /** - * Reset the entire cache to an empty object. - * - * ```js - * app.clear(); - * ``` - * @api public - */ - - Cache.prototype.clear = function() { - if (prop) { - this[prop] = {}; - } - }; - - /** - * Visit `method` over the properties in the given object, or map - * visit over the object-elements in an array. - * - * @name .visit - * @param {String} `method` The name of the `base` method to call. - * @param {Object|Array} `val` The object or array to iterate over. - * @return {Object} Returns the instance for chaining. - * @api public - */ - - Cache.prototype.visit = function(method, val) { - visit(this, method, val); - return this; - }; - - return Cache; -} - -/** - * Cast val to an array - */ - -function arrayify(val) { - return val ? (Array.isArray(val) ? val : [val]) : []; -} - -/** - * Expose `Cache` - */ - -module.exports = namespace(); - -/** - * Expose `Cache.namespace` - */ - -module.exports.namespace = namespace; - - -/***/ }), -/* 772 */ -/***/ (function(module, exports, __webpack_require__) { - - -/** - * Expose `Emitter`. - */ - -if (true) { - module.exports = Emitter; -} - -/** - * Initialize a new `Emitter`. - * - * @api public - */ - -function Emitter(obj) { - if (obj) return mixin(obj); -}; - -/** - * Mixin the emitter properties. - * - * @param {Object} obj - * @return {Object} - * @api private - */ - -function mixin(obj) { - for (var key in Emitter.prototype) { - obj[key] = Emitter.prototype[key]; - } - return obj; -} - -/** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.on = -Emitter.prototype.addEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - (this._callbacks['$' + event] = this._callbacks['$' + event] || []) - .push(fn); - return this; -}; - -/** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.once = function(event, fn){ - function on() { - this.off(event, on); - fn.apply(this, arguments); - } - - on.fn = fn; - this.on(event, on); - return this; -}; - -/** - * Remove the given callback for `event` or all - * registered callbacks. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.off = -Emitter.prototype.removeListener = -Emitter.prototype.removeAllListeners = -Emitter.prototype.removeEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - - // all - if (0 == arguments.length) { - this._callbacks = {}; - return this; - } - - // specific event - var callbacks = this._callbacks['$' + event]; - if (!callbacks) return this; - - // remove all handlers - if (1 == arguments.length) { - delete this._callbacks['$' + event]; - return this; - } - - // remove specific handler - var cb; - for (var i = 0; i < callbacks.length; i++) { - cb = callbacks[i]; - if (cb === fn || cb.fn === fn) { - callbacks.splice(i, 1); - break; - } - } - return this; -}; - -/** - * Emit `event` with the given args. - * - * @param {String} event - * @param {Mixed} ... - * @return {Emitter} - */ - -Emitter.prototype.emit = function(event){ - this._callbacks = this._callbacks || {}; - var args = [].slice.call(arguments, 1) - , callbacks = this._callbacks['$' + event]; - - if (callbacks) { - callbacks = callbacks.slice(0); - for (var i = 0, len = callbacks.length; i < len; ++i) { - callbacks[i].apply(this, args); - } - } - - return this; -}; - -/** - * Return array of callbacks for `event`. - * - * @param {String} event - * @return {Array} - * @api public - */ - -Emitter.prototype.listeners = function(event){ - this._callbacks = this._callbacks || {}; - return this._callbacks['$' + event] || []; -}; - -/** - * Check if this emitter has `event` handlers. - * - * @param {String} event - * @return {Boolean} - * @api public - */ - -Emitter.prototype.hasListeners = function(event){ - return !! this.listeners(event).length; -}; - - -/***/ }), -/* 773 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * collection-visit - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var visit = __webpack_require__(774); -var mapVisit = __webpack_require__(775); - -module.exports = function(collection, method, val) { - var result; - - if (typeof val === 'string' && (method in collection)) { - var args = [].slice.call(arguments, 2); - result = collection[method].apply(collection, args); - } else if (Array.isArray(val)) { - result = mapVisit.apply(null, arguments); - } else { - result = visit.apply(null, arguments); - } - - if (typeof result !== 'undefined') { - return result; - } - - return collection; -}; - - -/***/ }), -/* 774 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * object-visit - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isObject = __webpack_require__(748); - -module.exports = function visit(thisArg, method, target, val) { - if (!isObject(thisArg) && typeof thisArg !== 'function') { - throw new Error('object-visit expects `thisArg` to be an object.'); - } - - if (typeof method !== 'string') { - throw new Error('object-visit expects `method` name to be a string'); - } - - if (typeof thisArg[method] !== 'function') { - return thisArg; - } - - var args = [].slice.call(arguments, 3); - target = target || {}; - - for (var key in target) { - var arr = [key, target[key]].concat(args); - thisArg[method].apply(thisArg, arr); - } - return thisArg; -}; - - -/***/ }), -/* 775 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var util = __webpack_require__(29); -var visit = __webpack_require__(774); - -/** - * Map `visit` over an array of objects. - * - * @param {Object} `collection` The context in which to invoke `method` - * @param {String} `method` Name of the method to call on `collection` - * @param {Object} `arr` Array of objects. - */ - -module.exports = function mapVisit(collection, method, val) { - if (isObject(val)) { - return visit.apply(null, arguments); - } - - if (!Array.isArray(val)) { - throw new TypeError('expected an array: ' + util.inspect(val)); - } - - var args = [].slice.call(arguments, 3); - - for (var i = 0; i < val.length; i++) { - var ele = val[i]; - if (isObject(ele)) { - visit.apply(null, [collection, method, ele].concat(args)); - } else { - collection[method].apply(collection, [ele].concat(args)); - } - } -}; - -function isObject(val) { - return val && (typeof val === 'function' || (!Array.isArray(val) && typeof val === 'object')); -} - - -/***/ }), -/* 776 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * to-object-path - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var typeOf = __webpack_require__(753); - -module.exports = function toPath(args) { - if (typeOf(args) !== 'arguments') { - args = arguments; - } - return filter(args).join('.'); -}; - -function filter(arr) { - var len = arr.length; - var idx = -1; - var res = []; - - while (++idx < len) { - var ele = arr[idx]; - if (typeOf(ele) === 'arguments' || Array.isArray(ele)) { - res.push.apply(res, filter(ele)); - } else if (typeof ele === 'string') { - res.push(ele); - } - } - return res; -} - - -/***/ }), -/* 777 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isObject = __webpack_require__(739); -var union = __webpack_require__(778); -var get = __webpack_require__(779); -var set = __webpack_require__(780); - -module.exports = function unionValue(obj, prop, value) { - if (!isObject(obj)) { - throw new TypeError('union-value expects the first argument to be an object.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('union-value expects `prop` to be a string.'); - } - - var arr = arrayify(get(obj, prop)); - set(obj, prop, union(arr, arrayify(value))); - return obj; -}; - -function arrayify(val) { - if (val === null || typeof val === 'undefined') { - return []; - } - if (Array.isArray(val)) { - return val; - } - return [val]; -} - - -/***/ }), -/* 778 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -module.exports = function union(init) { - if (!Array.isArray(init)) { - throw new TypeError('arr-union expects the first argument to be an array.'); - } - - var len = arguments.length; - var i = 0; - - while (++i < len) { - var arg = arguments[i]; - if (!arg) continue; - - if (!Array.isArray(arg)) { - arg = [arg]; - } - - for (var j = 0; j < arg.length; j++) { - var ele = arg[j]; - - if (init.indexOf(ele) >= 0) { - continue; - } - init.push(ele); - } - } - return init; -}; - - -/***/ }), -/* 779 */ -/***/ (function(module, exports) { - -/*! - * get-value - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - -module.exports = function(obj, prop, a, b, c) { - if (!isObject(obj) || !prop) { - return obj; - } - - prop = toString(prop); - - // allowing for multiple properties to be passed as - // a string or array, but much faster (3-4x) than doing - // `[].slice.call(arguments)` - if (a) prop += '.' + toString(a); - if (b) prop += '.' + toString(b); - if (c) prop += '.' + toString(c); - - if (prop in obj) { - return obj[prop]; - } - - var segs = prop.split('.'); - var len = segs.length; - var i = -1; - - while (obj && (++i < len)) { - var key = segs[i]; - while (key[key.length - 1] === '\\') { - key = key.slice(0, -1) + '.' + segs[++i]; - } - obj = obj[key]; - } - return obj; -}; - -function isObject(val) { - return val !== null && (typeof val === 'object' || typeof val === 'function'); -} - -function toString(val) { - if (!val) return ''; - if (Array.isArray(val)) { - return val.join('.'); - } - return val; -} - - -/***/ }), -/* 780 */ -/***/ (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__(744); -var extend = __webpack_require__(738); -var isPlainObject = __webpack_require__(747); -var isObject = __webpack_require__(739); - -module.exports = function(obj, prop, val) { - if (!isObject(obj)) { - return obj; - } - - if (Array.isArray(prop)) { - prop = [].concat.apply([], prop).join('.'); - } - - if (typeof prop !== 'string') { - return obj; - } - - var keys = split(prop, {sep: '.', brackets: true}).filter(isValidKey); - 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; -}; - -function isValidKey(key) { - return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'; -} - - -/***/ }), -/* 781 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * unset-value - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isObject = __webpack_require__(748); -var has = __webpack_require__(782); - -module.exports = function unset(obj, prop) { - if (!isObject(obj)) { - throw new TypeError('expected an object.'); - } - if (obj.hasOwnProperty(prop)) { - delete obj[prop]; - return true; - } - - if (has(obj, prop)) { - var segs = prop.split('.'); - var last = segs.pop(); - while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { - last = segs.pop().slice(0, -1) + '.' + last; - } - while (segs.length) obj = obj[prop = segs.shift()]; - return (delete obj[last]); - } - return true; -}; - - -/***/ }), -/* 782 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * has-value - * - * Copyright (c) 2014-2016, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isObject = __webpack_require__(783); -var hasValues = __webpack_require__(785); -var get = __webpack_require__(779); - -module.exports = function(obj, prop, noZero) { - if (isObject(obj)) { - return hasValues(get(obj, prop), noZero); - } - return hasValues(obj, prop); -}; - - -/***/ }), -/* 783 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * isobject - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isArray = __webpack_require__(784); - -module.exports = function isObject(val) { - return val != null && typeof val === 'object' && isArray(val) === false; -}; - - -/***/ }), -/* 784 */ -/***/ (function(module, exports) { - -var toString = {}.toString; - -module.exports = Array.isArray || function (arr) { - return toString.call(arr) == '[object Array]'; -}; - - -/***/ }), -/* 785 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * has-values - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -module.exports = function hasValue(o, noZero) { - if (o === null || o === undefined) { - return false; - } - - if (typeof o === 'boolean') { - return true; - } - - if (typeof o === 'number') { - if (o === 0 && noZero === true) { - return false; - } - return true; - } - - if (o.length !== undefined) { - return o.length !== 0; - } - - for (var key in o) { - if (o.hasOwnProperty(key)) { - return true; - } - } - return false; -}; - - -/***/ }), -/* 786 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * has-value - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isObject = __webpack_require__(748); -var hasValues = __webpack_require__(787); -var get = __webpack_require__(779); - -module.exports = function(val, prop) { - return hasValues(isObject(val) && prop ? get(val, prop) : val); -}; - - -/***/ }), -/* 787 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * has-values - * - * Copyright (c) 2014-2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(788); -var isNumber = __webpack_require__(752); - -module.exports = function hasValue(val) { - // is-number checks for NaN and other edge cases - if (isNumber(val)) { - return true; - } - - switch (typeOf(val)) { - case 'null': - case 'boolean': - case 'function': - return true; - case 'string': - case 'arguments': - return val.length !== 0; - case 'error': - return val.message !== ''; - case 'array': - var len = val.length; - if (len === 0) { - return false; - } - for (var i = 0; i < len; i++) { - if (hasValue(val[i])) { - return true; - } - } - return false; - case 'file': - case 'map': - case 'set': - return val.size !== 0; - case 'object': - var keys = Object.keys(val); - if (keys.length === 0) { - return false; - } - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - if (hasValue(val[key])) { - return true; - } - } - return false; - default: { - return false; - } - } -}; - - -/***/ }), -/* 788 */ -/***/ (function(module, exports, __webpack_require__) { - -var isBuffer = __webpack_require__(735); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - var type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - - -/***/ }), -/* 789 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isExtendable = __webpack_require__(790); -var forIn = __webpack_require__(791); - -function mixinDeep(target, objects) { - var len = arguments.length, i = 0; - while (++i < len) { - var obj = arguments[i]; - if (isObject(obj)) { - forIn(obj, copy, target); - } - } - return target; -} - -/** - * Copy properties from the source object to the - * target object. - * - * @param {*} `val` - * @param {String} `key` - */ - -function copy(val, key) { - if (!isValidKey(key)) { - return; - } - - var obj = this[key]; - if (isObject(val) && isObject(obj)) { - mixinDeep(obj, val); - } else { - this[key] = val; - } -} - -/** - * Returns true if `val` is an object or function. - * - * @param {any} val - * @return {Boolean} - */ - -function isObject(val) { - return isExtendable(val) && !Array.isArray(val); -} - -/** - * Returns true if `key` is a valid key to use when extending objects. - * - * @param {String} `key` - * @return {Boolean} - */ - -function isValidKey(key) { - return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'; -}; - -/** - * Expose `mixinDeep` - */ - -module.exports = mixinDeep; - - -/***/ }), -/* 790 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-extendable - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isPlainObject = __webpack_require__(747); - -module.exports = function isExtendable(val) { - return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); -}; - - -/***/ }), -/* 791 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * for-in - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -module.exports = function forIn(obj, fn, thisArg) { - for (var key in obj) { - if (fn.call(thisArg, obj[key], key, obj) === false) { - break; - } - } -}; - - -/***/ }), -/* 792 */ -/***/ (function(module, exports) { - -/*! - * pascalcase - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - -function pascalcase(str) { - if (typeof str !== 'string') { - throw new TypeError('expected a string.'); - } - str = str.replace(/([A-Z])/g, ' $1'); - if (str.length === 1) { return str.toUpperCase(); } - str = str.replace(/^[\W_]+|[\W_]+$/g, '').toLowerCase(); - str = str.charAt(0).toUpperCase() + str.slice(1); - return str.replace(/[\W_]+(\w|$)/g, function (_, ch) { - return ch.toUpperCase(); - }); -} - -module.exports = pascalcase; - - -/***/ }), -/* 793 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var util = __webpack_require__(29); -var utils = __webpack_require__(794); - -/** - * Expose class utils - */ - -var cu = module.exports; - -/** - * Expose class utils: `cu` - */ - -cu.isObject = function isObject(val) { - return utils.isObj(val) || typeof val === 'function'; -}; - -/** - * Returns true if an array has any of the given elements, or an - * object has any of the give keys. - * - * ```js - * cu.has(['a', 'b', 'c'], 'c'); - * //=> true - * - * cu.has(['a', 'b', 'c'], ['c', 'z']); - * //=> true - * - * cu.has({a: 'b', c: 'd'}, ['c', 'z']); - * //=> true - * ``` - * @param {Object} `obj` - * @param {String|Array} `val` - * @return {Boolean} - * @api public - */ - -cu.has = function has(obj, val) { - val = cu.arrayify(val); - var len = val.length; - - if (cu.isObject(obj)) { - for (var key in obj) { - if (val.indexOf(key) > -1) { - return true; - } - } - - var keys = cu.nativeKeys(obj); - return cu.has(keys, val); - } - - if (Array.isArray(obj)) { - var arr = obj; - while (len--) { - if (arr.indexOf(val[len]) > -1) { - return true; - } - } - return false; - } - - throw new TypeError('expected an array or object.'); -}; - -/** - * Returns true if an array or object has all of the given values. - * - * ```js - * cu.hasAll(['a', 'b', 'c'], 'c'); - * //=> true - * - * cu.hasAll(['a', 'b', 'c'], ['c', 'z']); - * //=> false - * - * cu.hasAll({a: 'b', c: 'd'}, ['c', 'z']); - * //=> false - * ``` - * @param {Object|Array} `val` - * @param {String|Array} `values` - * @return {Boolean} - * @api public - */ - -cu.hasAll = function hasAll(val, values) { - values = cu.arrayify(values); - var len = values.length; - while (len--) { - if (!cu.has(val, values[len])) { - return false; - } - } - return true; -}; - -/** - * Cast the given value to an array. - * - * ```js - * cu.arrayify('foo'); - * //=> ['foo'] - * - * cu.arrayify(['foo']); - * //=> ['foo'] - * ``` - * - * @param {String|Array} `val` - * @return {Array} - * @api public - */ - -cu.arrayify = function arrayify(val) { - return val ? (Array.isArray(val) ? val : [val]) : []; -}; - -/** - * Noop - */ - -cu.noop = function noop() { - return; -}; - -/** - * Returns the first argument passed to the function. - */ - -cu.identity = function identity(val) { - return val; -}; - -/** - * Returns true if a value has a `contructor` - * - * ```js - * cu.hasConstructor({}); - * //=> true - * - * cu.hasConstructor(Object.create(null)); - * //=> false - * ``` - * @param {Object} `value` - * @return {Boolean} - * @api public - */ - -cu.hasConstructor = function hasConstructor(val) { - return cu.isObject(val) && typeof val.constructor !== 'undefined'; -}; - -/** - * Get the native `ownPropertyNames` from the constructor of the - * given `object`. An empty array is returned if the object does - * not have a constructor. - * - * ```js - * cu.nativeKeys({a: 'b', b: 'c', c: 'd'}) - * //=> ['a', 'b', 'c'] - * - * cu.nativeKeys(function(){}) - * //=> ['length', 'caller'] - * ``` - * - * @param {Object} `obj` Object that has a `constructor`. - * @return {Array} Array of keys. - * @api public - */ - -cu.nativeKeys = function nativeKeys(val) { - if (!cu.hasConstructor(val)) return []; - return Object.getOwnPropertyNames(val); -}; - -/** - * Returns property descriptor `key` if it's an "own" property - * of the given object. - * - * ```js - * function App() {} - * Object.defineProperty(App.prototype, 'count', { - * get: function() { - * return Object.keys(this).length; - * } - * }); - * cu.getDescriptor(App.prototype, 'count'); - * // returns: - * // { - * // get: [Function], - * // set: undefined, - * // enumerable: false, - * // configurable: false - * // } - * ``` - * - * @param {Object} `obj` - * @param {String} `key` - * @return {Object} Returns descriptor `key` - * @api public - */ - -cu.getDescriptor = function getDescriptor(obj, key) { - if (!cu.isObject(obj)) { - throw new TypeError('expected an object.'); - } - if (typeof key !== 'string') { - throw new TypeError('expected key to be a string.'); - } - return Object.getOwnPropertyDescriptor(obj, key); -}; - -/** - * Copy a descriptor from one object to another. - * - * ```js - * function App() {} - * Object.defineProperty(App.prototype, 'count', { - * get: function() { - * return Object.keys(this).length; - * } - * }); - * var obj = {}; - * cu.copyDescriptor(obj, App.prototype, 'count'); - * ``` - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String} `name` - * @return {Object} - * @api public - */ - -cu.copyDescriptor = function copyDescriptor(receiver, provider, name) { - if (!cu.isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!cu.isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - if (typeof name !== 'string') { - throw new TypeError('expected name to be a string.'); - } - - var val = cu.getDescriptor(provider, name); - if (val) Object.defineProperty(receiver, name, val); -}; - -/** - * Copy static properties, prototype properties, and descriptors - * from one object to another. - * - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String|Array} `omit` One or more properties to omit - * @return {Object} - * @api public - */ - -cu.copy = function copy(receiver, provider, omit) { - if (!cu.isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!cu.isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - var props = Object.getOwnPropertyNames(provider); - var keys = Object.keys(provider); - var len = props.length, - key; - omit = cu.arrayify(omit); - - while (len--) { - key = props[len]; - - if (cu.has(keys, key)) { - utils.define(receiver, key, provider[key]); - } else if (!(key in receiver) && !cu.has(omit, key)) { - cu.copyDescriptor(receiver, provider, key); - } - } -}; - -/** - * Inherit the static properties, prototype properties, and descriptors - * from of an object. - * - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String|Array} `omit` One or more properties to omit - * @return {Object} - * @api public - */ - -cu.inherit = function inherit(receiver, provider, omit) { - if (!cu.isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!cu.isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - - var keys = []; - for (var key in provider) { - keys.push(key); - receiver[key] = provider[key]; - } - - keys = keys.concat(cu.arrayify(omit)); - - var a = provider.prototype || provider; - var b = receiver.prototype || receiver; - cu.copy(b, a, keys); -}; - -/** - * Returns a function for extending the static properties, - * prototype properties, and descriptors from the `Parent` - * constructor onto `Child` constructors. - * - * ```js - * var extend = cu.extend(Parent); - * Parent.extend(Child); - * - * // optional methods - * Parent.extend(Child, { - * foo: function() {}, - * bar: function() {} - * }); - * ``` - * @param {Function} `Parent` Parent ctor - * @param {Function} `extend` Optional extend function to handle custom extensions. Useful when updating methods that require a specific prototype. - * @param {Function} `Child` Child ctor - * @param {Object} `proto` Optionally pass additional prototype properties to inherit. - * @return {Object} - * @api public - */ - -cu.extend = function() { - // keep it lazy, instead of assigning to `cu.extend` - return utils.staticExtend.apply(null, arguments); -}; - -/** - * Bubble up events emitted from static methods on the Parent ctor. - * - * @param {Object} `Parent` - * @param {Array} `events` Event names to bubble up - * @api public - */ - -cu.bubble = function(Parent, events) { - events = events || []; - Parent.bubble = function(Child, arr) { - if (Array.isArray(arr)) { - events = utils.union([], events, arr); - } - var len = events.length; - var idx = -1; - while (++idx < len) { - var name = events[idx]; - Parent.on(name, Child.emit.bind(Child, name)); - } - cu.bubble(Child, events); - }; -}; - - -/***/ }), -/* 794 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var utils = {}; - - - -/** - * Lazily required module dependencies - */ - -utils.union = __webpack_require__(778); -utils.define = __webpack_require__(730); -utils.isObj = __webpack_require__(748); -utils.staticExtend = __webpack_require__(795); - - -/** - * Expose `utils` - */ - -module.exports = utils; - - -/***/ }), -/* 795 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * static-extend - * - * Copyright (c) 2016, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var copy = __webpack_require__(796); -var define = __webpack_require__(730); -var util = __webpack_require__(29); - -/** - * Returns a function for extending the static properties, - * prototype properties, and descriptors from the `Parent` - * constructor onto `Child` constructors. - * - * ```js - * var extend = require('static-extend'); - * Parent.extend = extend(Parent); - * - * // optionally pass a custom merge function as the second arg - * Parent.extend = extend(Parent, function(Child) { - * Child.prototype.mixin = function(key, val) { - * Child.prototype[key] = val; - * }; - * }); - * - * // extend "child" constructors - * Parent.extend(Child); - * - * // optionally define prototype methods as the second arg - * Parent.extend(Child, { - * foo: function() {}, - * bar: function() {} - * }); - * ``` - * @param {Function} `Parent` Parent ctor - * @param {Function} `extendFn` Optional extend function for handling any necessary custom merging. Useful when updating methods that require a specific prototype. - * @param {Function} `Child` Child ctor - * @param {Object} `proto` Optionally pass additional prototype properties to inherit. - * @return {Object} - * @api public - */ - -function extend(Parent, extendFn) { - if (typeof Parent !== 'function') { - throw new TypeError('expected Parent to be a function.'); - } - - return function(Ctor, proto) { - if (typeof Ctor !== 'function') { - throw new TypeError('expected Ctor to be a function.'); - } - - util.inherits(Ctor, Parent); - copy(Ctor, Parent); - - // proto can be null or a plain object - if (typeof proto === 'object') { - var obj = Object.create(proto); - - for (var k in obj) { - Ctor.prototype[k] = obj[k]; - } - } - - // keep a reference to the parent prototype - define(Ctor.prototype, '_parent_', { - configurable: true, - set: function() {}, - get: function() { - return Parent.prototype; - } - }); - - if (typeof extendFn === 'function') { - extendFn(Ctor, Parent); - } - - Ctor.extend = extend(Ctor, extendFn); - }; -}; - -/** - * Expose `extend` - */ - -module.exports = extend; - - -/***/ }), -/* 796 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var typeOf = __webpack_require__(753); -var copyDescriptor = __webpack_require__(797); -var define = __webpack_require__(730); - -/** - * Copy static properties, prototype properties, and descriptors from one object to another. - * - * ```js - * function App() {} - * var proto = App.prototype; - * App.prototype.set = function() {}; - * App.prototype.get = function() {}; - * - * var obj = {}; - * copy(obj, proto); - * ``` - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String|Array} `omit` One or more properties to omit - * @return {Object} - * @api public - */ - -function copy(receiver, provider, omit) { - if (!isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - - var props = nativeKeys(provider); - var keys = Object.keys(provider); - var len = props.length; - omit = arrayify(omit); - - while (len--) { - var key = props[len]; - - if (has(keys, key)) { - define(receiver, key, provider[key]); - } else if (!(key in receiver) && !has(omit, key)) { - copyDescriptor(receiver, provider, key); - } - } -}; - -/** - * Return true if the given value is an object or function - */ - -function isObject(val) { - return typeOf(val) === 'object' || typeof val === 'function'; -} - -/** - * Returns true if an array has any of the given elements, or an - * object has any of the give keys. - * - * ```js - * has(['a', 'b', 'c'], 'c'); - * //=> true - * - * has(['a', 'b', 'c'], ['c', 'z']); - * //=> true - * - * has({a: 'b', c: 'd'}, ['c', 'z']); - * //=> true - * ``` - * @param {Object} `obj` - * @param {String|Array} `val` - * @return {Boolean} - */ - -function has(obj, val) { - val = arrayify(val); - var len = val.length; - - if (isObject(obj)) { - for (var key in obj) { - if (val.indexOf(key) > -1) { - return true; - } - } - - var keys = nativeKeys(obj); - return has(keys, val); - } - - if (Array.isArray(obj)) { - var arr = obj; - while (len--) { - if (arr.indexOf(val[len]) > -1) { - return true; - } - } - return false; - } - - throw new TypeError('expected an array or object.'); -} - -/** - * Cast the given value to an array. - * - * ```js - * arrayify('foo'); - * //=> ['foo'] - * - * arrayify(['foo']); - * //=> ['foo'] - * ``` - * - * @param {String|Array} `val` - * @return {Array} - */ - -function arrayify(val) { - return val ? (Array.isArray(val) ? val : [val]) : []; -} - -/** - * Returns true if a value has a `contructor` - * - * ```js - * hasConstructor({}); - * //=> true - * - * hasConstructor(Object.create(null)); - * //=> false - * ``` - * @param {Object} `value` - * @return {Boolean} - */ - -function hasConstructor(val) { - return isObject(val) && typeof val.constructor !== 'undefined'; -} - -/** - * Get the native `ownPropertyNames` from the constructor of the - * given `object`. An empty array is returned if the object does - * not have a constructor. - * - * ```js - * nativeKeys({a: 'b', b: 'c', c: 'd'}) - * //=> ['a', 'b', 'c'] - * - * nativeKeys(function(){}) - * //=> ['length', 'caller'] - * ``` - * - * @param {Object} `obj` Object that has a `constructor`. - * @return {Array} Array of keys. - */ - -function nativeKeys(val) { - if (!hasConstructor(val)) return []; - return Object.getOwnPropertyNames(val); -} - -/** - * Expose `copy` - */ - -module.exports = copy; - -/** - * Expose `copy.has` for tests - */ - -module.exports.has = has; - - -/***/ }), -/* 797 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * copy-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -/** - * Copy a descriptor from one object to another. - * - * ```js - * function App() { - * this.cache = {}; - * } - * App.prototype.set = function(key, val) { - * this.cache[key] = val; - * return this; - * }; - * Object.defineProperty(App.prototype, 'count', { - * get: function() { - * return Object.keys(this.cache).length; - * } - * }); - * - * copy(App.prototype, 'count', 'len'); - * - * // create an instance - * var app = new App(); - * - * app.set('a', true); - * app.set('b', true); - * app.set('c', true); - * - * console.log(app.count); - * //=> 3 - * console.log(app.len); - * //=> 3 - * ``` - * @name copy - * @param {Object} `receiver` The target object - * @param {Object} `provider` The provider object - * @param {String} `from` The key to copy on provider. - * @param {String} `to` Optionally specify a new key name to use. - * @return {Object} - * @api public - */ - -module.exports = function copyDescriptor(receiver, provider, from, to) { - if (!isObject(provider) && typeof provider !== 'function') { - to = from; - from = provider; - provider = receiver; - } - if (!isObject(receiver) && typeof receiver !== 'function') { - throw new TypeError('expected the first argument to be an object'); - } - if (!isObject(provider) && typeof provider !== 'function') { - throw new TypeError('expected provider to be an object'); - } - - if (typeof to !== 'string') { - to = from; - } - if (typeof from !== 'string') { - throw new TypeError('expected key to be a string'); - } - - if (!(from in provider)) { - throw new Error('property "' + from + '" does not exist'); - } - - var val = Object.getOwnPropertyDescriptor(provider, from); - if (val) Object.defineProperty(receiver, to, val); -}; - -function isObject(val) { - return {}.toString.call(val) === '[object Object]'; -} - - - -/***/ }), -/* 798 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var use = __webpack_require__(799); -var define = __webpack_require__(730); -var debug = __webpack_require__(801)('snapdragon:compiler'); -var utils = __webpack_require__(807); - -/** - * Create a new `Compiler` with the given `options`. - * @param {Object} `options` - */ - -function Compiler(options, state) { - debug('initializing', __filename); - this.options = utils.extend({source: 'string'}, options); - this.state = state || {}; - this.compilers = {}; - this.output = ''; - this.set('eos', function(node) { - return this.emit(node.val, node); - }); - this.set('noop', function(node) { - return this.emit(node.val, node); - }); - this.set('bos', function(node) { - return this.emit(node.val, node); - }); - use(this); -} - -/** - * Prototype methods - */ - -Compiler.prototype = { - - /** - * Throw an error message with details including the cursor position. - * @param {String} `msg` Message to use in the Error. - */ - - error: function(msg, node) { - var pos = node.position || {start: {column: 0}}; - var message = this.options.source + ' column:' + pos.start.column + ': ' + msg; - - var err = new Error(message); - err.reason = msg; - err.column = pos.start.column; - err.source = this.pattern; - - if (this.options.silent) { - this.errors.push(err); - } else { - throw err; - } - }, - - /** - * Define a non-enumberable property on the `Compiler` instance. - * - * ```js - * compiler.define('foo', 'bar'); - * ``` - * @name .define - * @param {String} `key` propery name - * @param {any} `val` property value - * @return {Object} Returns the Compiler instance for chaining. - * @api public - */ - - define: function(key, val) { - define(this, key, val); - return this; - }, - - /** - * Emit `node.val` - */ - - emit: function(str, node) { - this.output += str; - return str; - }, - - /** - * Add a compiler `fn` with the given `name` - */ - - set: function(name, fn) { - this.compilers[name] = fn; - return this; - }, - - /** - * Get compiler `name`. - */ - - get: function(name) { - return this.compilers[name]; - }, - - /** - * Get the previous AST node. - */ - - prev: function(n) { - return this.ast.nodes[this.idx - (n || 1)] || { type: 'bos', val: '' }; - }, - - /** - * Get the next AST node. - */ - - next: function(n) { - return this.ast.nodes[this.idx + (n || 1)] || { type: 'eos', val: '' }; - }, - - /** - * Visit `node`. - */ - - visit: function(node, nodes, i) { - var fn = this.compilers[node.type]; - this.idx = i; - - if (typeof fn !== 'function') { - throw this.error('compiler "' + node.type + '" is not registered', node); - } - return fn.call(this, node, nodes, i); - }, - - /** - * Map visit over array of `nodes`. - */ - - mapVisit: function(nodes) { - if (!Array.isArray(nodes)) { - throw new TypeError('expected an array'); - } - var len = nodes.length; - var idx = -1; - while (++idx < len) { - this.visit(nodes[idx], nodes, idx); - } - return this; - }, - - /** - * Compile `ast`. - */ - - compile: function(ast, options) { - var opts = utils.extend({}, this.options, options); - this.ast = ast; - this.parsingErrors = this.ast.errors; - this.output = ''; - - // source map support - if (opts.sourcemap) { - var sourcemaps = __webpack_require__(826); - sourcemaps(this); - this.mapVisit(this.ast.nodes); - this.applySourceMaps(); - this.map = opts.sourcemap === 'generator' ? this.map : this.map.toJSON(); - return this; - } - - this.mapVisit(this.ast.nodes); - return this; - } -}; - -/** - * Expose `Compiler` - */ - -module.exports = Compiler; - - -/***/ }), -/* 799 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * use - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var utils = __webpack_require__(800); - -module.exports = function base(app, opts) { - if (!utils.isObject(app) && typeof app !== 'function') { - throw new TypeError('use: expect `app` be an object or function'); - } - - if (!utils.isObject(opts)) { - opts = {}; - } - - var prop = utils.isString(opts.prop) ? opts.prop : 'fns'; - if (!Array.isArray(app[prop])) { - utils.define(app, prop, []); - } - - /** - * Define a plugin function to be passed to use. The only - * parameter exposed to the plugin is `app`, the object or function. - * passed to `use(app)`. `app` is also exposed as `this` in plugins. - * - * Additionally, **if a plugin returns a function, the function will - * be pushed onto the `fns` array**, allowing the plugin to be - * called at a later point by the `run` method. - * - * ```js - * var use = require('use'); - * - * // define a plugin - * function foo(app) { - * // do stuff - * } - * - * var app = function(){}; - * use(app); - * - * // register plugins - * app.use(foo); - * app.use(bar); - * app.use(baz); - * ``` - * @name .use - * @param {Function} `fn` plugin function to call - * @api public - */ - - utils.define(app, 'use', use); - - /** - * Run all plugins on `fns`. Any plugin that returns a function - * when called by `use` is pushed onto the `fns` array. - * - * ```js - * var config = {}; - * app.run(config); - * ``` - * @name .run - * @param {Object} `value` Object to be modified by plugins. - * @return {Object} Returns the object passed to `run` - * @api public - */ - - utils.define(app, 'run', function(val) { - if (!utils.isObject(val)) return; - decorate(val); - - var self = this || app; - var fns = self[prop]; - var len = fns.length; - var idx = -1; - - while (++idx < len) { - val.use(fns[idx]); - } - return val; - }); - - /** - * Call plugin `fn`. If a function is returned push it into the - * `fns` array to be called by the `run` method. - */ - - function use(fn, options) { - if (typeof fn !== 'function') { - throw new TypeError('.use expects `fn` be a function'); - } - - var self = this || app; - if (typeof opts.fn === 'function') { - opts.fn.call(self, self, options); - } - - var plugin = fn.call(self, self); - if (typeof plugin === 'function') { - var fns = self[prop]; - fns.push(plugin); - } - return self; - } - - /** - * Ensure the `.use` method exists on `val` - */ - - function decorate(val) { - if (!val.use || !val.run) { - base(val); - } - } - - return app; -}; - - -/***/ }), -/* 800 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var utils = {}; - - - -/** - * Lazily required module dependencies - */ - -utils.define = __webpack_require__(730); -utils.isObject = __webpack_require__(748); - - -utils.isString = function(val) { - return val && typeof val === 'string'; -}; - -/** - * Expose `utils` modules - */ - -module.exports = utils; - - -/***/ }), -/* 801 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Detect Electron renderer process, which is node, but we should - * treat as a browser. - */ - -if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(802); -} else { - module.exports = __webpack_require__(805); -} - - -/***/ }), -/* 802 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = __webpack_require__(803); -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); - -/** - * Colors. - */ - -exports.colors = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' -]; - -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ - -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { - return true; - } - - // is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -exports.formatters.j = function(v) { - try { - return JSON.stringify(v); - } catch (err) { - return '[UnexpectedJSONParseError]: ' + err.message; - } -}; - - -/** - * Colorize log arguments if enabled. - * - * @api public - */ - -function formatArgs(args) { - var useColors = this.useColors; - - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - - if (!useColors) return; - - var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit') - - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, function(match) { - if ('%%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - - args.splice(lastC, 0, c); -} - -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ - -function log() { - // this hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); -} - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - -function save(namespaces) { - try { - if (null == namespaces) { - exports.storage.removeItem('debug'); - } else { - exports.storage.debug = namespaces; - } - } catch(e) {} -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - -function load() { - var r; - try { - r = exports.storage.debug; - } catch(e) {} - - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; - } - - return r; -} - -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ - -exports.enable(load()); - -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ - -function localstorage() { - try { - return window.localStorage; - } catch (e) {} -} - - -/***/ }), -/* 803 */ -/***/ (function(module, exports, __webpack_require__) { - - -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = __webpack_require__(804); - -/** - * The currently active debug mode names, and names to skip. - */ - -exports.names = []; -exports.skips = []; - -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - -exports.formatters = {}; - -/** - * Previous log timestamp. - */ - -var prevTime; - -/** - * Select a color. - * @param {String} namespace - * @return {Number} - * @api private - */ - -function selectColor(namespace) { - var hash = 0, i; - - for (i in namespace) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer - } - - return exports.colors[Math.abs(hash) % exports.colors.length]; -} - -/** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - -function createDebug(namespace) { - - function debug() { - // disabled? - if (!debug.enabled) return; - - var self = debug; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // turn the `arguments` into a proper Array - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } - - args[0] = exports.coerce(args[0]); - - if ('string' !== typeof args[0]) { - // anything else let's inspect with %O - args.unshift('%O'); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); - - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - // apply env-specific formatting (colors, etc.) - exports.formatArgs.call(self, args); - - var logFn = debug.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - - debug.namespace = namespace; - debug.enabled = exports.enabled(namespace); - debug.useColors = exports.useColors(); - debug.color = selectColor(namespace); - - // env-specific initialization logic for debug instances - if ('function' === typeof exports.init) { - exports.init(debug); - } - - return debug; -} - -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - -function enable(namespaces) { - exports.save(namespaces); - - exports.names = []; - exports.skips = []; - - var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - var len = split.length; - - for (var i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } -} - -/** - * Disable debug output. - * - * @api public - */ - -function disable() { - exports.enable(''); -} - -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - -function enabled(name) { - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; -} - -/** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} - - -/***/ }), -/* 804 */ -/***/ (function(module, exports) { - -/** - * Helpers. - */ - -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; -var y = d * 365.25; - -/** - * Parse or format the given `val`. - * - * Options: - * - * - `long` verbose formatting [false] - * - * @param {String|Number} val - * @param {Object} [options] - * @throws {Error} throw an error if val is not a non-empty string or a number - * @return {String|Number} - * @api public - */ - -module.exports = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse(val); - } else if (type === 'number' && isNaN(val) === false) { - return options.long ? fmtLong(val) : fmtShort(val); - } - throw new Error( - 'val is not a non-empty string or a valid number. val=' + - JSON.stringify(val) - ); -}; - -/** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ - -function parse(str) { - str = String(str); - if (str.length > 100) { - return; - } - var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( - str - ); - if (!match) { - return; - } - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'yrs': - case 'yr': - case 'y': - return n * y; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'hrs': - case 'hr': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'mins': - case 'min': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 'secs': - case 'sec': - case 's': - return n * s; - case 'milliseconds': - case 'millisecond': - case 'msecs': - case 'msec': - case 'ms': - return n; - default: - return undefined; - } -} - -/** - * Short format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtShort(ms) { - if (ms >= d) { - return Math.round(ms / d) + 'd'; - } - if (ms >= h) { - return Math.round(ms / h) + 'h'; - } - if (ms >= m) { - return Math.round(ms / m) + 'm'; - } - if (ms >= s) { - return Math.round(ms / s) + 's'; - } - return ms + 'ms'; -} - -/** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtLong(ms) { - return plural(ms, d, 'day') || - plural(ms, h, 'hour') || - plural(ms, m, 'minute') || - plural(ms, s, 'second') || - ms + ' ms'; -} - -/** - * Pluralization helper. - */ - -function plural(ms, n, name) { - if (ms < n) { - return; - } - if (ms < n * 1.5) { - return Math.floor(ms / n) + ' ' + name; - } - return Math.ceil(ms / n) + ' ' + name + 's'; -} - - -/***/ }), -/* 805 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Module dependencies. - */ - -var tty = __webpack_require__(480); -var util = __webpack_require__(29); - -/** - * This is the Node.js implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = __webpack_require__(803); -exports.init = init; -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; - -/** - * Colors. - */ - -exports.colors = [6, 2, 3, 4, 5, 1]; - -/** - * Build up the default `inspectOpts` object from the environment variables. - * - * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js - */ - -exports.inspectOpts = Object.keys(process.env).filter(function (key) { - return /^debug_/i.test(key); -}).reduce(function (obj, key) { - // camel-case - var prop = key - .substring(6) - .toLowerCase() - .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); - - // coerce string value into JS value - var val = process.env[key]; - if (/^(yes|on|true|enabled)$/i.test(val)) val = true; - else if (/^(no|off|false|disabled)$/i.test(val)) val = false; - else if (val === 'null') val = null; - else val = Number(val); - - obj[prop] = val; - return obj; -}, {}); - -/** - * The file descriptor to write the `debug()` calls to. - * Set the `DEBUG_FD` env variable to override with another value. i.e.: - * - * $ DEBUG_FD=3 node script.js 3>debug.log - */ - -var fd = parseInt(process.env.DEBUG_FD, 10) || 2; - -if (1 !== fd && 2 !== fd) { - util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')() -} - -var stream = 1 === fd ? process.stdout : - 2 === fd ? process.stderr : - createWritableStdioStream(fd); - -/** - * Is stdout a TTY? Colored output is enabled when `true`. - */ - -function useColors() { - return 'colors' in exports.inspectOpts - ? Boolean(exports.inspectOpts.colors) - : tty.isatty(fd); -} - -/** - * Map %o to `util.inspect()`, all on a single line. - */ - -exports.formatters.o = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts) - .split('\n').map(function(str) { - return str.trim() - }).join(' '); -}; - -/** - * Map %o to `util.inspect()`, allowing multiple lines if needed. - */ - -exports.formatters.O = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts); -}; - -/** - * Adds ANSI color escape codes if enabled. - * - * @api public - */ - -function formatArgs(args) { - var name = this.namespace; - var useColors = this.useColors; - - if (useColors) { - var c = this.color; - var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m'; - - args[0] = prefix + args[0].split('\n').join('\n' + prefix); - args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); - } else { - args[0] = new Date().toUTCString() - + ' ' + name + ' ' + args[0]; - } -} - -/** - * Invokes `util.format()` with the specified arguments and writes to `stream`. - */ - -function log() { - return stream.write(util.format.apply(util, arguments) + '\n'); -} - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - -function save(namespaces) { - if (null == namespaces) { - // If you set a process.env field to null or undefined, it gets cast to the - // string 'null' or 'undefined'. Just delete instead. - delete process.env.DEBUG; - } else { - process.env.DEBUG = namespaces; - } -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - -function load() { - return process.env.DEBUG; -} - -/** - * Copied from `node/src/node.js`. - * - * XXX: It's lame that node doesn't expose this API out-of-the-box. It also - * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. - */ - -function createWritableStdioStream (fd) { - var stream; - var tty_wrap = process.binding('tty_wrap'); - - // Note stream._type is used for test-module-load-list.js - - switch (tty_wrap.guessHandleType(fd)) { - case 'TTY': - stream = new tty.WriteStream(fd); - stream._type = 'tty'; - - // Hack to have stream not keep the event loop alive. - // See https://github.com/joyent/node/issues/1726 - if (stream._handle && stream._handle.unref) { - stream._handle.unref(); - } - break; - - case 'FILE': - var fs = __webpack_require__(23); - stream = new fs.SyncWriteStream(fd, { autoClose: false }); - stream._type = 'fs'; - break; - - case 'PIPE': - case 'TCP': - var net = __webpack_require__(806); - stream = new net.Socket({ - fd: fd, - readable: false, - writable: true - }); - - // FIXME Should probably have an option in net.Socket to create a - // stream from an existing fd which is writable only. But for now - // we'll just add this hack and set the `readable` member to false. - // Test: ./node test/fixtures/echo.js < /etc/passwd - stream.readable = false; - stream.read = null; - stream._type = 'pipe'; - - // FIXME Hack to have stream not keep the event loop alive. - // See https://github.com/joyent/node/issues/1726 - if (stream._handle && stream._handle.unref) { - stream._handle.unref(); - } - break; - - default: - // Probably an error on in uv_guess_handle() - throw new Error('Implement me. Unknown stream file type!'); - } - - // For supporting legacy API we put the FD here. - stream.fd = fd; - - stream._isStdio = true; - - return stream; -} - -/** - * Init logic for `debug` instances. - * - * Create a new `inspectOpts` object in case `useColors` is set - * differently for a particular `debug` instance. - */ - -function init (debug) { - debug.inspectOpts = {}; - - var keys = Object.keys(exports.inspectOpts); - for (var i = 0; i < keys.length; i++) { - debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; - } -} - -/** - * Enable namespaces listed in `process.env.DEBUG` initially. - */ - -exports.enable(load()); - - -/***/ }), -/* 806 */ -/***/ (function(module, exports) { - -module.exports = require("net"); - -/***/ }), -/* 807 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Module dependencies - */ - -exports.extend = __webpack_require__(738); -exports.SourceMap = __webpack_require__(808); -exports.sourceMapResolve = __webpack_require__(819); - -/** - * Convert backslash in the given string to forward slashes - */ - -exports.unixify = function(fp) { - return fp.split(/\\+/).join('/'); -}; - -/** - * Return true if `val` is a non-empty string - * - * @param {String} `str` - * @return {Boolean} - */ - -exports.isString = function(str) { - return str && typeof str === 'string'; -}; - -/** - * Cast `val` to an array - * @return {Array} - */ - -exports.arrayify = function(val) { - if (typeof val === 'string') return [val]; - return val ? (Array.isArray(val) ? val : [val]) : []; -}; - -/** - * Get the last `n` element from the given `array` - * @param {Array} `array` - * @return {*} - */ - -exports.last = function(arr, n) { - return arr[arr.length - (n || 1)]; -}; - - -/***/ }), -/* 808 */ -/***/ (function(module, exports, __webpack_require__) { - -/* - * Copyright 2009-2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE.txt or: - * http://opensource.org/licenses/BSD-3-Clause - */ -exports.SourceMapGenerator = __webpack_require__(809).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(815).SourceMapConsumer; -exports.SourceNode = __webpack_require__(818).SourceNode; - - -/***/ }), -/* 809 */ -/***/ (function(module, exports, __webpack_require__) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ - -var base64VLQ = __webpack_require__(810); -var util = __webpack_require__(812); -var ArraySet = __webpack_require__(813).ArraySet; -var MappingList = __webpack_require__(814).MappingList; - -/** - * An instance of the SourceMapGenerator represents a source map which is - * being built incrementally. You may pass an object with the following - * properties: - * - * - file: The filename of the generated source. - * - sourceRoot: A root for all relative URLs in this source map. - */ -function SourceMapGenerator(aArgs) { - if (!aArgs) { - aArgs = {}; - } - this._file = util.getArg(aArgs, 'file', null); - this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); - this._skipValidation = util.getArg(aArgs, 'skipValidation', false); - this._sources = new ArraySet(); - this._names = new ArraySet(); - this._mappings = new MappingList(); - this._sourcesContents = null; -} - -SourceMapGenerator.prototype._version = 3; - -/** - * Creates a new SourceMapGenerator based on a SourceMapConsumer - * - * @param aSourceMapConsumer The SourceMap. - */ -SourceMapGenerator.fromSourceMap = - function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { - var sourceRoot = aSourceMapConsumer.sourceRoot; - var generator = new SourceMapGenerator({ - file: aSourceMapConsumer.file, - sourceRoot: sourceRoot - }); - aSourceMapConsumer.eachMapping(function (mapping) { - var newMapping = { - generated: { - line: mapping.generatedLine, - column: mapping.generatedColumn - } - }; - - if (mapping.source != null) { - newMapping.source = mapping.source; - if (sourceRoot != null) { - newMapping.source = util.relative(sourceRoot, newMapping.source); - } - - newMapping.original = { - line: mapping.originalLine, - column: mapping.originalColumn - }; - - if (mapping.name != null) { - newMapping.name = mapping.name; - } - } - - generator.addMapping(newMapping); - }); - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content != null) { - generator.setSourceContent(sourceFile, content); - } - }); - return generator; - }; - -/** - * Add a single mapping from original source line and column to the generated - * source's line and column for this source map being created. The mapping - * object should have the following properties: - * - * - generated: An object with the generated line and column positions. - * - original: An object with the original line and column positions. - * - source: The original source file (relative to the sourceRoot). - * - name: An optional original token name for this mapping. - */ -SourceMapGenerator.prototype.addMapping = - function SourceMapGenerator_addMapping(aArgs) { - var generated = util.getArg(aArgs, 'generated'); - var original = util.getArg(aArgs, 'original', null); - var source = util.getArg(aArgs, 'source', null); - var name = util.getArg(aArgs, 'name', null); - - if (!this._skipValidation) { - this._validateMapping(generated, original, source, name); - } - - if (source != null) { - source = String(source); - if (!this._sources.has(source)) { - this._sources.add(source); - } - } - - if (name != null) { - name = String(name); - if (!this._names.has(name)) { - this._names.add(name); - } - } - - this._mappings.add({ - generatedLine: generated.line, - generatedColumn: generated.column, - originalLine: original != null && original.line, - originalColumn: original != null && original.column, - source: source, - name: name - }); - }; - -/** - * Set the source content for a source file. - */ -SourceMapGenerator.prototype.setSourceContent = - function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { - var source = aSourceFile; - if (this._sourceRoot != null) { - source = util.relative(this._sourceRoot, source); - } - - if (aSourceContent != null) { - // Add the source content to the _sourcesContents map. - // Create a new _sourcesContents map if the property is null. - if (!this._sourcesContents) { - this._sourcesContents = Object.create(null); - } - this._sourcesContents[util.toSetString(source)] = aSourceContent; - } else if (this._sourcesContents) { - // Remove the source file from the _sourcesContents map. - // If the _sourcesContents map is empty, set the property to null. - delete this._sourcesContents[util.toSetString(source)]; - if (Object.keys(this._sourcesContents).length === 0) { - this._sourcesContents = null; - } - } - }; - -/** - * Applies the mappings of a sub-source-map for a specific source file to the - * source map being generated. Each mapping to the supplied source file is - * rewritten using the supplied source map. Note: The resolution for the - * resulting mappings is the minimium of this map and the supplied map. - * - * @param aSourceMapConsumer The source map to be applied. - * @param aSourceFile Optional. The filename of the source file. - * If omitted, SourceMapConsumer's file property will be used. - * @param aSourceMapPath Optional. The dirname of the path to the source map - * to be applied. If relative, it is relative to the SourceMapConsumer. - * This parameter is needed when the two source maps aren't in the same - * directory, and the source map to be applied contains relative source - * paths. If so, those relative source paths need to be rewritten - * relative to the SourceMapGenerator. - */ -SourceMapGenerator.prototype.applySourceMap = - function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { - var sourceFile = aSourceFile; - // If aSourceFile is omitted, we will use the file property of the SourceMap - if (aSourceFile == null) { - if (aSourceMapConsumer.file == null) { - throw new Error( - 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + - 'or the source map\'s "file" property. Both were omitted.' - ); - } - sourceFile = aSourceMapConsumer.file; - } - var sourceRoot = this._sourceRoot; - // Make "sourceFile" relative if an absolute Url is passed. - if (sourceRoot != null) { - sourceFile = util.relative(sourceRoot, sourceFile); - } - // Applying the SourceMap can add and remove items from the sources and - // the names array. - var newSources = new ArraySet(); - var newNames = new ArraySet(); - - // Find mappings for the "sourceFile" - this._mappings.unsortedForEach(function (mapping) { - if (mapping.source === sourceFile && mapping.originalLine != null) { - // Check if it can be mapped by the source map, then update the mapping. - var original = aSourceMapConsumer.originalPositionFor({ - line: mapping.originalLine, - column: mapping.originalColumn - }); - if (original.source != null) { - // Copy mapping - mapping.source = original.source; - if (aSourceMapPath != null) { - mapping.source = util.join(aSourceMapPath, mapping.source) - } - if (sourceRoot != null) { - mapping.source = util.relative(sourceRoot, mapping.source); - } - mapping.originalLine = original.line; - mapping.originalColumn = original.column; - if (original.name != null) { - mapping.name = original.name; - } - } - } - - var source = mapping.source; - if (source != null && !newSources.has(source)) { - newSources.add(source); - } - - var name = mapping.name; - if (name != null && !newNames.has(name)) { - newNames.add(name); - } - - }, this); - this._sources = newSources; - this._names = newNames; - - // Copy sourcesContents of applied map. - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content != null) { - if (aSourceMapPath != null) { - sourceFile = util.join(aSourceMapPath, sourceFile); - } - if (sourceRoot != null) { - sourceFile = util.relative(sourceRoot, sourceFile); - } - this.setSourceContent(sourceFile, content); - } - }, this); - }; - -/** - * A mapping can have one of the three levels of data: - * - * 1. Just the generated position. - * 2. The Generated position, original position, and original source. - * 3. Generated and original position, original source, as well as a name - * token. - * - * To maintain consistency, we validate that any new mapping being added falls - * in to one of these categories. - */ -SourceMapGenerator.prototype._validateMapping = - function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, - aName) { - // When aOriginal is truthy but has empty values for .line and .column, - // it is most likely a programmer error. In this case we throw a very - // specific error message to try to guide them the right way. - // For example: https://github.com/Polymer/polymer-bundler/pull/519 - if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') { - throw new Error( - 'original.line and original.column are not numbers -- you probably meant to omit ' + - 'the original mapping entirely and only map the generated position. If so, pass ' + - 'null for the original mapping instead of an object with empty or null values.' - ); - } - - if (aGenerated && 'line' in aGenerated && 'column' in aGenerated - && aGenerated.line > 0 && aGenerated.column >= 0 - && !aOriginal && !aSource && !aName) { - // Case 1. - return; - } - else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated - && aOriginal && 'line' in aOriginal && 'column' in aOriginal - && aGenerated.line > 0 && aGenerated.column >= 0 - && aOriginal.line > 0 && aOriginal.column >= 0 - && aSource) { - // Cases 2 and 3. - return; - } - else { - throw new Error('Invalid mapping: ' + JSON.stringify({ - generated: aGenerated, - source: aSource, - original: aOriginal, - name: aName - })); - } - }; - -/** - * Serialize the accumulated mappings in to the stream of base 64 VLQs - * specified by the source map format. - */ -SourceMapGenerator.prototype._serializeMappings = - function SourceMapGenerator_serializeMappings() { - var previousGeneratedColumn = 0; - var previousGeneratedLine = 1; - var previousOriginalColumn = 0; - var previousOriginalLine = 0; - var previousName = 0; - var previousSource = 0; - var result = ''; - var next; - var mapping; - var nameIdx; - var sourceIdx; - - var mappings = this._mappings.toArray(); - for (var i = 0, len = mappings.length; i < len; i++) { - mapping = mappings[i]; - next = '' - - if (mapping.generatedLine !== previousGeneratedLine) { - previousGeneratedColumn = 0; - while (mapping.generatedLine !== previousGeneratedLine) { - next += ';'; - previousGeneratedLine++; - } - } - else { - if (i > 0) { - if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { - continue; - } - next += ','; - } - } - - next += base64VLQ.encode(mapping.generatedColumn - - previousGeneratedColumn); - previousGeneratedColumn = mapping.generatedColumn; - - if (mapping.source != null) { - sourceIdx = this._sources.indexOf(mapping.source); - next += base64VLQ.encode(sourceIdx - previousSource); - previousSource = sourceIdx; - - // lines are stored 0-based in SourceMap spec version 3 - next += base64VLQ.encode(mapping.originalLine - 1 - - previousOriginalLine); - previousOriginalLine = mapping.originalLine - 1; - - next += base64VLQ.encode(mapping.originalColumn - - previousOriginalColumn); - previousOriginalColumn = mapping.originalColumn; - - if (mapping.name != null) { - nameIdx = this._names.indexOf(mapping.name); - next += base64VLQ.encode(nameIdx - previousName); - previousName = nameIdx; - } - } - - result += next; - } - - return result; - }; - -SourceMapGenerator.prototype._generateSourcesContent = - function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { - return aSources.map(function (source) { - if (!this._sourcesContents) { - return null; - } - if (aSourceRoot != null) { - source = util.relative(aSourceRoot, source); - } - var key = util.toSetString(source); - return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) - ? this._sourcesContents[key] - : null; - }, this); - }; - -/** - * Externalize the source map. - */ -SourceMapGenerator.prototype.toJSON = - function SourceMapGenerator_toJSON() { - var map = { - version: this._version, - sources: this._sources.toArray(), - names: this._names.toArray(), - mappings: this._serializeMappings() - }; - if (this._file != null) { - map.file = this._file; - } - if (this._sourceRoot != null) { - map.sourceRoot = this._sourceRoot; - } - if (this._sourcesContents) { - map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); - } - - return map; - }; - -/** - * Render the source map being generated to a string. - */ -SourceMapGenerator.prototype.toString = - function SourceMapGenerator_toString() { - return JSON.stringify(this.toJSON()); - }; - -exports.SourceMapGenerator = SourceMapGenerator; - - -/***/ }), -/* 810 */ -/***/ (function(module, exports, __webpack_require__) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - * - * Based on the Base 64 VLQ implementation in Closure Compiler: - * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java - * - * Copyright 2011 The Closure Compiler Authors. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -var base64 = __webpack_require__(811); - -// A single base 64 digit can contain 6 bits of data. For the base 64 variable -// length quantities we use in the source map spec, the first bit is the sign, -// the next four bits are the actual value, and the 6th bit is the -// continuation bit. The continuation bit tells us whether there are more -// digits in this value following this digit. -// -// Continuation -// | Sign -// | | -// V V -// 101011 - -var VLQ_BASE_SHIFT = 5; - -// binary: 100000 -var VLQ_BASE = 1 << VLQ_BASE_SHIFT; - -// binary: 011111 -var VLQ_BASE_MASK = VLQ_BASE - 1; - -// binary: 100000 -var VLQ_CONTINUATION_BIT = VLQ_BASE; - -/** - * Converts from a two-complement value to a value where the sign bit is - * placed in the least significant bit. For example, as decimals: - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) - */ -function toVLQSigned(aValue) { - return aValue < 0 - ? ((-aValue) << 1) + 1 - : (aValue << 1) + 0; -} - -/** - * Converts to a two-complement value from a value where the sign bit is - * placed in the least significant bit. For example, as decimals: - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 - */ -function fromVLQSigned(aValue) { - var isNegative = (aValue & 1) === 1; - var shifted = aValue >> 1; - return isNegative - ? -shifted - : shifted; -} - -/** - * Returns the base 64 VLQ encoded value. - */ -exports.encode = function base64VLQ_encode(aValue) { - var encoded = ""; - var digit; - - var vlq = toVLQSigned(aValue); - - do { - digit = vlq & VLQ_BASE_MASK; - vlq >>>= VLQ_BASE_SHIFT; - if (vlq > 0) { - // There are still more digits in this value, so we must make sure the - // continuation bit is marked. - digit |= VLQ_CONTINUATION_BIT; - } - encoded += base64.encode(digit); - } while (vlq > 0); - - return encoded; -}; - -/** - * Decodes the next base 64 VLQ value from the given string and returns the - * value and the rest of the string via the out parameter. - */ -exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { - var strLen = aStr.length; - var result = 0; - var shift = 0; - var continuation, digit; - - do { - if (aIndex >= strLen) { - throw new Error("Expected more digits in base 64 VLQ value."); - } - - digit = base64.decode(aStr.charCodeAt(aIndex++)); - if (digit === -1) { - throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); - } - - continuation = !!(digit & VLQ_CONTINUATION_BIT); - digit &= VLQ_BASE_MASK; - result = result + (digit << shift); - shift += VLQ_BASE_SHIFT; - } while (continuation); - - aOutParam.value = fromVLQSigned(result); - aOutParam.rest = aIndex; -}; - - -/***/ }), -/* 811 */ -/***/ (function(module, exports) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ - -var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); - -/** - * Encode an integer in the range of 0 to 63 to a single base 64 digit. - */ -exports.encode = function (number) { - if (0 <= number && number < intToCharMap.length) { - return intToCharMap[number]; - } - throw new TypeError("Must be between 0 and 63: " + number); -}; - -/** - * Decode a single base 64 character code digit to an integer. Returns -1 on - * failure. - */ -exports.decode = function (charCode) { - var bigA = 65; // 'A' - var bigZ = 90; // 'Z' - - var littleA = 97; // 'a' - var littleZ = 122; // 'z' - - var zero = 48; // '0' - var nine = 57; // '9' - - var plus = 43; // '+' - var slash = 47; // '/' - - var littleOffset = 26; - var numberOffset = 52; - - // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ - if (bigA <= charCode && charCode <= bigZ) { - return (charCode - bigA); - } - - // 26 - 51: abcdefghijklmnopqrstuvwxyz - if (littleA <= charCode && charCode <= littleZ) { - return (charCode - littleA + littleOffset); - } - - // 52 - 61: 0123456789 - if (zero <= charCode && charCode <= nine) { - return (charCode - zero + numberOffset); - } - - // 62: + - if (charCode == plus) { - return 62; - } - - // 63: / - if (charCode == slash) { - return 63; - } - - // Invalid base64 digit. - return -1; -}; - - -/***/ }), -/* 812 */ -/***/ (function(module, exports) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ - -/** - * This is a helper function for getting values from parameter/options - * objects. - * - * @param args The object we are extracting values from - * @param name The name of the property we are getting. - * @param defaultValue An optional value to return if the property is missing - * from the object. If this is not specified and the property is missing, an - * error will be thrown. - */ -function getArg(aArgs, aName, aDefaultValue) { - if (aName in aArgs) { - return aArgs[aName]; - } else if (arguments.length === 3) { - return aDefaultValue; - } else { - throw new Error('"' + aName + '" is a required argument.'); - } -} -exports.getArg = getArg; - -var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; -var dataUrlRegexp = /^data:.+\,.+$/; - -function urlParse(aUrl) { - var match = aUrl.match(urlRegexp); - if (!match) { - return null; - } - return { - scheme: match[1], - auth: match[2], - host: match[3], - port: match[4], - path: match[5] - }; -} -exports.urlParse = urlParse; - -function urlGenerate(aParsedUrl) { - var url = ''; - if (aParsedUrl.scheme) { - url += aParsedUrl.scheme + ':'; - } - url += '//'; - if (aParsedUrl.auth) { - url += aParsedUrl.auth + '@'; - } - if (aParsedUrl.host) { - url += aParsedUrl.host; - } - if (aParsedUrl.port) { - url += ":" + aParsedUrl.port - } - if (aParsedUrl.path) { - url += aParsedUrl.path; - } - return url; -} -exports.urlGenerate = urlGenerate; - -/** - * Normalizes a path, or the path portion of a URL: - * - * - Replaces consecutive slashes with one slash. - * - Removes unnecessary '.' parts. - * - Removes unnecessary '/..' parts. - * - * Based on code in the Node.js 'path' core module. - * - * @param aPath The path or url to normalize. - */ -function normalize(aPath) { - var path = aPath; - var url = urlParse(aPath); - if (url) { - if (!url.path) { - return aPath; - } - path = url.path; - } - var isAbsolute = exports.isAbsolute(path); - - var parts = path.split(/\/+/); - for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { - part = parts[i]; - if (part === '.') { - parts.splice(i, 1); - } else if (part === '..') { - up++; - } else if (up > 0) { - if (part === '') { - // The first part is blank if the path is absolute. Trying to go - // above the root is a no-op. Therefore we can remove all '..' parts - // directly after the root. - parts.splice(i + 1, up); - up = 0; - } else { - parts.splice(i, 2); - up--; - } - } - } - path = parts.join('/'); - - if (path === '') { - path = isAbsolute ? '/' : '.'; - } - - if (url) { - url.path = path; - return urlGenerate(url); - } - return path; -} -exports.normalize = normalize; - -/** - * Joins two paths/URLs. - * - * @param aRoot The root path or URL. - * @param aPath The path or URL to be joined with the root. - * - * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a - * scheme-relative URL: Then the scheme of aRoot, if any, is prepended - * first. - * - Otherwise aPath is a path. If aRoot is a URL, then its path portion - * is updated with the result and aRoot is returned. Otherwise the result - * is returned. - * - If aPath is absolute, the result is aPath. - * - Otherwise the two paths are joined with a slash. - * - Joining for example 'http://' and 'www.example.com' is also supported. - */ -function join(aRoot, aPath) { - if (aRoot === "") { - aRoot = "."; - } - if (aPath === "") { - aPath = "."; - } - var aPathUrl = urlParse(aPath); - var aRootUrl = urlParse(aRoot); - if (aRootUrl) { - aRoot = aRootUrl.path || '/'; - } - - // `join(foo, '//www.example.org')` - if (aPathUrl && !aPathUrl.scheme) { - if (aRootUrl) { - aPathUrl.scheme = aRootUrl.scheme; - } - return urlGenerate(aPathUrl); - } - - if (aPathUrl || aPath.match(dataUrlRegexp)) { - return aPath; - } - - // `join('http://', 'www.example.com')` - if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { - aRootUrl.host = aPath; - return urlGenerate(aRootUrl); - } - - var joined = aPath.charAt(0) === '/' - ? aPath - : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); - - if (aRootUrl) { - aRootUrl.path = joined; - return urlGenerate(aRootUrl); - } - return joined; -} -exports.join = join; - -exports.isAbsolute = function (aPath) { - return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); -}; - -/** - * Make a path relative to a URL or another path. - * - * @param aRoot The root path or URL. - * @param aPath The path or URL to be made relative to aRoot. - */ -function relative(aRoot, aPath) { - if (aRoot === "") { - aRoot = "."; - } - - aRoot = aRoot.replace(/\/$/, ''); - - // It is possible for the path to be above the root. In this case, simply - // checking whether the root is a prefix of the path won't work. Instead, we - // need to remove components from the root one by one, until either we find - // a prefix that fits, or we run out of components to remove. - var level = 0; - while (aPath.indexOf(aRoot + '/') !== 0) { - var index = aRoot.lastIndexOf("/"); - if (index < 0) { - return aPath; - } - - // If the only part of the root that is left is the scheme (i.e. http://, - // file:///, etc.), one or more slashes (/), or simply nothing at all, we - // have exhausted all components, so the path is not relative to the root. - aRoot = aRoot.slice(0, index); - if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { - return aPath; - } - - ++level; - } - - // Make sure we add a "../" for each component we removed from the root. - return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); -} -exports.relative = relative; - -var supportsNullProto = (function () { - var obj = Object.create(null); - return !('__proto__' in obj); -}()); - -function identity (s) { - return s; -} - -/** - * Because behavior goes wacky when you set `__proto__` on objects, we - * have to prefix all the strings in our set with an arbitrary character. - * - * See https://github.com/mozilla/source-map/pull/31 and - * https://github.com/mozilla/source-map/issues/30 - * - * @param String aStr - */ -function toSetString(aStr) { - if (isProtoString(aStr)) { - return '$' + aStr; - } - - return aStr; -} -exports.toSetString = supportsNullProto ? identity : toSetString; - -function fromSetString(aStr) { - if (isProtoString(aStr)) { - return aStr.slice(1); - } - - return aStr; -} -exports.fromSetString = supportsNullProto ? identity : fromSetString; - -function isProtoString(s) { - if (!s) { - return false; - } - - var length = s.length; - - if (length < 9 /* "__proto__".length */) { - return false; - } - - if (s.charCodeAt(length - 1) !== 95 /* '_' */ || - s.charCodeAt(length - 2) !== 95 /* '_' */ || - s.charCodeAt(length - 3) !== 111 /* 'o' */ || - s.charCodeAt(length - 4) !== 116 /* 't' */ || - s.charCodeAt(length - 5) !== 111 /* 'o' */ || - s.charCodeAt(length - 6) !== 114 /* 'r' */ || - s.charCodeAt(length - 7) !== 112 /* 'p' */ || - s.charCodeAt(length - 8) !== 95 /* '_' */ || - s.charCodeAt(length - 9) !== 95 /* '_' */) { - return false; - } - - for (var i = length - 10; i >= 0; i--) { - if (s.charCodeAt(i) !== 36 /* '$' */) { - return false; - } - } - - return true; -} - -/** - * Comparator between two mappings where the original positions are compared. - * - * Optionally pass in `true` as `onlyCompareGenerated` to consider two - * mappings with the same original source/line/column, but different generated - * line and column the same. Useful when searching for a mapping with a - * stubbed out mapping. - */ -function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { - var cmp = mappingA.source - mappingB.source; - if (cmp !== 0) { - return cmp; - } - - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp !== 0) { - return cmp; - } - - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp !== 0 || onlyCompareOriginal) { - return cmp; - } - - cmp = mappingA.generatedColumn - mappingB.generatedColumn; - if (cmp !== 0) { - return cmp; - } - - cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp !== 0) { - return cmp; - } - - return mappingA.name - mappingB.name; -} -exports.compareByOriginalPositions = compareByOriginalPositions; - -/** - * Comparator between two mappings with deflated source and name indices where - * the generated positions are compared. - * - * Optionally pass in `true` as `onlyCompareGenerated` to consider two - * mappings with the same generated line and column, but different - * source/name/original line and column the same. Useful when searching for a - * mapping with a stubbed out mapping. - */ -function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { - var cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp !== 0) { - return cmp; - } - - cmp = mappingA.generatedColumn - mappingB.generatedColumn; - if (cmp !== 0 || onlyCompareGenerated) { - return cmp; - } - - cmp = mappingA.source - mappingB.source; - if (cmp !== 0) { - return cmp; - } - - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp !== 0) { - return cmp; - } - - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp !== 0) { - return cmp; - } - - return mappingA.name - mappingB.name; -} -exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; - -function strcmp(aStr1, aStr2) { - if (aStr1 === aStr2) { - return 0; - } - - if (aStr1 > aStr2) { - return 1; - } - - return -1; -} - -/** - * Comparator between two mappings with inflated source and name strings where - * the generated positions are compared. - */ -function compareByGeneratedPositionsInflated(mappingA, mappingB) { - var cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp !== 0) { - return cmp; - } - - cmp = mappingA.generatedColumn - mappingB.generatedColumn; - if (cmp !== 0) { - return cmp; - } - - cmp = strcmp(mappingA.source, mappingB.source); - if (cmp !== 0) { - return cmp; - } - - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp !== 0) { - return cmp; - } - - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp !== 0) { - return cmp; - } - - return strcmp(mappingA.name, mappingB.name); -} -exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; - - -/***/ }), -/* 813 */ -/***/ (function(module, exports, __webpack_require__) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ - -var util = __webpack_require__(812); -var has = Object.prototype.hasOwnProperty; -var hasNativeMap = typeof Map !== "undefined"; - -/** - * A data structure which is a combination of an array and a set. Adding a new - * member is O(1), testing for membership is O(1), and finding the index of an - * element is O(1). Removing elements from the set is not supported. Only - * strings are supported for membership. - */ -function ArraySet() { - this._array = []; - this._set = hasNativeMap ? new Map() : Object.create(null); -} - -/** - * Static method for creating ArraySet instances from an existing array. - */ -ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { - var set = new ArraySet(); - for (var i = 0, len = aArray.length; i < len; i++) { - set.add(aArray[i], aAllowDuplicates); - } - return set; -}; - -/** - * Return how many unique items are in this ArraySet. If duplicates have been - * added, than those do not count towards the size. - * - * @returns Number - */ -ArraySet.prototype.size = function ArraySet_size() { - return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length; -}; - -/** - * Add the given string to this set. - * - * @param String aStr - */ -ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { - var sStr = hasNativeMap ? aStr : util.toSetString(aStr); - var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr); - var idx = this._array.length; - if (!isDuplicate || aAllowDuplicates) { - this._array.push(aStr); - } - if (!isDuplicate) { - if (hasNativeMap) { - this._set.set(aStr, idx); - } else { - this._set[sStr] = idx; - } - } -}; - -/** - * Is the given string a member of this set? - * - * @param String aStr - */ -ArraySet.prototype.has = function ArraySet_has(aStr) { - if (hasNativeMap) { - return this._set.has(aStr); - } else { - var sStr = util.toSetString(aStr); - return has.call(this._set, sStr); - } -}; - -/** - * What is the index of the given string in the array? - * - * @param String aStr - */ -ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { - if (hasNativeMap) { - var idx = this._set.get(aStr); - if (idx >= 0) { - return idx; - } - } else { - var sStr = util.toSetString(aStr); - if (has.call(this._set, sStr)) { - return this._set[sStr]; - } - } - - throw new Error('"' + aStr + '" is not in the set.'); -}; - -/** - * What is the element at the given index? - * - * @param Number aIdx - */ -ArraySet.prototype.at = function ArraySet_at(aIdx) { - if (aIdx >= 0 && aIdx < this._array.length) { - return this._array[aIdx]; - } - throw new Error('No element indexed by ' + aIdx); -}; - -/** - * Returns the array representation of this set (which has the proper indices - * indicated by indexOf). Note that this is a copy of the internal array used - * for storing the members so that no one can mess with internal state. - */ -ArraySet.prototype.toArray = function ArraySet_toArray() { - return this._array.slice(); -}; - -exports.ArraySet = ArraySet; - - -/***/ }), -/* 814 */ -/***/ (function(module, exports, __webpack_require__) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2014 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ - -var util = __webpack_require__(812); - -/** - * Determine whether mappingB is after mappingA with respect to generated - * position. - */ -function generatedPositionAfter(mappingA, mappingB) { - // Optimized for most common case - var lineA = mappingA.generatedLine; - var lineB = mappingB.generatedLine; - var columnA = mappingA.generatedColumn; - var columnB = mappingB.generatedColumn; - return lineB > lineA || lineB == lineA && columnB >= columnA || - util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; -} - -/** - * A data structure to provide a sorted view of accumulated mappings in a - * performance conscious manner. It trades a neglibable overhead in general - * case for a large speedup in case of mappings being added in order. - */ -function MappingList() { - this._array = []; - this._sorted = true; - // Serves as infimum - this._last = {generatedLine: -1, generatedColumn: 0}; -} - -/** - * Iterate through internal items. This method takes the same arguments that - * `Array.prototype.forEach` takes. - * - * NOTE: The order of the mappings is NOT guaranteed. - */ -MappingList.prototype.unsortedForEach = - function MappingList_forEach(aCallback, aThisArg) { - this._array.forEach(aCallback, aThisArg); - }; - -/** - * Add the given source mapping. - * - * @param Object aMapping - */ -MappingList.prototype.add = function MappingList_add(aMapping) { - if (generatedPositionAfter(this._last, aMapping)) { - this._last = aMapping; - this._array.push(aMapping); - } else { - this._sorted = false; - this._array.push(aMapping); - } -}; - -/** - * Returns the flat, sorted array of mappings. The mappings are sorted by - * generated position. - * - * WARNING: This method returns internal data without copying, for - * performance. The return value must NOT be mutated, and should be treated as - * an immutable borrow. If you want to take ownership, you must make your own - * copy. - */ -MappingList.prototype.toArray = function MappingList_toArray() { - if (!this._sorted) { - this._array.sort(util.compareByGeneratedPositionsInflated); - this._sorted = true; - } - return this._array; -}; - -exports.MappingList = MappingList; - - -/***/ }), -/* 815 */ -/***/ (function(module, exports, __webpack_require__) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ - -var util = __webpack_require__(812); -var binarySearch = __webpack_require__(816); -var ArraySet = __webpack_require__(813).ArraySet; -var base64VLQ = __webpack_require__(810); -var quickSort = __webpack_require__(817).quickSort; - -function SourceMapConsumer(aSourceMap) { - var sourceMap = aSourceMap; - if (typeof aSourceMap === 'string') { - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); - } - - return sourceMap.sections != null - ? new IndexedSourceMapConsumer(sourceMap) - : new BasicSourceMapConsumer(sourceMap); -} - -SourceMapConsumer.fromSourceMap = function(aSourceMap) { - return BasicSourceMapConsumer.fromSourceMap(aSourceMap); -} - -/** - * The version of the source mapping spec that we are consuming. - */ -SourceMapConsumer.prototype._version = 3; - -// `__generatedMappings` and `__originalMappings` are arrays that hold the -// parsed mapping coordinates from the source map's "mappings" attribute. They -// are lazily instantiated, accessed via the `_generatedMappings` and -// `_originalMappings` getters respectively, and we only parse the mappings -// and create these arrays once queried for a source location. We jump through -// these hoops because there can be many thousands of mappings, and parsing -// them is expensive, so we only want to do it if we must. -// -// Each object in the arrays is of the form: -// -// { -// generatedLine: The line number in the generated code, -// generatedColumn: The column number in the generated code, -// source: The path to the original source file that generated this -// chunk of code, -// originalLine: The line number in the original source that -// corresponds to this chunk of generated code, -// originalColumn: The column number in the original source that -// corresponds to this chunk of generated code, -// name: The name of the original symbol which generated this chunk of -// code. -// } -// -// All properties except for `generatedLine` and `generatedColumn` can be -// `null`. -// -// `_generatedMappings` is ordered by the generated positions. -// -// `_originalMappings` is ordered by the original positions. - -SourceMapConsumer.prototype.__generatedMappings = null; -Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { - get: function () { - if (!this.__generatedMappings) { - this._parseMappings(this._mappings, this.sourceRoot); - } - - return this.__generatedMappings; - } -}); - -SourceMapConsumer.prototype.__originalMappings = null; -Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { - get: function () { - if (!this.__originalMappings) { - this._parseMappings(this._mappings, this.sourceRoot); - } - - return this.__originalMappings; - } -}); - -SourceMapConsumer.prototype._charIsMappingSeparator = - function SourceMapConsumer_charIsMappingSeparator(aStr, index) { - var c = aStr.charAt(index); - return c === ";" || c === ","; - }; - -/** - * Parse the mappings in a string in to a data structure which we can easily - * query (the ordered arrays in the `this.__generatedMappings` and - * `this.__originalMappings` properties). - */ -SourceMapConsumer.prototype._parseMappings = - function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { - throw new Error("Subclasses must implement _parseMappings"); - }; - -SourceMapConsumer.GENERATED_ORDER = 1; -SourceMapConsumer.ORIGINAL_ORDER = 2; - -SourceMapConsumer.GREATEST_LOWER_BOUND = 1; -SourceMapConsumer.LEAST_UPPER_BOUND = 2; - -/** - * Iterate over each mapping between an original source/line/column and a - * generated line/column in this source map. - * - * @param Function aCallback - * The function that is called with each mapping. - * @param Object aContext - * Optional. If specified, this object will be the value of `this` every - * time that `aCallback` is called. - * @param aOrder - * Either `SourceMapConsumer.GENERATED_ORDER` or - * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to - * iterate over the mappings sorted by the generated file's line/column - * order or the original's source/line/column order, respectively. Defaults to - * `SourceMapConsumer.GENERATED_ORDER`. - */ -SourceMapConsumer.prototype.eachMapping = - function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { - var context = aContext || null; - var order = aOrder || SourceMapConsumer.GENERATED_ORDER; - - var mappings; - switch (order) { - case SourceMapConsumer.GENERATED_ORDER: - mappings = this._generatedMappings; - break; - case SourceMapConsumer.ORIGINAL_ORDER: - mappings = this._originalMappings; - break; - default: - throw new Error("Unknown order of iteration."); - } - - var sourceRoot = this.sourceRoot; - mappings.map(function (mapping) { - var source = mapping.source === null ? null : this._sources.at(mapping.source); - if (source != null && sourceRoot != null) { - source = util.join(sourceRoot, source); - } - return { - source: source, - generatedLine: mapping.generatedLine, - generatedColumn: mapping.generatedColumn, - originalLine: mapping.originalLine, - originalColumn: mapping.originalColumn, - name: mapping.name === null ? null : this._names.at(mapping.name) - }; - }, this).forEach(aCallback, context); - }; - -/** - * Returns all generated line and column information for the original source, - * line, and column provided. If no column is provided, returns all mappings - * corresponding to a either the line we are searching for or the next - * closest line that has any mappings. Otherwise, returns all mappings - * corresponding to the given line and either the column we are searching for - * or the next closest column that has any offsets. - * - * The only argument is an object with the following properties: - * - * - source: The filename of the original source. - * - line: The line number in the original source. - * - column: Optional. the column number in the original source. - * - * and an array of objects is returned, each with the following properties: - * - * - line: The line number in the generated source, or null. - * - column: The column number in the generated source, or null. - */ -SourceMapConsumer.prototype.allGeneratedPositionsFor = - function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { - var line = util.getArg(aArgs, 'line'); - - // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping - // returns the index of the closest mapping less than the needle. By - // setting needle.originalColumn to 0, we thus find the last mapping for - // the given line, provided such a mapping exists. - var needle = { - source: util.getArg(aArgs, 'source'), - originalLine: line, - originalColumn: util.getArg(aArgs, 'column', 0) - }; - - if (this.sourceRoot != null) { - needle.source = util.relative(this.sourceRoot, needle.source); - } - if (!this._sources.has(needle.source)) { - return []; - } - needle.source = this._sources.indexOf(needle.source); - - var mappings = []; - - var index = this._findMapping(needle, - this._originalMappings, - "originalLine", - "originalColumn", - util.compareByOriginalPositions, - binarySearch.LEAST_UPPER_BOUND); - if (index >= 0) { - var mapping = this._originalMappings[index]; - - if (aArgs.column === undefined) { - var originalLine = mapping.originalLine; - - // Iterate until either we run out of mappings, or we run into - // a mapping for a different line than the one we found. Since - // mappings are sorted, this is guaranteed to find all mappings for - // the line we found. - while (mapping && mapping.originalLine === originalLine) { - mappings.push({ - line: util.getArg(mapping, 'generatedLine', null), - column: util.getArg(mapping, 'generatedColumn', null), - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) - }); - - mapping = this._originalMappings[++index]; - } - } else { - var originalColumn = mapping.originalColumn; - - // Iterate until either we run out of mappings, or we run into - // a mapping for a different line than the one we were searching for. - // Since mappings are sorted, this is guaranteed to find all mappings for - // the line we are searching for. - while (mapping && - mapping.originalLine === line && - mapping.originalColumn == originalColumn) { - mappings.push({ - line: util.getArg(mapping, 'generatedLine', null), - column: util.getArg(mapping, 'generatedColumn', null), - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) - }); - - mapping = this._originalMappings[++index]; - } - } - } - - return mappings; - }; - -exports.SourceMapConsumer = SourceMapConsumer; - -/** - * A BasicSourceMapConsumer instance represents a parsed source map which we can - * query for information about the original file positions by giving it a file - * position in the generated source. - * - * The only parameter is the raw source map (either as a JSON string, or - * already parsed to an object). According to the spec, source maps have the - * following attributes: - * - * - version: Which version of the source map spec this map is following. - * - sources: An array of URLs to the original source files. - * - names: An array of identifiers which can be referrenced by individual mappings. - * - sourceRoot: Optional. The URL root from which all sources are relative. - * - sourcesContent: Optional. An array of contents of the original source files. - * - mappings: A string of base64 VLQs which contain the actual mappings. - * - file: Optional. The generated file this source map is associated with. - * - * Here is an example source map, taken from the source map spec[0]: - * - * { - * version : 3, - * file: "out.js", - * sourceRoot : "", - * sources: ["foo.js", "bar.js"], - * names: ["src", "maps", "are", "fun"], - * mappings: "AA,AB;;ABCDE;" - * } - * - * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# - */ -function BasicSourceMapConsumer(aSourceMap) { - var sourceMap = aSourceMap; - if (typeof aSourceMap === 'string') { - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); - } - - var version = util.getArg(sourceMap, 'version'); - var sources = util.getArg(sourceMap, 'sources'); - // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which - // requires the array) to play nice here. - var names = util.getArg(sourceMap, 'names', []); - var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); - var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); - var mappings = util.getArg(sourceMap, 'mappings'); - var file = util.getArg(sourceMap, 'file', null); - - // Once again, Sass deviates from the spec and supplies the version as a - // string rather than a number, so we use loose equality checking here. - if (version != this._version) { - throw new Error('Unsupported version: ' + version); - } - - sources = sources - .map(String) - // Some source maps produce relative source paths like "./foo.js" instead of - // "foo.js". Normalize these first so that future comparisons will succeed. - // See bugzil.la/1090768. - .map(util.normalize) - // Always ensure that absolute sources are internally stored relative to - // the source root, if the source root is absolute. Not doing this would - // be particularly problematic when the source root is a prefix of the - // source (valid, but why??). See github issue #199 and bugzil.la/1188982. - .map(function (source) { - return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) - ? util.relative(sourceRoot, source) - : source; - }); - - // Pass `true` below to allow duplicate names and sources. While source maps - // are intended to be compressed and deduplicated, the TypeScript compiler - // sometimes generates source maps with duplicates in them. See Github issue - // #72 and bugzil.la/889492. - this._names = ArraySet.fromArray(names.map(String), true); - this._sources = ArraySet.fromArray(sources, true); - - this.sourceRoot = sourceRoot; - this.sourcesContent = sourcesContent; - this._mappings = mappings; - this.file = file; -} - -BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); -BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; - -/** - * Create a BasicSourceMapConsumer from a SourceMapGenerator. - * - * @param SourceMapGenerator aSourceMap - * The source map that will be consumed. - * @returns BasicSourceMapConsumer - */ -BasicSourceMapConsumer.fromSourceMap = - function SourceMapConsumer_fromSourceMap(aSourceMap) { - var smc = Object.create(BasicSourceMapConsumer.prototype); - - var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); - var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); - smc.sourceRoot = aSourceMap._sourceRoot; - smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), - smc.sourceRoot); - smc.file = aSourceMap._file; - - // Because we are modifying the entries (by converting string sources and - // names to indices into the sources and names ArraySets), we have to make - // a copy of the entry or else bad things happen. Shared mutable state - // strikes again! See github issue #191. - - var generatedMappings = aSourceMap._mappings.toArray().slice(); - var destGeneratedMappings = smc.__generatedMappings = []; - var destOriginalMappings = smc.__originalMappings = []; - - for (var i = 0, length = generatedMappings.length; i < length; i++) { - var srcMapping = generatedMappings[i]; - var destMapping = new Mapping; - destMapping.generatedLine = srcMapping.generatedLine; - destMapping.generatedColumn = srcMapping.generatedColumn; - - if (srcMapping.source) { - destMapping.source = sources.indexOf(srcMapping.source); - destMapping.originalLine = srcMapping.originalLine; - destMapping.originalColumn = srcMapping.originalColumn; - - if (srcMapping.name) { - destMapping.name = names.indexOf(srcMapping.name); - } - - destOriginalMappings.push(destMapping); - } - - destGeneratedMappings.push(destMapping); - } - - quickSort(smc.__originalMappings, util.compareByOriginalPositions); - - return smc; - }; - -/** - * The version of the source mapping spec that we are consuming. - */ -BasicSourceMapConsumer.prototype._version = 3; - -/** - * The list of original sources. - */ -Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { - get: function () { - return this._sources.toArray().map(function (s) { - return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; - }, this); - } -}); - -/** - * Provide the JIT with a nice shape / hidden class. - */ -function Mapping() { - this.generatedLine = 0; - this.generatedColumn = 0; - this.source = null; - this.originalLine = null; - this.originalColumn = null; - this.name = null; -} - -/** - * Parse the mappings in a string in to a data structure which we can easily - * query (the ordered arrays in the `this.__generatedMappings` and - * `this.__originalMappings` properties). - */ -BasicSourceMapConsumer.prototype._parseMappings = - function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { - var generatedLine = 1; - var previousGeneratedColumn = 0; - var previousOriginalLine = 0; - var previousOriginalColumn = 0; - var previousSource = 0; - var previousName = 0; - var length = aStr.length; - var index = 0; - var cachedSegments = {}; - var temp = {}; - var originalMappings = []; - var generatedMappings = []; - var mapping, str, segment, end, value; - - while (index < length) { - if (aStr.charAt(index) === ';') { - generatedLine++; - index++; - previousGeneratedColumn = 0; - } - else if (aStr.charAt(index) === ',') { - index++; - } - else { - mapping = new Mapping(); - mapping.generatedLine = generatedLine; - - // Because each offset is encoded relative to the previous one, - // many segments often have the same encoding. We can exploit this - // fact by caching the parsed variable length fields of each segment, - // allowing us to avoid a second parse if we encounter the same - // segment again. - for (end = index; end < length; end++) { - if (this._charIsMappingSeparator(aStr, end)) { - break; - } - } - str = aStr.slice(index, end); - - segment = cachedSegments[str]; - if (segment) { - index += str.length; - } else { - segment = []; - while (index < end) { - base64VLQ.decode(aStr, index, temp); - value = temp.value; - index = temp.rest; - segment.push(value); - } - - if (segment.length === 2) { - throw new Error('Found a source, but no line and column'); - } - - if (segment.length === 3) { - throw new Error('Found a source and line, but no column'); - } - - cachedSegments[str] = segment; - } - - // Generated column. - mapping.generatedColumn = previousGeneratedColumn + segment[0]; - previousGeneratedColumn = mapping.generatedColumn; - - if (segment.length > 1) { - // Original source. - mapping.source = previousSource + segment[1]; - previousSource += segment[1]; - - // Original line. - mapping.originalLine = previousOriginalLine + segment[2]; - previousOriginalLine = mapping.originalLine; - // Lines are stored 0-based - mapping.originalLine += 1; - - // Original column. - mapping.originalColumn = previousOriginalColumn + segment[3]; - previousOriginalColumn = mapping.originalColumn; - - if (segment.length > 4) { - // Original name. - mapping.name = previousName + segment[4]; - previousName += segment[4]; - } - } - - generatedMappings.push(mapping); - if (typeof mapping.originalLine === 'number') { - originalMappings.push(mapping); - } - } - } - - quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); - this.__generatedMappings = generatedMappings; - - quickSort(originalMappings, util.compareByOriginalPositions); - this.__originalMappings = originalMappings; - }; - -/** - * Find the mapping that best matches the hypothetical "needle" mapping that - * we are searching for in the given "haystack" of mappings. - */ -BasicSourceMapConsumer.prototype._findMapping = - function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, - aColumnName, aComparator, aBias) { - // To return the position we are searching for, we must first find the - // mapping for the given position and then return the opposite position it - // points to. Because the mappings are sorted, we can use binary search to - // find the best mapping. - - if (aNeedle[aLineName] <= 0) { - throw new TypeError('Line must be greater than or equal to 1, got ' - + aNeedle[aLineName]); - } - if (aNeedle[aColumnName] < 0) { - throw new TypeError('Column must be greater than or equal to 0, got ' - + aNeedle[aColumnName]); - } - - return binarySearch.search(aNeedle, aMappings, aComparator, aBias); - }; - -/** - * Compute the last column for each generated mapping. The last column is - * inclusive. - */ -BasicSourceMapConsumer.prototype.computeColumnSpans = - function SourceMapConsumer_computeColumnSpans() { - for (var index = 0; index < this._generatedMappings.length; ++index) { - var mapping = this._generatedMappings[index]; - - // Mappings do not contain a field for the last generated columnt. We - // can come up with an optimistic estimate, however, by assuming that - // mappings are contiguous (i.e. given two consecutive mappings, the - // first mapping ends where the second one starts). - if (index + 1 < this._generatedMappings.length) { - var nextMapping = this._generatedMappings[index + 1]; - - if (mapping.generatedLine === nextMapping.generatedLine) { - mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; - continue; - } - } - - // The last mapping for each line spans the entire line. - mapping.lastGeneratedColumn = Infinity; - } - }; - -/** - * Returns the original source, line, and column information for the generated - * source's line and column positions provided. The only argument is an object - * with the following properties: - * - * - line: The line number in the generated source. - * - column: The column number in the generated source. - * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or - * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. - * - * and an object is returned with the following properties: - * - * - source: The original source file, or null. - * - line: The line number in the original source, or null. - * - column: The column number in the original source, or null. - * - name: The original identifier, or null. - */ -BasicSourceMapConsumer.prototype.originalPositionFor = - function SourceMapConsumer_originalPositionFor(aArgs) { - var needle = { - generatedLine: util.getArg(aArgs, 'line'), - generatedColumn: util.getArg(aArgs, 'column') - }; - - var index = this._findMapping( - needle, - this._generatedMappings, - "generatedLine", - "generatedColumn", - util.compareByGeneratedPositionsDeflated, - util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) - ); - - if (index >= 0) { - var mapping = this._generatedMappings[index]; - - if (mapping.generatedLine === needle.generatedLine) { - var source = util.getArg(mapping, 'source', null); - if (source !== null) { - source = this._sources.at(source); - if (this.sourceRoot != null) { - source = util.join(this.sourceRoot, source); - } - } - var name = util.getArg(mapping, 'name', null); - if (name !== null) { - name = this._names.at(name); - } - return { - source: source, - line: util.getArg(mapping, 'originalLine', null), - column: util.getArg(mapping, 'originalColumn', null), - name: name - }; - } - } - - return { - source: null, - line: null, - column: null, - name: null - }; - }; - -/** - * Return true if we have the source content for every source in the source - * map, false otherwise. - */ -BasicSourceMapConsumer.prototype.hasContentsOfAllSources = - function BasicSourceMapConsumer_hasContentsOfAllSources() { - if (!this.sourcesContent) { - return false; - } - return this.sourcesContent.length >= this._sources.size() && - !this.sourcesContent.some(function (sc) { return sc == null; }); - }; - -/** - * Returns the original source content. The only argument is the url of the - * original source file. Returns null if no original source content is - * available. - */ -BasicSourceMapConsumer.prototype.sourceContentFor = - function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { - if (!this.sourcesContent) { - return null; - } - - if (this.sourceRoot != null) { - aSource = util.relative(this.sourceRoot, aSource); - } - - if (this._sources.has(aSource)) { - return this.sourcesContent[this._sources.indexOf(aSource)]; - } - - var url; - if (this.sourceRoot != null - && (url = util.urlParse(this.sourceRoot))) { - // XXX: file:// URIs and absolute paths lead to unexpected behavior for - // many users. We can help them out when they expect file:// URIs to - // behave like it would if they were running a local HTTP server. See - // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. - var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); - if (url.scheme == "file" - && this._sources.has(fileUriAbsPath)) { - return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] - } - - if ((!url.path || url.path == "/") - && this._sources.has("/" + aSource)) { - return this.sourcesContent[this._sources.indexOf("/" + aSource)]; - } - } - - // This function is used recursively from - // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we - // don't want to throw if we can't find the source - we just want to - // return null, so we provide a flag to exit gracefully. - if (nullOnMissing) { - return null; - } - else { - throw new Error('"' + aSource + '" is not in the SourceMap.'); - } - }; - -/** - * Returns the generated line and column information for the original source, - * line, and column positions provided. The only argument is an object with - * the following properties: - * - * - source: The filename of the original source. - * - line: The line number in the original source. - * - column: The column number in the original source. - * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or - * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. - * - * and an object is returned with the following properties: - * - * - line: The line number in the generated source, or null. - * - column: The column number in the generated source, or null. - */ -BasicSourceMapConsumer.prototype.generatedPositionFor = - function SourceMapConsumer_generatedPositionFor(aArgs) { - var source = util.getArg(aArgs, 'source'); - if (this.sourceRoot != null) { - source = util.relative(this.sourceRoot, source); - } - if (!this._sources.has(source)) { - return { - line: null, - column: null, - lastColumn: null - }; - } - source = this._sources.indexOf(source); - - var needle = { - source: source, - originalLine: util.getArg(aArgs, 'line'), - originalColumn: util.getArg(aArgs, 'column') - }; - - var index = this._findMapping( - needle, - this._originalMappings, - "originalLine", - "originalColumn", - util.compareByOriginalPositions, - util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) - ); - - if (index >= 0) { - var mapping = this._originalMappings[index]; - - if (mapping.source === needle.source) { - return { - line: util.getArg(mapping, 'generatedLine', null), - column: util.getArg(mapping, 'generatedColumn', null), - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) - }; - } - } - - return { - line: null, - column: null, - lastColumn: null - }; - }; - -exports.BasicSourceMapConsumer = BasicSourceMapConsumer; - -/** - * An IndexedSourceMapConsumer instance represents a parsed source map which - * we can query for information. It differs from BasicSourceMapConsumer in - * that it takes "indexed" source maps (i.e. ones with a "sections" field) as - * input. - * - * The only parameter is a raw source map (either as a JSON string, or already - * parsed to an object). According to the spec for indexed source maps, they - * have the following attributes: - * - * - version: Which version of the source map spec this map is following. - * - file: Optional. The generated file this source map is associated with. - * - sections: A list of section definitions. - * - * Each value under the "sections" field has two fields: - * - offset: The offset into the original specified at which this section - * begins to apply, defined as an object with a "line" and "column" - * field. - * - map: A source map definition. This source map could also be indexed, - * but doesn't have to be. - * - * Instead of the "map" field, it's also possible to have a "url" field - * specifying a URL to retrieve a source map from, but that's currently - * unsupported. - * - * Here's an example source map, taken from the source map spec[0], but - * modified to omit a section which uses the "url" field. - * - * { - * version : 3, - * file: "app.js", - * sections: [{ - * offset: {line:100, column:10}, - * map: { - * version : 3, - * file: "section.js", - * sources: ["foo.js", "bar.js"], - * names: ["src", "maps", "are", "fun"], - * mappings: "AAAA,E;;ABCDE;" - * } - * }], - * } - * - * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt - */ -function IndexedSourceMapConsumer(aSourceMap) { - var sourceMap = aSourceMap; - if (typeof aSourceMap === 'string') { - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); - } - - var version = util.getArg(sourceMap, 'version'); - var sections = util.getArg(sourceMap, 'sections'); - - if (version != this._version) { - throw new Error('Unsupported version: ' + version); - } - - this._sources = new ArraySet(); - this._names = new ArraySet(); - - var lastOffset = { - line: -1, - column: 0 - }; - this._sections = sections.map(function (s) { - if (s.url) { - // The url field will require support for asynchronicity. - // See https://github.com/mozilla/source-map/issues/16 - throw new Error('Support for url field in sections not implemented.'); - } - var offset = util.getArg(s, 'offset'); - var offsetLine = util.getArg(offset, 'line'); - var offsetColumn = util.getArg(offset, 'column'); - - if (offsetLine < lastOffset.line || - (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { - throw new Error('Section offsets must be ordered and non-overlapping.'); - } - lastOffset = offset; - - return { - generatedOffset: { - // The offset fields are 0-based, but we use 1-based indices when - // encoding/decoding from VLQ. - generatedLine: offsetLine + 1, - generatedColumn: offsetColumn + 1 - }, - consumer: new SourceMapConsumer(util.getArg(s, 'map')) - } - }); -} - -IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); -IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; - -/** - * The version of the source mapping spec that we are consuming. - */ -IndexedSourceMapConsumer.prototype._version = 3; - -/** - * The list of original sources. - */ -Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { - get: function () { - var sources = []; - for (var i = 0; i < this._sections.length; i++) { - for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { - sources.push(this._sections[i].consumer.sources[j]); - } - } - return sources; - } -}); - -/** - * Returns the original source, line, and column information for the generated - * source's line and column positions provided. The only argument is an object - * with the following properties: - * - * - line: The line number in the generated source. - * - column: The column number in the generated source. - * - * and an object is returned with the following properties: - * - * - source: The original source file, or null. - * - line: The line number in the original source, or null. - * - column: The column number in the original source, or null. - * - name: The original identifier, or null. - */ -IndexedSourceMapConsumer.prototype.originalPositionFor = - function IndexedSourceMapConsumer_originalPositionFor(aArgs) { - var needle = { - generatedLine: util.getArg(aArgs, 'line'), - generatedColumn: util.getArg(aArgs, 'column') - }; - - // Find the section containing the generated position we're trying to map - // to an original position. - var sectionIndex = binarySearch.search(needle, this._sections, - function(needle, section) { - var cmp = needle.generatedLine - section.generatedOffset.generatedLine; - if (cmp) { - return cmp; - } - - return (needle.generatedColumn - - section.generatedOffset.generatedColumn); - }); - var section = this._sections[sectionIndex]; - - if (!section) { - return { - source: null, - line: null, - column: null, - name: null - }; - } - - return section.consumer.originalPositionFor({ - line: needle.generatedLine - - (section.generatedOffset.generatedLine - 1), - column: needle.generatedColumn - - (section.generatedOffset.generatedLine === needle.generatedLine - ? section.generatedOffset.generatedColumn - 1 - : 0), - bias: aArgs.bias - }); - }; - -/** - * Return true if we have the source content for every source in the source - * map, false otherwise. - */ -IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = - function IndexedSourceMapConsumer_hasContentsOfAllSources() { - return this._sections.every(function (s) { - return s.consumer.hasContentsOfAllSources(); - }); - }; - -/** - * Returns the original source content. The only argument is the url of the - * original source file. Returns null if no original source content is - * available. - */ -IndexedSourceMapConsumer.prototype.sourceContentFor = - function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { - for (var i = 0; i < this._sections.length; i++) { - var section = this._sections[i]; - - var content = section.consumer.sourceContentFor(aSource, true); - if (content) { - return content; - } - } - if (nullOnMissing) { - return null; - } - else { - throw new Error('"' + aSource + '" is not in the SourceMap.'); - } - }; - -/** - * Returns the generated line and column information for the original source, - * line, and column positions provided. The only argument is an object with - * the following properties: - * - * - source: The filename of the original source. - * - line: The line number in the original source. - * - column: The column number in the original source. - * - * and an object is returned with the following properties: - * - * - line: The line number in the generated source, or null. - * - column: The column number in the generated source, or null. - */ -IndexedSourceMapConsumer.prototype.generatedPositionFor = - function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { - for (var i = 0; i < this._sections.length; i++) { - var section = this._sections[i]; - - // Only consider this section if the requested source is in the list of - // sources of the consumer. - if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { - continue; - } - var generatedPosition = section.consumer.generatedPositionFor(aArgs); - if (generatedPosition) { - var ret = { - line: generatedPosition.line + - (section.generatedOffset.generatedLine - 1), - column: generatedPosition.column + - (section.generatedOffset.generatedLine === generatedPosition.line - ? section.generatedOffset.generatedColumn - 1 - : 0) - }; - return ret; - } - } - - return { - line: null, - column: null - }; - }; - -/** - * Parse the mappings in a string in to a data structure which we can easily - * query (the ordered arrays in the `this.__generatedMappings` and - * `this.__originalMappings` properties). - */ -IndexedSourceMapConsumer.prototype._parseMappings = - function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { - this.__generatedMappings = []; - this.__originalMappings = []; - for (var i = 0; i < this._sections.length; i++) { - var section = this._sections[i]; - var sectionMappings = section.consumer._generatedMappings; - for (var j = 0; j < sectionMappings.length; j++) { - var mapping = sectionMappings[j]; - - var source = section.consumer._sources.at(mapping.source); - if (section.consumer.sourceRoot !== null) { - source = util.join(section.consumer.sourceRoot, source); - } - this._sources.add(source); - source = this._sources.indexOf(source); - - var name = section.consumer._names.at(mapping.name); - this._names.add(name); - name = this._names.indexOf(name); - - // The mappings coming from the consumer for the section have - // generated positions relative to the start of the section, so we - // need to offset them to be relative to the start of the concatenated - // generated file. - var adjustedMapping = { - source: source, - generatedLine: mapping.generatedLine + - (section.generatedOffset.generatedLine - 1), - generatedColumn: mapping.generatedColumn + - (section.generatedOffset.generatedLine === mapping.generatedLine - ? section.generatedOffset.generatedColumn - 1 - : 0), - originalLine: mapping.originalLine, - originalColumn: mapping.originalColumn, - name: name - }; - - this.__generatedMappings.push(adjustedMapping); - if (typeof adjustedMapping.originalLine === 'number') { - this.__originalMappings.push(adjustedMapping); - } - } - } - - quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); - quickSort(this.__originalMappings, util.compareByOriginalPositions); - }; - -exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; - - -/***/ }), -/* 816 */ -/***/ (function(module, exports) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ - -exports.GREATEST_LOWER_BOUND = 1; -exports.LEAST_UPPER_BOUND = 2; - -/** - * Recursive implementation of binary search. - * - * @param aLow Indices here and lower do not contain the needle. - * @param aHigh Indices here and higher do not contain the needle. - * @param aNeedle The element being searched for. - * @param aHaystack The non-empty array being searched. - * @param aCompare Function which takes two elements and returns -1, 0, or 1. - * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or - * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - */ -function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { - // This function terminates when one of the following is true: - // - // 1. We find the exact element we are looking for. - // - // 2. We did not find the exact element, but we can return the index of - // the next-closest element. - // - // 3. We did not find the exact element, and there is no next-closest - // element than the one we are searching for, so we return -1. - var mid = Math.floor((aHigh - aLow) / 2) + aLow; - var cmp = aCompare(aNeedle, aHaystack[mid], true); - if (cmp === 0) { - // Found the element we are looking for. - return mid; - } - else if (cmp > 0) { - // Our needle is greater than aHaystack[mid]. - if (aHigh - mid > 1) { - // The element is in the upper half. - return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); - } - - // The exact needle element was not found in this haystack. Determine if - // we are in termination case (3) or (2) and return the appropriate thing. - if (aBias == exports.LEAST_UPPER_BOUND) { - return aHigh < aHaystack.length ? aHigh : -1; - } else { - return mid; - } - } - else { - // Our needle is less than aHaystack[mid]. - if (mid - aLow > 1) { - // The element is in the lower half. - return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); - } - - // we are in termination case (3) or (2) and return the appropriate thing. - if (aBias == exports.LEAST_UPPER_BOUND) { - return mid; - } else { - return aLow < 0 ? -1 : aLow; - } - } -} - -/** - * This is an implementation of binary search which will always try and return - * the index of the closest element if there is no exact hit. This is because - * mappings between original and generated line/col pairs are single points, - * and there is an implicit region between each of them, so a miss just means - * that you aren't on the very start of a region. - * - * @param aNeedle The element you are looking for. - * @param aHaystack The array that is being searched. - * @param aCompare A function which takes the needle and an element in the - * array and returns -1, 0, or 1 depending on whether the needle is less - * than, equal to, or greater than the element, respectively. - * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or - * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. - */ -exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { - if (aHaystack.length === 0) { - return -1; - } - - var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, - aCompare, aBias || exports.GREATEST_LOWER_BOUND); - if (index < 0) { - return -1; - } - - // We have found either the exact element, or the next-closest element than - // the one we are searching for. However, there may be more than one such - // element. Make sure we always return the smallest of these. - while (index - 1 >= 0) { - if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { - break; - } - --index; - } - - return index; -}; - - -/***/ }), -/* 817 */ -/***/ (function(module, exports) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ - -// It turns out that some (most?) JavaScript engines don't self-host -// `Array.prototype.sort`. This makes sense because C++ will likely remain -// faster than JS when doing raw CPU-intensive sorting. However, when using a -// custom comparator function, calling back and forth between the VM's C++ and -// JIT'd JS is rather slow *and* loses JIT type information, resulting in -// worse generated code for the comparator function than would be optimal. In -// fact, when sorting with a comparator, these costs outweigh the benefits of -// sorting in C++. By using our own JS-implemented Quick Sort (below), we get -// a ~3500ms mean speed-up in `bench/bench.html`. - -/** - * Swap the elements indexed by `x` and `y` in the array `ary`. - * - * @param {Array} ary - * The array. - * @param {Number} x - * The index of the first item. - * @param {Number} y - * The index of the second item. - */ -function swap(ary, x, y) { - var temp = ary[x]; - ary[x] = ary[y]; - ary[y] = temp; -} - -/** - * Returns a random integer within the range `low .. high` inclusive. - * - * @param {Number} low - * The lower bound on the range. - * @param {Number} high - * The upper bound on the range. - */ -function randomIntInRange(low, high) { - return Math.round(low + (Math.random() * (high - low))); -} - -/** - * The Quick Sort algorithm. - * - * @param {Array} ary - * An array to sort. - * @param {function} comparator - * Function to use to compare two items. - * @param {Number} p - * Start index of the array - * @param {Number} r - * End index of the array - */ -function doQuickSort(ary, comparator, p, r) { - // If our lower bound is less than our upper bound, we (1) partition the - // array into two pieces and (2) recurse on each half. If it is not, this is - // the empty array and our base case. - - if (p < r) { - // (1) Partitioning. - // - // The partitioning chooses a pivot between `p` and `r` and moves all - // elements that are less than or equal to the pivot to the before it, and - // all the elements that are greater than it after it. The effect is that - // once partition is done, the pivot is in the exact place it will be when - // the array is put in sorted order, and it will not need to be moved - // again. This runs in O(n) time. - - // Always choose a random pivot so that an input array which is reverse - // sorted does not cause O(n^2) running time. - var pivotIndex = randomIntInRange(p, r); - var i = p - 1; - - swap(ary, pivotIndex, r); - var pivot = ary[r]; - - // Immediately after `j` is incremented in this loop, the following hold - // true: - // - // * Every element in `ary[p .. i]` is less than or equal to the pivot. - // - // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. - for (var j = p; j < r; j++) { - if (comparator(ary[j], pivot) <= 0) { - i += 1; - swap(ary, i, j); - } - } - - swap(ary, i + 1, j); - var q = i + 1; - - // (2) Recurse on each half. - - doQuickSort(ary, comparator, p, q - 1); - doQuickSort(ary, comparator, q + 1, r); - } -} - -/** - * Sort the given array in-place with the given comparator function. - * - * @param {Array} ary - * An array to sort. - * @param {function} comparator - * Function to use to compare two items. - */ -exports.quickSort = function (ary, comparator) { - doQuickSort(ary, comparator, 0, ary.length - 1); -}; - - -/***/ }), -/* 818 */ -/***/ (function(module, exports, __webpack_require__) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ - -var SourceMapGenerator = __webpack_require__(809).SourceMapGenerator; -var util = __webpack_require__(812); - -// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other -// operating systems these days (capturing the result). -var REGEX_NEWLINE = /(\r?\n)/; - -// Newline character code for charCodeAt() comparisons -var NEWLINE_CODE = 10; - -// Private symbol for identifying `SourceNode`s when multiple versions of -// the source-map library are loaded. This MUST NOT CHANGE across -// versions! -var isSourceNode = "$$$isSourceNode$$$"; - -/** - * SourceNodes provide a way to abstract over interpolating/concatenating - * snippets of generated JavaScript source code while maintaining the line and - * column information associated with the original source code. - * - * @param aLine The original line number. - * @param aColumn The original column number. - * @param aSource The original source's filename. - * @param aChunks Optional. An array of strings which are snippets of - * generated JS, or other SourceNodes. - * @param aName The original identifier. - */ -function SourceNode(aLine, aColumn, aSource, aChunks, aName) { - this.children = []; - this.sourceContents = {}; - this.line = aLine == null ? null : aLine; - this.column = aColumn == null ? null : aColumn; - this.source = aSource == null ? null : aSource; - this.name = aName == null ? null : aName; - this[isSourceNode] = true; - if (aChunks != null) this.add(aChunks); -} - -/** - * Creates a SourceNode from generated code and a SourceMapConsumer. - * - * @param aGeneratedCode The generated code - * @param aSourceMapConsumer The SourceMap for the generated code - * @param aRelativePath Optional. The path that relative sources in the - * SourceMapConsumer should be relative to. - */ -SourceNode.fromStringWithSourceMap = - function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { - // The SourceNode we want to fill with the generated code - // and the SourceMap - var node = new SourceNode(); - - // All even indices of this array are one line of the generated code, - // while all odd indices are the newlines between two adjacent lines - // (since `REGEX_NEWLINE` captures its match). - // Processed fragments are accessed by calling `shiftNextLine`. - var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); - var remainingLinesIndex = 0; - var shiftNextLine = function() { - var lineContents = getNextLine(); - // The last line of a file might not have a newline. - var newLine = getNextLine() || ""; - return lineContents + newLine; - - function getNextLine() { - return remainingLinesIndex < remainingLines.length ? - remainingLines[remainingLinesIndex++] : undefined; - } - }; - - // We need to remember the position of "remainingLines" - var lastGeneratedLine = 1, lastGeneratedColumn = 0; - - // The generate SourceNodes we need a code range. - // To extract it current and last mapping is used. - // Here we store the last mapping. - var lastMapping = null; - - aSourceMapConsumer.eachMapping(function (mapping) { - if (lastMapping !== null) { - // We add the code from "lastMapping" to "mapping": - // First check if there is a new line in between. - if (lastGeneratedLine < mapping.generatedLine) { - // Associate first line with "lastMapping" - addMappingWithCode(lastMapping, shiftNextLine()); - lastGeneratedLine++; - lastGeneratedColumn = 0; - // The remaining code is added without mapping - } else { - // There is no new line in between. - // Associate the code between "lastGeneratedColumn" and - // "mapping.generatedColumn" with "lastMapping" - var nextLine = remainingLines[remainingLinesIndex]; - var code = nextLine.substr(0, mapping.generatedColumn - - lastGeneratedColumn); - remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - - lastGeneratedColumn); - lastGeneratedColumn = mapping.generatedColumn; - addMappingWithCode(lastMapping, code); - // No more remaining code, continue - lastMapping = mapping; - return; - } - } - // We add the generated code until the first mapping - // to the SourceNode without any mapping. - // Each line is added as separate string. - while (lastGeneratedLine < mapping.generatedLine) { - node.add(shiftNextLine()); - lastGeneratedLine++; - } - if (lastGeneratedColumn < mapping.generatedColumn) { - var nextLine = remainingLines[remainingLinesIndex]; - node.add(nextLine.substr(0, mapping.generatedColumn)); - remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn); - lastGeneratedColumn = mapping.generatedColumn; - } - lastMapping = mapping; - }, this); - // We have processed all mappings. - if (remainingLinesIndex < remainingLines.length) { - if (lastMapping) { - // Associate the remaining code in the current line with "lastMapping" - addMappingWithCode(lastMapping, shiftNextLine()); - } - // and add the remaining lines without any mapping - node.add(remainingLines.splice(remainingLinesIndex).join("")); - } - - // Copy sourcesContent into SourceNode - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content != null) { - if (aRelativePath != null) { - sourceFile = util.join(aRelativePath, sourceFile); - } - node.setSourceContent(sourceFile, content); - } - }); - - return node; - - function addMappingWithCode(mapping, code) { - if (mapping === null || mapping.source === undefined) { - node.add(code); - } else { - var source = aRelativePath - ? util.join(aRelativePath, mapping.source) - : mapping.source; - node.add(new SourceNode(mapping.originalLine, - mapping.originalColumn, - source, - code, - mapping.name)); - } - } - }; - -/** - * Add a chunk of generated JS to this source node. - * - * @param aChunk A string snippet of generated JS code, another instance of - * SourceNode, or an array where each member is one of those things. - */ -SourceNode.prototype.add = function SourceNode_add(aChunk) { - if (Array.isArray(aChunk)) { - aChunk.forEach(function (chunk) { - this.add(chunk); - }, this); - } - else if (aChunk[isSourceNode] || typeof aChunk === "string") { - if (aChunk) { - this.children.push(aChunk); - } - } - else { - throw new TypeError( - "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk - ); - } - return this; -}; - -/** - * Add a chunk of generated JS to the beginning of this source node. - * - * @param aChunk A string snippet of generated JS code, another instance of - * SourceNode, or an array where each member is one of those things. - */ -SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { - if (Array.isArray(aChunk)) { - for (var i = aChunk.length-1; i >= 0; i--) { - this.prepend(aChunk[i]); - } - } - else if (aChunk[isSourceNode] || typeof aChunk === "string") { - this.children.unshift(aChunk); - } - else { - throw new TypeError( - "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk - ); - } - return this; -}; - -/** - * Walk over the tree of JS snippets in this node and its children. The - * walking function is called once for each snippet of JS and is passed that - * snippet and the its original associated source's line/column location. - * - * @param aFn The traversal function. - */ -SourceNode.prototype.walk = function SourceNode_walk(aFn) { - var chunk; - for (var i = 0, len = this.children.length; i < len; i++) { - chunk = this.children[i]; - if (chunk[isSourceNode]) { - chunk.walk(aFn); - } - else { - if (chunk !== '') { - aFn(chunk, { source: this.source, - line: this.line, - column: this.column, - name: this.name }); - } - } - } -}; - -/** - * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between - * each of `this.children`. - * - * @param aSep The separator. - */ -SourceNode.prototype.join = function SourceNode_join(aSep) { - var newChildren; - var i; - var len = this.children.length; - if (len > 0) { - newChildren = []; - for (i = 0; i < len-1; i++) { - newChildren.push(this.children[i]); - newChildren.push(aSep); - } - newChildren.push(this.children[i]); - this.children = newChildren; - } - return this; -}; - -/** - * Call String.prototype.replace on the very right-most source snippet. Useful - * for trimming whitespace from the end of a source node, etc. - * - * @param aPattern The pattern to replace. - * @param aReplacement The thing to replace the pattern with. - */ -SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { - var lastChild = this.children[this.children.length - 1]; - if (lastChild[isSourceNode]) { - lastChild.replaceRight(aPattern, aReplacement); - } - else if (typeof lastChild === 'string') { - this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); - } - else { - this.children.push(''.replace(aPattern, aReplacement)); - } - return this; -}; - -/** - * Set the source content for a source file. This will be added to the SourceMapGenerator - * in the sourcesContent field. - * - * @param aSourceFile The filename of the source file - * @param aSourceContent The content of the source file - */ -SourceNode.prototype.setSourceContent = - function SourceNode_setSourceContent(aSourceFile, aSourceContent) { - this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; - }; - -/** - * Walk over the tree of SourceNodes. The walking function is called for each - * source file content and is passed the filename and source content. - * - * @param aFn The traversal function. - */ -SourceNode.prototype.walkSourceContents = - function SourceNode_walkSourceContents(aFn) { - for (var i = 0, len = this.children.length; i < len; i++) { - if (this.children[i][isSourceNode]) { - this.children[i].walkSourceContents(aFn); - } - } - - var sources = Object.keys(this.sourceContents); - for (var i = 0, len = sources.length; i < len; i++) { - aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); - } - }; - -/** - * Return the string representation of this source node. Walks over the tree - * and concatenates all the various snippets together to one string. - */ -SourceNode.prototype.toString = function SourceNode_toString() { - var str = ""; - this.walk(function (chunk) { - str += chunk; - }); - return str; -}; - -/** - * Returns the string representation of this source node along with a source - * map. - */ -SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { - var generated = { - code: "", - line: 1, - column: 0 - }; - var map = new SourceMapGenerator(aArgs); - var sourceMappingActive = false; - var lastOriginalSource = null; - var lastOriginalLine = null; - var lastOriginalColumn = null; - var lastOriginalName = null; - this.walk(function (chunk, original) { - generated.code += chunk; - if (original.source !== null - && original.line !== null - && original.column !== null) { - if(lastOriginalSource !== original.source - || lastOriginalLine !== original.line - || lastOriginalColumn !== original.column - || lastOriginalName !== original.name) { - map.addMapping({ - source: original.source, - original: { - line: original.line, - column: original.column - }, - generated: { - line: generated.line, - column: generated.column - }, - name: original.name - }); - } - lastOriginalSource = original.source; - lastOriginalLine = original.line; - lastOriginalColumn = original.column; - lastOriginalName = original.name; - sourceMappingActive = true; - } else if (sourceMappingActive) { - map.addMapping({ - generated: { - line: generated.line, - column: generated.column - } - }); - lastOriginalSource = null; - sourceMappingActive = false; - } - for (var idx = 0, length = chunk.length; idx < length; idx++) { - if (chunk.charCodeAt(idx) === NEWLINE_CODE) { - generated.line++; - generated.column = 0; - // Mappings end at eol - if (idx + 1 === length) { - lastOriginalSource = null; - sourceMappingActive = false; - } else if (sourceMappingActive) { - map.addMapping({ - source: original.source, - original: { - line: original.line, - column: original.column - }, - generated: { - line: generated.line, - column: generated.column - }, - name: original.name - }); - } - } else { - generated.column++; - } - } - }); - this.walkSourceContents(function (sourceFile, sourceContent) { - map.setSourceContent(sourceFile, sourceContent); - }); - - return { code: generated.code, map: map }; -}; - -exports.SourceNode = SourceNode; - - -/***/ }), -/* 819 */ -/***/ (function(module, exports, __webpack_require__) { - -// Copyright 2014, 2015, 2016, 2017 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var sourceMappingURL = __webpack_require__(820) -var resolveUrl = __webpack_require__(821) -var decodeUriComponent = __webpack_require__(822) -var urix = __webpack_require__(824) -var atob = __webpack_require__(825) - - - -function callbackAsync(callback, error, result) { - setImmediate(function() { callback(error, result) }) -} - -function parseMapToJSON(string, data) { - try { - return JSON.parse(string.replace(/^\)\]\}'/, "")) - } catch (error) { - error.sourceMapData = data - throw error - } -} - -function readSync(read, url, data) { - var readUrl = decodeUriComponent(url) - try { - return String(read(readUrl)) - } catch (error) { - error.sourceMapData = data - throw error - } -} - - - -function resolveSourceMap(code, codeUrl, read, callback) { - var mapData - try { - mapData = resolveSourceMapHelper(code, codeUrl) - } catch (error) { - return callbackAsync(callback, error) - } - if (!mapData || mapData.map) { - return callbackAsync(callback, null, mapData) - } - var readUrl = decodeUriComponent(mapData.url) - read(readUrl, function(error, result) { - if (error) { - error.sourceMapData = mapData - return callback(error) - } - mapData.map = String(result) - try { - mapData.map = parseMapToJSON(mapData.map, mapData) - } catch (error) { - return callback(error) - } - callback(null, mapData) - }) -} - -function resolveSourceMapSync(code, codeUrl, read) { - var mapData = resolveSourceMapHelper(code, codeUrl) - if (!mapData || mapData.map) { - return mapData - } - mapData.map = readSync(read, mapData.url, mapData) - mapData.map = parseMapToJSON(mapData.map, mapData) - return mapData -} - -var dataUriRegex = /^data:([^,;]*)(;[^,;]*)*(?:,(.*))?$/ -var jsonMimeTypeRegex = /^(?:application|text)\/json$/ - -function resolveSourceMapHelper(code, codeUrl) { - codeUrl = urix(codeUrl) - - var url = sourceMappingURL.getFrom(code) - if (!url) { - return null - } - - var dataUri = url.match(dataUriRegex) - if (dataUri) { - var mimeType = dataUri[1] - var lastParameter = dataUri[2] || "" - var encoded = dataUri[3] || "" - var data = { - sourceMappingURL: url, - url: null, - sourcesRelativeTo: codeUrl, - map: encoded - } - if (!jsonMimeTypeRegex.test(mimeType)) { - var error = new Error("Unuseful data uri mime type: " + (mimeType || "text/plain")) - error.sourceMapData = data - throw error - } - data.map = parseMapToJSON( - lastParameter === ";base64" ? atob(encoded) : decodeURIComponent(encoded), - data - ) - return data - } - - var mapUrl = resolveUrl(codeUrl, url) - return { - sourceMappingURL: url, - url: mapUrl, - sourcesRelativeTo: mapUrl, - map: null - } -} - - - -function resolveSources(map, mapUrl, read, options, callback) { - if (typeof options === "function") { - callback = options - options = {} - } - var pending = map.sources ? map.sources.length : 0 - var result = { - sourcesResolved: [], - sourcesContent: [] - } - - if (pending === 0) { - callbackAsync(callback, null, result) - return - } - - var done = function() { - pending-- - if (pending === 0) { - callback(null, result) - } - } - - resolveSourcesHelper(map, mapUrl, options, function(fullUrl, sourceContent, index) { - result.sourcesResolved[index] = fullUrl - if (typeof sourceContent === "string") { - result.sourcesContent[index] = sourceContent - callbackAsync(done, null) - } else { - var readUrl = decodeUriComponent(fullUrl) - read(readUrl, function(error, source) { - result.sourcesContent[index] = error ? error : String(source) - done() - }) - } - }) -} - -function resolveSourcesSync(map, mapUrl, read, options) { - var result = { - sourcesResolved: [], - sourcesContent: [] - } - - if (!map.sources || map.sources.length === 0) { - return result - } - - resolveSourcesHelper(map, mapUrl, options, function(fullUrl, sourceContent, index) { - result.sourcesResolved[index] = fullUrl - if (read !== null) { - if (typeof sourceContent === "string") { - result.sourcesContent[index] = sourceContent - } else { - var readUrl = decodeUriComponent(fullUrl) - try { - result.sourcesContent[index] = String(read(readUrl)) - } catch (error) { - result.sourcesContent[index] = error - } - } - } - }) - - return result -} - -var endingSlash = /\/?$/ - -function resolveSourcesHelper(map, mapUrl, options, fn) { - options = options || {} - mapUrl = urix(mapUrl) - var fullUrl - var sourceContent - var sourceRoot - for (var index = 0, len = map.sources.length; index < len; index++) { - sourceRoot = null - if (typeof options.sourceRoot === "string") { - sourceRoot = options.sourceRoot - } else if (typeof map.sourceRoot === "string" && options.sourceRoot !== false) { - sourceRoot = map.sourceRoot - } - // If the sourceRoot is the empty string, it is equivalent to not setting - // the property at all. - if (sourceRoot === null || sourceRoot === '') { - fullUrl = resolveUrl(mapUrl, map.sources[index]) - } else { - // Make sure that the sourceRoot ends with a slash, so that `/scripts/subdir` becomes - // `/scripts/subdir/`, not `/scripts/`. Pointing to a file as source root - // does not make sense. - fullUrl = resolveUrl(mapUrl, sourceRoot.replace(endingSlash, "/"), map.sources[index]) - } - sourceContent = (map.sourcesContent || [])[index] - fn(fullUrl, sourceContent, index) - } -} - - - -function resolve(code, codeUrl, read, options, callback) { - if (typeof options === "function") { - callback = options - options = {} - } - if (code === null) { - var mapUrl = codeUrl - var data = { - sourceMappingURL: null, - url: mapUrl, - sourcesRelativeTo: mapUrl, - map: null - } - var readUrl = decodeUriComponent(mapUrl) - read(readUrl, function(error, result) { - if (error) { - error.sourceMapData = data - return callback(error) - } - data.map = String(result) - try { - data.map = parseMapToJSON(data.map, data) - } catch (error) { - return callback(error) - } - _resolveSources(data) - }) - } else { - resolveSourceMap(code, codeUrl, read, function(error, mapData) { - if (error) { - return callback(error) - } - if (!mapData) { - return callback(null, null) - } - _resolveSources(mapData) - }) - } - - function _resolveSources(mapData) { - resolveSources(mapData.map, mapData.sourcesRelativeTo, read, options, function(error, result) { - if (error) { - return callback(error) - } - mapData.sourcesResolved = result.sourcesResolved - mapData.sourcesContent = result.sourcesContent - callback(null, mapData) - }) - } -} - -function resolveSync(code, codeUrl, read, options) { - var mapData - if (code === null) { - var mapUrl = codeUrl - mapData = { - sourceMappingURL: null, - url: mapUrl, - sourcesRelativeTo: mapUrl, - map: null - } - mapData.map = readSync(read, mapUrl, mapData) - mapData.map = parseMapToJSON(mapData.map, mapData) - } else { - mapData = resolveSourceMapSync(code, codeUrl, read) - if (!mapData) { - return null - } - } - var result = resolveSourcesSync(mapData.map, mapData.sourcesRelativeTo, read, options) - mapData.sourcesResolved = result.sourcesResolved - mapData.sourcesContent = result.sourcesContent - return mapData -} - - - -module.exports = { - resolveSourceMap: resolveSourceMap, - resolveSourceMapSync: resolveSourceMapSync, - resolveSources: resolveSources, - resolveSourcesSync: resolveSourcesSync, - resolve: resolve, - resolveSync: resolveSync, - parseMapToJSON: parseMapToJSON -} - - -/***/ }), -/* 820 */ -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -void (function(root, factory) { - if (true) { - !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : - __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) - } else {} -}(this, function() { - - var innerRegex = /[#@] sourceMappingURL=([^\s'"]*)/ - - var regex = RegExp( - "(?:" + - "/\\*" + - "(?:\\s*\r?\n(?://)?)?" + - "(?:" + innerRegex.source + ")" + - "\\s*" + - "\\*/" + - "|" + - "//(?:" + innerRegex.source + ")" + - ")" + - "\\s*" - ) - - return { - - regex: regex, - _innerRegex: innerRegex, - - getFrom: function(code) { - var match = code.match(regex) - return (match ? match[1] || match[2] || "" : null) - }, - - existsIn: function(code) { - return regex.test(code) - }, - - removeFrom: function(code) { - return code.replace(regex, "") - }, - - insertBefore: function(code, string) { - var match = code.match(regex) - if (match) { - return code.slice(0, match.index) + string + code.slice(match.index) - } else { - return code + string - } - } - } - -})); - - -/***/ }), -/* 821 */ -/***/ (function(module, exports, __webpack_require__) { - -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var url = __webpack_require__(454) - -function resolveUrl(/* ...urls */) { - return Array.prototype.reduce.call(arguments, function(resolved, nextUrl) { - return url.resolve(resolved, nextUrl) - }) -} - -module.exports = resolveUrl - - -/***/ }), -/* 822 */ -/***/ (function(module, exports, __webpack_require__) { - -// Copyright 2017 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var decodeUriComponent = __webpack_require__(823) - -function customDecodeUriComponent(string) { - // `decodeUriComponent` turns `+` into ` `, but that's not wanted. - return decodeUriComponent(string.replace(/\+/g, "%2B")) -} - -module.exports = customDecodeUriComponent - - -/***/ }), -/* 823 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -var token = '%[a-f0-9]{2}'; -var singleMatcher = new RegExp(token, 'gi'); -var multiMatcher = new RegExp('(' + token + ')+', 'gi'); - -function decodeComponents(components, split) { - try { - // Try to decode the entire string first - return decodeURIComponent(components.join('')); - } catch (err) { - // Do nothing - } - - if (components.length === 1) { - return components; - } - - split = split || 1; - - // Split the array in 2 parts - var left = components.slice(0, split); - var right = components.slice(split); - - return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right)); -} - -function decode(input) { - try { - return decodeURIComponent(input); - } catch (err) { - var tokens = input.match(singleMatcher); - - for (var i = 1; i < tokens.length; i++) { - input = decodeComponents(tokens, i).join(''); - - tokens = input.match(singleMatcher); - } - - return input; - } -} - -function customDecodeURIComponent(input) { - // Keep track of all the replacements and prefill the map with the `BOM` - var replaceMap = { - '%FE%FF': '\uFFFD\uFFFD', - '%FF%FE': '\uFFFD\uFFFD' - }; - - var match = multiMatcher.exec(input); - while (match) { - try { - // Decode as big chunks as possible - replaceMap[match[0]] = decodeURIComponent(match[0]); - } catch (err) { - var result = decode(match[0]); - - if (result !== match[0]) { - replaceMap[match[0]] = result; - } - } - - match = multiMatcher.exec(input); - } - - // Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else - replaceMap['%C2'] = '\uFFFD'; - - var entries = Object.keys(replaceMap); - - for (var i = 0; i < entries.length; i++) { - // Replace all decoded components - var key = entries[i]; - input = input.replace(new RegExp(key, 'g'), replaceMap[key]); - } - - return input; -} - -module.exports = function (encodedURI) { - if (typeof encodedURI !== 'string') { - throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`'); - } - - try { - encodedURI = encodedURI.replace(/\+/g, ' '); - - // Try the built in decoder first - return decodeURIComponent(encodedURI); - } catch (err) { - // Fallback to a more advanced decoder - return customDecodeURIComponent(encodedURI); - } -}; - - -/***/ }), -/* 824 */ -/***/ (function(module, exports, __webpack_require__) { - -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var path = __webpack_require__(16) - -"use strict" - -function urix(aPath) { - if (path.sep === "\\") { - return aPath - .replace(/\\/g, "/") - .replace(/^[a-z]:\/?/i, "/") - } - return aPath -} - -module.exports = urix - - -/***/ }), -/* 825 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -function atob(str) { - return Buffer.from(str, 'base64').toString('binary'); -} - -module.exports = atob.atob = atob; - - -/***/ }), -/* 826 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var fs = __webpack_require__(23); -var path = __webpack_require__(16); -var define = __webpack_require__(730); -var utils = __webpack_require__(807); - -/** - * Expose `mixin()`. - * This code is based on `source-maps-support.js` in reworkcss/css - * https://github.com/reworkcss/css/blob/master/lib/stringify/source-map-support.js - * Copyright (c) 2012 TJ Holowaychuk - */ - -module.exports = mixin; - -/** - * Mixin source map support into `compiler`. - * - * @param {Object} `compiler` - * @api public - */ - -function mixin(compiler) { - define(compiler, '_comment', compiler.comment); - compiler.map = new utils.SourceMap.SourceMapGenerator(); - compiler.position = { line: 1, column: 1 }; - compiler.content = {}; - compiler.files = {}; - - for (var key in exports) { - define(compiler, key, exports[key]); - } -} - -/** - * Update position. - * - * @param {String} str - */ - -exports.updatePosition = function(str) { - var lines = str.match(/\n/g); - if (lines) this.position.line += lines.length; - var i = str.lastIndexOf('\n'); - this.position.column = ~i ? str.length - i : this.position.column + str.length; -}; - -/** - * Emit `str` with `position`. - * - * @param {String} str - * @param {Object} [pos] - * @return {String} - */ - -exports.emit = function(str, node) { - var position = node.position || {}; - var source = position.source; - if (source) { - if (position.filepath) { - source = utils.unixify(position.filepath); - } - - this.map.addMapping({ - source: source, - generated: { - line: this.position.line, - column: Math.max(this.position.column - 1, 0) - }, - original: { - line: position.start.line, - column: position.start.column - 1 - } - }); - - if (position.content) { - this.addContent(source, position); - } - if (position.filepath) { - this.addFile(source, position); - } - - this.updatePosition(str); - this.output += str; - } - return str; -}; - -/** - * Adds a file to the source map output if it has not already been added - * @param {String} `file` - * @param {Object} `pos` - */ - -exports.addFile = function(file, position) { - if (typeof position.content !== 'string') return; - if (Object.prototype.hasOwnProperty.call(this.files, file)) return; - this.files[file] = position.content; -}; - -/** - * Adds a content source to the source map output if it has not already been added - * @param {String} `source` - * @param {Object} `position` - */ - -exports.addContent = function(source, position) { - if (typeof position.content !== 'string') return; - if (Object.prototype.hasOwnProperty.call(this.content, source)) return; - this.map.setSourceContent(source, position.content); -}; - -/** - * Applies any original source maps to the output and embeds the source file - * contents in the source map. - */ - -exports.applySourceMaps = function() { - Object.keys(this.files).forEach(function(file) { - var content = this.files[file]; - this.map.setSourceContent(file, content); - - if (this.options.inputSourcemaps === true) { - var originalMap = utils.sourceMapResolve.resolveSync(content, file, fs.readFileSync); - if (originalMap) { - var map = new utils.SourceMap.SourceMapConsumer(originalMap.map); - var relativeTo = originalMap.sourcesRelativeTo; - this.map.applySourceMap(map, file, utils.unixify(path.dirname(relativeTo))); - } - } - }, this); -}; - -/** - * Process comments, drops sourceMap comments. - * @param {Object} node - */ - -exports.comment = function(node) { - if (/^# sourceMappingURL=/.test(node.comment)) { - return this.emit('', node.position); - } - return this._comment(node); -}; - - -/***/ }), -/* 827 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var use = __webpack_require__(799); -var util = __webpack_require__(29); -var Cache = __webpack_require__(828); -var define = __webpack_require__(730); -var debug = __webpack_require__(801)('snapdragon:parser'); -var Position = __webpack_require__(829); -var utils = __webpack_require__(807); - -/** - * Create a new `Parser` with the given `input` and `options`. - * @param {String} `input` - * @param {Object} `options` - * @api public - */ - -function Parser(options) { - debug('initializing', __filename); - this.options = utils.extend({source: 'string'}, options); - this.init(this.options); - use(this); -} - -/** - * Prototype methods - */ - -Parser.prototype = { - constructor: Parser, - - init: function(options) { - this.orig = ''; - this.input = ''; - this.parsed = ''; - - this.column = 1; - this.line = 1; - - this.regex = new Cache(); - this.errors = this.errors || []; - this.parsers = this.parsers || {}; - this.types = this.types || []; - this.sets = this.sets || {}; - this.fns = this.fns || []; - this.currentType = 'root'; - - var pos = this.position(); - this.bos = pos({type: 'bos', val: ''}); - - this.ast = { - type: 'root', - errors: this.errors, - nodes: [this.bos] - }; - - define(this.bos, 'parent', this.ast); - this.nodes = [this.ast]; - - this.count = 0; - this.setCount = 0; - this.stack = []; - }, - - /** - * Throw a formatted error with the cursor column and `msg`. - * @param {String} `msg` Message to use in the Error. - */ - - error: function(msg, node) { - var pos = node.position || {start: {column: 0, line: 0}}; - var line = pos.start.line; - var column = pos.start.column; - var source = this.options.source; - - var message = source + ' : ' + msg; - var err = new Error(message); - err.source = source; - err.reason = msg; - err.pos = pos; - - if (this.options.silent) { - this.errors.push(err); - } else { - throw err; - } - }, - - /** - * Define a non-enumberable property on the `Parser` instance. - * - * ```js - * parser.define('foo', 'bar'); - * ``` - * @name .define - * @param {String} `key` propery name - * @param {any} `val` property value - * @return {Object} Returns the Parser instance for chaining. - * @api public - */ - - define: function(key, val) { - define(this, key, val); - return this; - }, - - /** - * Mark position and patch `node.position`. - */ - - position: function() { - var start = { line: this.line, column: this.column }; - var self = this; - - return function(node) { - define(node, 'position', new Position(start, self)); - return node; - }; - }, - - /** - * Set parser `name` with the given `fn` - * @param {String} `name` - * @param {Function} `fn` - * @api public - */ - - set: function(type, fn) { - if (this.types.indexOf(type) === -1) { - this.types.push(type); - } - this.parsers[type] = fn.bind(this); - return this; - }, - - /** - * Get parser `name` - * @param {String} `name` - * @api public - */ - - get: function(name) { - return this.parsers[name]; - }, - - /** - * Push a `token` onto the `type` stack. - * - * @param {String} `type` - * @return {Object} `token` - * @api public - */ - - push: function(type, token) { - this.sets[type] = this.sets[type] || []; - this.count++; - this.stack.push(token); - return this.sets[type].push(token); - }, - - /** - * Pop a token off of the `type` stack - * @param {String} `type` - * @returns {Object} Returns a token - * @api public - */ - - pop: function(type) { - this.sets[type] = this.sets[type] || []; - this.count--; - this.stack.pop(); - return this.sets[type].pop(); - }, - - /** - * Return true if inside a `stack` node. Types are `braces`, `parens` or `brackets`. - * - * @param {String} `type` - * @return {Boolean} - * @api public - */ - - isInside: function(type) { - this.sets[type] = this.sets[type] || []; - return this.sets[type].length > 0; - }, - - /** - * Return true if `node` is the given `type`. - * - * ```js - * parser.isType(node, 'brace'); - * ``` - * @param {Object} `node` - * @param {String} `type` - * @return {Boolean} - * @api public - */ - - isType: function(node, type) { - return node && node.type === type; - }, - - /** - * Get the previous AST node - * @return {Object} - */ - - prev: function(n) { - return this.stack.length > 0 - ? utils.last(this.stack, n) - : utils.last(this.nodes, n); - }, - - /** - * Update line and column based on `str`. - */ - - consume: function(len) { - this.input = this.input.substr(len); - }, - - /** - * Update column based on `str`. - */ - - updatePosition: function(str, len) { - var lines = str.match(/\n/g); - if (lines) this.line += lines.length; - var i = str.lastIndexOf('\n'); - this.column = ~i ? len - i : this.column + len; - this.parsed += str; - this.consume(len); - }, - - /** - * Match `regex`, return captures, and update the cursor position by `match[0]` length. - * @param {RegExp} `regex` - * @return {Object} - */ - - match: function(regex) { - var m = regex.exec(this.input); - if (m) { - this.updatePosition(m[0], m[0].length); - return m; - } - }, - - /** - * Capture `type` with the given regex. - * @param {String} `type` - * @param {RegExp} `regex` - * @return {Function} - */ - - capture: function(type, regex) { - if (typeof regex === 'function') { - return this.set.apply(this, arguments); - } - - this.regex.set(type, regex); - this.set(type, function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(regex); - if (!m || !m[0]) return; - - var prev = this.prev(); - var node = pos({ - type: type, - val: m[0], - parsed: parsed, - rest: this.input - }); - - if (m[1]) { - node.inner = m[1]; - } - - define(node, 'inside', this.stack.length > 0); - define(node, 'parent', prev); - prev.nodes.push(node); - }.bind(this)); - return this; - }, - - /** - * Create a parser with open and close for parens, - * brackets or braces - */ - - capturePair: function(type, openRegex, closeRegex, fn) { - this.sets[type] = this.sets[type] || []; - - /** - * Open - */ - - this.set(type + '.open', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(openRegex); - if (!m || !m[0]) return; - - var val = m[0]; - this.setCount++; - this.specialChars = true; - var open = pos({ - type: type + '.open', - val: val, - rest: this.input - }); - - if (typeof m[1] !== 'undefined') { - open.inner = m[1]; - } - - var prev = this.prev(); - var node = pos({ - type: type, - nodes: [open] - }); - - define(node, 'rest', this.input); - define(node, 'parsed', parsed); - define(node, 'prefix', m[1]); - define(node, 'parent', prev); - define(open, 'parent', node); - - if (typeof fn === 'function') { - fn.call(this, open, node); - } - - this.push(type, node); - prev.nodes.push(node); - }); - - /** - * Close - */ - - this.set(type + '.close', function() { - var pos = this.position(); - var m = this.match(closeRegex); - if (!m || !m[0]) return; - - var parent = this.pop(type); - var node = pos({ - type: type + '.close', - rest: this.input, - suffix: m[1], - val: m[0] - }); - - if (!this.isType(parent, type)) { - if (this.options.strict) { - throw new Error('missing opening "' + type + '"'); - } - - this.setCount--; - node.escaped = true; - return node; - } - - if (node.suffix === '\\') { - parent.escaped = true; - node.escaped = true; - } - - parent.nodes.push(node); - define(node, 'parent', parent); - }); - - return this; - }, - - /** - * Capture end-of-string - */ - - eos: function() { - var pos = this.position(); - if (this.input) return; - var prev = this.prev(); - - while (prev.type !== 'root' && !prev.visited) { - if (this.options.strict === true) { - throw new SyntaxError('invalid syntax:' + util.inspect(prev, null, 2)); - } - - if (!hasDelims(prev)) { - prev.parent.escaped = true; - prev.escaped = true; - } - - visit(prev, function(node) { - if (!hasDelims(node.parent)) { - node.parent.escaped = true; - node.escaped = true; - } - }); - - prev = prev.parent; - } - - var tok = pos({ - type: 'eos', - val: this.append || '' - }); - - define(tok, 'parent', this.ast); - return tok; - }, - - /** - * Run parsers to advance the cursor position - */ - - next: function() { - var parsed = this.parsed; - var len = this.types.length; - var idx = -1; - var tok; - - while (++idx < len) { - if ((tok = this.parsers[this.types[idx]].call(this))) { - define(tok, 'rest', this.input); - define(tok, 'parsed', parsed); - this.last = tok; - return tok; - } - } - }, - - /** - * Parse the given string. - * @return {Array} - */ - - parse: function(input) { - if (typeof input !== 'string') { - throw new TypeError('expected a string'); - } - - this.init(this.options); - this.orig = input; - this.input = input; - var self = this; - - function parse() { - // check input before calling `.next()` - input = self.input; - - // get the next AST ndoe - var node = self.next(); - if (node) { - var prev = self.prev(); - if (prev) { - define(node, 'parent', prev); - if (prev.nodes) { - prev.nodes.push(node); - } - } - - if (self.sets.hasOwnProperty(prev.type)) { - self.currentType = prev.type; - } - } - - // if we got here but input is not changed, throw an error - if (self.input && input === self.input) { - throw new Error('no parsers registered for: "' + self.input.slice(0, 5) + '"'); - } - } - - while (this.input) parse(); - if (this.stack.length && this.options.strict) { - var node = this.stack.pop(); - throw this.error('missing opening ' + node.type + ': "' + this.orig + '"'); - } - - var eos = this.eos(); - var tok = this.prev(); - if (tok.type !== 'eos') { - this.ast.nodes.push(eos); - } - - return this.ast; - } -}; - -/** - * Visit `node` with the given `fn` - */ - -function visit(node, fn) { - if (!node.visited) { - define(node, 'visited', true); - return node.nodes ? mapVisit(node.nodes, fn) : fn(node); - } - return node; -} - -/** - * Map visit over array of `nodes`. - */ - -function mapVisit(nodes, fn) { - var len = nodes.length; - var idx = -1; - while (++idx < len) { - visit(nodes[idx], fn); - } -} - -function hasOpen(node) { - return node.nodes && node.nodes[0].type === (node.type + '.open'); -} - -function hasClose(node) { - return node.nodes && utils.last(node.nodes).type === (node.type + '.close'); -} - -function hasDelims(node) { - return hasOpen(node) && hasClose(node); -} - -/** - * Expose `Parser` - */ - -module.exports = Parser; - - -/***/ }), -/* 828 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * map-cache - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var hasOwn = Object.prototype.hasOwnProperty; - -/** - * Expose `MapCache` - */ - -module.exports = MapCache; - -/** - * Creates a cache object to store key/value pairs. - * - * ```js - * var cache = new MapCache(); - * ``` - * - * @api public - */ - -function MapCache(data) { - this.__data__ = data || {}; -} - -/** - * Adds `value` to `key` on the cache. - * - * ```js - * cache.set('foo', 'bar'); - * ``` - * - * @param {String} `key` The key of the value to cache. - * @param {*} `value` The value to cache. - * @returns {Object} Returns the `Cache` object for chaining. - * @api public - */ - -MapCache.prototype.set = function mapSet(key, value) { - if (key !== '__proto__') { - this.__data__[key] = value; - } - return this; -}; - -/** - * Gets the cached value for `key`. - * - * ```js - * cache.get('foo'); - * //=> 'bar' - * ``` - * - * @param {String} `key` The key of the value to get. - * @returns {*} Returns the cached value. - * @api public - */ - -MapCache.prototype.get = function mapGet(key) { - return key === '__proto__' ? undefined : this.__data__[key]; -}; - -/** - * Checks if a cached value for `key` exists. - * - * ```js - * cache.has('foo'); - * //=> true - * ``` - * - * @param {String} `key` The key of the entry to check. - * @returns {Boolean} Returns `true` if an entry for `key` exists, else `false`. - * @api public - */ - -MapCache.prototype.has = function mapHas(key) { - return key !== '__proto__' && hasOwn.call(this.__data__, key); -}; - -/** - * Removes `key` and its value from the cache. - * - * ```js - * cache.del('foo'); - * ``` - * @title .del - * @param {String} `key` The key of the value to remove. - * @returns {Boolean} Returns `true` if the entry was removed successfully, else `false`. - * @api public - */ - -MapCache.prototype.del = function mapDelete(key) { - return this.has(key) && delete this.__data__[key]; -}; - - -/***/ }), -/* 829 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var define = __webpack_require__(730); - -/** - * Store position for a node - */ - -module.exports = function Position(start, parser) { - this.start = start; - this.end = { line: parser.line, column: parser.column }; - define(this, 'content', parser.orig); - define(this, 'source', parser.options.source); -}; - - -/***/ }), -/* 830 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var safe = __webpack_require__(831); -var define = __webpack_require__(837); -var extend = __webpack_require__(838); -var not = __webpack_require__(840); -var MAX_LENGTH = 1024 * 64; - -/** - * Session cache - */ - -var cache = {}; - -/** - * Create a regular expression from the given `pattern` string. - * - * @param {String|RegExp} `pattern` Pattern can be a string or regular expression. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ - -module.exports = function(patterns, options) { - if (!Array.isArray(patterns)) { - return makeRe(patterns, options); - } - return makeRe(patterns.join('|'), options); -}; - -/** - * Create a regular expression from the given `pattern` string. - * - * @param {String|RegExp} `pattern` Pattern can be a string or regular expression. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ - -function makeRe(pattern, options) { - if (pattern instanceof RegExp) { - return pattern; - } - - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - if (pattern.length > MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); - } - - var key = pattern; - // do this before shallow cloning options, it's a lot faster - if (!options || (options && options.cache !== false)) { - key = createKey(pattern, options); - - if (cache.hasOwnProperty(key)) { - return cache[key]; - } - } - - var opts = extend({}, options); - if (opts.contains === true) { - if (opts.negate === true) { - opts.strictNegate = false; - } else { - opts.strict = false; - } - } - - if (opts.strict === false) { - opts.strictOpen = false; - opts.strictClose = false; - } - - var open = opts.strictOpen !== false ? '^' : ''; - var close = opts.strictClose !== false ? '$' : ''; - var flags = opts.flags || ''; - var regex; - - if (opts.nocase === true && !/i/.test(flags)) { - flags += 'i'; - } - - try { - if (opts.negate || typeof opts.strictNegate === 'boolean') { - pattern = not.create(pattern, opts); - } - - var str = open + '(?:' + pattern + ')' + close; - regex = new RegExp(str, flags); - - if (opts.safe === true && safe(regex) === false) { - throw new Error('potentially unsafe regular expression: ' + regex.source); - } - - } catch (err) { - if (opts.strictErrors === true || opts.safe === true) { - err.key = key; - err.pattern = pattern; - err.originalOptions = options; - err.createdOptions = opts; - throw err; - } - - try { - regex = new RegExp('^' + pattern.replace(/(\W)/g, '\\$1') + '$'); - } catch (err) { - regex = /.^/; //<= match nothing - } - } - - if (opts.cache !== false) { - memoize(regex, key, pattern, opts); - } - return regex; -} - -/** - * Memoize generated regex. This can result in dramatic speed improvements - * and simplify debugging by adding options and pattern to the regex. It can be - * disabled by passing setting `options.cache` to false. - */ - -function memoize(regex, key, pattern, options) { - define(regex, 'cached', true); - define(regex, 'pattern', pattern); - define(regex, 'options', options); - define(regex, 'key', key); - cache[key] = regex; -} - -/** - * Create the key to use for memoization. The key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. - */ - -function createKey(pattern, options) { - if (!options) return pattern; - var key = pattern; - for (var prop in options) { - if (options.hasOwnProperty(prop)) { - key += ';' + prop + '=' + String(options[prop]); - } - } - return key; -} - -/** - * Expose `makeRe` - */ - -module.exports.makeRe = makeRe; - - -/***/ }), -/* 831 */ -/***/ (function(module, exports, __webpack_require__) { - -var parse = __webpack_require__(832); -var types = parse.types; - -module.exports = function (re, opts) { - if (!opts) opts = {}; - var replimit = opts.limit === undefined ? 25 : opts.limit; - - if (isRegExp(re)) re = re.source; - else if (typeof re !== 'string') re = String(re); - - try { re = parse(re) } - catch (err) { return false } - - var reps = 0; - return (function walk (node, starHeight) { - if (node.type === types.REPETITION) { - starHeight ++; - reps ++; - if (starHeight > 1) return false; - if (reps > replimit) return false; - } - - if (node.options) { - for (var i = 0, len = node.options.length; i < len; i++) { - var ok = walk({ stack: node.options[i] }, starHeight); - if (!ok) return false; - } - } - var stack = node.stack || (node.value && node.value.stack); - if (!stack) return true; - - for (var i = 0; i < stack.length; i++) { - var ok = walk(stack[i], starHeight); - if (!ok) return false; - } - - return true; - })(re, 0); -}; - -function isRegExp (x) { - return {}.toString.call(x) === '[object RegExp]'; -} - - -/***/ }), -/* 832 */ -/***/ (function(module, exports, __webpack_require__) { - -var util = __webpack_require__(833); -var types = __webpack_require__(834); -var sets = __webpack_require__(835); -var positions = __webpack_require__(836); - - -module.exports = function(regexpStr) { - var i = 0, l, c, - start = { type: types.ROOT, stack: []}, - - // Keep track of last clause/group and stack. - lastGroup = start, - last = start.stack, - groupStack = []; - - - var repeatErr = function(i) { - util.error(regexpStr, 'Nothing to repeat at column ' + (i - 1)); - }; - - // Decode a few escaped characters. - var str = util.strToChars(regexpStr); - l = str.length; - - // Iterate through each character in string. - while (i < l) { - c = str[i++]; - - switch (c) { - // Handle escaped characters, inclues a few sets. - case '\\': - c = str[i++]; - - switch (c) { - case 'b': - last.push(positions.wordBoundary()); - break; - - case 'B': - last.push(positions.nonWordBoundary()); - break; - - case 'w': - last.push(sets.words()); - break; - - case 'W': - last.push(sets.notWords()); - break; - - case 'd': - last.push(sets.ints()); - break; - - case 'D': - last.push(sets.notInts()); - break; - - case 's': - last.push(sets.whitespace()); - break; - - case 'S': - last.push(sets.notWhitespace()); - break; - - default: - // Check if c is integer. - // In which case it's a reference. - if (/\d/.test(c)) { - last.push({ type: types.REFERENCE, value: parseInt(c, 10) }); - - // Escaped character. - } else { - last.push({ type: types.CHAR, value: c.charCodeAt(0) }); - } - } - - break; - - - // Positionals. - case '^': - last.push(positions.begin()); - break; - - case '$': - last.push(positions.end()); - break; - - - // Handle custom sets. - case '[': - // Check if this class is 'anti' i.e. [^abc]. - var not; - if (str[i] === '^') { - not = true; - i++; - } else { - not = false; - } - - // Get all the characters in class. - var classTokens = util.tokenizeClass(str.slice(i), regexpStr); - - // Increase index by length of class. - i += classTokens[1]; - last.push({ - type: types.SET, - set: classTokens[0], - not: not, - }); - - break; - - - // Class of any character except \n. - case '.': - last.push(sets.anyChar()); - break; - - - // Push group onto stack. - case '(': - // Create group. - var group = { - type: types.GROUP, - stack: [], - remember: true, - }; - - c = str[i]; - - // If if this is a special kind of group. - if (c === '?') { - c = str[i + 1]; - i += 2; - - // Match if followed by. - if (c === '=') { - group.followedBy = true; - - // Match if not followed by. - } else if (c === '!') { - group.notFollowedBy = true; - - } else if (c !== ':') { - util.error(regexpStr, - 'Invalid group, character \'' + c + - '\' after \'?\' at column ' + (i - 1)); - } - - group.remember = false; - } - - // Insert subgroup into current group stack. - last.push(group); - - // Remember the current group for when the group closes. - groupStack.push(lastGroup); - - // Make this new group the current group. - lastGroup = group; - last = group.stack; - break; - - - // Pop group out of stack. - case ')': - if (groupStack.length === 0) { - util.error(regexpStr, 'Unmatched ) at column ' + (i - 1)); - } - lastGroup = groupStack.pop(); - - // Check if this group has a PIPE. - // To get back the correct last stack. - last = lastGroup.options ? - lastGroup.options[lastGroup.options.length - 1] : lastGroup.stack; - break; - - - // Use pipe character to give more choices. - case '|': - // Create array where options are if this is the first PIPE - // in this clause. - if (!lastGroup.options) { - lastGroup.options = [lastGroup.stack]; - delete lastGroup.stack; - } - - // Create a new stack and add to options for rest of clause. - var stack = []; - lastGroup.options.push(stack); - last = stack; - break; - - - // Repetition. - // For every repetition, remove last element from last stack - // then insert back a RANGE object. - // This design is chosen because there could be more than - // one repetition symbols in a regex i.e. `a?+{2,3}`. - case '{': - var rs = /^(\d+)(,(\d+)?)?\}/.exec(str.slice(i)), min, max; - if (rs !== null) { - if (last.length === 0) { - repeatErr(i); - } - min = parseInt(rs[1], 10); - max = rs[2] ? rs[3] ? parseInt(rs[3], 10) : Infinity : min; - i += rs[0].length; - - last.push({ - type: types.REPETITION, - min: min, - max: max, - value: last.pop(), - }); - } else { - last.push({ - type: types.CHAR, - value: 123, - }); - } - break; - - case '?': - if (last.length === 0) { - repeatErr(i); - } - last.push({ - type: types.REPETITION, - min: 0, - max: 1, - value: last.pop(), - }); - break; - - case '+': - if (last.length === 0) { - repeatErr(i); - } - last.push({ - type: types.REPETITION, - min: 1, - max: Infinity, - value: last.pop(), - }); - break; - - case '*': - if (last.length === 0) { - repeatErr(i); - } - last.push({ - type: types.REPETITION, - min: 0, - max: Infinity, - value: last.pop(), - }); - break; - - - // Default is a character that is not `\[](){}?+*^$`. - default: - last.push({ - type: types.CHAR, - value: c.charCodeAt(0), - }); - } - - } - - // Check if any groups have not been closed. - if (groupStack.length !== 0) { - util.error(regexpStr, 'Unterminated group'); - } - - return start; -}; - -module.exports.types = types; - - -/***/ }), -/* 833 */ -/***/ (function(module, exports, __webpack_require__) { - -var types = __webpack_require__(834); -var sets = __webpack_require__(835); - - -// All of these are private and only used by randexp. -// It's assumed that they will always be called with the correct input. - -var CTRL = '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ ?'; -var SLSH = { '0': 0, 't': 9, 'n': 10, 'v': 11, 'f': 12, 'r': 13 }; - -/** - * Finds character representations in str and convert all to - * their respective characters - * - * @param {String} str - * @return {String} - */ -exports.strToChars = function(str) { - /* jshint maxlen: false */ - var chars_regex = /(\[\\b\])|(\\)?\\(?:u([A-F0-9]{4})|x([A-F0-9]{2})|(0?[0-7]{2})|c([@A-Z\[\\\]\^?])|([0tnvfr]))/g; - str = str.replace(chars_regex, function(s, b, lbs, a16, b16, c8, dctrl, eslsh) { - if (lbs) { - return s; - } - - var code = b ? 8 : - a16 ? parseInt(a16, 16) : - b16 ? parseInt(b16, 16) : - c8 ? parseInt(c8, 8) : - dctrl ? CTRL.indexOf(dctrl) : - SLSH[eslsh]; - - var c = String.fromCharCode(code); - - // Escape special regex characters. - if (/[\[\]{}\^$.|?*+()]/.test(c)) { - c = '\\' + c; - } - - return c; - }); - - return str; -}; - - -/** - * turns class into tokens - * reads str until it encounters a ] not preceeded by a \ - * - * @param {String} str - * @param {String} regexpStr - * @return {Array., Number>} - */ -exports.tokenizeClass = function(str, regexpStr) { - /* jshint maxlen: false */ - var tokens = []; - var regexp = /\\(?:(w)|(d)|(s)|(W)|(D)|(S))|((?:(?:\\)(.)|([^\]\\]))-(?:\\)?([^\]]))|(\])|(?:\\)?(.)/g; - var rs, c; - - - while ((rs = regexp.exec(str)) != null) { - if (rs[1]) { - tokens.push(sets.words()); - - } else if (rs[2]) { - tokens.push(sets.ints()); - - } else if (rs[3]) { - tokens.push(sets.whitespace()); - - } else if (rs[4]) { - tokens.push(sets.notWords()); - - } else if (rs[5]) { - tokens.push(sets.notInts()); - - } else if (rs[6]) { - tokens.push(sets.notWhitespace()); - - } else if (rs[7]) { - tokens.push({ - type: types.RANGE, - from: (rs[8] || rs[9]).charCodeAt(0), - to: rs[10].charCodeAt(0), - }); - - } else if (c = rs[12]) { - tokens.push({ - type: types.CHAR, - value: c.charCodeAt(0), - }); - - } else { - return [tokens, regexp.lastIndex]; - } - } - - exports.error(regexpStr, 'Unterminated character class'); -}; - - -/** - * Shortcut to throw errors. - * - * @param {String} regexp - * @param {String} msg - */ -exports.error = function(regexp, msg) { - throw new SyntaxError('Invalid regular expression: /' + regexp + '/: ' + msg); -}; - - -/***/ }), -/* 834 */ -/***/ (function(module, exports) { - -module.exports = { - ROOT : 0, - GROUP : 1, - POSITION : 2, - SET : 3, - RANGE : 4, - REPETITION : 5, - REFERENCE : 6, - CHAR : 7, -}; - - -/***/ }), -/* 835 */ -/***/ (function(module, exports, __webpack_require__) { - -var types = __webpack_require__(834); - -var INTS = function() { - return [{ type: types.RANGE , from: 48, to: 57 }]; -}; - -var WORDS = function() { - return [ - { type: types.CHAR, value: 95 }, - { type: types.RANGE, from: 97, to: 122 }, - { type: types.RANGE, from: 65, to: 90 } - ].concat(INTS()); -}; - -var WHITESPACE = function() { - return [ - { type: types.CHAR, value: 9 }, - { type: types.CHAR, value: 10 }, - { type: types.CHAR, value: 11 }, - { type: types.CHAR, value: 12 }, - { type: types.CHAR, value: 13 }, - { type: types.CHAR, value: 32 }, - { type: types.CHAR, value: 160 }, - { type: types.CHAR, value: 5760 }, - { type: types.CHAR, value: 6158 }, - { type: types.CHAR, value: 8192 }, - { type: types.CHAR, value: 8193 }, - { type: types.CHAR, value: 8194 }, - { type: types.CHAR, value: 8195 }, - { type: types.CHAR, value: 8196 }, - { type: types.CHAR, value: 8197 }, - { type: types.CHAR, value: 8198 }, - { type: types.CHAR, value: 8199 }, - { type: types.CHAR, value: 8200 }, - { type: types.CHAR, value: 8201 }, - { type: types.CHAR, value: 8202 }, - { type: types.CHAR, value: 8232 }, - { type: types.CHAR, value: 8233 }, - { type: types.CHAR, value: 8239 }, - { type: types.CHAR, value: 8287 }, - { type: types.CHAR, value: 12288 }, - { type: types.CHAR, value: 65279 } - ]; -}; - -var NOTANYCHAR = function() { - return [ - { type: types.CHAR, value: 10 }, - { type: types.CHAR, value: 13 }, - { type: types.CHAR, value: 8232 }, - { type: types.CHAR, value: 8233 }, - ]; -}; - -// Predefined class objects. -exports.words = function() { - return { type: types.SET, set: WORDS(), not: false }; -}; - -exports.notWords = function() { - return { type: types.SET, set: WORDS(), not: true }; -}; - -exports.ints = function() { - return { type: types.SET, set: INTS(), not: false }; -}; - -exports.notInts = function() { - return { type: types.SET, set: INTS(), not: true }; -}; - -exports.whitespace = function() { - return { type: types.SET, set: WHITESPACE(), not: false }; -}; - -exports.notWhitespace = function() { - return { type: types.SET, set: WHITESPACE(), not: true }; -}; - -exports.anyChar = function() { - return { type: types.SET, set: NOTANYCHAR(), not: true }; -}; - - -/***/ }), -/* 836 */ -/***/ (function(module, exports, __webpack_require__) { - -var types = __webpack_require__(834); - -exports.wordBoundary = function() { - return { type: types.POSITION, value: 'b' }; -}; - -exports.nonWordBoundary = function() { - return { type: types.POSITION, value: 'B' }; -}; - -exports.begin = function() { - return { type: types.POSITION, value: '^' }; -}; - -exports.end = function() { - return { type: types.POSITION, value: '$' }; -}; - - -/***/ }), -/* 837 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015-2018, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isobject = __webpack_require__(748); -var isDescriptor = __webpack_require__(760); -var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) - ? Reflect.defineProperty - : Object.defineProperty; - -module.exports = function defineProperty(obj, key, val) { - if (!isobject(obj) && typeof obj !== 'function' && !Array.isArray(obj)) { - throw new TypeError('expected an object, function, or array'); - } - - if (typeof key !== 'string') { - throw new TypeError('expected "key" to be a string'); - } - - if (isDescriptor(val)) { - define(obj, key, val); - return obj; - } - - define(obj, key, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); - - return obj; -}; - - -/***/ }), -/* 838 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isExtendable = __webpack_require__(839); -var assignSymbols = __webpack_require__(749); - -module.exports = Object.assign || function(obj/*, objects*/) { - if (obj === null || typeof obj === 'undefined') { - throw new TypeError('Cannot convert undefined or null to object'); - } - if (!isObject(obj)) { - obj = {}; - } - for (var i = 1; i < arguments.length; i++) { - var val = arguments[i]; - if (isString(val)) { - val = toObject(val); - } - if (isObject(val)) { - assign(obj, val); - assignSymbols(obj, val); - } - } - return obj; -}; - -function assign(a, b) { - for (var key in b) { - if (hasOwn(b, key)) { - a[key] = b[key]; - } - } -} - -function isString(val) { - return (val && typeof val === 'string'); -} - -function toObject(str) { - var obj = {}; - for (var i in str) { - obj[i] = str[i]; - } - return obj; -} - -function isObject(val) { - return (val && typeof val === 'object') || isExtendable(val); -} - -/** - * Returns true if the given `key` is an own property of `obj`. - */ - -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - -function isEnum(obj, key) { - return Object.prototype.propertyIsEnumerable.call(obj, key); -} - - -/***/ }), -/* 839 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-extendable - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isPlainObject = __webpack_require__(747); - -module.exports = function isExtendable(val) { - return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); -}; - - -/***/ }), -/* 840 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var extend = __webpack_require__(838); -var safe = __webpack_require__(831); - -/** - * The main export is a function that takes a `pattern` string and an `options` object. - * - * ```js - & var not = require('regex-not'); - & console.log(not('foo')); - & //=> /^(?:(?!^(?:foo)$).)*$/ - * ``` - * - * @param {String} `pattern` - * @param {Object} `options` - * @return {RegExp} Converts the given `pattern` to a regex using the specified `options`. - * @api public - */ - -function toRegex(pattern, options) { - return new RegExp(toRegex.create(pattern, options)); -} - -/** - * Create a regex-compatible string from the given `pattern` and `options`. - * - * ```js - & var not = require('regex-not'); - & console.log(not.create('foo')); - & //=> '^(?:(?!^(?:foo)$).)*$' - * ``` - * @param {String} `pattern` - * @param {Object} `options` - * @return {String} - * @api public - */ - -toRegex.create = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - var opts = extend({}, options); - if (opts.contains === true) { - opts.strictNegate = false; - } - - var open = opts.strictOpen !== false ? '^' : ''; - var close = opts.strictClose !== false ? '$' : ''; - var endChar = opts.endChar ? opts.endChar : '+'; - var str = pattern; - - if (opts.strictNegate === false) { - str = '(?:(?!(?:' + pattern + ')).)' + endChar; - } else { - str = '(?:(?!^(?:' + pattern + ')$).)' + endChar; - } - - var res = open + str + close; - if (opts.safe === true && safe(res) === false) { - throw new Error('potentially unsafe regular expression: ' + res); - } - - return res; -}; - -/** - * Expose `toRegex` - */ - -module.exports = toRegex; - - -/***/ }), -/* 841 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var nanomatch = __webpack_require__(842); -var extglob = __webpack_require__(857); - -module.exports = function(snapdragon) { - var compilers = snapdragon.compiler.compilers; - var opts = snapdragon.options; - - // register nanomatch compilers - snapdragon.use(nanomatch.compilers); - - // get references to some specific nanomatch compilers before they - // are overridden by the extglob and/or custom compilers - var escape = compilers.escape; - var qmark = compilers.qmark; - var slash = compilers.slash; - var star = compilers.star; - var text = compilers.text; - var plus = compilers.plus; - var dot = compilers.dot; - - // register extglob compilers or escape exglobs if disabled - if (opts.extglob === false || opts.noext === true) { - snapdragon.compiler.use(escapeExtglobs); - } else { - snapdragon.use(extglob.compilers); - } - - snapdragon.use(function() { - this.options.star = this.options.star || function(/*node*/) { - return '[^\\\\/]*?'; - }; - }); - - // custom micromatch compilers - snapdragon.compiler - - // reset referenced compiler - .set('dot', dot) - .set('escape', escape) - .set('plus', plus) - .set('slash', slash) - .set('qmark', qmark) - .set('star', star) - .set('text', text); -}; - -function escapeExtglobs(compiler) { - compiler.set('paren', function(node) { - var val = ''; - visit(node, function(tok) { - if (tok.val) val += (/^\W/.test(tok.val) ? '\\' : '') + tok.val; - }); - return this.emit(val, node); - }); - - /** - * Visit `node` with the given `fn` - */ - - function visit(node, fn) { - return node.nodes ? mapVisit(node.nodes, fn) : fn(node); - } - - /** - * Map visit over array of `nodes`. - */ - - function mapVisit(nodes, fn) { - var len = nodes.length; - var idx = -1; - while (++idx < len) { - visit(nodes[idx], fn); - } - } -} - - -/***/ }), -/* 842 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Module dependencies - */ - -var util = __webpack_require__(29); -var toRegex = __webpack_require__(729); -var extend = __webpack_require__(843); - -/** - * Local dependencies - */ - -var compilers = __webpack_require__(845); -var parsers = __webpack_require__(846); -var cache = __webpack_require__(849); -var utils = __webpack_require__(851); -var MAX_LENGTH = 1024 * 64; - -/** - * The main function takes a list of strings and one or more - * glob patterns to use for matching. - * - * ```js - * var nm = require('nanomatch'); - * nm(list, patterns[, options]); - * - * console.log(nm(['a.js', 'a.txt'], ['*.js'])); - * //=> [ 'a.js' ] - * ``` - * @param {Array} `list` A 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) for changing how matches are performed - * @return {Array} Returns an array of matches - * @summary false - * @api public - */ - -function nanomatch(list, patterns, options) { - patterns = utils.arrayify(patterns); - list = utils.arrayify(list); - - var len = patterns.length; - if (list.length === 0 || len === 0) { - return []; - } - - if (len === 1) { - return nanomatch.match(list, patterns[0], options); - } - - var negated = false; - var omit = []; - var keep = []; - var idx = -1; - - while (++idx < len) { - var pattern = patterns[idx]; - - if (typeof pattern === 'string' && pattern.charCodeAt(0) === 33 /* ! */) { - omit.push.apply(omit, nanomatch.match(list, pattern.slice(1), options)); - negated = true; - } else { - keep.push.apply(keep, nanomatch.match(list, pattern, options)); - } - } - - // minimatch.match parity - if (negated && keep.length === 0) { - if (options && options.unixify === false) { - keep = list.slice(); - } else { - var unixify = utils.unixify(options); - for (var i = 0; i < list.length; i++) { - keep.push(unixify(list[i])); - } - } - } - - var matches = utils.diff(keep, omit); - if (!options || options.nodupes !== false) { - return utils.unique(matches); - } - - return matches; -} - -/** - * Similar to the main function, but `pattern` must be a string. - * - * ```js - * var nm = require('nanomatch'); - * nm.match(list, pattern[, options]); - * - * console.log(nm.match(['a.a', 'a.aa', 'a.b', 'a.c'], '*.a')); - * //=> ['a.a', 'a.aa'] - * ``` - * @param {Array} `list` Array of strings to match - * @param {String} `pattern` 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 matches - * @api public - */ - -nanomatch.match = function(list, pattern, options) { - if (Array.isArray(pattern)) { - throw new TypeError('expected pattern to be a string'); - } - - var unixify = utils.unixify(options); - var isMatch = memoize('match', pattern, options, nanomatch.matcher); - var matches = []; - - list = utils.arrayify(list); - var len = list.length; - var idx = -1; - - while (++idx < len) { - var ele = list[idx]; - if (ele === pattern || isMatch(ele)) { - matches.push(utils.value(ele, unixify, options)); - } - } - - // if no options were passed, uniquify results and return - if (typeof options === 'undefined') { - return utils.unique(matches); - } - - if (matches.length === 0) { - if (options.failglob === true) { - throw new Error('no matches found for "' + pattern + '"'); - } - if (options.nonull === true || options.nullglob === true) { - return [options.unescape ? utils.unescape(pattern) : pattern]; - } - } - - // if `opts.ignore` was defined, diff ignored list - if (options.ignore) { - matches = nanomatch.not(matches, options.ignore, options); - } - - return options.nodupes !== false ? utils.unique(matches) : matches; -}; - -/** - * Returns true if the specified `string` matches the given glob `pattern`. - * - * ```js - * var nm = require('nanomatch'); - * nm.isMatch(string, pattern[, options]); - * - * console.log(nm.isMatch('a.a', '*.a')); - * //=> true - * console.log(nm.isMatch('a.b', '*.a')); - * //=> false - * ``` - * @param {String} `string` String to match - * @param {String} `pattern` 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 string matches the glob pattern. - * @api public - */ - -nanomatch.isMatch = function(str, pattern, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string: "' + util.inspect(str) + '"'); - } - - if (utils.isEmptyString(str) || utils.isEmptyString(pattern)) { - return false; - } - - var equals = utils.equalsPattern(options); - if (equals(str)) { - return true; - } - - var isMatch = memoize('isMatch', pattern, options, nanomatch.matcher); - return isMatch(str); -}; - -/** - * Returns true if some of the elements in the given `list` match any of the - * given glob `patterns`. - * - * ```js - * var nm = require('nanomatch'); - * nm.some(list, patterns[, options]); - * - * console.log(nm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); - * // true - * console.log(nm.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 - */ - -nanomatch.some = function(list, patterns, options) { - if (typeof list === 'string') { - list = [list]; - } - - for (var i = 0; i < list.length; i++) { - if (nanomatch(list[i], patterns, options).length === 1) { - return true; - } - } - - return false; -}; - -/** - * Returns true if every element in the given `list` matches - * at least one of the given glob `patterns`. - * - * ```js - * var nm = require('nanomatch'); - * nm.every(list, patterns[, options]); - * - * console.log(nm.every('foo.js', ['foo.js'])); - * // true - * console.log(nm.every(['foo.js', 'bar.js'], ['*.js'])); - * // true - * console.log(nm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); - * // false - * console.log(nm.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 - */ - -nanomatch.every = function(list, patterns, options) { - if (typeof list === 'string') { - list = [list]; - } - - for (var i = 0; i < list.length; i++) { - if (nanomatch(list[i], patterns, options).length !== 1) { - return false; - } - } - - return true; -}; - -/** - * Returns true if **any** of the given glob `patterns` - * match the specified `string`. - * - * ```js - * var nm = require('nanomatch'); - * nm.any(string, patterns[, options]); - * - * console.log(nm.any('a.a', ['b.*', '*.a'])); - * //=> true - * console.log(nm.any('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) for changing how matches are performed - * @return {Boolean} Returns true if any patterns match `str` - * @api public - */ - -nanomatch.any = function(str, patterns, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string: "' + util.inspect(str) + '"'); - } - - if (utils.isEmptyString(str) || utils.isEmptyString(patterns)) { - return false; - } - - if (typeof patterns === 'string') { - patterns = [patterns]; - } - - for (var i = 0; i < patterns.length; i++) { - if (nanomatch.isMatch(str, patterns[i], options)) { - return true; - } - } - return false; -}; - -/** - * Returns true if **all** of the given `patterns` - * match the specified string. - * - * ```js - * var nm = require('nanomatch'); - * nm.all(string, patterns[, options]); - * - * console.log(nm.all('foo.js', ['foo.js'])); - * // true - * - * console.log(nm.all('foo.js', ['*.js', '!foo.js'])); - * // false - * - * console.log(nm.all('foo.js', ['*.js', 'foo.js'])); - * // true - * - * console.log(nm.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 - */ - -nanomatch.all = function(str, patterns, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string: "' + util.inspect(str) + '"'); - } - - if (typeof patterns === 'string') { - patterns = [patterns]; - } - - for (var i = 0; i < patterns.length; i++) { - if (!nanomatch.isMatch(str, patterns[i], options)) { - return false; - } - } - return true; -}; - -/** - * Returns a list of strings that _**do not match any**_ of the given `patterns`. - * - * ```js - * var nm = require('nanomatch'); - * nm.not(list, patterns[, options]); - * - * console.log(nm.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 - */ - -nanomatch.not = function(list, patterns, options) { - var opts = extend({}, options); - var ignore = opts.ignore; - delete opts.ignore; - - list = utils.arrayify(list); - - var matches = utils.diff(list, nanomatch(list, patterns, opts)); - if (ignore) { - matches = utils.diff(matches, nanomatch(list, ignore)); - } - - return opts.nodupes !== false ? utils.unique(matches) : matches; -}; - -/** - * 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 nm = require('nanomatch'); - * nm.contains(string, pattern[, options]); - * - * console.log(nm.contains('aa/bb/cc', '*b')); - * //=> true - * console.log(nm.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 - */ - -nanomatch.contains = function(str, patterns, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string: "' + util.inspect(str) + '"'); - } - - if (typeof patterns === 'string') { - if (utils.isEmptyString(str) || utils.isEmptyString(patterns)) { - return false; - } - - var equals = utils.equalsPattern(patterns, options); - if (equals(str)) { - return true; - } - var contains = utils.containsPattern(patterns, options); - if (contains(str)) { - return true; - } - } - - var opts = extend({}, options, {contains: true}); - return nanomatch.any(str, patterns, opts); -}; - -/** - * Returns true if the given pattern and options should enable - * the `matchBase` option. - * @return {Boolean} - * @api private - */ - -nanomatch.matchBase = function(pattern, options) { - if (pattern && pattern.indexOf('/') !== -1 || !options) return false; - return options.basename === true || options.matchBase === 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 - * var nm = require('nanomatch'); - * nm.matchKeys(object, patterns[, options]); - * - * var obj = { aa: 'a', ab: 'b', ac: 'c' }; - * console.log(nm.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 - */ - -nanomatch.matchKeys = function(obj, patterns, options) { - if (!utils.isObject(obj)) { - throw new TypeError('expected the first argument to be an object'); - } - var keys = nanomatch(Object.keys(obj), patterns, options); - return utils.pick(obj, keys); -}; - -/** - * Returns a memoized 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 - * var nm = require('nanomatch'); - * nm.matcher(pattern[, options]); - * - * var isMatch = nm.matcher('*.!(*a)'); - * console.log(isMatch('a.a')); - * //=> false - * console.log(isMatch('a.b')); - * //=> true - * ``` - * @param {String} `pattern` Glob pattern - * @param {Object} `options` See available [options](#options) for changing how matches are performed. - * @return {Function} Returns a matcher function. - * @api public - */ - -nanomatch.matcher = function matcher(pattern, options) { - if (utils.isEmptyString(pattern)) { - return function() { - return false; - }; - } - - if (Array.isArray(pattern)) { - return compose(pattern, options, matcher); - } - - // if pattern is a regex - if (pattern instanceof RegExp) { - return test(pattern); - } - - // if pattern is invalid - if (!utils.isString(pattern)) { - throw new TypeError('expected pattern to be an array, string or regex'); - } - - // if pattern is a non-glob string - if (!utils.hasSpecialChars(pattern)) { - if (options && options.nocase === true) { - pattern = pattern.toLowerCase(); - } - return utils.matchPath(pattern, options); - } - - // if pattern is a glob string - var re = nanomatch.makeRe(pattern, options); - - // if `options.matchBase` or `options.basename` is defined - if (nanomatch.matchBase(pattern, options)) { - return utils.matchBasename(re, options); - } - - function test(regex) { - var equals = utils.equalsPattern(options); - var unixify = utils.unixify(options); - - return function(str) { - if (equals(str)) { - return true; - } - - if (regex.test(unixify(str))) { - return true; - } - return false; - }; - } - - // create matcher function - var matcherFn = test(re); - // set result object from compiler on matcher function, - // as a non-enumerable property. useful for debugging - utils.define(matcherFn, 'result', re.result); - return matcherFn; -}; - -/** - * Returns an array of matches captured by `pattern` in `string, or - * `null` if the pattern did not match. - * - * ```js - * var nm = require('nanomatch'); - * nm.capture(pattern, string[, options]); - * - * console.log(nm.capture('test/*.js', 'test/foo.js')); - * //=> ['foo'] - * console.log(nm.capture('test/*.js', 'foo/bar.css')); - * //=> null - * ``` - * @param {String} `pattern` Glob pattern to use for matching. - * @param {String} `string` 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 string matches the glob pattern, otherwise `null`. - * @api public - */ - -nanomatch.capture = function(pattern, str, options) { - var re = nanomatch.makeRe(pattern, extend({capture: true}, options)); - var unixify = utils.unixify(options); - - function match() { - return function(string) { - var match = re.exec(unixify(string)); - if (!match) { - return null; - } - - return match.slice(1); - }; - } - - var capture = memoize('capture', pattern, options, match); - return capture(str); -}; - -/** - * Create a regular expression from the given glob `pattern`. - * - * ```js - * var nm = require('nanomatch'); - * nm.makeRe(pattern[, options]); - * - * console.log(nm.makeRe('*.js')); - * //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/ - * ``` - * @param {String} `pattern` A glob pattern to convert to regex. - * @param {Object} `options` See available [options](#options) for changing how matches are performed. - * @return {RegExp} Returns a regex created from the given pattern. - * @api public - */ - -nanomatch.makeRe = function(pattern, options) { - if (pattern instanceof RegExp) { - return pattern; - } - - if (typeof pattern !== 'string') { - throw new TypeError('expected pattern to be a string'); - } - - if (pattern.length > MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); - } - - function makeRe() { - var opts = utils.extend({wrap: false}, options); - var result = nanomatch.create(pattern, opts); - var regex = toRegex(result.output, opts); - utils.define(regex, 'result', result); - return regex; - } - - return memoize('makeRe', pattern, options, makeRe); -}; - -/** - * Parses the given glob `pattern` and returns an object with the compiled `output` - * and optional source `map`. - * - * ```js - * var nm = require('nanomatch'); - * nm.create(pattern[, options]); - * - * console.log(nm.create('abc/*.js')); - * // { options: { source: 'string', sourcemap: true }, - * // state: {}, - * // compilers: - * // { ... }, - * // output: '(\\.[\\\\\\/])?abc\\/(?!\\.)(?=.)[^\\/]*?\\.js', - * // ast: - * // { type: 'root', - * // errors: [], - * // nodes: - * // [ ... ], - * // dot: false, - * // input: 'abc/*.js' }, - * // parsingErrors: [], - * // map: - * // { version: 3, - * // sources: [ 'string' ], - * // names: [], - * // mappings: 'AAAA,GAAG,EAAC,kBAAC,EAAC,EAAE', - * // sourcesContent: [ 'abc/*.js' ] }, - * // position: { line: 1, column: 28 }, - * // content: {}, - * // files: {}, - * // idx: 6 } - * ``` - * @param {String} `pattern` Glob pattern to parse and compile. - * @param {Object} `options` Any [options](#options) to change how parsing and compiling is performed. - * @return {Object} Returns an object with the parsed AST, compiled string and optional source map. - * @api public - */ - -nanomatch.create = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - function create() { - return nanomatch.compile(nanomatch.parse(pattern, options), options); - } - return memoize('create', pattern, options, create); -}; - -/** - * Parse the given `str` with the given `options`. - * - * ```js - * var nm = require('nanomatch'); - * nm.parse(pattern[, options]); - * - * var ast = nm.parse('a/{b,c}/d'); - * console.log(ast); - * // { type: 'root', - * // errors: [], - * // input: 'a/{b,c}/d', - * // nodes: - * // [ { type: 'bos', val: '' }, - * // { type: 'text', val: 'a/' }, - * // { type: 'brace', - * // nodes: - * // [ { type: 'brace.open', val: '{' }, - * // { type: 'text', val: 'b,c' }, - * // { type: 'brace.close', val: '}' } ] }, - * // { type: 'text', val: '/d' }, - * // { type: 'eos', val: '' } ] } - * ``` - * @param {String} `str` - * @param {Object} `options` - * @return {Object} Returns an AST - * @api public - */ - -nanomatch.parse = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - function parse() { - var snapdragon = utils.instantiate(null, options); - parsers(snapdragon, options); - - var ast = snapdragon.parse(pattern, options); - utils.define(ast, 'snapdragon', snapdragon); - ast.input = pattern; - return ast; - } - - return memoize('parse', pattern, options, parse); -}; - -/** - * Compile the given `ast` or string with the given `options`. - * - * ```js - * var nm = require('nanomatch'); - * nm.compile(ast[, options]); - * - * var ast = nm.parse('a/{b,c}/d'); - * console.log(nm.compile(ast)); - * // { options: { source: 'string' }, - * // state: {}, - * // compilers: - * // { eos: [Function], - * // noop: [Function], - * // bos: [Function], - * // brace: [Function], - * // 'brace.open': [Function], - * // text: [Function], - * // 'brace.close': [Function] }, - * // output: [ 'a/(b|c)/d' ], - * // ast: - * // { ... }, - * // parsingErrors: [] } - * ``` - * @param {Object|String} `ast` - * @param {Object} `options` - * @return {Object} Returns an object that has an `output` property with the compiled string. - * @api public - */ - -nanomatch.compile = function(ast, options) { - if (typeof ast === 'string') { - ast = nanomatch.parse(ast, options); - } - - function compile() { - var snapdragon = utils.instantiate(ast, options); - compilers(snapdragon, options); - return snapdragon.compile(ast, options); - } - - return memoize('compile', ast.input, options, compile); -}; - -/** - * Clear the regex cache. - * - * ```js - * nm.clearCache(); - * ``` - * @api public - */ - -nanomatch.clearCache = function() { - nanomatch.cache.__data__ = {}; -}; - -/** - * Compose a matcher function with the given patterns. - * This allows matcher functions to be compiled once and - * called multiple times. - */ - -function compose(patterns, options, matcher) { - var matchers; - - return memoize('compose', String(patterns), options, function() { - return function(file) { - // delay composition until it's invoked the first time, - // after that it won't be called again - if (!matchers) { - matchers = []; - for (var i = 0; i < patterns.length; i++) { - matchers.push(matcher(patterns[i], options)); - } - } - - var len = matchers.length; - while (len--) { - if (matchers[len](file) === true) { - return true; - } - } - return false; - }; - }); -} - -/** - * Memoize a generated regex or function. A unique key is generated - * from the `type` (usually method name), the `pattern`, and - * user-defined options. - */ - -function memoize(type, pattern, options, fn) { - var key = utils.createKey(type + '=' + pattern, options); - - if (options && options.cache === false) { - return fn(pattern, options); - } - - if (cache.has(type, key)) { - return cache.get(type, key); - } - - var val = fn(pattern, options); - cache.set(type, key, val); - return val; -} - -/** - * Expose compiler, parser and cache on `nanomatch` - */ - -nanomatch.compilers = compilers; -nanomatch.parsers = parsers; -nanomatch.cache = cache; - -/** - * Expose `nanomatch` - * @type {Function} - */ - -module.exports = nanomatch; - - -/***/ }), -/* 843 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isExtendable = __webpack_require__(844); -var assignSymbols = __webpack_require__(749); - -module.exports = Object.assign || function(obj/*, objects*/) { - if (obj === null || typeof obj === 'undefined') { - throw new TypeError('Cannot convert undefined or null to object'); - } - if (!isObject(obj)) { - obj = {}; - } - for (var i = 1; i < arguments.length; i++) { - var val = arguments[i]; - if (isString(val)) { - val = toObject(val); - } - if (isObject(val)) { - assign(obj, val); - assignSymbols(obj, val); - } - } - return obj; -}; - -function assign(a, b) { - for (var key in b) { - if (hasOwn(b, key)) { - a[key] = b[key]; - } - } -} - -function isString(val) { - return (val && typeof val === 'string'); -} - -function toObject(str) { - var obj = {}; - for (var i in str) { - obj[i] = str[i]; - } - return obj; -} - -function isObject(val) { - return (val && typeof val === 'object') || isExtendable(val); -} - -/** - * Returns true if the given `key` is an own property of `obj`. - */ - -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - -function isEnum(obj, key) { - return Object.prototype.propertyIsEnumerable.call(obj, key); -} - - -/***/ }), -/* 844 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-extendable - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isPlainObject = __webpack_require__(747); - -module.exports = function isExtendable(val) { - return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); -}; - - -/***/ }), -/* 845 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** -* Nanomatch compilers -*/ - -module.exports = function(nanomatch, options) { - function slash() { - if (options && typeof options.slash === 'string') { - return options.slash; - } - if (options && typeof options.slash === 'function') { - return options.slash.call(nanomatch); - } - return '\\\\/'; - } - - function star() { - if (options && typeof options.star === 'string') { - return options.star; - } - if (options && typeof options.star === 'function') { - return options.star.call(nanomatch); - } - return '[^' + slash() + ']*?'; - } - - var ast = nanomatch.ast = nanomatch.parser.ast; - ast.state = nanomatch.parser.state; - nanomatch.compiler.state = ast.state; - nanomatch.compiler - - /** - * Negation / escaping - */ - - .set('not', function(node) { - var prev = this.prev(); - if (this.options.nonegate === true || prev.type !== 'bos') { - return this.emit('\\' + node.val, node); - } - return this.emit(node.val, node); - }) - .set('escape', function(node) { - if (this.options.unescape && /^[-\w_.]/.test(node.val)) { - return this.emit(node.val, node); - } - return this.emit('\\' + node.val, node); - }) - .set('quoted', function(node) { - return this.emit(node.val, node); - }) - - /** - * Regex - */ - - .set('dollar', function(node) { - if (node.parent.type === 'bracket') { - return this.emit(node.val, node); - } - return this.emit('\\' + node.val, node); - }) - - /** - * Dot: "." - */ - - .set('dot', function(node) { - if (node.dotfiles === true) this.dotfiles = true; - return this.emit('\\' + node.val, node); - }) - - /** - * Slashes: "/" and "\" - */ - - .set('backslash', function(node) { - return this.emit(node.val, node); - }) - .set('slash', function(node, nodes, i) { - var val = '[' + slash() + ']'; - var parent = node.parent; - var prev = this.prev(); - - // set "node.hasSlash" to true on all ancestor parens nodes - while (parent.type === 'paren' && !parent.hasSlash) { - parent.hasSlash = true; - parent = parent.parent; - } - - if (prev.addQmark) { - val += '?'; - } - - // word boundary - if (node.rest.slice(0, 2) === '\\b') { - return this.emit(val, node); - } - - // globstars - if (node.parsed === '**' || node.parsed === './**') { - this.output = '(?:' + this.output; - return this.emit(val + ')?', node); - } - - // negation - if (node.parsed === '!**' && this.options.nonegate !== true) { - return this.emit(val + '?\\b', node); - } - return this.emit(val, node); - }) - - /** - * Square brackets - */ - - .set('bracket', function(node) { - var close = node.close; - var open = !node.escaped ? '[' : '\\['; - var negated = node.negated; - var inner = node.inner; - var val = node.val; - - if (node.escaped === true) { - inner = inner.replace(/\\?(\W)/g, '\\$1'); - negated = ''; - } - - if (inner === ']-') { - inner = '\\]\\-'; - } - - if (negated && inner.indexOf('.') === -1) { - inner += '.'; - } - if (negated && inner.indexOf('/') === -1) { - inner += '/'; - } - - val = open + negated + inner + close; - return this.emit(val, node); - }) - - /** - * Square: "[.]" (only matches a single character in brackets) - */ - - .set('square', function(node) { - var val = (/^\W/.test(node.val) ? '\\' : '') + node.val; - return this.emit(val, node); - }) - - /** - * Question mark: "?" - */ - - .set('qmark', function(node) { - var prev = this.prev(); - // don't use "slash" variable so that we always avoid - // matching backslashes and slashes with a qmark - var val = '[^.\\\\/]'; - if (this.options.dot || (prev.type !== 'bos' && prev.type !== 'slash')) { - val = '[^\\\\/]'; - } - - if (node.parsed.slice(-1) === '(') { - var ch = node.rest.charAt(0); - if (ch === '!' || ch === '=' || ch === ':') { - return this.emit(node.val, node); - } - } - - if (node.val.length > 1) { - val += '{' + node.val.length + '}'; - } - return this.emit(val, node); - }) - - /** - * Plus - */ - - .set('plus', function(node) { - var prev = node.parsed.slice(-1); - if (prev === ']' || prev === ')') { - return this.emit(node.val, node); - } - if (!this.output || (/[?*+]/.test(ch) && node.parent.type !== 'bracket')) { - return this.emit('\\+', node); - } - var ch = this.output.slice(-1); - if (/\w/.test(ch) && !node.inside) { - return this.emit('+\\+?', node); - } - return this.emit('+', node); - }) - - /** - * globstar: '**' - */ - - .set('globstar', function(node, nodes, i) { - if (!this.output) { - this.state.leadingGlobstar = true; - } - - var prev = this.prev(); - var before = this.prev(2); - var next = this.next(); - var after = this.next(2); - var type = prev.type; - var val = node.val; - - if (prev.type === 'slash' && next.type === 'slash') { - if (before.type === 'text') { - this.output += '?'; - - if (after.type !== 'text') { - this.output += '\\b'; - } - } - } - - var parsed = node.parsed; - if (parsed.charAt(0) === '!') { - parsed = parsed.slice(1); - } - - var isInside = node.isInside.paren || node.isInside.brace; - if (parsed && type !== 'slash' && type !== 'bos' && !isInside) { - val = star(); - } else { - val = this.options.dot !== true - ? '(?:(?!(?:[' + slash() + ']|^)\\.).)*?' - : '(?:(?!(?:[' + slash() + ']|^)(?:\\.{1,2})($|[' + slash() + ']))(?!\\.{2}).)*?'; - } - - if ((type === 'slash' || type === 'bos') && this.options.dot !== true) { - val = '(?!\\.)' + val; - } - - if (prev.type === 'slash' && next.type === 'slash' && before.type !== 'text') { - if (after.type === 'text' || after.type === 'star') { - node.addQmark = true; - } - } - - if (this.options.capture) { - val = '(' + val + ')'; - } - - return this.emit(val, node); - }) - - /** - * Star: "*" - */ - - .set('star', function(node, nodes, i) { - var prior = nodes[i - 2] || {}; - var prev = this.prev(); - var next = this.next(); - var type = prev.type; - - function isStart(n) { - return n.type === 'bos' || n.type === 'slash'; - } - - if (this.output === '' && this.options.contains !== true) { - this.output = '(?![' + slash() + '])'; - } - - if (type === 'bracket' && this.options.bash === false) { - var str = next && next.type === 'bracket' ? star() : '*?'; - if (!prev.nodes || prev.nodes[1].type !== 'posix') { - return this.emit(str, node); - } - } - - var prefix = !this.dotfiles && type !== 'text' && type !== 'escape' - ? (this.options.dot ? '(?!(?:^|[' + slash() + '])\\.{1,2}(?:$|[' + slash() + ']))' : '(?!\\.)') - : ''; - - if (isStart(prev) || (isStart(prior) && type === 'not')) { - if (prefix !== '(?!\\.)') { - prefix += '(?!(\\.{2}|\\.[' + slash() + ']))(?=.)'; - } else { - prefix += '(?=.)'; - } - } else if (prefix === '(?!\\.)') { - prefix = ''; - } - - if (prev.type === 'not' && prior.type === 'bos' && this.options.dot === true) { - this.output = '(?!\\.)' + this.output; - } - - var output = prefix + star(); - if (this.options.capture) { - output = '(' + output + ')'; - } - - return this.emit(output, node); - }) - - /** - * Text - */ - - .set('text', function(node) { - return this.emit(node.val, node); - }) - - /** - * End-of-string - */ - - .set('eos', function(node) { - var prev = this.prev(); - var val = node.val; - - this.output = '(?:\\.[' + slash() + '](?=.))?' + this.output; - if (this.state.metachar && prev.type !== 'qmark' && prev.type !== 'slash') { - val += (this.options.contains ? '[' + slash() + ']?' : '(?:[' + slash() + ']|$)'); - } - - return this.emit(val, node); - }); - - /** - * Allow custom compilers to be passed on options - */ - - if (options && typeof options.compilers === 'function') { - options.compilers(nanomatch.compiler); - } -}; - - - -/***/ }), -/* 846 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var regexNot = __webpack_require__(740); -var toRegex = __webpack_require__(729); -var isOdd = __webpack_require__(847); - -/** - * Characters to use in negation regex (we want to "not" match - * characters that are matched by other parsers) - */ - -var cached; -var NOT_REGEX = '[\\[!*+?$^"\'.\\\\/]+'; -var not = createTextRegex(NOT_REGEX); - -/** - * Nanomatch parsers - */ - -module.exports = function(nanomatch, options) { - var parser = nanomatch.parser; - var opts = parser.options; - - parser.state = { - slashes: 0, - paths: [] - }; - - parser.ast.state = parser.state; - parser - - /** - * Beginning-of-string - */ - - .capture('prefix', function() { - if (this.parsed) return; - var m = this.match(/^\.[\\/]/); - if (!m) return; - this.state.strictOpen = !!this.options.strictOpen; - this.state.addPrefix = true; - }) - - /** - * Escape: "\\." - */ - - .capture('escape', function() { - if (this.isInside('bracket')) return; - var pos = this.position(); - var m = this.match(/^(?:\\(.)|([$^]))/); - if (!m) return; - - return pos({ - type: 'escape', - val: m[2] || m[1] - }); - }) - - /** - * Quoted strings - */ - - .capture('quoted', function() { - var pos = this.position(); - var m = this.match(/^["']/); - if (!m) return; - - var quote = m[0]; - if (this.input.indexOf(quote) === -1) { - return pos({ - type: 'escape', - val: quote - }); - } - - var tok = advanceTo(this.input, quote); - this.consume(tok.len); - - return pos({ - type: 'quoted', - val: tok.esc - }); - }) - - /** - * Negations: "!" - */ - - .capture('not', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(this.notRegex || /^!+/); - if (!m) return; - var val = m[0]; - - var isNegated = isOdd(val.length); - if (parsed === '' && !isNegated) { - val = ''; - } - - // if nothing has been parsed, we know `!` is at the start, - // so we need to wrap the result in a negation regex - if (parsed === '' && isNegated && this.options.nonegate !== true) { - this.bos.val = '(?!^(?:'; - this.append = ')$).*'; - val = ''; - } - return pos({ - type: 'not', - val: val - }); - }) - - /** - * Dot: "." - */ - - .capture('dot', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(/^\.+/); - if (!m) return; - - var val = m[0]; - this.state.dot = val === '.' && (parsed === '' || parsed.slice(-1) === '/'); - - return pos({ - type: 'dot', - dotfiles: this.state.dot, - val: val - }); - }) - - /** - * Plus: "+" - */ - - .capture('plus', /^\+(?!\()/) - - /** - * Question mark: "?" - */ - - .capture('qmark', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(/^\?+(?!\()/); - if (!m) return; - - this.state.metachar = true; - this.state.qmark = true; - - return pos({ - type: 'qmark', - parsed: parsed, - val: m[0] - }); - }) - - /** - * Globstar: "**" - */ - - .capture('globstar', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(/^\*{2}(?![*(])(?=[,)/]|$)/); - if (!m) return; - - var type = opts.noglobstar !== true ? 'globstar' : 'star'; - var node = pos({type: type, parsed: parsed}); - this.state.metachar = true; - - while (this.input.slice(0, 4) === '/**/') { - this.input = this.input.slice(3); - } - - node.isInside = { - brace: this.isInside('brace'), - paren: this.isInside('paren') - }; - - if (type === 'globstar') { - this.state.globstar = true; - node.val = '**'; - - } else { - this.state.star = true; - node.val = '*'; - } - - return node; - }) - - /** - * Star: "*" - */ - - .capture('star', function() { - var pos = this.position(); - var starRe = /^(?:\*(?![*(])|[*]{3,}(?!\()|[*]{2}(?![(/]|$)|\*(?=\*\())/; - var m = this.match(starRe); - if (!m) return; - - this.state.metachar = true; - this.state.star = true; - return pos({ - type: 'star', - val: m[0] - }); - }) - - /** - * Slash: "/" - */ - - .capture('slash', function() { - var pos = this.position(); - var m = this.match(/^\//); - if (!m) return; - - this.state.slashes++; - return pos({ - type: 'slash', - val: m[0] - }); - }) - - /** - * Backslash: "\\" - */ - - .capture('backslash', function() { - var pos = this.position(); - var m = this.match(/^\\(?![*+?(){}[\]'"])/); - if (!m) return; - - var val = m[0]; - - if (this.isInside('bracket')) { - val = '\\'; - } else if (val.length > 1) { - val = '\\\\'; - } - - return pos({ - type: 'backslash', - val: val - }); - }) - - /** - * Square: "[.]" - */ - - .capture('square', function() { - if (this.isInside('bracket')) return; - var pos = this.position(); - var m = this.match(/^\[([^!^\\])\]/); - if (!m) return; - - return pos({ - type: 'square', - val: m[1] - }); - }) - - /** - * Brackets: "[...]" (basic, this can be overridden by other parsers) - */ - - .capture('bracket', function() { - var pos = this.position(); - var m = this.match(/^(?:\[([!^]?)([^\]]+|\]-)(\]|[^*+?]+)|\[)/); - if (!m) return; - - var val = m[0]; - var negated = m[1] ? '^' : ''; - var inner = (m[2] || '').replace(/\\\\+/, '\\\\'); - var close = m[3] || ''; - - if (m[2] && inner.length < m[2].length) { - val = val.replace(/\\\\+/, '\\\\'); - } - - var esc = this.input.slice(0, 2); - if (inner === '' && esc === '\\]') { - inner += esc; - this.consume(2); - - var str = this.input; - var idx = -1; - var ch; - - while ((ch = str[++idx])) { - this.consume(1); - if (ch === ']') { - close = ch; - break; - } - inner += ch; - } - } - - return pos({ - type: 'bracket', - val: val, - escaped: close !== ']', - negated: negated, - inner: inner, - close: close - }); - }) - - /** - * Text - */ - - .capture('text', function() { - if (this.isInside('bracket')) return; - var pos = this.position(); - var m = this.match(not); - if (!m || !m[0]) return; - - return pos({ - type: 'text', - val: m[0] - }); - }); - - /** - * Allow custom parsers to be passed on options - */ - - if (options && typeof options.parsers === 'function') { - options.parsers(nanomatch.parser); - } -}; - -/** - * Advance to the next non-escaped character - */ - -function advanceTo(input, endChar) { - var ch = input.charAt(0); - var tok = { len: 1, val: '', esc: '' }; - var idx = 0; - - function advance() { - if (ch !== '\\') { - tok.esc += '\\' + ch; - tok.val += ch; - } - - ch = input.charAt(++idx); - tok.len++; - - if (ch === '\\') { - advance(); - advance(); - } - } - - while (ch && ch !== endChar) { - advance(); - } - return tok; -} - -/** - * Create text regex - */ - -function createTextRegex(pattern) { - if (cached) return cached; - var opts = {contains: true, strictClose: false}; - var not = regexNot.create(pattern, opts); - var re = toRegex('^(?:[*]\\((?=.)|' + not + ')', opts); - return (cached = re); -} - -/** - * Expose negation string - */ - -module.exports.not = NOT_REGEX; - - -/***/ }), -/* 847 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-odd - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isNumber = __webpack_require__(848); - -module.exports = function isOdd(i) { - if (!isNumber(i)) { - throw new TypeError('is-odd expects a number.'); - } - if (Number(i) !== Math.floor(i)) { - throw new RangeError('is-odd expects an integer.'); - } - return !!(~~i & 1); -}; - - -/***/ }), -/* 848 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-number - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -module.exports = function isNumber(num) { - var type = typeof num; - - if (type === 'string' || num instanceof String) { - // an empty string would be coerced to true with the below logic - if (!num.trim()) return false; - } else if (type !== 'number' && !(num instanceof Number)) { - return false; - } - - return (num - num + 1) >= 0; -}; - - -/***/ }), -/* 849 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = new (__webpack_require__(850))(); - - -/***/ }), -/* 850 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * fragment-cache - * - * Copyright (c) 2016-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var MapCache = __webpack_require__(828); - -/** - * Create a new `FragmentCache` with an optional object to use for `caches`. - * - * ```js - * var fragment = new FragmentCache(); - * ``` - * @name FragmentCache - * @param {String} `cacheName` - * @return {Object} Returns the [map-cache][] instance. - * @api public - */ - -function FragmentCache(caches) { - this.caches = caches || {}; -} - -/** - * Prototype - */ - -FragmentCache.prototype = { - - /** - * Get cache `name` from the `fragment.caches` object. Creates a new - * `MapCache` if it doesn't already exist. - * - * ```js - * var cache = fragment.cache('files'); - * console.log(fragment.caches.hasOwnProperty('files')); - * //=> true - * ``` - * @name .cache - * @param {String} `cacheName` - * @return {Object} Returns the [map-cache][] instance. - * @api public - */ - - cache: function(cacheName) { - return this.caches[cacheName] || (this.caches[cacheName] = new MapCache()); - }, - - /** - * Set a value for property `key` on cache `name` - * - * ```js - * fragment.set('files', 'somefile.js', new File({path: 'somefile.js'})); - * ``` - * @name .set - * @param {String} `name` - * @param {String} `key` Property name to set - * @param {any} `val` The value of `key` - * @return {Object} The cache instance for chaining - * @api public - */ - - set: function(cacheName, key, val) { - var cache = this.cache(cacheName); - cache.set(key, val); - return cache; - }, - - /** - * Returns true if a non-undefined value is set for `key` on fragment cache `name`. - * - * ```js - * var cache = fragment.cache('files'); - * cache.set('somefile.js'); - * - * console.log(cache.has('somefile.js')); - * //=> true - * - * console.log(cache.has('some-other-file.js')); - * //=> false - * ``` - * @name .has - * @param {String} `name` Cache name - * @param {String} `key` Optionally specify a property to check for on cache `name` - * @return {Boolean} - * @api public - */ - - has: function(cacheName, key) { - return typeof this.get(cacheName, key) !== 'undefined'; - }, - - /** - * Get `name`, or if specified, the value of `key`. Invokes the [cache]() method, - * so that cache `name` will be created it doesn't already exist. If `key` is not passed, - * the entire cache (`name`) is returned. - * - * ```js - * var Vinyl = require('vinyl'); - * var cache = fragment.cache('files'); - * cache.set('somefile.js', new Vinyl({path: 'somefile.js'})); - * console.log(cache.get('somefile.js')); - * //=> - * ``` - * @name .get - * @param {String} `name` - * @return {Object} Returns cache `name`, or the value of `key` if specified - * @api public - */ - - get: function(name, key) { - var cache = this.cache(name); - if (typeof key === 'string') { - return cache.get(key); - } - return cache; - } -}; - -/** - * Expose `FragmentCache` - */ - -exports = module.exports = FragmentCache; - - -/***/ }), -/* 851 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var utils = module.exports; -var path = __webpack_require__(16); - -/** - * Module dependencies - */ - -var isWindows = __webpack_require__(852)(); -var Snapdragon = __webpack_require__(768); -utils.define = __webpack_require__(853); -utils.diff = __webpack_require__(854); -utils.extend = __webpack_require__(843); -utils.pick = __webpack_require__(855); -utils.typeOf = __webpack_require__(856); -utils.unique = __webpack_require__(741); - -/** - * Returns true if the given value is effectively an empty string - */ - -utils.isEmptyString = function(val) { - return String(val) === '' || String(val) === './'; -}; - -/** - * Returns true if the platform is windows, or `path.sep` is `\\`. - * This is defined as a function to allow `path.sep` to be set in unit tests, - * or by the user, if there is a reason to do so. - * @return {Boolean} - */ - -utils.isWindows = function() { - return path.sep === '\\' || isWindows === true; -}; - -/** - * Return the last element from an array - */ - -utils.last = function(arr, n) { - return arr[arr.length - (n || 1)]; -}; - -/** - * Get the `Snapdragon` instance to use - */ - -utils.instantiate = function(ast, options) { - var snapdragon; - // if an instance was created by `.parse`, use that instance - if (utils.typeOf(ast) === 'object' && ast.snapdragon) { - snapdragon = ast.snapdragon; - // if the user supplies an instance on options, use that instance - } else if (utils.typeOf(options) === 'object' && options.snapdragon) { - snapdragon = options.snapdragon; - // create a new instance - } else { - snapdragon = new Snapdragon(options); - } - - utils.define(snapdragon, 'parse', function(str, options) { - var parsed = Snapdragon.prototype.parse.call(this, str, options); - parsed.input = str; - - // escape unmatched brace/bracket/parens - var last = this.parser.stack.pop(); - if (last && this.options.strictErrors !== true) { - var open = last.nodes[0]; - var inner = last.nodes[1]; - if (last.type === 'bracket') { - if (inner.val.charAt(0) === '[') { - inner.val = '\\' + inner.val; - } - - } else { - open.val = '\\' + open.val; - var sibling = open.parent.nodes[1]; - if (sibling.type === 'star') { - sibling.loose = true; - } - } - } - - // add non-enumerable parser reference - utils.define(parsed, 'parser', this.parser); - return parsed; - }); - - return snapdragon; -}; - -/** - * Create the key to use for memoization. The key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. - */ - -utils.createKey = function(pattern, options) { - if (typeof options === 'undefined') { - return pattern; - } - var key = pattern; - for (var prop in options) { - if (options.hasOwnProperty(prop)) { - key += ';' + prop + '=' + String(options[prop]); - } - } - return key; -}; - -/** - * Cast `val` to an array - * @return {Array} - */ - -utils.arrayify = function(val) { - if (typeof val === 'string') return [val]; - return val ? (Array.isArray(val) ? val : [val]) : []; -}; - -/** - * Return true if `val` is a non-empty string - */ - -utils.isString = function(val) { - return typeof val === 'string'; -}; - -/** - * Return true if `val` is a non-empty string - */ - -utils.isRegex = function(val) { - return utils.typeOf(val) === 'regexp'; -}; - -/** - * Return true if `val` is a non-empty string - */ - -utils.isObject = function(val) { - return utils.typeOf(val) === 'object'; -}; - -/** - * Escape regex characters in the given string - */ - -utils.escapeRegex = function(str) { - return str.replace(/[-[\]{}()^$|*+?.\\/\s]/g, '\\$&'); -}; - -/** - * Combines duplicate characters in the provided `input` string. - * @param {String} `input` - * @returns {String} - */ - -utils.combineDupes = function(input, patterns) { - patterns = utils.arrayify(patterns).join('|').split('|'); - patterns = patterns.map(function(s) { - return s.replace(/\\?([+*\\/])/g, '\\$1'); - }); - var substr = patterns.join('|'); - var regex = new RegExp('(' + substr + ')(?=\\1)', 'g'); - return input.replace(regex, ''); -}; - -/** - * Returns true if the given `str` has special characters - */ - -utils.hasSpecialChars = function(str) { - return /(?:(?:(^|\/)[!.])|[*?+()|[\]{}]|[+@]\()/.test(str); -}; - -/** - * Normalize slashes in the given filepath. - * - * @param {String} `filepath` - * @return {String} - */ - -utils.toPosixPath = function(str) { - return str.replace(/\\+/g, '/'); -}; - -/** - * Strip backslashes before special characters in a string. - * - * @param {String} `str` - * @return {String} - */ - -utils.unescape = function(str) { - return utils.toPosixPath(str.replace(/\\(?=[*+?!.])/g, '')); -}; - -/** - * Strip the drive letter from a windows filepath - * @param {String} `fp` - * @return {String} - */ - -utils.stripDrive = function(fp) { - return utils.isWindows() ? fp.replace(/^[a-z]:[\\/]+?/i, '/') : fp; -}; - -/** - * Strip the prefix from a filepath - * @param {String} `fp` - * @return {String} - */ - -utils.stripPrefix = function(str) { - if (str.charAt(0) === '.' && (str.charAt(1) === '/' || str.charAt(1) === '\\')) { - return str.slice(2); - } - return str; -}; - -/** - * Returns true if `str` is a common character that doesn't need - * to be processed to be used for matching. - * @param {String} `str` - * @return {Boolean} - */ - -utils.isSimpleChar = function(str) { - return str.trim() === '' || str === '.'; -}; - -/** - * Returns true if the given str is an escaped or - * unescaped path character - */ - -utils.isSlash = function(str) { - return str === '/' || str === '\\/' || str === '\\' || str === '\\\\'; -}; - -/** - * Returns a function that returns true if the given - * pattern matches or contains a `filepath` - * - * @param {String} `pattern` - * @return {Function} - */ - -utils.matchPath = function(pattern, options) { - return (options && options.contains) - ? utils.containsPattern(pattern, options) - : utils.equalsPattern(pattern, options); -}; - -/** - * Returns true if the given (original) filepath or unixified path are equal - * to the given pattern. - */ - -utils._equals = function(filepath, unixPath, pattern) { - return pattern === filepath || pattern === unixPath; -}; - -/** - * Returns true if the given (original) filepath or unixified path contain - * the given pattern. - */ - -utils._contains = function(filepath, unixPath, pattern) { - return filepath.indexOf(pattern) !== -1 || unixPath.indexOf(pattern) !== -1; -}; - -/** - * Returns a function that returns true if the given - * pattern is the same as a given `filepath` - * - * @param {String} `pattern` - * @return {Function} - */ - -utils.equalsPattern = function(pattern, options) { - var unixify = utils.unixify(options); - options = options || {}; - - return function fn(filepath) { - var equal = utils._equals(filepath, unixify(filepath), pattern); - if (equal === true || options.nocase !== true) { - return equal; - } - var lower = filepath.toLowerCase(); - return utils._equals(lower, unixify(lower), pattern); - }; -}; - -/** - * Returns a function that returns true if the given - * pattern contains a `filepath` - * - * @param {String} `pattern` - * @return {Function} - */ - -utils.containsPattern = function(pattern, options) { - var unixify = utils.unixify(options); - options = options || {}; - - return function(filepath) { - var contains = utils._contains(filepath, unixify(filepath), pattern); - if (contains === true || options.nocase !== true) { - return contains; - } - var lower = filepath.toLowerCase(); - return utils._contains(lower, unixify(lower), pattern); - }; -}; - -/** - * Returns a function that returns true if the given - * regex matches the `filename` of a file path. - * - * @param {RegExp} `re` Matching regex - * @return {Function} - */ - -utils.matchBasename = function(re) { - return function(filepath) { - return re.test(filepath) || re.test(path.basename(filepath)); - }; -}; - -/** - * Returns the given value unchanced. - * @return {any} - */ - -utils.identity = function(val) { - return val; -}; - -/** - * Determines the filepath to return based on the provided options. - * @return {any} - */ - -utils.value = function(str, unixify, options) { - if (options && options.unixify === false) { - return str; - } - if (options && typeof options.unixify === 'function') { - return options.unixify(str); - } - return unixify(str); -}; - -/** - * Returns a function that normalizes slashes in a string to forward - * slashes, strips `./` from beginning of paths, and optionally unescapes - * special characters. - * @return {Function} - */ - -utils.unixify = function(options) { - var opts = options || {}; - return function(filepath) { - if (opts.stripPrefix !== false) { - filepath = utils.stripPrefix(filepath); - } - if (opts.unescape === true) { - filepath = utils.unescape(filepath); - } - if (opts.unixify === true || utils.isWindows()) { - filepath = utils.toPosixPath(filepath); - } - return filepath; - }; -}; - - -/***/ }), -/* 852 */ -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! - * is-windows - * - * Copyright © 2015-2018, Jon Schlinkert. - * Released under the MIT License. - */ - -(function(factory) { - if (exports && typeof exports === 'object' && typeof module !== 'undefined') { - module.exports = factory(); - } else if (true) { - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else {} -})(function() { - 'use strict'; - return function isWindows() { - return process && (process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE)); - }; -}); - - -/***/ }), -/* 853 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015-2018, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isobject = __webpack_require__(748); -var isDescriptor = __webpack_require__(760); -var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) - ? Reflect.defineProperty - : Object.defineProperty; - -module.exports = function defineProperty(obj, key, val) { - if (!isobject(obj) && typeof obj !== 'function' && !Array.isArray(obj)) { - throw new TypeError('expected an object, function, or array'); - } - - if (typeof key !== 'string') { - throw new TypeError('expected "key" to be a string'); - } - - if (isDescriptor(val)) { - define(obj, key, val); - return obj; - } - - define(obj, key, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); - - return obj; -}; - - -/***/ }), -/* 854 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * arr-diff - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -module.exports = function diff(arr/*, arrays*/) { - var len = arguments.length; - var idx = 0; - while (++idx < len) { - arr = diffArray(arr, arguments[idx]); - } - return arr; -}; - -function diffArray(one, two) { - if (!Array.isArray(two)) { - return one.slice(); - } - - var tlen = two.length - var olen = one.length; - var idx = -1; - var arr = []; - - while (++idx < olen) { - var ele = one[idx]; - - var hasEle = false; - for (var i = 0; i < tlen; i++) { - var val = two[i]; - - if (ele === val) { - hasEle = true; - break; - } - } - - if (hasEle === false) { - arr.push(ele); - } - } - return arr; -} - - -/***/ }), -/* 855 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * object.pick - * - * Copyright (c) 2014-2015 Jon Schlinkert, contributors. - * Licensed under the MIT License - */ - - - -var isObject = __webpack_require__(748); - -module.exports = function pick(obj, keys) { - if (!isObject(obj) && typeof obj !== 'function') { - return {}; - } - - var res = {}; - if (typeof keys === 'string') { - if (keys in obj) { - res[keys] = obj[keys]; - } - return res; - } - - var len = keys.length; - var idx = -1; - - while (++idx < len) { - var key = keys[idx]; - if (key in obj) { - res[key] = obj[key]; - } - } - return res; -}; - - -/***/ }), -/* 856 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } - - if (isGeneratorObj(val)) { - return 'generator'; - } - - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } - - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} - -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } - } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; -} - - -/***/ }), -/* 857 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Module dependencies - */ - -var extend = __webpack_require__(738); -var unique = __webpack_require__(741); -var toRegex = __webpack_require__(729); - -/** - * Local dependencies - */ - -var compilers = __webpack_require__(858); -var parsers = __webpack_require__(869); -var Extglob = __webpack_require__(872); -var utils = __webpack_require__(871); -var MAX_LENGTH = 1024 * 64; - -/** - * Convert the given `extglob` pattern into a regex-compatible string. Returns - * an object with the compiled result and the parsed AST. - * - * ```js - * var extglob = require('extglob'); - * console.log(extglob('*.!(*a)')); - * //=> '(?!\\.)[^/]*?\\.(?!(?!\\.)[^/]*?a\\b).*?' - * ``` - * @param {String} `pattern` - * @param {Object} `options` - * @return {String} - * @api public - */ - -function extglob(pattern, options) { - return extglob.create(pattern, options).output; -} - -/** - * Takes an array of strings and an extglob pattern and returns a new - * array that contains only the strings that match the pattern. - * - * ```js - * var extglob = require('extglob'); - * console.log(extglob.match(['a.a', 'a.b', 'a.c'], '*.!(*a)')); - * //=> ['a.b', 'a.c'] - * ``` - * @param {Array} `list` Array of strings to match - * @param {String} `pattern` Extglob pattern - * @param {Object} `options` - * @return {Array} Returns an array of matches - * @api public - */ - -extglob.match = function(list, pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected pattern to be a string'); - } - - list = utils.arrayify(list); - var isMatch = extglob.matcher(pattern, options); - var len = list.length; - var idx = -1; - var matches = []; - - while (++idx < len) { - var ele = list[idx]; - - if (isMatch(ele)) { - matches.push(ele); - } - } - - // if no options were passed, uniquify results and return - if (typeof options === 'undefined') { - return unique(matches); - } - - if (matches.length === 0) { - if (options.failglob === true) { - throw new Error('no matches found for "' + pattern + '"'); - } - if (options.nonull === true || options.nullglob === true) { - return [pattern.split('\\').join('')]; - } - } - - return options.nodupes !== false ? unique(matches) : matches; -}; - -/** - * Returns true if the specified `string` matches the given - * extglob `pattern`. - * - * ```js - * var extglob = require('extglob'); - * - * console.log(extglob.isMatch('a.a', '*.!(*a)')); - * //=> false - * console.log(extglob.isMatch('a.b', '*.!(*a)')); - * //=> true - * ``` - * @param {String} `string` String to match - * @param {String} `pattern` Extglob pattern - * @param {String} `options` - * @return {Boolean} - * @api public - */ - -extglob.isMatch = function(str, pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected pattern to be a string'); - } - - if (typeof str !== 'string') { - throw new TypeError('expected a string'); - } - - if (pattern === str) { - return true; - } - - if (pattern === '' || pattern === ' ' || pattern === '.') { - return pattern === str; - } - - var isMatch = utils.memoize('isMatch', pattern, options, extglob.matcher); - return isMatch(str); -}; - -/** - * Returns true if the given `string` contains the given pattern. Similar to `.isMatch` but - * the pattern can match any part of the string. - * - * ```js - * var extglob = require('extglob'); - * console.log(extglob.contains('aa/bb/cc', '*b')); - * //=> true - * console.log(extglob.contains('aa/bb/cc', '*d')); - * //=> false - * ``` - * @param {String} `str` The string to match. - * @param {String} `pattern` Glob pattern to use for matching. - * @param {Object} `options` - * @return {Boolean} Returns true if the patter matches any part of `str`. - * @api public - */ - -extglob.contains = function(str, pattern, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string'); - } - - if (pattern === '' || pattern === ' ' || pattern === '.') { - return pattern === str; - } - - var opts = extend({}, options, {contains: true}); - opts.strictClose = false; - opts.strictOpen = false; - return extglob.isMatch(str, pattern, opts); -}; - -/** - * Takes an extglob pattern and returns a matcher function. The returned - * function takes the string to match as its only argument. - * - * ```js - * var extglob = require('extglob'); - * var isMatch = extglob.matcher('*.!(*a)'); - * - * console.log(isMatch('a.a')); - * //=> false - * console.log(isMatch('a.b')); - * //=> true - * ``` - * @param {String} `pattern` Extglob pattern - * @param {String} `options` - * @return {Boolean} - * @api public - */ - -extglob.matcher = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected pattern to be a string'); - } - - function matcher() { - var re = extglob.makeRe(pattern, options); - return function(str) { - return re.test(str); - }; - } - - return utils.memoize('matcher', pattern, options, matcher); -}; - -/** - * Convert the given `extglob` pattern into a regex-compatible string. Returns - * an object with the compiled result and the parsed AST. - * - * ```js - * var extglob = require('extglob'); - * console.log(extglob.create('*.!(*a)').output); - * //=> '(?!\\.)[^/]*?\\.(?!(?!\\.)[^/]*?a\\b).*?' - * ``` - * @param {String} `str` - * @param {Object} `options` - * @return {String} - * @api public - */ - -extglob.create = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected pattern to be a string'); - } - - function create() { - var ext = new Extglob(options); - var ast = ext.parse(pattern, options); - return ext.compile(ast, options); - } - - return utils.memoize('create', pattern, options, create); -}; - -/** - * Returns an array of matches captured by `pattern` in `string`, or `null` - * if the pattern did not match. - * - * ```js - * var extglob = require('extglob'); - * extglob.capture(pattern, string[, options]); - * - * console.log(extglob.capture('test/*.js', 'test/foo.js')); - * //=> ['foo'] - * console.log(extglob.capture('test/*.js', 'foo/bar.css')); - * //=> null - * ``` - * @param {String} `pattern` Glob pattern to use for matching. - * @param {String} `string` 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 string matches the glob pattern, otherwise `null`. - * @api public - */ - -extglob.capture = function(pattern, str, options) { - var re = extglob.makeRe(pattern, extend({capture: true}, options)); - - function match() { - return function(string) { - var match = re.exec(string); - if (!match) { - return null; - } - - return match.slice(1); - }; - } - - var capture = utils.memoize('capture', pattern, options, match); - return capture(str); -}; - -/** - * Create a regular expression from the given `pattern` and `options`. - * - * ```js - * var extglob = require('extglob'); - * var re = extglob.makeRe('*.!(*a)'); - * console.log(re); - * //=> /^[^\/]*?\.(?![^\/]*?a)[^\/]*?$/ - * ``` - * @param {String} `pattern` The pattern to convert to regex. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ - -extglob.makeRe = function(pattern, options) { - if (pattern instanceof RegExp) { - return pattern; - } - - if (typeof pattern !== 'string') { - throw new TypeError('expected pattern to be a string'); - } - - if (pattern.length > MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); - } - - function makeRe() { - var opts = extend({strictErrors: false}, options); - if (opts.strictErrors === true) opts.strict = true; - var res = extglob.create(pattern, opts); - return toRegex(res.output, opts); - } - - var regex = utils.memoize('makeRe', pattern, options, makeRe); - if (regex.source.length > MAX_LENGTH) { - throw new SyntaxError('potentially malicious regex detected'); - } - - return regex; -}; - -/** - * Cache - */ - -extglob.cache = utils.cache; -extglob.clearCache = function() { - extglob.cache.__data__ = {}; -}; - -/** - * Expose `Extglob` constructor, parsers and compilers - */ - -extglob.Extglob = Extglob; -extglob.compilers = compilers; -extglob.parsers = parsers; - -/** - * Expose `extglob` - * @type {Function} - */ - -module.exports = extglob; - - -/***/ }), -/* 858 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var brackets = __webpack_require__(859); - -/** - * Extglob compilers - */ - -module.exports = function(extglob) { - function star() { - if (typeof extglob.options.star === 'function') { - return extglob.options.star.apply(this, arguments); - } - if (typeof extglob.options.star === 'string') { - return extglob.options.star; - } - return '.*?'; - } - - /** - * Use `expand-brackets` compilers - */ - - extglob.use(brackets.compilers); - extglob.compiler - - /** - * Escaped: "\\*" - */ - - .set('escape', function(node) { - return this.emit(node.val, node); - }) - - /** - * Dot: "." - */ - - .set('dot', function(node) { - return this.emit('\\' + node.val, node); - }) - - /** - * Question mark: "?" - */ - - .set('qmark', function(node) { - var val = '[^\\\\/.]'; - var prev = this.prev(); - - if (node.parsed.slice(-1) === '(') { - var ch = node.rest.charAt(0); - if (ch !== '!' && ch !== '=' && ch !== ':') { - return this.emit(val, node); - } - return this.emit(node.val, node); - } - - if (prev.type === 'text' && prev.val) { - return this.emit(val, node); - } - - if (node.val.length > 1) { - val += '{' + node.val.length + '}'; - } - return this.emit(val, node); - }) - - /** - * Plus: "+" - */ - - .set('plus', function(node) { - var prev = node.parsed.slice(-1); - if (prev === ']' || prev === ')') { - return this.emit(node.val, node); - } - var ch = this.output.slice(-1); - if (!this.output || (/[?*+]/.test(ch) && node.parent.type !== 'bracket')) { - return this.emit('\\+', node); - } - if (/\w/.test(ch) && !node.inside) { - return this.emit('+\\+?', node); - } - return this.emit('+', node); - }) - - /** - * Star: "*" - */ - - .set('star', function(node) { - var prev = this.prev(); - var prefix = prev.type !== 'text' && prev.type !== 'escape' - ? '(?!\\.)' - : ''; - - return this.emit(prefix + star.call(this, node), node); - }) - - /** - * Parens - */ - - .set('paren', function(node) { - return this.mapVisit(node.nodes); - }) - .set('paren.open', function(node) { - var capture = this.options.capture ? '(' : ''; - - switch (node.parent.prefix) { - case '!': - case '^': - return this.emit(capture + '(?:(?!(?:', node); - case '*': - case '+': - case '?': - case '@': - return this.emit(capture + '(?:', node); - default: { - var val = node.val; - if (this.options.bash === true) { - val = '\\' + val; - } else if (!this.options.capture && val === '(' && node.parent.rest[0] !== '?') { - val += '?:'; - } - - return this.emit(val, node); - } - } - }) - .set('paren.close', function(node) { - var capture = this.options.capture ? ')' : ''; - - switch (node.prefix) { - case '!': - case '^': - var prefix = /^(\)|$)/.test(node.rest) ? '$' : ''; - var str = star.call(this, node); - - // if the extglob has a slash explicitly defined, we know the user wants - // to match slashes, so we need to ensure the "star" regex allows for it - if (node.parent.hasSlash && !this.options.star && this.options.slash !== false) { - str = '.*?'; - } - - return this.emit(prefix + ('))' + str + ')') + capture, node); - case '*': - case '+': - case '?': - return this.emit(')' + node.prefix + capture, node); - case '@': - return this.emit(')' + capture, node); - default: { - var val = (this.options.bash === true ? '\\' : '') + ')'; - return this.emit(val, node); - } - } - }) - - /** - * Text - */ - - .set('text', function(node) { - var val = node.val.replace(/[\[\]]/g, '\\$&'); - return this.emit(val, node); - }); -}; - - -/***/ }), -/* 859 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Local dependencies - */ - -var compilers = __webpack_require__(860); -var parsers = __webpack_require__(862); - -/** - * Module dependencies - */ - -var debug = __webpack_require__(864)('expand-brackets'); -var extend = __webpack_require__(738); -var Snapdragon = __webpack_require__(768); -var toRegex = __webpack_require__(729); - -/** - * Parses the given POSIX character class `pattern` and returns a - * string that can be used for creating regular expressions for matching. - * - * @param {String} `pattern` - * @param {Object} `options` - * @return {Object} - * @api public - */ - -function brackets(pattern, options) { - debug('initializing from <%s>', __filename); - var res = brackets.create(pattern, options); - return res.output; -} - -/** - * Takes an array of strings and a POSIX character class pattern, and returns a new - * array with only the strings that matched the pattern. - * - * ```js - * var brackets = require('expand-brackets'); - * console.log(brackets.match(['1', 'a', 'ab'], '[[:alpha:]]')); - * //=> ['a'] - * - * console.log(brackets.match(['1', 'a', 'ab'], '[[:alpha:]]+')); - * //=> ['a', 'ab'] - * ``` - * @param {Array} `arr` Array of strings to match - * @param {String} `pattern` POSIX character class pattern(s) - * @param {Object} `options` - * @return {Array} - * @api public - */ - -brackets.match = function(arr, pattern, options) { - arr = [].concat(arr); - var opts = extend({}, options); - var isMatch = brackets.matcher(pattern, opts); - var len = arr.length; - var idx = -1; - var res = []; - - while (++idx < len) { - var ele = arr[idx]; - if (isMatch(ele)) { - res.push(ele); - } - } - - if (res.length === 0) { - if (opts.failglob === true) { - throw new Error('no matches found for "' + pattern + '"'); - } - - if (opts.nonull === true || opts.nullglob === true) { - return [pattern.split('\\').join('')]; - } - } - return res; -}; - -/** - * Returns true if the specified `string` matches the given - * brackets `pattern`. - * - * ```js - * var brackets = require('expand-brackets'); - * - * console.log(brackets.isMatch('a.a', '[[:alpha:]].[[:alpha:]]')); - * //=> true - * console.log(brackets.isMatch('1.2', '[[:alpha:]].[[:alpha:]]')); - * //=> false - * ``` - * @param {String} `string` String to match - * @param {String} `pattern` Poxis pattern - * @param {String} `options` - * @return {Boolean} - * @api public - */ - -brackets.isMatch = function(str, pattern, options) { - return brackets.matcher(pattern, options)(str); -}; - -/** - * Takes a POSIX character class pattern and returns a matcher function. The returned - * function takes the string to match as its only argument. - * - * ```js - * var brackets = require('expand-brackets'); - * var isMatch = brackets.matcher('[[:lower:]].[[:upper:]]'); - * - * console.log(isMatch('a.a')); - * //=> false - * console.log(isMatch('a.A')); - * //=> true - * ``` - * @param {String} `pattern` Poxis pattern - * @param {String} `options` - * @return {Boolean} - * @api public - */ - -brackets.matcher = function(pattern, options) { - var re = brackets.makeRe(pattern, options); - return function(str) { - return re.test(str); - }; -}; - -/** - * Create a regular expression from the given `pattern`. - * - * ```js - * var brackets = require('expand-brackets'); - * var re = brackets.makeRe('[[:alpha:]]'); - * console.log(re); - * //=> /^(?:[a-zA-Z])$/ - * ``` - * @param {String} `pattern` The pattern to convert to regex. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ - -brackets.makeRe = function(pattern, options) { - var res = brackets.create(pattern, options); - var opts = extend({strictErrors: false}, options); - return toRegex(res.output, opts); -}; - -/** - * Parses the given POSIX character class `pattern` and returns an object - * with the compiled `output` and optional source `map`. - * - * ```js - * var brackets = require('expand-brackets'); - * console.log(brackets('[[:alpha:]]')); - * // { options: { source: 'string' }, - * // input: '[[:alpha:]]', - * // state: {}, - * // compilers: - * // { eos: [Function], - * // noop: [Function], - * // bos: [Function], - * // not: [Function], - * // escape: [Function], - * // text: [Function], - * // posix: [Function], - * // bracket: [Function], - * // 'bracket.open': [Function], - * // 'bracket.inner': [Function], - * // 'bracket.literal': [Function], - * // 'bracket.close': [Function] }, - * // output: '[a-zA-Z]', - * // ast: - * // { type: 'root', - * // errors: [], - * // nodes: [ [Object], [Object], [Object] ] }, - * // parsingErrors: [] } - * ``` - * @param {String} `pattern` - * @param {Object} `options` - * @return {Object} - * @api public - */ - -brackets.create = function(pattern, options) { - var snapdragon = (options && options.snapdragon) || new Snapdragon(options); - compilers(snapdragon); - parsers(snapdragon); - - var ast = snapdragon.parse(pattern, options); - ast.input = pattern; - var res = snapdragon.compile(ast, options); - res.input = pattern; - return res; -}; - -/** - * Expose `brackets` constructor, parsers and compilers - */ - -brackets.compilers = compilers; -brackets.parsers = parsers; - -/** - * Expose `brackets` - * @type {Function} - */ - -module.exports = brackets; - - -/***/ }), -/* 860 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var posix = __webpack_require__(861); - -module.exports = function(brackets) { - brackets.compiler - - /** - * Escaped characters - */ - - .set('escape', function(node) { - return this.emit('\\' + node.val.replace(/^\\/, ''), node); - }) - - /** - * Text - */ - - .set('text', function(node) { - return this.emit(node.val.replace(/([{}])/g, '\\$1'), node); - }) - - /** - * POSIX character classes - */ - - .set('posix', function(node) { - if (node.val === '[::]') { - return this.emit('\\[::\\]', node); - } - - var val = posix[node.inner]; - if (typeof val === 'undefined') { - val = '[' + node.inner + ']'; - } - return this.emit(val, node); - }) - - /** - * Non-posix brackets - */ - - .set('bracket', function(node) { - return this.mapVisit(node.nodes); - }) - .set('bracket.open', function(node) { - return this.emit(node.val, node); - }) - .set('bracket.inner', function(node) { - var inner = node.val; - - if (inner === '[' || inner === ']') { - return this.emit('\\' + node.val, node); - } - if (inner === '^]') { - return this.emit('^\\]', node); - } - if (inner === '^') { - return this.emit('^', node); - } - - if (/-/.test(inner) && !/(\d-\d|\w-\w)/.test(inner)) { - inner = inner.split('-').join('\\-'); - } - - var isNegated = inner.charAt(0) === '^'; - // add slashes to negated brackets, per spec - if (isNegated && inner.indexOf('/') === -1) { - inner += '/'; - } - if (isNegated && inner.indexOf('.') === -1) { - inner += '.'; - } - - // don't unescape `0` (octal literal) - inner = inner.replace(/\\([1-9])/g, '$1'); - return this.emit(inner, node); - }) - .set('bracket.close', function(node) { - var val = node.val.replace(/^\\/, ''); - if (node.parent.escaped === true) { - return this.emit('\\' + val, node); - } - return this.emit(val, node); - }); -}; - - -/***/ }), -/* 861 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * POSIX character classes - */ - -module.exports = { - 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' -}; - - -/***/ }), -/* 862 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var utils = __webpack_require__(863); -var define = __webpack_require__(730); - -/** - * Text regex - */ - -var TEXT_REGEX = '(\\[(?=.*\\])|\\])+'; -var not = utils.createRegex(TEXT_REGEX); - -/** - * Brackets parsers - */ - -function parsers(brackets) { - brackets.state = brackets.state || {}; - brackets.parser.sets.bracket = brackets.parser.sets.bracket || []; - brackets.parser - - .capture('escape', function() { - if (this.isInside('bracket')) return; - var pos = this.position(); - var m = this.match(/^\\(.)/); - if (!m) return; - - return pos({ - type: 'escape', - val: m[0] - }); - }) - - /** - * Text parser - */ - - .capture('text', function() { - if (this.isInside('bracket')) return; - var pos = this.position(); - var m = this.match(not); - if (!m || !m[0]) return; - - return pos({ - type: 'text', - val: m[0] - }); - }) - - /** - * POSIX character classes: "[[:alpha:][:digits:]]" - */ - - .capture('posix', function() { - var pos = this.position(); - var m = this.match(/^\[:(.*?):\](?=.*\])/); - if (!m) return; - - var inside = this.isInside('bracket'); - if (inside) { - brackets.posix++; - } - - return pos({ - type: 'posix', - insideBracket: inside, - inner: m[1], - val: m[0] - }); - }) - - /** - * Bracket (noop) - */ - - .capture('bracket', function() {}) - - /** - * Open: '[' - */ - - .capture('bracket.open', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(/^\[(?=.*\])/); - if (!m) return; - - var prev = this.prev(); - var last = utils.last(prev.nodes); - - if (parsed.slice(-1) === '\\' && !this.isInside('bracket')) { - last.val = last.val.slice(0, last.val.length - 1); - return pos({ - type: 'escape', - val: m[0] - }); - } - - var open = pos({ - type: 'bracket.open', - val: m[0] - }); - - if (last.type === 'bracket.open' || this.isInside('bracket')) { - open.val = '\\' + open.val; - open.type = 'bracket.inner'; - open.escaped = true; - return open; - } - - var node = pos({ - type: 'bracket', - nodes: [open] - }); - - define(node, 'parent', prev); - define(open, 'parent', node); - this.push('bracket', node); - prev.nodes.push(node); - }) - - /** - * Bracket text - */ - - .capture('bracket.inner', function() { - if (!this.isInside('bracket')) return; - var pos = this.position(); - var m = this.match(not); - if (!m || !m[0]) return; - - var next = this.input.charAt(0); - var val = m[0]; - - var node = pos({ - type: 'bracket.inner', - val: val - }); - - if (val === '\\\\') { - return node; - } - - var first = val.charAt(0); - var last = val.slice(-1); - - if (first === '!') { - val = '^' + val.slice(1); - } - - if (last === '\\' || (val === '^' && next === ']')) { - val += this.input[0]; - this.consume(1); - } - - node.val = val; - return node; - }) - - /** - * Close: ']' - */ - - .capture('bracket.close', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(/^\]/); - if (!m) return; - - var prev = this.prev(); - var last = utils.last(prev.nodes); - - if (parsed.slice(-1) === '\\' && !this.isInside('bracket')) { - last.val = last.val.slice(0, last.val.length - 1); - - return pos({ - type: 'escape', - val: m[0] - }); - } - - var node = pos({ - type: 'bracket.close', - rest: this.input, - val: m[0] - }); - - if (last.type === 'bracket.open') { - node.type = 'bracket.inner'; - node.escaped = true; - return node; - } - - var bracket = this.pop('bracket'); - if (!this.isType(bracket, 'bracket')) { - if (this.options.strict) { - throw new Error('missing opening "["'); - } - node.type = 'bracket.inner'; - node.escaped = true; - return node; - } - - bracket.nodes.push(node); - define(node, 'parent', bracket); - }); -} - -/** - * Brackets parsers - */ - -module.exports = parsers; - -/** - * Expose text regex - */ - -module.exports.TEXT_REGEX = TEXT_REGEX; - - -/***/ }), -/* 863 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var toRegex = __webpack_require__(729); -var regexNot = __webpack_require__(740); -var cached; - -/** - * Get the last element from `array` - * @param {Array} `array` - * @return {*} - */ - -exports.last = function(arr) { - return arr[arr.length - 1]; -}; - -/** - * Create and cache regex to use for text nodes - */ - -exports.createRegex = function(pattern, include) { - if (cached) return cached; - var opts = {contains: true, strictClose: false}; - var not = regexNot.create(pattern, opts); - var re; - - if (typeof include === 'string') { - re = toRegex('^(?:' + include + '|' + not + ')', opts); - } else { - re = toRegex(not, opts); - } - - return (cached = re); -}; - - -/***/ }), -/* 864 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Detect Electron renderer process, which is node, but we should - * treat as a browser. - */ - -if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(865); -} else { - module.exports = __webpack_require__(868); -} - - -/***/ }), -/* 865 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = __webpack_require__(866); -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); - -/** - * Colors. - */ - -exports.colors = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' -]; - -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ - -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { - return true; - } - - // is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -exports.formatters.j = function(v) { - try { - return JSON.stringify(v); - } catch (err) { - return '[UnexpectedJSONParseError]: ' + err.message; - } -}; - - -/** - * Colorize log arguments if enabled. - * - * @api public - */ - -function formatArgs(args) { - var useColors = this.useColors; - - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - - if (!useColors) return; - - var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit') - - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, function(match) { - if ('%%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - - args.splice(lastC, 0, c); -} - -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ - -function log() { - // this hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); -} - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - -function save(namespaces) { - try { - if (null == namespaces) { - exports.storage.removeItem('debug'); - } else { - exports.storage.debug = namespaces; - } - } catch(e) {} -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - -function load() { - var r; - try { - r = exports.storage.debug; - } catch(e) {} - - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; - } - - return r; -} - -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ - -exports.enable(load()); - -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ - -function localstorage() { - try { - return window.localStorage; - } catch (e) {} -} - - -/***/ }), -/* 866 */ -/***/ (function(module, exports, __webpack_require__) { - - -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = __webpack_require__(867); - -/** - * The currently active debug mode names, and names to skip. - */ - -exports.names = []; -exports.skips = []; - -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - -exports.formatters = {}; - -/** - * Previous log timestamp. - */ - -var prevTime; - -/** - * Select a color. - * @param {String} namespace - * @return {Number} - * @api private - */ - -function selectColor(namespace) { - var hash = 0, i; - - for (i in namespace) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer - } - - return exports.colors[Math.abs(hash) % exports.colors.length]; -} - -/** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - -function createDebug(namespace) { - - function debug() { - // disabled? - if (!debug.enabled) return; - - var self = debug; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // turn the `arguments` into a proper Array - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } - - args[0] = exports.coerce(args[0]); - - if ('string' !== typeof args[0]) { - // anything else let's inspect with %O - args.unshift('%O'); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); - - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - // apply env-specific formatting (colors, etc.) - exports.formatArgs.call(self, args); - - var logFn = debug.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - - debug.namespace = namespace; - debug.enabled = exports.enabled(namespace); - debug.useColors = exports.useColors(); - debug.color = selectColor(namespace); - - // env-specific initialization logic for debug instances - if ('function' === typeof exports.init) { - exports.init(debug); - } - - return debug; -} - -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - -function enable(namespaces) { - exports.save(namespaces); - - exports.names = []; - exports.skips = []; - - var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - var len = split.length; - - for (var i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } -} - -/** - * Disable debug output. - * - * @api public - */ - -function disable() { - exports.enable(''); -} - -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - -function enabled(name) { - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; -} - -/** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} - - -/***/ }), -/* 867 */ -/***/ (function(module, exports) { - -/** - * Helpers. - */ - -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; -var y = d * 365.25; - -/** - * Parse or format the given `val`. - * - * Options: - * - * - `long` verbose formatting [false] - * - * @param {String|Number} val - * @param {Object} [options] - * @throws {Error} throw an error if val is not a non-empty string or a number - * @return {String|Number} - * @api public - */ - -module.exports = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse(val); - } else if (type === 'number' && isNaN(val) === false) { - return options.long ? fmtLong(val) : fmtShort(val); - } - throw new Error( - 'val is not a non-empty string or a valid number. val=' + - JSON.stringify(val) - ); -}; - -/** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ - -function parse(str) { - str = String(str); - if (str.length > 100) { - return; - } - var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( - str - ); - if (!match) { - return; - } - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'yrs': - case 'yr': - case 'y': - return n * y; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'hrs': - case 'hr': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'mins': - case 'min': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 'secs': - case 'sec': - case 's': - return n * s; - case 'milliseconds': - case 'millisecond': - case 'msecs': - case 'msec': - case 'ms': - return n; - default: - return undefined; - } -} - -/** - * Short format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtShort(ms) { - if (ms >= d) { - return Math.round(ms / d) + 'd'; - } - if (ms >= h) { - return Math.round(ms / h) + 'h'; - } - if (ms >= m) { - return Math.round(ms / m) + 'm'; - } - if (ms >= s) { - return Math.round(ms / s) + 's'; - } - return ms + 'ms'; -} - -/** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtLong(ms) { - return plural(ms, d, 'day') || - plural(ms, h, 'hour') || - plural(ms, m, 'minute') || - plural(ms, s, 'second') || - ms + ' ms'; -} - -/** - * Pluralization helper. - */ - -function plural(ms, n, name) { - if (ms < n) { - return; - } - if (ms < n * 1.5) { - return Math.floor(ms / n) + ' ' + name; - } - return Math.ceil(ms / n) + ' ' + name + 's'; -} - - -/***/ }), -/* 868 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Module dependencies. - */ - -var tty = __webpack_require__(480); -var util = __webpack_require__(29); - -/** - * This is the Node.js implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = __webpack_require__(866); -exports.init = init; -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; - -/** - * Colors. - */ - -exports.colors = [6, 2, 3, 4, 5, 1]; - -/** - * Build up the default `inspectOpts` object from the environment variables. - * - * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js - */ - -exports.inspectOpts = Object.keys(process.env).filter(function (key) { - return /^debug_/i.test(key); -}).reduce(function (obj, key) { - // camel-case - var prop = key - .substring(6) - .toLowerCase() - .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); - - // coerce string value into JS value - var val = process.env[key]; - if (/^(yes|on|true|enabled)$/i.test(val)) val = true; - else if (/^(no|off|false|disabled)$/i.test(val)) val = false; - else if (val === 'null') val = null; - else val = Number(val); - - obj[prop] = val; - return obj; -}, {}); - -/** - * The file descriptor to write the `debug()` calls to. - * Set the `DEBUG_FD` env variable to override with another value. i.e.: - * - * $ DEBUG_FD=3 node script.js 3>debug.log - */ - -var fd = parseInt(process.env.DEBUG_FD, 10) || 2; - -if (1 !== fd && 2 !== fd) { - util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')() -} - -var stream = 1 === fd ? process.stdout : - 2 === fd ? process.stderr : - createWritableStdioStream(fd); - -/** - * Is stdout a TTY? Colored output is enabled when `true`. - */ - -function useColors() { - return 'colors' in exports.inspectOpts - ? Boolean(exports.inspectOpts.colors) - : tty.isatty(fd); -} - -/** - * Map %o to `util.inspect()`, all on a single line. - */ - -exports.formatters.o = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts) - .split('\n').map(function(str) { - return str.trim() - }).join(' '); -}; - -/** - * Map %o to `util.inspect()`, allowing multiple lines if needed. - */ - -exports.formatters.O = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts); -}; - -/** - * Adds ANSI color escape codes if enabled. - * - * @api public - */ - -function formatArgs(args) { - var name = this.namespace; - var useColors = this.useColors; - - if (useColors) { - var c = this.color; - var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m'; - - args[0] = prefix + args[0].split('\n').join('\n' + prefix); - args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); - } else { - args[0] = new Date().toUTCString() - + ' ' + name + ' ' + args[0]; - } -} - -/** - * Invokes `util.format()` with the specified arguments and writes to `stream`. - */ - -function log() { - return stream.write(util.format.apply(util, arguments) + '\n'); -} - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - -function save(namespaces) { - if (null == namespaces) { - // If you set a process.env field to null or undefined, it gets cast to the - // string 'null' or 'undefined'. Just delete instead. - delete process.env.DEBUG; - } else { - process.env.DEBUG = namespaces; - } -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - -function load() { - return process.env.DEBUG; -} - -/** - * Copied from `node/src/node.js`. - * - * XXX: It's lame that node doesn't expose this API out-of-the-box. It also - * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. - */ - -function createWritableStdioStream (fd) { - var stream; - var tty_wrap = process.binding('tty_wrap'); - - // Note stream._type is used for test-module-load-list.js - - switch (tty_wrap.guessHandleType(fd)) { - case 'TTY': - stream = new tty.WriteStream(fd); - stream._type = 'tty'; - - // Hack to have stream not keep the event loop alive. - // See https://github.com/joyent/node/issues/1726 - if (stream._handle && stream._handle.unref) { - stream._handle.unref(); - } - break; - - case 'FILE': - var fs = __webpack_require__(23); - stream = new fs.SyncWriteStream(fd, { autoClose: false }); - stream._type = 'fs'; - break; - - case 'PIPE': - case 'TCP': - var net = __webpack_require__(806); - stream = new net.Socket({ - fd: fd, - readable: false, - writable: true - }); - - // FIXME Should probably have an option in net.Socket to create a - // stream from an existing fd which is writable only. But for now - // we'll just add this hack and set the `readable` member to false. - // Test: ./node test/fixtures/echo.js < /etc/passwd - stream.readable = false; - stream.read = null; - stream._type = 'pipe'; - - // FIXME Hack to have stream not keep the event loop alive. - // See https://github.com/joyent/node/issues/1726 - if (stream._handle && stream._handle.unref) { - stream._handle.unref(); - } - break; - - default: - // Probably an error on in uv_guess_handle() - throw new Error('Implement me. Unknown stream file type!'); - } - - // For supporting legacy API we put the FD here. - stream.fd = fd; - - stream._isStdio = true; - - return stream; -} - -/** - * Init logic for `debug` instances. - * - * Create a new `inspectOpts` object in case `useColors` is set - * differently for a particular `debug` instance. - */ - -function init (debug) { - debug.inspectOpts = {}; - - var keys = Object.keys(exports.inspectOpts); - for (var i = 0; i < keys.length; i++) { - debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; - } -} - -/** - * Enable namespaces listed in `process.env.DEBUG` initially. - */ - -exports.enable(load()); - - -/***/ }), -/* 869 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var brackets = __webpack_require__(859); -var define = __webpack_require__(870); -var utils = __webpack_require__(871); - -/** - * Characters to use in text regex (we want to "not" match - * characters that are matched by other parsers) - */ - -var TEXT_REGEX = '([!@*?+]?\\(|\\)|[*?.+\\\\]|\\[:?(?=.*\\])|:?\\])+'; -var not = utils.createRegex(TEXT_REGEX); - -/** - * Extglob parsers - */ - -function parsers(extglob) { - extglob.state = extglob.state || {}; - - /** - * Use `expand-brackets` parsers - */ - - extglob.use(brackets.parsers); - extglob.parser.sets.paren = extglob.parser.sets.paren || []; - extglob.parser - - /** - * Extglob open: "*(" - */ - - .capture('paren.open', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(/^([!@*?+])?\(/); - if (!m) return; - - var prev = this.prev(); - var prefix = m[1]; - var val = m[0]; - - var open = pos({ - type: 'paren.open', - parsed: parsed, - val: val - }); - - var node = pos({ - type: 'paren', - prefix: prefix, - nodes: [open] - }); - - // if nested negation extglobs, just cancel them out to simplify - if (prefix === '!' && prev.type === 'paren' && prev.prefix === '!') { - prev.prefix = '@'; - node.prefix = '@'; - } - - define(node, 'rest', this.input); - define(node, 'parsed', parsed); - define(node, 'parent', prev); - define(open, 'parent', node); - - this.push('paren', node); - prev.nodes.push(node); - }) - - /** - * Extglob close: ")" - */ - - .capture('paren.close', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(/^\)/); - if (!m) return; - - var parent = this.pop('paren'); - var node = pos({ - type: 'paren.close', - rest: this.input, - parsed: parsed, - val: m[0] - }); - - if (!this.isType(parent, 'paren')) { - if (this.options.strict) { - throw new Error('missing opening paren: "("'); - } - node.escaped = true; - return node; - } - - node.prefix = parent.prefix; - parent.nodes.push(node); - define(node, 'parent', parent); - }) - - /** - * Escape: "\\." - */ - - .capture('escape', function() { - var pos = this.position(); - var m = this.match(/^\\(.)/); - if (!m) return; - - return pos({ - type: 'escape', - val: m[0], - ch: m[1] - }); - }) - - /** - * Question marks: "?" - */ - - .capture('qmark', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(/^\?+(?!\()/); - if (!m) return; - extglob.state.metachar = true; - return pos({ - type: 'qmark', - rest: this.input, - parsed: parsed, - val: m[0] - }); - }) - - /** - * Character parsers - */ - - .capture('star', /^\*(?!\()/) - .capture('plus', /^\+(?!\()/) - .capture('dot', /^\./) - .capture('text', not); -}; - -/** - * Expose text regex string - */ - -module.exports.TEXT_REGEX = TEXT_REGEX; - -/** - * Extglob parsers - */ - -module.exports = parsers; - - -/***/ }), -/* 870 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isDescriptor = __webpack_require__(760); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } - - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } - - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; - - -/***/ }), -/* 871 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var regex = __webpack_require__(740); -var Cache = __webpack_require__(850); - -/** - * Utils - */ - -var utils = module.exports; -var cache = utils.cache = new Cache(); - -/** - * Cast `val` to an array - * @return {Array} - */ - -utils.arrayify = function(val) { - if (!Array.isArray(val)) { - return [val]; - } - return val; -}; - -/** - * Memoize a generated regex or function - */ - -utils.memoize = function(type, pattern, options, fn) { - var key = utils.createKey(type + pattern, options); - - if (cache.has(type, key)) { - return cache.get(type, key); - } - - var val = fn(pattern, options); - if (options && options.cache === false) { - return val; - } - - cache.set(type, key, val); - return val; -}; - -/** - * Create the key to use for memoization. The key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. - */ - -utils.createKey = function(pattern, options) { - var key = pattern; - if (typeof options === 'undefined') { - return key; - } - for (var prop in options) { - key += ';' + prop + '=' + String(options[prop]); - } - return key; -}; - -/** - * Create the regex to use for matching text - */ - -utils.createRegex = function(str) { - var opts = {contains: true, strictClose: false}; - return regex(str, opts); -}; - - -/***/ }), -/* 872 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Module dependencies - */ - -var Snapdragon = __webpack_require__(768); -var define = __webpack_require__(870); -var extend = __webpack_require__(738); - -/** - * Local dependencies - */ - -var compilers = __webpack_require__(858); -var parsers = __webpack_require__(869); - -/** - * Customize Snapdragon parser and renderer - */ - -function Extglob(options) { - this.options = extend({source: 'extglob'}, options); - this.snapdragon = this.options.snapdragon || new Snapdragon(this.options); - this.snapdragon.patterns = this.snapdragon.patterns || {}; - this.compiler = this.snapdragon.compiler; - this.parser = this.snapdragon.parser; - - compilers(this.snapdragon); - parsers(this.snapdragon); - - /** - * Override Snapdragon `.parse` method - */ - - define(this.snapdragon, 'parse', function(str, options) { - var parsed = Snapdragon.prototype.parse.apply(this, arguments); - parsed.input = str; - - // escape unmatched brace/bracket/parens - var last = this.parser.stack.pop(); - if (last && this.options.strict !== true) { - var node = last.nodes[0]; - node.val = '\\' + node.val; - var sibling = node.parent.nodes[1]; - if (sibling.type === 'star') { - sibling.loose = true; - } - } - - // add non-enumerable parser reference - define(parsed, 'parser', this.parser); - return parsed; - }); - - /** - * Decorate `.parse` method - */ - - define(this, 'parse', function(ast, options) { - return this.snapdragon.parse.apply(this.snapdragon, arguments); - }); - - /** - * Decorate `.compile` method - */ - - define(this, 'compile', function(ast, options) { - return this.snapdragon.compile.apply(this.snapdragon, arguments); - }); - -} - -/** - * Expose `Extglob` - */ - -module.exports = Extglob; - - -/***/ }), -/* 873 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var extglob = __webpack_require__(857); -var nanomatch = __webpack_require__(842); -var regexNot = __webpack_require__(740); -var toRegex = __webpack_require__(830); -var not; - -/** - * Characters to use in negation regex (we want to "not" match - * characters that are matched by other parsers) - */ - -var TEXT = '([!@*?+]?\\(|\\)|\\[:?(?=.*?:?\\])|:?\\]|[*+?!^$.\\\\/])+'; -var createNotRegex = function(opts) { - return not || (not = textRegex(TEXT)); -}; - -/** - * Parsers - */ - -module.exports = function(snapdragon) { - var parsers = snapdragon.parser.parsers; - - // register nanomatch parsers - snapdragon.use(nanomatch.parsers); - - // get references to some specific nanomatch parsers before they - // are overridden by the extglob and/or parsers - var escape = parsers.escape; - var slash = parsers.slash; - var qmark = parsers.qmark; - var plus = parsers.plus; - var star = parsers.star; - var dot = parsers.dot; - - // register extglob parsers - snapdragon.use(extglob.parsers); - - // custom micromatch parsers - snapdragon.parser - .use(function() { - // override "notRegex" created in nanomatch parser - this.notRegex = /^\!+(?!\()/; - }) - // reset the referenced parsers - .capture('escape', escape) - .capture('slash', slash) - .capture('qmark', qmark) - .capture('star', star) - .capture('plus', plus) - .capture('dot', dot) - - /** - * Override `text` parser - */ - - .capture('text', function() { - if (this.isInside('bracket')) return; - var pos = this.position(); - var m = this.match(createNotRegex(this.options)); - if (!m || !m[0]) return; - - // escape regex boundary characters and simple brackets - var val = m[0].replace(/([[\]^$])/g, '\\$1'); - - return pos({ - type: 'text', - val: val - }); - }); -}; - -/** - * Create text regex - */ - -function textRegex(pattern) { - var notStr = regexNot.create(pattern, {contains: true, strictClose: false}); - var prefix = '(?:[\\^]|\\\\|'; - return toRegex(prefix + notStr + ')', {strictClose: false}); -} - - -/***/ }), -/* 874 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = new (__webpack_require__(850))(); - - -/***/ }), -/* 875 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var utils = module.exports; -var path = __webpack_require__(16); - -/** - * Module dependencies - */ - -var Snapdragon = __webpack_require__(768); -utils.define = __webpack_require__(837); -utils.diff = __webpack_require__(854); -utils.extend = __webpack_require__(838); -utils.pick = __webpack_require__(855); -utils.typeOf = __webpack_require__(876); -utils.unique = __webpack_require__(741); - -/** - * Returns true if the platform is windows, or `path.sep` is `\\`. - * This is defined as a function to allow `path.sep` to be set in unit tests, - * or by the user, if there is a reason to do so. - * @return {Boolean} - */ - -utils.isWindows = function() { - return path.sep === '\\' || process.platform === 'win32'; -}; - -/** - * Get the `Snapdragon` instance to use - */ - -utils.instantiate = function(ast, options) { - var snapdragon; - // if an instance was created by `.parse`, use that instance - if (utils.typeOf(ast) === 'object' && ast.snapdragon) { - snapdragon = ast.snapdragon; - // if the user supplies an instance on options, use that instance - } else if (utils.typeOf(options) === 'object' && options.snapdragon) { - snapdragon = options.snapdragon; - // create a new instance - } else { - snapdragon = new Snapdragon(options); - } - - utils.define(snapdragon, 'parse', function(str, options) { - var parsed = Snapdragon.prototype.parse.apply(this, arguments); - parsed.input = str; - - // escape unmatched brace/bracket/parens - var last = this.parser.stack.pop(); - if (last && this.options.strictErrors !== true) { - var open = last.nodes[0]; - var inner = last.nodes[1]; - if (last.type === 'bracket') { - if (inner.val.charAt(0) === '[') { - inner.val = '\\' + inner.val; - } - - } else { - open.val = '\\' + open.val; - var sibling = open.parent.nodes[1]; - if (sibling.type === 'star') { - sibling.loose = true; - } - } - } - - // add non-enumerable parser reference - utils.define(parsed, 'parser', this.parser); - return parsed; - }); - - return snapdragon; -}; - -/** - * Create the key to use for memoization. The key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. - */ - -utils.createKey = function(pattern, options) { - if (utils.typeOf(options) !== 'object') { - return pattern; - } - var val = pattern; - var keys = Object.keys(options); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - val += ';' + key + '=' + String(options[key]); - } - return val; -}; - -/** - * Cast `val` to an array - * @return {Array} - */ - -utils.arrayify = function(val) { - if (typeof val === 'string') return [val]; - return val ? (Array.isArray(val) ? val : [val]) : []; -}; - -/** - * Return true if `val` is a non-empty string - */ - -utils.isString = function(val) { - return typeof val === 'string'; -}; - -/** - * Return true if `val` is a non-empty string - */ - -utils.isObject = function(val) { - return utils.typeOf(val) === 'object'; -}; - -/** - * Returns true if the given `str` has special characters - */ - -utils.hasSpecialChars = function(str) { - return /(?:(?:(^|\/)[!.])|[*?+()|\[\]{}]|[+@]\()/.test(str); -}; - -/** - * Escape regex characters in the given string - */ - -utils.escapeRegex = function(str) { - return str.replace(/[-[\]{}()^$|*+?.\\\/\s]/g, '\\$&'); -}; - -/** - * Normalize slashes in the given filepath. - * - * @param {String} `filepath` - * @return {String} - */ - -utils.toPosixPath = function(str) { - return str.replace(/\\+/g, '/'); -}; - -/** - * Strip backslashes before special characters in a string. - * - * @param {String} `str` - * @return {String} - */ - -utils.unescape = function(str) { - return utils.toPosixPath(str.replace(/\\(?=[*+?!.])/g, '')); -}; - -/** - * Strip the prefix from a filepath - * @param {String} `fp` - * @return {String} - */ - -utils.stripPrefix = function(str) { - if (str.charAt(0) !== '.') { - return str; - } - var ch = str.charAt(1); - if (utils.isSlash(ch)) { - return str.slice(2); - } - return str; -}; - -/** - * Returns true if the given str is an escaped or - * unescaped path character - */ - -utils.isSlash = function(str) { - return str === '/' || str === '\\/' || str === '\\' || str === '\\\\'; -}; - -/** - * Returns a function that returns true if the given - * pattern matches or contains a `filepath` - * - * @param {String} `pattern` - * @return {Function} - */ - -utils.matchPath = function(pattern, options) { - return (options && options.contains) - ? utils.containsPattern(pattern, options) - : utils.equalsPattern(pattern, options); -}; - -/** - * Returns true if the given (original) filepath or unixified path are equal - * to the given pattern. - */ - -utils._equals = function(filepath, unixPath, pattern) { - return pattern === filepath || pattern === unixPath; -}; - -/** - * Returns true if the given (original) filepath or unixified path contain - * the given pattern. - */ - -utils._contains = function(filepath, unixPath, pattern) { - return filepath.indexOf(pattern) !== -1 || unixPath.indexOf(pattern) !== -1; -}; - -/** - * Returns a function that returns true if the given - * pattern is the same as a given `filepath` - * - * @param {String} `pattern` - * @return {Function} - */ - -utils.equalsPattern = function(pattern, options) { - var unixify = utils.unixify(options); - options = options || {}; - - return function fn(filepath) { - var equal = utils._equals(filepath, unixify(filepath), pattern); - if (equal === true || options.nocase !== true) { - return equal; - } - var lower = filepath.toLowerCase(); - return utils._equals(lower, unixify(lower), pattern); - }; -}; - -/** - * Returns a function that returns true if the given - * pattern contains a `filepath` - * - * @param {String} `pattern` - * @return {Function} - */ - -utils.containsPattern = function(pattern, options) { - var unixify = utils.unixify(options); - options = options || {}; - - return function(filepath) { - var contains = utils._contains(filepath, unixify(filepath), pattern); - if (contains === true || options.nocase !== true) { - return contains; - } - var lower = filepath.toLowerCase(); - return utils._contains(lower, unixify(lower), pattern); - }; -}; - -/** - * Returns a function that returns true if the given - * regex matches the `filename` of a file path. - * - * @param {RegExp} `re` Matching regex - * @return {Function} - */ - -utils.matchBasename = function(re) { - return function(filepath) { - return re.test(path.basename(filepath)); - }; -}; - -/** - * Determines the filepath to return based on the provided options. - * @return {any} - */ - -utils.value = function(str, unixify, options) { - if (options && options.unixify === false) { - return str; - } - return unixify(str); -}; - -/** - * Returns a function that normalizes slashes in a string to forward - * slashes, strips `./` from beginning of paths, and optionally unescapes - * special characters. - * @return {Function} - */ - -utils.unixify = function(options) { - options = options || {}; - return function(filepath) { - if (utils.isWindows() || options.unixify === true) { - filepath = utils.toPosixPath(filepath); - } - if (options.stripPrefix !== false) { - filepath = utils.stripPrefix(filepath); - } - if (options.unescape === true) { - filepath = utils.unescape(filepath); - } - return filepath; - }; -}; - - -/***/ }), -/* 876 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } - - if (isGeneratorObj(val)) { - return 'generator'; - } - - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } - - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} - -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } - } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; -} - - -/***/ }), -/* 877 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(878); -var reader_1 = __webpack_require__(891); -var fs_stream_1 = __webpack_require__(895); -var ReaderAsync = /** @class */ (function (_super) { - __extends(ReaderAsync, _super); - function ReaderAsync() { - return _super !== null && _super.apply(this, arguments) || this; - } - Object.defineProperty(ReaderAsync.prototype, "fsAdapter", { - /** - * Returns FileSystem adapter. - */ - get: function () { - return new fs_stream_1.default(this.options); - }, - enumerable: true, - configurable: true - }); - /** - * Use async API to read entries for Task. - */ - ReaderAsync.prototype.read = function (task) { - var _this = this; - var root = this.getRootDirectory(task); - var options = this.getReaderOptions(task); - var entries = []; - return new Promise(function (resolve, reject) { - var stream = _this.api(root, task, options); - stream.on('error', function (err) { - _this.isEnoentCodeError(err) ? resolve([]) : reject(err); - stream.pause(); - }); - stream.on('data', function (entry) { return entries.push(_this.transform(entry)); }); - stream.on('end', function () { return resolve(entries); }); - }); - }; - /** - * Returns founded paths. - */ - ReaderAsync.prototype.api = function (root, task, options) { - if (task.dynamic) { - return this.dynamicApi(root, options); - } - return this.staticApi(task, options); - }; - /** - * Api for dynamic tasks. - */ - ReaderAsync.prototype.dynamicApi = function (root, options) { - return readdir.readdirStreamStat(root, options); - }; - /** - * Api for static tasks. - */ - ReaderAsync.prototype.staticApi = function (task, options) { - return this.fsAdapter.read(task.patterns, options.filter); - }; - return ReaderAsync; -}(reader_1.default)); -exports.default = ReaderAsync; - - -/***/ }), -/* 878 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const readdirSync = __webpack_require__(879); -const readdirAsync = __webpack_require__(887); -const readdirStream = __webpack_require__(890); - -module.exports = exports = readdirAsyncPath; -exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; -exports.readdirAsyncStat = exports.async.stat = readdirAsyncStat; -exports.readdirStream = exports.stream = readdirStreamPath; -exports.readdirStreamStat = exports.stream.stat = readdirStreamStat; -exports.readdirSync = exports.sync = readdirSyncPath; -exports.readdirSyncStat = exports.sync.stat = readdirSyncStat; - -/** - * Synchronous readdir that returns an array of string paths. - * - * @param {string} dir - * @param {object} [options] - * @returns {string[]} - */ -function readdirSyncPath (dir, options) { - return readdirSync(dir, options, {}); -} - -/** - * Synchronous readdir that returns results as an array of {@link fs.Stats} objects - * - * @param {string} dir - * @param {object} [options] - * @returns {fs.Stats[]} - */ -function readdirSyncStat (dir, options) { - return readdirSync(dir, options, { stats: true }); -} - -/** - * Aynchronous readdir (accepts an error-first callback or returns a {@link Promise}). - * Results are an array of path strings. - * - * @param {string} dir - * @param {object} [options] - * @param {function} [callback] - * @returns {Promise} - */ -function readdirAsyncPath (dir, options, callback) { - return readdirAsync(dir, options, callback, {}); -} - -/** - * Aynchronous readdir (accepts an error-first callback or returns a {@link Promise}). - * Results are an array of {@link fs.Stats} objects. - * - * @param {string} dir - * @param {object} [options] - * @param {function} [callback] - * @returns {Promise} - */ -function readdirAsyncStat (dir, options, callback) { - return readdirAsync(dir, options, callback, { stats: true }); -} - -/** - * Aynchronous readdir that returns a {@link stream.Readable} (which is also an {@link EventEmitter}). - * All stream data events ("data", "file", "directory", "symlink") are passed a path string. - * - * @param {string} dir - * @param {object} [options] - * @returns {stream.Readable} - */ -function readdirStreamPath (dir, options) { - return readdirStream(dir, options, {}); -} - -/** - * Aynchronous readdir that returns a {@link stream.Readable} (which is also an {@link EventEmitter}) - * All stream data events ("data", "file", "directory", "symlink") are passed an {@link fs.Stats} object. - * - * @param {string} dir - * @param {object} [options] - * @returns {stream.Readable} - */ -function readdirStreamStat (dir, options) { - return readdirStream(dir, options, { stats: true }); -} - - -/***/ }), -/* 879 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -module.exports = readdirSync; - -const DirectoryReader = __webpack_require__(880); - -let syncFacade = { - fs: __webpack_require__(885), - forEach: __webpack_require__(886), - sync: true -}; - -/** - * Returns the buffered output from a synchronous {@link DirectoryReader}. - * - * @param {string} dir - * @param {object} [options] - * @param {object} internalOptions - */ -function readdirSync (dir, options, internalOptions) { - internalOptions.facade = syncFacade; - - let reader = new DirectoryReader(dir, options, internalOptions); - let stream = reader.stream; - - let results = []; - let data = stream.read(); - while (data !== null) { - results.push(data); - data = stream.read(); - } - - return results; -} - - -/***/ }), -/* 880 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const Readable = __webpack_require__(27).Readable; -const EventEmitter = __webpack_require__(379).EventEmitter; -const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(881); -const stat = __webpack_require__(883); -const call = __webpack_require__(884); - -/** - * Asynchronously reads the contents of a directory and streams the results - * via a {@link stream.Readable}. - */ -class DirectoryReader { - /** - * @param {string} dir - The absolute or relative directory path to read - * @param {object} [options] - User-specified options, if any (see {@link normalizeOptions}) - * @param {object} internalOptions - Internal options that aren't part of the public API - * @class - */ - constructor (dir, options, internalOptions) { - this.options = options = normalizeOptions(options, internalOptions); - - // Indicates whether we should keep reading - // This is set false if stream.Readable.push() returns false. - this.shouldRead = true; - - // The directories to read - // (initialized with the top-level directory) - this.queue = [{ - path: dir, - basePath: options.basePath, - posixBasePath: options.posixBasePath, - depth: 0 - }]; - - // The number of directories that are currently being processed - this.pending = 0; - - // The data that has been read, but not yet emitted - this.buffer = []; - - this.stream = new Readable({ objectMode: true }); - this.stream._read = () => { - // Start (or resume) reading - this.shouldRead = true; - - // If we have data in the buffer, then send the next chunk - if (this.buffer.length > 0) { - this.pushFromBuffer(); - } - - // If we have directories queued, then start processing the next one - if (this.queue.length > 0) { - if (this.options.facade.sync) { - while (this.queue.length > 0) { - this.readNextDirectory(); - } - } - else { - this.readNextDirectory(); - } - } - - this.checkForEOF(); - }; - } - - /** - * Reads the next directory in the queue - */ - readNextDirectory () { - let facade = this.options.facade; - let dir = this.queue.shift(); - this.pending++; - - // Read the directory listing - call.safe(facade.fs.readdir, dir.path, (err, items) => { - if (err) { - // fs.readdir threw an error - this.emit('error', err); - return this.finishedReadingDirectory(); - } - - try { - // Process each item in the directory (simultaneously, if async) - facade.forEach( - items, - this.processItem.bind(this, dir), - this.finishedReadingDirectory.bind(this, dir) - ); - } - catch (err2) { - // facade.forEach threw an error - // (probably because fs.readdir returned an invalid result) - this.emit('error', err2); - this.finishedReadingDirectory(); - } - }); - } - - /** - * This method is called after all items in a directory have been processed. - * - * NOTE: This does not necessarily mean that the reader is finished, since there may still - * be other directories queued or pending. - */ - finishedReadingDirectory () { - this.pending--; - - if (this.shouldRead) { - // If we have directories queued, then start processing the next one - if (this.queue.length > 0 && this.options.facade.async) { - this.readNextDirectory(); - } - - this.checkForEOF(); - } - } - - /** - * Determines whether the reader has finished processing all items in all directories. - * If so, then the "end" event is fired (via {@Readable#push}) - */ - checkForEOF () { - if (this.buffer.length === 0 && // The stuff we've already read - this.pending === 0 && // The stuff we're currently reading - this.queue.length === 0) { // The stuff we haven't read yet - // There's no more stuff! - this.stream.push(null); - } - } - - /** - * Processes a single item in a directory. - * - * If the item is a directory, and `option.deep` is enabled, then the item will be added - * to the directory queue. - * - * If the item meets the filter criteria, then it will be emitted to the reader's stream. - * - * @param {object} dir - A directory object from the queue - * @param {string} item - The name of the item (name only, no path) - * @param {function} done - A callback function that is called after the item has been processed - */ - processItem (dir, item, done) { - let stream = this.stream; - let options = this.options; - - let itemPath = dir.basePath + item; - let posixPath = dir.posixBasePath + item; - let fullPath = path.join(dir.path, item); - - // If `options.deep` is a number, and we've already recursed to the max depth, - // then there's no need to check fs.Stats to know if it's a directory. - // If `options.deep` is a function, then we'll need fs.Stats - let maxDepthReached = dir.depth >= options.recurseDepth; - - // Do we need to call `fs.stat`? - let needStats = - !maxDepthReached || // we need the fs.Stats to know if it's a directory - options.stats || // the user wants fs.Stats objects returned - options.recurseFn || // we need fs.Stats for the recurse function - options.filterFn || // we need fs.Stats for the filter function - EventEmitter.listenerCount(stream, 'file') || // we need the fs.Stats to know if it's a file - EventEmitter.listenerCount(stream, 'directory') || // we need the fs.Stats to know if it's a directory - EventEmitter.listenerCount(stream, 'symlink'); // we need the fs.Stats to know if it's a symlink - - // If we don't need stats, then exit early - if (!needStats) { - if (this.filter(itemPath, posixPath)) { - this.pushOrBuffer({ data: itemPath }); - } - return done(); - } - - // Get the fs.Stats object for this path - stat(options.facade.fs, fullPath, (err, stats) => { - if (err) { - // fs.stat threw an error - this.emit('error', err); - return done(); - } - - try { - // Add the item's path to the fs.Stats object - // The base of this path, and its separators are determined by the options - // (i.e. options.basePath and options.sep) - stats.path = itemPath; - - // Add depth of the path to the fs.Stats object for use this in the filter function - stats.depth = dir.depth; - - if (this.shouldRecurse(stats, posixPath, maxDepthReached)) { - // Add this subdirectory to the queue - this.queue.push({ - path: fullPath, - basePath: itemPath + options.sep, - posixBasePath: posixPath + '/', - depth: dir.depth + 1, - }); - } - - // Determine whether this item matches the filter criteria - if (this.filter(stats, posixPath)) { - this.pushOrBuffer({ - data: options.stats ? stats : itemPath, - file: stats.isFile(), - directory: stats.isDirectory(), - symlink: stats.isSymbolicLink(), - }); - } - - done(); - } - catch (err2) { - // An error occurred while processing the item - // (probably during a user-specified function, such as options.deep, options.filter, etc.) - this.emit('error', err2); - done(); - } - }); - } - - /** - * Pushes the given chunk of data to the stream, or adds it to the buffer, - * depending on the state of the stream. - * - * @param {object} chunk - */ - pushOrBuffer (chunk) { - // Add the chunk to the buffer - this.buffer.push(chunk); - - // If we're still reading, then immediately emit the next chunk in the buffer - // (which may or may not be the chunk that we just added) - if (this.shouldRead) { - this.pushFromBuffer(); - } - } - - /** - * Immediately pushes the next chunk in the buffer to the reader's stream. - * The "data" event will always be fired (via {@link Readable#push}). - * In addition, the "file", "directory", and/or "symlink" events may be fired, - * depending on the type of properties of the chunk. - */ - pushFromBuffer () { - let stream = this.stream; - let chunk = this.buffer.shift(); - - // Stream the data - try { - this.shouldRead = stream.push(chunk.data); - } - catch (err) { - this.emit('error', err); - } - - // Also emit specific events, based on the type of chunk - chunk.file && this.emit('file', chunk.data); - chunk.symlink && this.emit('symlink', chunk.data); - chunk.directory && this.emit('directory', chunk.data); - } - - /** - * Determines whether the given directory meets the user-specified recursion criteria. - * If the user didn't specify recursion criteria, then this function will default to true. - * - * @param {fs.Stats} stats - The directory's {@link fs.Stats} object - * @param {string} posixPath - The item's POSIX path (used for glob matching) - * @param {boolean} maxDepthReached - Whether we've already crawled the user-specified depth - * @returns {boolean} - */ - shouldRecurse (stats, posixPath, maxDepthReached) { - let options = this.options; - - if (maxDepthReached) { - // We've already crawled to the maximum depth. So no more recursion. - return false; - } - else if (!stats.isDirectory()) { - // It's not a directory. So don't try to crawl it. - return false; - } - else if (options.recurseGlob) { - // Glob patterns are always tested against the POSIX path, even on Windows - // https://github.com/isaacs/node-glob#windows - return options.recurseGlob.test(posixPath); - } - else if (options.recurseRegExp) { - // Regular expressions are tested against the normal path - // (based on the OS or options.sep) - return options.recurseRegExp.test(stats.path); - } - else if (options.recurseFn) { - try { - // Run the user-specified recursion criteria - return options.recurseFn.call(null, stats); - } - catch (err) { - // An error occurred in the user's code. - // In Sync and Async modes, this will return an error. - // In Streaming mode, we emit an "error" event, but continue processing - this.emit('error', err); - } - } - else { - // No recursion function was specified, and we're within the maximum depth. - // So crawl this directory. - return true; - } - } - - /** - * Determines whether the given item meets the user-specified filter criteria. - * If the user didn't specify a filter, then this function will always return true. - * - * @param {string|fs.Stats} value - Either the item's path, or the item's {@link fs.Stats} object - * @param {string} posixPath - The item's POSIX path (used for glob matching) - * @returns {boolean} - */ - filter (value, posixPath) { - let options = this.options; - - if (options.filterGlob) { - // Glob patterns are always tested against the POSIX path, even on Windows - // https://github.com/isaacs/node-glob#windows - return options.filterGlob.test(posixPath); - } - else if (options.filterRegExp) { - // Regular expressions are tested against the normal path - // (based on the OS or options.sep) - return options.filterRegExp.test(value.path || value); - } - else if (options.filterFn) { - try { - // Run the user-specified filter function - return options.filterFn.call(null, value); - } - catch (err) { - // An error occurred in the user's code. - // In Sync and Async modes, this will return an error. - // In Streaming mode, we emit an "error" event, but continue processing - this.emit('error', err); - } - } - else { - // No filter was specified, so match everything - return true; - } - } - - /** - * Emits an event. If one of the event listeners throws an error, - * then an "error" event is emitted. - * - * @param {string} eventName - * @param {*} data - */ - emit (eventName, data) { - let stream = this.stream; - - try { - stream.emit(eventName, data); - } - catch (err) { - if (eventName === 'error') { - // Don't recursively emit "error" events. - // If the first one fails, then just throw - throw err; - } - else { - stream.emit('error', err); - } - } - } -} - -module.exports = DirectoryReader; - - -/***/ }), -/* 881 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(882); - -module.exports = normalizeOptions; - -let isWindows = /^win/.test(process.platform); - -/** - * @typedef {Object} FSFacade - * @property {fs.readdir} readdir - * @property {fs.stat} stat - * @property {fs.lstat} lstat - */ - -/** - * Validates and normalizes the options argument - * - * @param {object} [options] - User-specified options, if any - * @param {object} internalOptions - Internal options that aren't part of the public API - * - * @param {number|boolean|function} [options.deep] - * The number of directories to recursively traverse. Any falsy value or negative number will - * default to zero, so only the top-level contents will be returned. Set to `true` or `Infinity` - * to traverse all subdirectories. Or provide a function that accepts a {@link fs.Stats} object - * and returns a truthy value if the directory's contents should be crawled. - * - * @param {function|string|RegExp} [options.filter] - * A function that accepts a {@link fs.Stats} object and returns a truthy value if the data should - * be returned. Or a RegExp or glob string pattern, to filter by file name. - * - * @param {string} [options.sep] - * The path separator to use. By default, the OS-specific separator will be used, but this can be - * set to a specific value to ensure consistency across platforms. - * - * @param {string} [options.basePath] - * The base path to prepend to each result. If empty, then all results will be relative to `dir`. - * - * @param {FSFacade} [options.fs] - * Synchronous or asynchronous facades for Node.js File System module - * - * @param {object} [internalOptions.facade] - * Synchronous or asynchronous facades for various methods, including for the Node.js File System module - * - * @param {boolean} [internalOptions.emit] - * Indicates whether the reader should emit "file", "directory", and "symlink" events - * - * @param {boolean} [internalOptions.stats] - * Indicates whether the reader should emit {@link fs.Stats} objects instead of path strings - * - * @returns {object} - */ -function normalizeOptions (options, internalOptions) { - if (options === null || options === undefined) { - options = {}; - } - else if (typeof options !== 'object') { - throw new TypeError('options must be an object'); - } - - let recurseDepth, recurseFn, recurseRegExp, recurseGlob, deep = options.deep; - if (deep === null || deep === undefined) { - recurseDepth = 0; - } - else if (typeof deep === 'boolean') { - recurseDepth = deep ? Infinity : 0; - } - else if (typeof deep === 'number') { - if (deep < 0 || isNaN(deep)) { - throw new Error('options.deep must be a positive number'); - } - else if (Math.floor(deep) !== deep) { - throw new Error('options.deep must be an integer'); - } - else { - recurseDepth = deep; - } - } - else if (typeof deep === 'function') { - recurseDepth = Infinity; - recurseFn = deep; - } - else if (deep instanceof RegExp) { - recurseDepth = Infinity; - recurseRegExp = deep; - } - else if (typeof deep === 'string' && deep.length > 0) { - recurseDepth = Infinity; - recurseGlob = globToRegExp(deep, { extended: true, globstar: true }); - } - else { - throw new TypeError('options.deep must be a boolean, number, function, regular expression, or glob pattern'); - } - - let filterFn, filterRegExp, filterGlob, filter = options.filter; - if (filter !== null && filter !== undefined) { - if (typeof filter === 'function') { - filterFn = filter; - } - else if (filter instanceof RegExp) { - filterRegExp = filter; - } - else if (typeof filter === 'string' && filter.length > 0) { - filterGlob = globToRegExp(filter, { extended: true, globstar: true }); - } - else { - throw new TypeError('options.filter must be a function, regular expression, or glob pattern'); - } - } - - let sep = options.sep; - if (sep === null || sep === undefined) { - sep = path.sep; - } - else if (typeof sep !== 'string') { - throw new TypeError('options.sep must be a string'); - } - - let basePath = options.basePath; - if (basePath === null || basePath === undefined) { - basePath = ''; - } - else if (typeof basePath === 'string') { - // Append a path separator to the basePath, if necessary - if (basePath && basePath.substr(-1) !== sep) { - basePath += sep; - } - } - else { - throw new TypeError('options.basePath must be a string'); - } - - // Convert the basePath to POSIX (forward slashes) - // so that glob pattern matching works consistently, even on Windows - let posixBasePath = basePath; - if (posixBasePath && sep !== '/') { - posixBasePath = posixBasePath.replace(new RegExp('\\' + sep, 'g'), '/'); - - /* istanbul ignore if */ - if (isWindows) { - // Convert Windows root paths (C:\) and UNCs (\\) to POSIX root paths - posixBasePath = posixBasePath.replace(/^([a-zA-Z]\:\/|\/\/)/, '/'); - } - } - - // Determine which facade methods to use - let facade; - if (options.fs === null || options.fs === undefined) { - // The user didn't provide their own facades, so use our internal ones - facade = internalOptions.facade; - } - else if (typeof options.fs === 'object') { - // Merge the internal facade methods with the user-provided `fs` facades - facade = Object.assign({}, internalOptions.facade); - facade.fs = Object.assign({}, internalOptions.facade.fs, options.fs); - } - else { - throw new TypeError('options.fs must be an object'); - } - - return { - recurseDepth, - recurseFn, - recurseRegExp, - recurseGlob, - filterFn, - filterRegExp, - filterGlob, - sep, - basePath, - posixBasePath, - facade, - emit: !!internalOptions.emit, - stats: !!internalOptions.stats, - }; -} - - -/***/ }), -/* 882 */ -/***/ (function(module, exports) { - -module.exports = function (glob, opts) { - if (typeof glob !== 'string') { - throw new TypeError('Expected a string'); - } - - var str = String(glob); - - // The regexp we are building, as a string. - var reStr = ""; - - // Whether we are matching so called "extended" globs (like bash) and should - // support single character matching, matching ranges of characters, group - // matching, etc. - var extended = opts ? !!opts.extended : false; - - // When globstar is _false_ (default), '/foo/*' is translated a regexp like - // '^\/foo\/.*$' which will match any string beginning with '/foo/' - // When globstar is _true_, '/foo/*' is translated to regexp like - // '^\/foo\/[^/]*$' which will match any string beginning with '/foo/' BUT - // which does not have a '/' to the right of it. - // E.g. with '/foo/*' these will match: '/foo/bar', '/foo/bar.txt' but - // these will not '/foo/bar/baz', '/foo/bar/baz.txt' - // Lastely, when globstar is _true_, '/foo/**' is equivelant to '/foo/*' when - // globstar is _false_ - var globstar = opts ? !!opts.globstar : false; - - // If we are doing extended matching, this boolean is true when we are inside - // a group (eg {*.html,*.js}), and false otherwise. - var inGroup = false; - - // RegExp flags (eg "i" ) to pass in to RegExp constructor. - var flags = opts && typeof( opts.flags ) === "string" ? opts.flags : ""; - - var c; - for (var i = 0, len = str.length; i < len; i++) { - c = str[i]; - - switch (c) { - case "\\": - case "/": - case "$": - case "^": - case "+": - case ".": - case "(": - case ")": - case "=": - case "!": - case "|": - reStr += "\\" + c; - break; - - case "?": - if (extended) { - reStr += "."; - break; - } - - case "[": - case "]": - if (extended) { - reStr += c; - break; - } - - case "{": - if (extended) { - inGroup = true; - reStr += "("; - break; - } - - case "}": - if (extended) { - inGroup = false; - reStr += ")"; - break; - } - - case ",": - if (inGroup) { - reStr += "|"; - break; - } - reStr += "\\" + c; - break; - - case "*": - // Move over all consecutive "*"'s. - // Also store the previous and next characters - var prevChar = str[i - 1]; - var starCount = 1; - while(str[i + 1] === "*") { - starCount++; - i++; - } - var nextChar = str[i + 1]; - - if (!globstar) { - // globstar is disabled, so treat any number of "*" as one - reStr += ".*"; - } else { - // globstar is enabled, so determine if this is a globstar segment - var isGlobstar = starCount > 1 // multiple "*"'s - && (prevChar === "/" || prevChar === undefined) // from the start of the segment - && (nextChar === "/" || nextChar === undefined) // to the end of the segment - - if (isGlobstar) { - // it's a globstar, so match zero or more path segments - reStr += "(?:[^/]*(?:\/|$))*"; - i++; // move over the "/" - } else { - // it's not a globstar, so only match one path segment - reStr += "[^/]*"; - } - } - break; - - default: - reStr += c; - } - } - - // When regexp 'g' flag is specified don't - // constrain the regular expression with ^ & $ - if (!flags || !~flags.indexOf('g')) { - reStr = "^" + reStr + "$"; - } - - return new RegExp(reStr, flags); -}; - - -/***/ }), -/* 883 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const call = __webpack_require__(884); - -module.exports = stat; - -/** - * Retrieves the {@link fs.Stats} for the given path. If the path is a symbolic link, - * then the Stats of the symlink's target are returned instead. If the symlink is broken, - * then the Stats of the symlink itself are returned. - * - * @param {object} fs - Synchronous or Asynchronouse facade for the "fs" module - * @param {string} path - The path to return stats for - * @param {function} callback - */ -function stat (fs, path, callback) { - let isSymLink = false; - - call.safe(fs.lstat, path, (err, lstats) => { - if (err) { - // fs.lstat threw an eror - return callback(err); - } - - try { - isSymLink = lstats.isSymbolicLink(); - } - catch (err2) { - // lstats.isSymbolicLink() threw an error - // (probably because fs.lstat returned an invalid result) - return callback(err2); - } - - if (isSymLink) { - // Try to resolve the symlink - symlinkStat(fs, path, lstats, callback); - } - else { - // It's not a symlink, so return the stats as-is - callback(null, lstats); - } - }); -} - -/** - * Retrieves the {@link fs.Stats} for the target of the given symlink. - * If the symlink is broken, then the Stats of the symlink itself are returned. - * - * @param {object} fs - Synchronous or Asynchronouse facade for the "fs" module - * @param {string} path - The path of the symlink to return stats for - * @param {object} lstats - The stats of the symlink - * @param {function} callback - */ -function symlinkStat (fs, path, lstats, callback) { - call.safe(fs.stat, path, (err, stats) => { - if (err) { - // The symlink is broken, so return the stats for the link itself - return callback(null, lstats); - } - - try { - // Return the stats for the resolved symlink target, - // and override the `isSymbolicLink` method to indicate that it's a symlink - stats.isSymbolicLink = () => true; - } - catch (err2) { - // Setting stats.isSymbolicLink threw an error - // (probably because fs.stat returned an invalid result) - return callback(err2); - } - - callback(null, stats); - }); -} - - -/***/ }), -/* 884 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -let call = module.exports = { - safe: safeCall, - once: callOnce, -}; - -/** - * Calls a function with the given arguments, and ensures that the error-first callback is _always_ - * invoked exactly once, even if the function throws an error. - * - * @param {function} fn - The function to invoke - * @param {...*} args - The arguments to pass to the function. The final argument must be a callback function. - */ -function safeCall (fn, args) { - // Get the function arguments as an array - args = Array.prototype.slice.call(arguments, 1); - - // Replace the callback function with a wrapper that ensures it will only be called once - let callback = call.once(args.pop()); - args.push(callback); - - try { - fn.apply(null, args); - } - catch (err) { - callback(err); - } -} - -/** - * Returns a wrapper function that ensures the given callback function is only called once. - * Subsequent calls are ignored, unless the first argument is an Error, in which case the - * error is thrown. - * - * @param {function} fn - The function that should only be called once - * @returns {function} - */ -function callOnce (fn) { - let fulfilled = false; - - return function onceWrapper (err) { - if (!fulfilled) { - fulfilled = true; - return fn.apply(this, arguments); - } - else if (err) { - // The callback has already been called, but now an error has occurred - // (most likely inside the callback function). So re-throw the error, - // so it gets handled further up the call stack - throw err; - } - }; -} - - -/***/ }), -/* 885 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const fs = __webpack_require__(23); -const call = __webpack_require__(884); - -/** - * A facade around {@link fs.readdirSync} that allows it to be called - * the same way as {@link fs.readdir}. - * - * @param {string} dir - * @param {function} callback - */ -exports.readdir = function (dir, callback) { - // Make sure the callback is only called once - callback = call.once(callback); - - try { - let items = fs.readdirSync(dir); - callback(null, items); - } - catch (err) { - callback(err); - } -}; - -/** - * A facade around {@link fs.statSync} that allows it to be called - * the same way as {@link fs.stat}. - * - * @param {string} path - * @param {function} callback - */ -exports.stat = function (path, callback) { - // Make sure the callback is only called once - callback = call.once(callback); - - try { - let stats = fs.statSync(path); - callback(null, stats); - } - catch (err) { - callback(err); - } -}; - -/** - * A facade around {@link fs.lstatSync} that allows it to be called - * the same way as {@link fs.lstat}. - * - * @param {string} path - * @param {function} callback - */ -exports.lstat = function (path, callback) { - // Make sure the callback is only called once - callback = call.once(callback); - - try { - let stats = fs.lstatSync(path); - callback(null, stats); - } - catch (err) { - callback(err); - } -}; - - -/***/ }), -/* 886 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -module.exports = syncForEach; - -/** - * A facade that allows {@link Array.forEach} to be called as though it were asynchronous. - * - * @param {array} array - The array to iterate over - * @param {function} iterator - The function to call for each item in the array - * @param {function} done - The function to call when all iterators have completed - */ -function syncForEach (array, iterator, done) { - array.forEach(item => { - iterator(item, () => { - // Note: No error-handling here because this is currently only ever called - // by DirectoryReader, which never passes an `error` parameter to the callback. - // Instead, DirectoryReader emits an "error" event if an error occurs. - }); - }); - - done(); -} - - -/***/ }), -/* 887 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -module.exports = readdirAsync; - -const maybe = __webpack_require__(888); -const DirectoryReader = __webpack_require__(880); - -let asyncFacade = { - fs: __webpack_require__(23), - forEach: __webpack_require__(889), - async: true -}; - -/** - * Returns the buffered output from an asynchronous {@link DirectoryReader}, - * via an error-first callback or a {@link Promise}. - * - * @param {string} dir - * @param {object} [options] - * @param {function} [callback] - * @param {object} internalOptions - */ -function readdirAsync (dir, options, callback, internalOptions) { - if (typeof options === 'function') { - callback = options; - options = undefined; - } - - return maybe(callback, new Promise(((resolve, reject) => { - let results = []; - - internalOptions.facade = asyncFacade; - - let reader = new DirectoryReader(dir, options, internalOptions); - let stream = reader.stream; - - stream.on('error', err => { - reject(err); - stream.pause(); - }); - stream.on('data', result => { - results.push(result); - }); - stream.on('end', () => { - resolve(results); - }); - }))); -} - - -/***/ }), -/* 888 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var next = (global.process && process.nextTick) || global.setImmediate || function (f) { - setTimeout(f, 0) -} - -module.exports = function maybe (cb, promise) { - if (cb) { - promise - .then(function (result) { - next(function () { cb(null, result) }) - }, function (err) { - next(function () { cb(err) }) - }) - return undefined - } - else { - return promise - } -} - - -/***/ }), -/* 889 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -module.exports = asyncForEach; - -/** - * Simultaneously processes all items in the given array. - * - * @param {array} array - The array to iterate over - * @param {function} iterator - The function to call for each item in the array - * @param {function} done - The function to call when all iterators have completed - */ -function asyncForEach (array, iterator, done) { - if (array.length === 0) { - // NOTE: Normally a bad idea to mix sync and async, but it's safe here because - // of the way that this method is currently used by DirectoryReader. - done(); - return; - } - - // Simultaneously process all items in the array. - let pending = array.length; - array.forEach(item => { - iterator(item, () => { - if (--pending === 0) { - done(); - } - }); - }); -} - - -/***/ }), -/* 890 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -module.exports = readdirStream; - -const DirectoryReader = __webpack_require__(880); - -let streamFacade = { - fs: __webpack_require__(23), - forEach: __webpack_require__(889), - async: true -}; - -/** - * Returns the {@link stream.Readable} of an asynchronous {@link DirectoryReader}. - * - * @param {string} dir - * @param {object} [options] - * @param {object} internalOptions - */ -function readdirStream (dir, options, internalOptions) { - internalOptions.facade = streamFacade; - - let reader = new DirectoryReader(dir, options, internalOptions); - return reader.stream; -} - - -/***/ }), -/* 891 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var path = __webpack_require__(16); -var deep_1 = __webpack_require__(892); -var entry_1 = __webpack_require__(894); -var pathUtil = __webpack_require__(893); -var Reader = /** @class */ (function () { - function Reader(options) { - this.options = options; - this.micromatchOptions = this.getMicromatchOptions(); - this.entryFilter = new entry_1.default(options, this.micromatchOptions); - this.deepFilter = new deep_1.default(options, this.micromatchOptions); - } - /** - * Returns root path to scanner. - */ - Reader.prototype.getRootDirectory = function (task) { - return path.resolve(this.options.cwd, task.base); - }; - /** - * Returns options for reader. - */ - Reader.prototype.getReaderOptions = function (task) { - return { - basePath: task.base === '.' ? '' : task.base, - filter: this.entryFilter.getFilter(task.positive, task.negative), - deep: this.deepFilter.getFilter(task.positive, task.negative), - sep: '/' - }; - }; - /** - * Returns options for micromatch. - */ - Reader.prototype.getMicromatchOptions = function () { - return { - dot: this.options.dot, - nobrace: !this.options.brace, - noglobstar: !this.options.globstar, - noext: !this.options.extension, - nocase: !this.options.case, - matchBase: this.options.matchBase - }; - }; - /** - * Returns transformed entry. - */ - Reader.prototype.transform = function (entry) { - if (this.options.absolute) { - entry.path = pathUtil.makeAbsolute(this.options.cwd, entry.path); - } - if (this.options.markDirectories && entry.isDirectory()) { - entry.path += '/'; - } - var item = this.options.stats ? entry : entry.path; - if (this.options.transform === null) { - return item; - } - return this.options.transform(item); - }; - /** - * Returns true if error has ENOENT code. - */ - Reader.prototype.isEnoentCodeError = function (err) { - return err.code === 'ENOENT'; - }; - return Reader; -}()); -exports.default = Reader; - - -/***/ }), -/* 892 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(893); -var patternUtils = __webpack_require__(722); -var DeepFilter = /** @class */ (function () { - function DeepFilter(options, micromatchOptions) { - this.options = options; - this.micromatchOptions = micromatchOptions; - } - /** - * Returns filter for directories. - */ - DeepFilter.prototype.getFilter = function (positive, negative) { - var _this = this; - var maxPatternDepth = this.getMaxPatternDepth(positive); - var negativeRe = this.getNegativePatternsRe(negative); - return function (entry) { return _this.filter(entry, negativeRe, maxPatternDepth); }; - }; - /** - * Returns max depth of the provided patterns. - */ - DeepFilter.prototype.getMaxPatternDepth = function (patterns) { - var globstar = patterns.some(patternUtils.hasGlobStar); - return globstar ? Infinity : patternUtils.getMaxNaivePatternsDepth(patterns); - }; - /** - * Returns RegExp's for patterns that can affect the depth of reading. - */ - DeepFilter.prototype.getNegativePatternsRe = function (patterns) { - var affectDepthOfReadingPatterns = patterns.filter(patternUtils.isAffectDepthOfReadingPattern); - return patternUtils.convertPatternsToRe(affectDepthOfReadingPatterns, this.micromatchOptions); - }; - /** - * Returns «true» for directory that should be read. - */ - DeepFilter.prototype.filter = function (entry, negativeRe, maxPatternDepth) { - if (this.isSkippedByDeepOption(entry.depth)) { - return false; - } - if (this.isSkippedByMaxPatternDepth(entry.depth, maxPatternDepth)) { - return false; - } - if (this.isSkippedSymlinkedDirectory(entry)) { - return false; - } - if (this.isSkippedDotDirectory(entry)) { - return false; - } - return this.isSkippedByNegativePatterns(entry, negativeRe); - }; - /** - * Returns «true» when the «deep» option is disabled or number and depth of the entry is greater that the option value. - */ - DeepFilter.prototype.isSkippedByDeepOption = function (entryDepth) { - return !this.options.deep || (typeof this.options.deep === 'number' && entryDepth >= this.options.deep); - }; - /** - * Returns «true» when depth parameter is not an Infinity and entry depth greater that the parameter value. - */ - DeepFilter.prototype.isSkippedByMaxPatternDepth = function (entryDepth, maxPatternDepth) { - return maxPatternDepth !== Infinity && entryDepth >= maxPatternDepth; - }; - /** - * Returns «true» for symlinked directory if the «followSymlinkedDirectories» option is disabled. - */ - DeepFilter.prototype.isSkippedSymlinkedDirectory = function (entry) { - return !this.options.followSymlinkedDirectories && entry.isSymbolicLink(); - }; - /** - * Returns «true» for a directory whose name starts with a period if «dot» option is disabled. - */ - DeepFilter.prototype.isSkippedDotDirectory = function (entry) { - return !this.options.dot && pathUtils.isDotDirectory(entry.path); - }; - /** - * Returns «true» for a directory whose path math to any negative pattern. - */ - DeepFilter.prototype.isSkippedByNegativePatterns = function (entry, negativeRe) { - return !patternUtils.matchAny(entry.path, negativeRe); - }; - return DeepFilter; -}()); -exports.default = DeepFilter; + // if we know it exists, but not what it is. + } + var exists + var stat = this.statCache[abs] + if (!stat) { + var lstat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { + this.statCache[abs] = false + return false + } + } -/***/ }), -/* 893 */ -/***/ (function(module, exports, __webpack_require__) { + if (lstat && lstat.isSymbolicLink()) { + try { + stat = fs.statSync(abs) + } catch (er) { + stat = lstat + } + } else { + stat = lstat + } + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var path = __webpack_require__(16); -/** - * Returns «true» if the last partial of the path starting with a period. - */ -function isDotDirectory(filepath) { - return path.basename(filepath).startsWith('.'); -} -exports.isDotDirectory = isDotDirectory; -/** - * Convert a windows-like path to a unix-style path. - */ -function normalize(filepath) { - return filepath.replace(/\\/g, '/'); -} -exports.normalize = normalize; -/** - * Returns normalized absolute path of provided filepath. - */ -function makeAbsolute(cwd, filepath) { - return normalize(path.resolve(cwd, filepath)); -} -exports.makeAbsolute = makeAbsolute; + this.statCache[abs] = stat + var c = true + if (stat) + c = stat.isDirectory() ? 'DIR' : 'FILE' -/***/ }), -/* 894 */ -/***/ (function(module, exports, __webpack_require__) { + this.cache[abs] = this.cache[abs] || c -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(893); -var patternUtils = __webpack_require__(722); -var EntryFilter = /** @class */ (function () { - function EntryFilter(options, micromatchOptions) { - this.options = options; - this.micromatchOptions = micromatchOptions; - this.index = new Map(); - } - /** - * Returns filter for directories. - */ - EntryFilter.prototype.getFilter = function (positive, negative) { - var _this = this; - var positiveRe = patternUtils.convertPatternsToRe(positive, this.micromatchOptions); - var negativeRe = patternUtils.convertPatternsToRe(negative, this.micromatchOptions); - return function (entry) { return _this.filter(entry, positiveRe, negativeRe); }; - }; - /** - * Returns true if entry must be added to result. - */ - EntryFilter.prototype.filter = function (entry, positiveRe, negativeRe) { - // Exclude duplicate results - if (this.options.unique) { - if (this.isDuplicateEntry(entry)) { - return false; - } - this.createIndexRecord(entry); - } - // Filter files and directories by options - if (this.onlyFileFilter(entry) || this.onlyDirectoryFilter(entry)) { - return false; - } - if (this.isSkippedByAbsoluteNegativePatterns(entry, negativeRe)) { - return false; - } - return this.isMatchToPatterns(entry.path, positiveRe) && !this.isMatchToPatterns(entry.path, negativeRe); - }; - /** - * Return true if the entry already has in the cross reader index. - */ - EntryFilter.prototype.isDuplicateEntry = function (entry) { - return this.index.has(entry.path); - }; - /** - * Create record in the cross reader index. - */ - EntryFilter.prototype.createIndexRecord = function (entry) { - this.index.set(entry.path, undefined); - }; - /** - * Returns true for non-files if the «onlyFiles» option is enabled. - */ - EntryFilter.prototype.onlyFileFilter = function (entry) { - return this.options.onlyFiles && !entry.isFile(); - }; - /** - * Returns true for non-directories if the «onlyDirectories» option is enabled. - */ - EntryFilter.prototype.onlyDirectoryFilter = function (entry) { - return this.options.onlyDirectories && !entry.isDirectory(); - }; - /** - * Return true when `absolute` option is enabled and matched to the negative patterns. - */ - EntryFilter.prototype.isSkippedByAbsoluteNegativePatterns = function (entry, negativeRe) { - if (!this.options.absolute) { - return false; - } - var fullpath = pathUtils.makeAbsolute(this.options.cwd, entry.path); - return this.isMatchToPatterns(fullpath, negativeRe); - }; - /** - * Return true when entry match to provided patterns. - * - * First, just trying to apply patterns to the path. - * Second, trying to apply patterns to the path with final slash (need to micromatch to support «directory/**» patterns). - */ - EntryFilter.prototype.isMatchToPatterns = function (filepath, patternsRe) { - return patternUtils.matchAny(filepath, patternsRe) || patternUtils.matchAny(filepath + '/', patternsRe); - }; - return EntryFilter; -}()); -exports.default = EntryFilter; + if (needDir && c === 'FILE') + return false + return c +} -/***/ }), -/* 895 */ -/***/ (function(module, exports, __webpack_require__) { +GlobSync.prototype._mark = function (p) { + return common.mark(this, p) +} -"use strict"; - -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var stream = __webpack_require__(27); -var fsStat = __webpack_require__(896); -var fs_1 = __webpack_require__(900); -var FileSystemStream = /** @class */ (function (_super) { - __extends(FileSystemStream, _super); - function FileSystemStream() { - return _super !== null && _super.apply(this, arguments) || this; - } - /** - * Use stream API to read entries for Task. - */ - FileSystemStream.prototype.read = function (patterns, filter) { - var _this = this; - var filepaths = patterns.map(this.getFullEntryPath, this); - var transform = new stream.Transform({ objectMode: true }); - transform._transform = function (index, _enc, done) { - return _this.getEntry(filepaths[index], patterns[index]).then(function (entry) { - if (entry !== null && filter(entry)) { - transform.push(entry); - } - if (index === filepaths.length - 1) { - transform.end(); - } - done(); - }); - }; - for (var i = 0; i < filepaths.length; i++) { - transform.write(i); - } - return transform; - }; - /** - * Return entry for the provided path. - */ - FileSystemStream.prototype.getEntry = function (filepath, pattern) { - var _this = this; - return this.getStat(filepath) - .then(function (stat) { return _this.makeEntry(stat, pattern); }) - .catch(function () { return null; }); - }; - /** - * Return fs.Stats for the provided path. - */ - FileSystemStream.prototype.getStat = function (filepath) { - return fsStat.stat(filepath, { throwErrorOnBrokenSymlinks: false }); - }; - return FileSystemStream; -}(fs_1.default)); -exports.default = FileSystemStream; +GlobSync.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} /***/ }), -/* 896 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +exports.alphasort = alphasort +exports.alphasorti = alphasorti +exports.setopts = setopts +exports.ownProp = ownProp +exports.makeAbs = makeAbs +exports.finish = finish +exports.mark = mark +exports.isIgnored = isIgnored +exports.childrenIgnored = childrenIgnored -Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(897); -const statProvider = __webpack_require__(899); -/** - * Asynchronous API. - */ -function stat(path, opts) { - return new Promise((resolve, reject) => { - statProvider.async(path, optionsManager.prepare(opts), (err, stats) => err ? reject(err) : resolve(stats)); - }); -} -exports.stat = stat; -function statCallback(path, optsOrCallback, callback) { - if (typeof optsOrCallback === 'function') { - callback = optsOrCallback; /* tslint:disable-line: no-parameter-reassignment */ - optsOrCallback = undefined; /* tslint:disable-line: no-parameter-reassignment */ - } - if (typeof callback === 'undefined') { - throw new TypeError('The "callback" argument must be of type Function.'); - } - statProvider.async(path, optionsManager.prepare(optsOrCallback), callback); +function ownProp (obj, field) { + return Object.prototype.hasOwnProperty.call(obj, field) } -exports.statCallback = statCallback; -/** - * Synchronous API. - */ -function statSync(path, opts) { - return statProvider.sync(path, optionsManager.prepare(opts)); + +var path = __webpack_require__(16) +var minimatch = __webpack_require__(505) +var isAbsolute = __webpack_require__(511) +var Minimatch = minimatch.Minimatch + +function alphasorti (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()) } -exports.statSync = statSync; +function alphasort (a, b) { + return a.localeCompare(b) +} -/***/ }), -/* 897 */ -/***/ (function(module, exports, __webpack_require__) { +function setupIgnores (self, options) { + self.ignore = options.ignore || [] -"use strict"; + if (!Array.isArray(self.ignore)) + self.ignore = [self.ignore] -Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(898); -function prepare(opts) { - const options = Object.assign({ - fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), - throwErrorOnBrokenSymlinks: true, - followSymlinks: true - }, opts); - return options; + if (self.ignore.length) { + self.ignore = self.ignore.map(ignoreMap) + } } -exports.prepare = prepare; +// ignore patterns are always in dot:true mode. +function ignoreMap (pattern) { + var gmatcher = null + if (pattern.slice(-3) === '/**') { + var gpattern = pattern.replace(/(\/\*\*)+$/, '') + gmatcher = new Minimatch(gpattern, { dot: true }) + } -/***/ }), -/* 898 */ -/***/ (function(module, exports, __webpack_require__) { + return { + matcher: new Minimatch(pattern, { dot: true }), + gmatcher: gmatcher + } +} -"use strict"; +function setopts (self, pattern, options) { + if (!options) + options = {} -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 getFileSystemAdapter(fsMethods) { - if (!fsMethods) { - return exports.FILE_SYSTEM_ADAPTER; + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") } - return Object.assign({}, exports.FILE_SYSTEM_ADAPTER, fsMethods); -} -exports.getFileSystemAdapter = getFileSystemAdapter; + pattern = "**/" + pattern + } + self.silent = !!options.silent + self.pattern = pattern + self.strict = options.strict !== false + self.realpath = !!options.realpath + self.realpathCache = options.realpathCache || Object.create(null) + self.follow = !!options.follow + self.dot = !!options.dot + self.mark = !!options.mark + self.nodir = !!options.nodir + if (self.nodir) + self.mark = true + self.sync = !!options.sync + self.nounique = !!options.nounique + self.nonull = !!options.nonull + self.nosort = !!options.nosort + self.nocase = !!options.nocase + self.stat = !!options.stat + self.noprocess = !!options.noprocess + self.absolute = !!options.absolute -/***/ }), -/* 899 */ -/***/ (function(module, exports, __webpack_require__) { + self.maxLength = options.maxLength || Infinity + self.cache = options.cache || Object.create(null) + self.statCache = options.statCache || Object.create(null) + self.symlinks = options.symlinks || Object.create(null) -"use strict"; + setupIgnores(self, options) -Object.defineProperty(exports, "__esModule", { value: true }); -function sync(path, options) { - const lstat = options.fs.lstatSync(path); - if (!isFollowedSymlink(lstat, options)) { - return lstat; - } - try { - const stat = options.fs.statSync(path); - stat.isSymbolicLink = () => true; - return stat; - } - catch (err) { - if (!options.throwErrorOnBrokenSymlinks) { - return lstat; - } - throw err; - } -} -exports.sync = sync; -function async(path, options, callback) { - options.fs.lstat(path, (err0, lstat) => { - if (err0) { - return callback(err0, undefined); - } - if (!isFollowedSymlink(lstat, options)) { - return callback(null, lstat); - } - options.fs.stat(path, (err1, stat) => { - if (err1) { - return options.throwErrorOnBrokenSymlinks ? callback(err1) : callback(null, lstat); - } - stat.isSymbolicLink = () => true; - callback(null, stat); - }); - }); -} -exports.async = async; -/** - * Returns `true` for followed symlink. - */ -function isFollowedSymlink(stat, options) { - return stat.isSymbolicLink() && options.followSymlinks; + self.changedCwd = false + var cwd = process.cwd() + if (!ownProp(options, "cwd")) + self.cwd = cwd + else { + self.cwd = path.resolve(options.cwd) + self.changedCwd = self.cwd !== cwd + } + + self.root = options.root || path.resolve(self.cwd, "/") + self.root = path.resolve(self.root) + if (process.platform === "win32") + self.root = self.root.replace(/\\/g, "/") + + // TODO: is an absolute `cwd` supposed to be resolved against `root`? + // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test') + self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd) + if (process.platform === "win32") + self.cwdAbs = self.cwdAbs.replace(/\\/g, "/") + self.nomount = !!options.nomount + + // disable comments and negation in Minimatch. + // Note that they are not supported in Glob itself anyway. + options.nonegate = true + options.nocomment = true + + self.minimatch = new Minimatch(pattern, options) + self.options = self.minimatch.options } -exports.isFollowedSymlink = isFollowedSymlink; +function finish (self) { + var nou = self.nounique + var all = nou ? [] : Object.create(null) -/***/ }), -/* 900 */ -/***/ (function(module, exports, __webpack_require__) { + for (var i = 0, l = self.matches.length; i < l; i ++) { + var matches = self.matches[i] + if (!matches || Object.keys(matches).length === 0) { + if (self.nonull) { + // do like the shell, and spit out the literal glob + var literal = self.minimatch.globSet[i] + if (nou) + all.push(literal) + else + all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) + all.push.apply(all, m) + else + m.forEach(function (m) { + all[m] = true + }) + } + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var path = __webpack_require__(16); -var FileSystem = /** @class */ (function () { - function FileSystem(options) { - this.options = options; - } - /** - * Return full path to entry. - */ - FileSystem.prototype.getFullEntryPath = function (filepath) { - return path.resolve(this.options.cwd, filepath); - }; - /** - * Return an implementation of the Entry interface. - */ - FileSystem.prototype.makeEntry = function (stat, pattern) { - stat.path = pattern; - stat.depth = pattern.split('/').length; - return stat; - }; - return FileSystem; -}()); -exports.default = FileSystem; + if (!nou) + all = Object.keys(all) + if (!self.nosort) + all = all.sort(self.nocase ? alphasorti : alphasort) -/***/ }), -/* 901 */ -/***/ (function(module, exports, __webpack_require__) { + // at *some* point we statted all of these + if (self.mark) { + for (var i = 0; i < all.length; i++) { + all[i] = self._mark(all[i]) + } + if (self.nodir) { + all = all.filter(function (e) { + var notDir = !(/\/$/.test(e)) + var c = self.cache[e] || self.cache[makeAbs(self, e)] + if (notDir && c) + notDir = c !== 'DIR' && !Array.isArray(c) + return notDir + }) + } + } -"use strict"; - -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var stream = __webpack_require__(27); -var readdir = __webpack_require__(878); -var reader_1 = __webpack_require__(891); -var fs_stream_1 = __webpack_require__(895); -var TransformStream = /** @class */ (function (_super) { - __extends(TransformStream, _super); - function TransformStream(reader) { - var _this = _super.call(this, { objectMode: true }) || this; - _this.reader = reader; - return _this; - } - TransformStream.prototype._transform = function (entry, _encoding, callback) { - callback(null, this.reader.transform(entry)); - }; - return TransformStream; -}(stream.Transform)); -var ReaderStream = /** @class */ (function (_super) { - __extends(ReaderStream, _super); - function ReaderStream() { - return _super !== null && _super.apply(this, arguments) || this; - } - Object.defineProperty(ReaderStream.prototype, "fsAdapter", { - /** - * Returns FileSystem adapter. - */ - get: function () { - return new fs_stream_1.default(this.options); - }, - enumerable: true, - configurable: true - }); - /** - * Use stream API to read entries for Task. - */ - ReaderStream.prototype.read = function (task) { - var _this = this; - var root = this.getRootDirectory(task); - var options = this.getReaderOptions(task); - var transform = new TransformStream(this); - var readable = this.api(root, task, options); - return readable - .on('error', function (err) { return _this.isEnoentCodeError(err) ? null : transform.emit('error', err); }) - .pipe(transform); - }; - /** - * Returns founded paths. - */ - ReaderStream.prototype.api = function (root, task, options) { - if (task.dynamic) { - return this.dynamicApi(root, options); - } - return this.staticApi(task, options); - }; - /** - * Api for dynamic tasks. - */ - ReaderStream.prototype.dynamicApi = function (root, options) { - return readdir.readdirStreamStat(root, options); - }; - /** - * Api for static tasks. - */ - ReaderStream.prototype.staticApi = function (task, options) { - return this.fsAdapter.read(task.patterns, options.filter); - }; - return ReaderStream; -}(reader_1.default)); -exports.default = ReaderStream; + if (self.ignore.length) + all = all.filter(function(m) { + return !isIgnored(self, m) + }) + self.found = all +} -/***/ }), -/* 902 */ -/***/ (function(module, exports, __webpack_require__) { +function mark (self, p) { + var abs = makeAbs(self, p) + var c = self.cache[abs] + var m = p + if (c) { + var isDir = c === 'DIR' || Array.isArray(c) + var slash = p.slice(-1) === '/' -"use strict"; - -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(878); -var reader_1 = __webpack_require__(891); -var fs_sync_1 = __webpack_require__(903); -var ReaderSync = /** @class */ (function (_super) { - __extends(ReaderSync, _super); - function ReaderSync() { - return _super !== null && _super.apply(this, arguments) || this; - } - Object.defineProperty(ReaderSync.prototype, "fsAdapter", { - /** - * Returns FileSystem adapter. - */ - get: function () { - return new fs_sync_1.default(this.options); - }, - enumerable: true, - configurable: true - }); - /** - * Use sync API to read entries for Task. - */ - ReaderSync.prototype.read = function (task) { - var root = this.getRootDirectory(task); - var options = this.getReaderOptions(task); - try { - var entries = this.api(root, task, options); - return entries.map(this.transform, this); - } - catch (err) { - if (this.isEnoentCodeError(err)) { - return []; - } - throw err; - } - }; - /** - * Returns founded paths. - */ - ReaderSync.prototype.api = function (root, task, options) { - if (task.dynamic) { - return this.dynamicApi(root, options); - } - return this.staticApi(task, options); - }; - /** - * Api for dynamic tasks. - */ - ReaderSync.prototype.dynamicApi = function (root, options) { - return readdir.readdirSyncStat(root, options); - }; - /** - * Api for static tasks. - */ - ReaderSync.prototype.staticApi = function (task, options) { - return this.fsAdapter.read(task.patterns, options.filter); - }; - return ReaderSync; -}(reader_1.default)); -exports.default = ReaderSync; + if (isDir && !slash) + m += '/' + else if (!isDir && slash) + m = m.slice(0, -1) + if (m !== p) { + var mabs = makeAbs(self, m) + self.statCache[mabs] = self.statCache[abs] + self.cache[mabs] = self.cache[abs] + } + } -/***/ }), -/* 903 */ -/***/ (function(module, exports, __webpack_require__) { + return m +} -"use strict"; - -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(896); -var fs_1 = __webpack_require__(900); -var FileSystemSync = /** @class */ (function (_super) { - __extends(FileSystemSync, _super); - function FileSystemSync() { - return _super !== null && _super.apply(this, arguments) || this; - } - /** - * Use sync API to read entries for Task. - */ - FileSystemSync.prototype.read = function (patterns, filter) { - var _this = this; - var entries = []; - patterns.forEach(function (pattern) { - var filepath = _this.getFullEntryPath(pattern); - var entry = _this.getEntry(filepath, pattern); - if (entry === null || !filter(entry)) { - return; - } - entries.push(entry); - }); - return entries; - }; - /** - * Return entry for the provided path. - */ - FileSystemSync.prototype.getEntry = function (filepath, pattern) { - try { - var stat = this.getStat(filepath); - return this.makeEntry(stat, pattern); - } - catch (err) { - return null; - } - }; - /** - * Return fs.Stats for the provided path. - */ - FileSystemSync.prototype.getStat = function (filepath) { - return fsStat.statSync(filepath, { throwErrorOnBrokenSymlinks: false }); - }; - return FileSystemSync; -}(fs_1.default)); -exports.default = FileSystemSync; +// lotta situps... +function makeAbs (self, f) { + var abs = f + if (f.charAt(0) === '/') { + abs = path.join(self.root, f) + } else if (isAbsolute(f) || f === '') { + abs = f + } else if (self.changedCwd) { + abs = path.resolve(self.cwd, f) + } else { + abs = path.resolve(f) + } + if (process.platform === 'win32') + abs = abs.replace(/\\/g, '/') -/***/ }), -/* 904 */ -/***/ (function(module, exports, __webpack_require__) { + return abs +} -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Flatten nested arrays (max depth is 2) into a non-nested array of non-array items. - */ -function flatten(items) { - return items.reduce(function (collection, item) { return [].concat(collection, item); }, []); -} -exports.flatten = flatten; +// Return true, if pattern ends with globstar '**', for the accompanying parent directory. +// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents +function isIgnored (self, path) { + if (!self.ignore.length) + return false -/***/ }), -/* 905 */ -/***/ (function(module, exports, __webpack_require__) { + return self.ignore.some(function(item) { + return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) + }) +} -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(590); -/** - * Merge multiple streams and propagate their errors into one stream in parallel. - */ -function merge(streams) { - var mergedStream = merge2(streams); - streams.forEach(function (stream) { - stream.on('error', function (err) { return mergedStream.emit('error', err); }); - }); - return mergedStream; -} -exports.merge = merge; +function childrenIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return !!(item.gmatcher && item.gmatcher.match(path)) + }) +} /***/ }), -/* 906 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(907); +const pathType = __webpack_require__(720); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -105865,13 +81870,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 907 */ +/* 720 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const pify = __webpack_require__(908); +const pify = __webpack_require__(721); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -105914,7 +81919,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 908 */ +/* 721 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106005,17 +82010,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 909 */ +/* 722 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(718); -const gitIgnore = __webpack_require__(910); -const pify = __webpack_require__(911); -const slash = __webpack_require__(912); +const fastGlob = __webpack_require__(596); +const gitIgnore = __webpack_require__(723); +const pify = __webpack_require__(724); +const slash = __webpack_require__(725); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -106113,7 +82118,7 @@ module.exports.sync = options => { /***/ }), -/* 910 */ +/* 723 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -106582,7 +82587,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 911 */ +/* 724 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106657,7 +82662,7 @@ module.exports = (input, options) => { /***/ }), -/* 912 */ +/* 725 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106675,17 +82680,17 @@ module.exports = input => { /***/ }), -/* 913 */ +/* 726 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const {constants: fsConstants} = __webpack_require__(23); -const pEvent = __webpack_require__(914); -const CpFileError = __webpack_require__(917); -const fs = __webpack_require__(921); -const ProgressEmitter = __webpack_require__(924); +const pEvent = __webpack_require__(727); +const CpFileError = __webpack_require__(730); +const fs = __webpack_require__(734); +const ProgressEmitter = __webpack_require__(737); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -106799,12 +82804,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 914 */ +/* 727 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(915); +const pTimeout = __webpack_require__(728); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -107095,12 +83100,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 915 */ +/* 728 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(916); +const pFinally = __webpack_require__(729); class TimeoutError extends Error { constructor(message) { @@ -107146,7 +83151,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 916 */ +/* 729 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107168,12 +83173,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 917 */ +/* 730 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(918); +const NestedError = __webpack_require__(731); class CpFileError extends NestedError { constructor(message, nested) { @@ -107187,10 +83192,10 @@ module.exports = CpFileError; /***/ }), -/* 918 */ +/* 731 */ /***/ (function(module, exports, __webpack_require__) { -var inherits = __webpack_require__(919); +var inherits = __webpack_require__(732); var NestedError = function (message, nested) { this.nested = nested; @@ -107241,7 +83246,7 @@ module.exports = NestedError; /***/ }), -/* 919 */ +/* 732 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -107249,12 +83254,12 @@ try { if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; } catch (e) { - module.exports = __webpack_require__(920); + module.exports = __webpack_require__(733); } /***/ }), -/* 920 */ +/* 733 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -107283,16 +83288,16 @@ if (typeof Object.create === 'function') { /***/ }), -/* 921 */ +/* 734 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const fs = __webpack_require__(22); -const makeDir = __webpack_require__(922); -const pEvent = __webpack_require__(914); -const CpFileError = __webpack_require__(917); +const makeDir = __webpack_require__(735); +const pEvent = __webpack_require__(727); +const CpFileError = __webpack_require__(730); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -107389,7 +83394,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 922 */ +/* 735 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107397,7 +83402,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const {promisify} = __webpack_require__(29); -const semver = __webpack_require__(923); +const semver = __webpack_require__(736); const defaults = { mode: 0o777 & (~process.umask()), @@ -107546,7 +83551,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 923 */ +/* 736 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -109148,7 +85153,7 @@ function coerce (version, options) { /***/ }), -/* 924 */ +/* 737 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -109189,7 +85194,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 925 */ +/* 738 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -109235,12 +85240,12 @@ exports.default = module.exports; /***/ }), -/* 926 */ +/* 739 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(927); +const NestedError = __webpack_require__(740); class CpyError extends NestedError { constructor(message, nested) { @@ -109254,7 +85259,7 @@ module.exports = CpyError; /***/ }), -/* 927 */ +/* 740 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(29).inherits; @@ -109310,7 +85315,7 @@ module.exports = NestedError; /***/ }), -/* 928 */ +/* 741 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; diff --git a/x-pack/legacy/plugins/siem/common/graphql/root/schema.gql.ts b/x-pack/legacy/plugins/siem/common/graphql/root/schema.gql.ts index 1665334827e8e..721270d1d6fcd 100644 --- a/x-pack/legacy/plugins/siem/common/graphql/root/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/common/graphql/root/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const rootSchema = gql` schema { 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 d043c1587d3c3..43c87caa9f181 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const sharedSchema = gql` input TimerangeInput { diff --git a/x-pack/legacy/plugins/siem/public/app/app.tsx b/x-pack/legacy/plugins/siem/public/app/app.tsx index 7413aeab549db..c65b016068f9d 100644 --- a/x-pack/legacy/plugins/siem/public/app/app.tsx +++ b/x-pack/legacy/plugins/siem/public/app/app.tsx @@ -6,7 +6,7 @@ import { createHashHistory, History } from 'history'; import React, { memo, useMemo, FC } from 'react'; -import { ApolloProvider } from 'react-apollo'; +import { ApolloProvider } from '@apollo/client'; import { Store } from 'redux'; import { Provider as ReduxStoreProvider } from 'react-redux'; import { ThemeProvider } from 'styled-components'; @@ -30,8 +30,6 @@ import { createStore, createInitialState } from '../store'; import { GlobalToaster, ManageGlobalToaster } from '../components/toasters'; import { MlCapabilitiesProvider } from '../components/ml/permissions/ml_capabilities_provider'; -import { ApolloClientContext } from '../utils/apollo_context'; - interface AppPluginRootComponentProps { apolloClient: AppApolloClient; history: History; @@ -48,15 +46,13 @@ const AppPluginRootComponent: React.FC = ({ - - - - - - - - - + + + + + + + diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.test.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.test.tsx index 9e8bde8d9ff92..efe5aed46f16a 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.test.tsx @@ -6,7 +6,7 @@ import { mount, shallow } from 'enzyme'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { mockBrowserFields, mocksSource } from '../../containers/source/mock'; import { TestProviders } from '../../mock'; @@ -20,7 +20,7 @@ describe('DragDropContextWrapper', () => { const wrapper = shallow( - + {message} diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx index e846c923c5cbe..92adc1a9adb7a 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx @@ -6,7 +6,7 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { mockBrowserFields, mocksSource } from '../../containers/source/mock'; import { TestProviders } from '../../mock'; @@ -24,7 +24,7 @@ describe('DraggableWrapper', () => { test('it renders against the snapshot', () => { const wrapper = shallow( - + message} /> diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/droppable_wrapper.test.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/droppable_wrapper.test.tsx index bd2f01721290f..aa3ad8f47af21 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/droppable_wrapper.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/droppable_wrapper.test.tsx @@ -6,7 +6,7 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { mockBrowserFields, mocksSource } from '../../containers/source/mock'; import { TestProviders } from '../../mock'; @@ -24,7 +24,7 @@ describe('DroppableWrapper', () => { const wrapper = shallow( - + {message} diff --git a/x-pack/legacy/plugins/siem/public/components/event_details/columns.tsx b/x-pack/legacy/plugins/siem/public/components/event_details/columns.tsx index e9903ce66d799..c62f44e1c5e31 100644 --- a/x-pack/legacy/plugins/siem/public/components/event_details/columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/event_details/columns.tsx @@ -20,7 +20,7 @@ import { Draggable } from 'react-beautiful-dnd'; import styled from 'styled-components'; import { BrowserFields } from '../../containers/source'; -import { ToStringArray } from '../../graphql/types'; +import { Scalars } from '../../graphql/types'; import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard'; import { ColumnHeaderOptions } from '../../store/timeline/model'; import { DragEffects } from '../drag_and_drop/draggable_wrapper'; @@ -159,7 +159,7 @@ export const getColumns = ({ name: i18n.VALUE, sortable: true, truncateText: false, - render: (values: ToStringArray | null | undefined, data: EventFieldsData) => ( + render: (values: Scalars['ToStringArray'] | null | undefined, data: EventFieldsData) => ( {values != null && values.map((value, i) => ( diff --git a/x-pack/legacy/plugins/siem/public/components/event_details/helpers.tsx b/x-pack/legacy/plugins/siem/public/components/event_details/helpers.tsx index 5d9c9d82490bb..ef002abbd252d 100644 --- a/x-pack/legacy/plugins/siem/public/components/event_details/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/components/event_details/helpers.tsx @@ -12,7 +12,7 @@ import { DEFAULT_DATE_COLUMN_MIN_WIDTH, DEFAULT_COLUMN_MIN_WIDTH, } from '../timeline/body/constants'; -import { ToStringArray } from '../../graphql/types'; +import { Scalars } from '../../graphql/types'; import * as i18n from './translations'; @@ -40,7 +40,7 @@ export interface Item { field: JSX.Element; fieldId: string; type: string; - values: ToStringArray; + values: Scalars['ToStringArray']; } export const getColumnHeaderFromBrowserField = ({ diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.test.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.test.tsx index d3cdf9886e469..756944b83c316 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.test.tsx @@ -5,7 +5,8 @@ */ import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; +import { act } from '@testing-library/react'; import useResizeObserver from 'use-resize-observer/polyfilled'; import { mockIndexPattern, TestProviders } from '../../mock'; @@ -52,7 +53,7 @@ describe('EventsViewer', () => { ); - await wait(); + await act(() => wait()); wrapper.update(); expect( @@ -77,7 +78,7 @@ describe('EventsViewer', () => { ); - await wait(); + await act(() => wait()); wrapper.update(); expect( @@ -102,7 +103,7 @@ describe('EventsViewer', () => { ); - await wait(); + await act(() => wait()); wrapper.update(); expect( @@ -128,7 +129,7 @@ describe('EventsViewer', () => { ); - await wait(); + await act(() => wait()); wrapper.update(); defaultHeaders.forEach(h => diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx index a913186d9ad3b..f460ea24d5447 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx @@ -201,7 +201,6 @@ const EventsViewerComponent: React.FC = ({ getUpdatedAt={getUpdatedAt} hasNextPage={getOr(false, 'hasNextPage', pageInfo)!} height={footerHeight} - isEventViewer={true} isLive={isLive} isLoading={loading} itemsCount={events.length} @@ -243,7 +242,7 @@ export const EventsViewer = React.memo( prevProps.kqlMode === nextProps.kqlMode && deepEqual(prevProps.query, nextProps.query) && prevProps.start === nextProps.start && - prevProps.sort === nextProps.sort && + deepEqual(prevProps.sort, nextProps.sort) && deepEqual(prevProps.timelineTypeContext, nextProps.timelineTypeContext) && prevProps.utilityBar === nextProps.utilityBar ); diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.test.tsx index 6f614c1e32f65..034579b9d157e 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.test.tsx @@ -5,7 +5,8 @@ */ import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; +import { act } from '@testing-library/react'; import useResizeObserver from 'use-resize-observer/polyfilled'; import { wait } from '../../lib/helpers'; @@ -51,7 +52,7 @@ describe('StatefulEventsViewer', () => { ); - await wait(); + await act(() => wait()); wrapper.update(); expect( @@ -77,7 +78,7 @@ describe('StatefulEventsViewer', () => { ); - await wait(); + await act(() => wait()); wrapper.update(); expect(wrapper.find(`InspectButtonContainer`).exists()).toBe(true); diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx index 22fc9f27ce26c..139dcd1943fad 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx @@ -9,6 +9,7 @@ import { defaultTo, getOr } from 'lodash/fp'; import React, { useCallback } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { State, timelineSelectors } from '../../store'; import { DataProvider } from '../timeline/data_providers/data_provider'; @@ -90,7 +91,17 @@ export const FlyoutComponent = React.memo( /> ); - } + }, + (prevProps, nextProps) => + prevProps.children === nextProps.children && + deepEqual(prevProps.dataProviders, nextProps.dataProviders) && + prevProps.flyoutHeight === nextProps.flyoutHeight && + prevProps.headerHeight === nextProps.headerHeight && + prevProps.show === nextProps.show && + prevProps.showTimeline === nextProps.showTimeline && + prevProps.timelineId === nextProps.timelineId && + prevProps.usersViewing === nextProps.usersViewing && + prevProps.width === nextProps.width ); FlyoutComponent.displayName = 'FlyoutComponent'; diff --git a/x-pack/legacy/plugins/siem/public/components/header_global/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/header_global/__snapshots__/index.test.tsx.snap index 25374c63fa897..6b4af62586c19 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_global/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/header_global/__snapshots__/index.test.tsx.snap @@ -9,11 +9,106 @@ exports[`HeaderGlobal it renders 1`] = ` justifyContent="spaceBetween" wrap={true} > - + + + + + + + + + + + + - - + + + + + + + Add data + + + + `; diff --git a/x-pack/legacy/plugins/siem/public/components/header_global/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/header_global/index.test.tsx index 098de39bbfef5..6c20daeab4cbc 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_global/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/header_global/index.test.tsx @@ -17,10 +17,15 @@ jest.mock('ui/new_platform'); jest.mock('../search_bar', () => ({ SiemSearchBar: () => null, })); +jest.mock('../../containers/source', () => ({ + useWithSource: () => ({ + contentAvailable: true, + }), +})); describe('HeaderGlobal', () => { test('it renders', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); diff --git a/x-pack/legacy/plugins/siem/public/components/header_global/index.tsx b/x-pack/legacy/plugins/siem/public/components/header_global/index.tsx index a12fab8a4f5d9..55c67a5af69ea 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_global/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/header_global/index.tsx @@ -16,7 +16,6 @@ import { getOverviewUrl } from '../link_to'; import { MlPopover } from '../ml_popover/ml_popover'; import { SiemNavigation } from '../navigation'; import * as i18n from './translations'; -import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; const Wrapper = styled.header` ${({ theme }) => css` @@ -34,65 +33,64 @@ const FlexItem = styled(EuiFlexItem)` FlexItem.displayName = 'FlexItem'; interface HeaderGlobalProps { + contentAvailable: boolean; hideDetectionEngine?: boolean; } -export const HeaderGlobal = React.memo(({ hideDetectionEngine = false }) => ( - - - - {({ indicesExist }) => ( - <> - - - - - - - +export const HeaderGlobal = React.memo( + ({ contentAvailable, hideDetectionEngine = false }) => ( + + + <> + + + + + + + - - {indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - key !== SiemPageName.detections, navTabs) - : navTabs - } - /> - ) : ( - key === SiemPageName.overview, navTabs)} - /> - )} - - - - - - - {indicesExistOrDataTemporarilyUnavailable(indicesExist) && ( - - - + + {contentAvailable ? ( + key !== SiemPageName.detections, navTabs) + : navTabs + } + /> + ) : ( + key === SiemPageName.overview, navTabs)} + /> )} + + + + + + {contentAvailable && ( - - {i18n.BUTTON_ADD_DATA} - + - - - - )} - - - -)); + )} + + + + {i18n.BUTTON_ADD_DATA} + + + + + + + + ) +); HeaderGlobal.displayName = 'HeaderGlobal'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts b/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts index 4f7d6cd64f1d9..3dd1b145e7d09 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import ApolloClient from 'apollo-client'; +import { ApolloClient } from '@apollo/client'; import { getOr, set } from 'lodash/fp'; import { Action } from 'typescript-fsa'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.test.tsx index 520e2094fb336..d3911fdf18f09 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.test.tsx @@ -6,14 +6,15 @@ import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; import { mount } from 'enzyme'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import React from 'react'; import { ThemeProvider } from 'styled-components'; +import { act } from '@testing-library/react'; import { wait } from '../../lib/helpers'; -import { TestProviderWithoutDragAndDrop, apolloClient } from '../../mock/test_providers'; -import { mockOpenTimelineQueryResults } from '../../mock/timeline_results'; -import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../pages/timelines/timelines_page'; +import { TestProviderWithoutDragAndDrop } from '../../mock/test_providers'; +import { mockOpenTimelineQueryResults, MockedProvidedQuery } from '../../mock/timeline_results'; +import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../pages/timelines'; import { StatefulOpenTimeline } from '.'; import { NotePreviews } from './note_previews'; @@ -24,15 +25,19 @@ jest.mock('../../lib/kibana'); describe('StatefulOpenTimeline', () => { const theme = () => ({ eui: euiDarkVars, darkMode: true }); const title = 'All Timelines / Open Timelines'; + let mocks: MockedProvidedQuery[]; + + beforeEach(() => { + mocks = mockOpenTimelineQueryResults; + }); test('it has the expected initial state', () => { const wrapper = mount( - + { }); describe('#onQueryChange', () => { - test('it updates the query state with the expected trimmed value when the user enters a query', () => { + test('it updates the query state with the expected trimmed value when the user enters a query', async () => { const wrapper = mount( - + { ); + wrapper .find('[data-test-subj="search-bar"] input') .simulate('keyup', { keyCode: 13, target: { value: ' abcd ' } }); + expect( wrapper .find('[data-test-subj="search-row"]') @@ -92,9 +98,8 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); wrapper .find('[data-test-subj="search-bar"] input') @@ -122,9 +127,8 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); wrapper .find('[data-test-subj="search-bar"] input') @@ -154,9 +158,8 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); expect( wrapper @@ -185,9 +188,8 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); wrapper .find('.euiCheckbox__input') @@ -231,9 +233,8 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); wrapper .find('.euiCheckbox__input') @@ -274,10 +275,9 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); wrapper .find('.euiCheckbox__input') @@ -308,10 +308,9 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { const wrapper = mount( - + { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); wrapper.update(); expect( @@ -423,10 +420,11 @@ describe('StatefulOpenTimeline', () => { '10849df0-7b44-11e9-a608-ab3d811609': ( ({ ...note, savedObjectId: note.noteId }) - ) + mocks[0].result.data!.getAllTimeline.timeline[0].notes != null + ? mocks[0].result.data!.getAllTimeline.timeline[0].notes.map(note => ({ + ...note, + savedObjectId: note.noteId, + })) : [] } /> @@ -438,10 +436,9 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); wrapper.update(); @@ -474,10 +471,9 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); expect( wrapper @@ -497,15 +493,14 @@ describe('StatefulOpenTimeline', () => { ).toEqual(title); }); - describe('#resetSelectionState', () => { + describe.skip('#resetSelectionState', () => { test('when the user deletes selected timelines, resetSelectionState is invoked to clear the selection state', async () => { const wrapper = mount( - + { .find('[data-test-subj="open-timeline"]') .last() .prop('selectedItems'); - await wait(); + await act(() => wait()); expect(getSelectedItem().length).toEqual(0); wrapper .find('.euiCheckbox__input') @@ -537,11 +532,10 @@ describe('StatefulOpenTimeline', () => { test('it renders the expected count of matching timelines when no query has been entered', async () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); wrapper.update(); + await act(() => wait()); + expect( wrapper .find('[data-test-subj="query-message"]') @@ -570,10 +566,9 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); wrapper .find( - `[data-test-subj="title-${ - mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0].savedObjectId - }"]` + `[data-test-subj="title-${mocks[0].result.data!.getAllTimeline.timeline[0].savedObjectId}"]` ) .first() .simulate('click'); expect(onOpenTimeline).toHaveBeenCalledWith({ duplicate: false, - timelineId: mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0] - .savedObjectId, + timelineId: mocks[0].result.data!.getAllTimeline.timeline[0].savedObjectId, }); }); @@ -608,10 +600,9 @@ describe('StatefulOpenTimeline', () => { const wrapper = mount( - + { ); - await wait(); + await act(() => wait()); wrapper .find('[data-test-subj="open-duplicate"]') 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 26a7487fee52b..455a60b89b9ab 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import ApolloClient from 'apollo-client'; +import { useApolloClient } from '@apollo/client'; import React, { useEffect, useState, useCallback } from 'react'; import { connect, ConnectedProps } from 'react-redux'; @@ -43,7 +43,6 @@ import { import { DEFAULT_SORT_FIELD, DEFAULT_SORT_DIRECTION } from './constants'; interface OwnProps { - apolloClient: ApolloClient; /** Displays open timeline in modal */ isModal: boolean; closeModalTimeline?: () => void; @@ -68,7 +67,6 @@ export const getSelectedTimelineIds = (selectedItems: OpenTimelineResult[]): str /** Manages the state (e.g table selection) of the (pure) `OpenTimeline` component */ export const StatefulOpenTimelineComponent = React.memo( ({ - apolloClient, closeModalTimeline, createNewTimeline, defaultPageSize, @@ -80,6 +78,7 @@ export const StatefulOpenTimelineComponent = React.memo( updateTimeline, updateIsLoading, }) => { + const apolloClient = useApolloClient(); /** Required by EuiTable for expandable rows: a map of `TimelineResult.savedObjectId` to rendered notes */ const [itemIdToExpandedNotesRowMap, setItemIdToExpandedNotesRowMap] = useState< Record diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline.test.tsx index a1ca7812bba34..6df1039b68716 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline.test.tsx @@ -10,7 +10,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import { ThemeProvider } from 'styled-components'; -import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../pages/timelines/timelines_page'; +import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../pages/timelines'; import { OpenTimelineResult } from './types'; import { TimelinesTableProps } from './timelines_table'; import { mockTimelineResults } from '../../mock/timeline_results'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.test.tsx index ca8fa50c572fe..4d9ecd0d6052f 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.test.tsx @@ -7,8 +7,9 @@ import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; import { mount } from 'enzyme'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { ThemeProvider } from 'styled-components'; +import { act } from '@testing-library/react'; import { wait } from '../../../lib/helpers'; import { TestProviderWithoutDragAndDrop } from '../../../mock/test_providers'; @@ -17,9 +18,6 @@ import { mockOpenTimelineQueryResults } from '../../../mock/timeline_results'; import { OpenTimelineModal } from '.'; jest.mock('../../../lib/kibana'); -jest.mock('../../../utils/apollo_context', () => ({ - useApolloClient: () => ({}), -})); describe('OpenTimelineModal', () => { const theme = () => ({ eui: euiDarkVars, darkMode: true }); @@ -35,7 +33,7 @@ describe('OpenTimelineModal', () => { ); - await wait(); + await act(() => wait()); wrapper.update(); 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 c530929a3c96e..5f5792efc1eb8 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 @@ -8,7 +8,6 @@ import { EuiModal, EuiOverlayMask } from '@elastic/eui'; import React from 'react'; import { TimelineModel } from '../../../store/timeline/model'; -import { useApolloClient } from '../../../utils/apollo_context'; import * as i18n from '../translations'; import { ActionTimelineToShow } from '../types'; @@ -25,31 +24,24 @@ const DEFAULT_SEARCH_RESULTS_PER_PAGE = 10; const OPEN_TIMELINE_MODAL_WIDTH = 1000; // px export const OpenTimelineModal = React.memo( - ({ hideActions = [], modalTitle, onClose, onOpen }) => { - const apolloClient = useApolloClient(); - - if (!apolloClient) return null; - - return ( - - - - - - ); - } + ({ hideActions = [], modalTitle, onClose, onOpen }) => ( + + + + + + ) ); OpenTimelineModal.displayName = 'OpenTimelineModal'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx index 2c3adb138b7ac..df24a43057a18 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx @@ -10,7 +10,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import { ThemeProvider } from 'styled-components'; -import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page'; +import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines'; import { OpenTimelineResult } from '../types'; import { TimelinesTableProps } from '../timelines_table'; import { mockTimelineResults } from '../../../mock/timeline_results'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_button.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_button.test.tsx index 66947a313f5e5..cafcc031f7a81 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_button.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_button.test.tsx @@ -7,8 +7,9 @@ import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; import { mount } from 'enzyme'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { ThemeProvider } from 'styled-components'; +import { act } from '@testing-library/react'; import { wait } from '../../../lib/helpers'; import { TestProviderWithoutDragAndDrop } from '../../../mock/test_providers'; @@ -29,7 +30,7 @@ describe('OpenTimelineModalButton', () => { ); - await wait(); + await act(() => wait()); wrapper.update(); @@ -54,7 +55,7 @@ describe('OpenTimelineModalButton', () => { ); - await wait(); + await act(() => wait()); wrapper .find('[data-test-subj="open-timeline-button"]') diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/actions_columns.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/actions_columns.test.tsx index eec11f571328f..26e0aa1ff5751 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/actions_columns.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/actions_columns.test.tsx @@ -11,7 +11,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import { ThemeProvider } from 'styled-components'; -import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page'; +import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines'; import { mockTimelineResults } from '../../../mock/timeline_results'; import { OpenTimelineResult } from '../types'; import { TimelinesTable } from '.'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/common_columns.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/common_columns.test.tsx index 0f2cda9d79f0b..bd5da06a37bbc 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/common_columns.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/common_columns.test.tsx @@ -11,7 +11,7 @@ import React from 'react'; import { ThemeProvider } from 'styled-components'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page'; +import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines'; import { getEmptyValue } from '../../empty_value'; import { OpenTimelineResult } from '../types'; import { mockTimelineResults } from '../../../mock/timeline_results'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/extended_columns.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/extended_columns.test.tsx index 4cbe1e45c473b..b6554aa794f9c 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/extended_columns.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/extended_columns.test.tsx @@ -10,7 +10,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import { ThemeProvider } from 'styled-components'; -import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page'; +import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines'; import { getEmptyValue } from '../../empty_value'; import { mockTimelineResults } from '../../../mock/timeline_results'; import { OpenTimelineResult } from '../types'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/icon_header_columns.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/icon_header_columns.test.tsx index 31377d176acac..3f06fbeb5921c 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/icon_header_columns.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/icon_header_columns.test.tsx @@ -10,7 +10,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import { ThemeProvider } from 'styled-components'; -import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page'; +import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines'; import { mockTimelineResults } from '../../../mock/timeline_results'; import { TimelinesTable } from '.'; import { OpenTimelineResult } from '../types'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/index.test.tsx index 26d9607a91fcd..9dc75e4c4534b 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/index.test.tsx @@ -10,7 +10,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import { ThemeProvider } from 'styled-components'; -import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page'; +import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines'; import { mockTimelineResults } from '../../../mock/timeline_results'; import { OpenTimelineResult } from '../types'; import { TimelinesTable, TimelinesTableProps } from '.'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/first_last_seen_host/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/first_last_seen_host/index.test.tsx index 4a836333f3311..a378c007cf56f 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/first_last_seen_host/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/first_last_seen_host/index.test.tsx @@ -6,7 +6,7 @@ import { cloneDeep } from 'lodash/fp'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { render, act } from '@testing-library/react'; import { mockFirstLastSeenHostQuery } from '../../../../containers/hosts/first_last_seen/mock'; @@ -19,16 +19,6 @@ describe('FirstLastSeen Component', () => { const firstSeen = 'Apr 8, 2019 @ 16:09:40.692'; const lastSeen = 'Apr 8, 2019 @ 18:35:45.064'; - // Suppress warnings about "react-apollo" until we migrate to apollo@3 - /* eslint-disable no-console */ - const originalError = console.error; - beforeAll(() => { - console.error = jest.fn(); - }); - afterAll(() => { - console.error = originalError; - }); - test('Loading', async () => { const { container } = render( 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 70dff5eda5939..3c162c559fe2f 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 @@ -6,7 +6,6 @@ import { EuiIcon, EuiLoadingSpinner, EuiText, EuiToolTip } from '@elastic/eui'; import React from 'react'; -import { ApolloConsumer } from 'react-apollo'; import { useFirstLastSeenHostQuery } from '../../../../containers/hosts/first_last_seen'; import { getEmptyTagValue } from '../../../empty_value'; @@ -19,44 +18,37 @@ export enum FirstLastSeenHostType { export const FirstLastSeenHost = React.memo<{ hostname: string; type: FirstLastSeenHostType }>( ({ hostname, type }) => { + const { loading, firstSeen, lastSeen, errorMessage } = useFirstLastSeenHostQuery( + hostname, + 'default' + ); + if (errorMessage != null) { + return ( + + + + ); + } + const valueSeen = type === FirstLastSeenHostType.FIRST_SEEN ? firstSeen : lastSeen; return ( - - {client => { - const { loading, firstSeen, lastSeen, errorMessage } = useFirstLastSeenHostQuery( - hostname, - 'default', - client - ); - if (errorMessage != null) { - return ( - - - - ); - } - const valueSeen = type === FirstLastSeenHostType.FIRST_SEEN ? firstSeen : lastSeen; - return ( - <> - {loading && } - {!loading && valueSeen != null && new Date(valueSeen).toString() === 'Invalid Date' - ? valueSeen - : !loading && - valueSeen != null && ( - - - - )} - {!loading && valueSeen == null && getEmptyTagValue()} - - ); - }} - + <> + {loading && } + {!loading && valueSeen != null && new Date(valueSeen).toString() === 'Invalid Date' + ? valueSeen + : !loading && + valueSeen != null && ( + + + + )} + {!loading && valueSeen == null && getEmptyTagValue()} + ); } ); diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/__snapshots__/index.test.tsx.snap index 3143e680913b2..1d70f4f72ac8b 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/__snapshots__/index.test.tsx.snap @@ -68,97 +68,6 @@ exports[`Hosts Table rendering it renders the default Hosts table 1`] = ` } fakeTotalCount={50} id="hostsQuery" - indexPattern={ - Object { - "fields": Array [ - Object { - "aggregatable": true, - "name": "@timestamp", - "searchable": true, - "type": "date", - }, - Object { - "aggregatable": true, - "name": "@version", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.ephemeral_id", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.hostname", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.id", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test1", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test2", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test3", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test4", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test5", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test6", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test7", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test8", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "host.name", - "searchable": true, - "type": "string", - }, - ], - "title": "filebeat-*,auditbeat-*,packetbeat-*", - } - } isInspect={false} loadPage={[MockFunction]} loading={false} diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.test.tsx index e561594013dea..cb70be5bc962c 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.test.tsx @@ -7,14 +7,9 @@ import { shallow } from 'enzyme'; import { getOr } from 'lodash/fp'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; -import { - apolloClientObservable, - mockIndexPattern, - mockGlobalState, - TestProviders, -} from '../../../../mock'; +import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock'; import { useMountAppended } from '../../../../utils/use_mount_appended'; import { createStore, hostsModel, State } from '../../../../store'; import { HostsTableType } from '../../../../store/hosts/model'; @@ -49,7 +44,6 @@ describe('Hosts Table', () => { data={mockData.Hosts.edges} id="hostsQuery" isInspect={false} - indexPattern={mockIndexPattern} fakeTotalCount={getOr(50, 'fakeTotalCount', mockData.Hosts.pageInfo)} loading={false} loadPage={loadPage} @@ -72,7 +66,6 @@ describe('Hosts Table', () => { void; @@ -78,7 +75,6 @@ const HostsTableComponent = React.memo( direction, fakeTotalCount, id, - indexPattern, isInspect, limit, loading, diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/kpi_hosts/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/kpi_hosts/index.tsx index 65d5924821844..ae6c22afc53d7 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/kpi_hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/kpi_hosts/index.tsx @@ -33,9 +33,7 @@ interface KpiHostDetailsProps extends GenericKpiHostProps { } const FlexGroupSpinner = styled(EuiFlexGroup)` - { - min-height: ${kpiWidgetHeight}px; - } + min-height: ${kpiWidgetHeight}px; `; FlexGroupSpinner.displayName = 'FlexGroupSpinner'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.test.tsx index e425057dd0f75..db0121298f2f9 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.test.tsx @@ -7,7 +7,7 @@ import { shallow } from 'enzyme'; import { getOr } from 'lodash/fp'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { Provider as ReduxStoreProvider } from 'react-redux'; import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.test.tsx index c4596ada5c74d..e28cfa0ab6755 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.test.tsx @@ -7,7 +7,7 @@ import { shallow } from 'enzyme'; import { getOr } from 'lodash/fp'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { Provider as ReduxStoreProvider } from 'react-redux'; import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.test.tsx index 764e440a5a4be..f73c4e1a02f8f 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.test.tsx @@ -7,7 +7,7 @@ import { shallow } from 'enzyme'; import { getOr } from 'lodash/fp'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { Provider as ReduxStoreProvider } from 'react-redux'; import { FlowTargetSourceDest } from '../../../../graphql/types'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.test.tsx index 78e8b15005f43..179ff4e2060bb 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.test.tsx @@ -7,7 +7,7 @@ import { shallow } from 'enzyme'; import { getOr } from 'lodash/fp'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { Provider as ReduxStoreProvider } from 'react-redux'; import { FlowTargetSourceDest } from '../../../../graphql/types'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.test.tsx index 81a472f3175e5..bb35eb638fe55 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.test.tsx @@ -7,7 +7,7 @@ import { shallow } from 'enzyme'; import { getOr } from 'lodash/fp'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { Provider as ReduxStoreProvider } from 'react-redux'; import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.test.tsx index 8dc3704a089ea..b4b88fb48da8a 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.test.tsx @@ -7,7 +7,7 @@ import { shallow } from 'enzyme'; import { getOr } from 'lodash/fp'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import { Provider as ReduxStoreProvider } from 'react-redux'; import { FlowTarget } from '../../../../graphql/types'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.test.tsx index 568cf032fb01c..2167ddd7b78a3 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.test.tsx @@ -7,14 +7,13 @@ import { cloneDeep } from 'lodash/fp'; import { mount } from 'enzyme'; import React from 'react'; +import { MockedResponse, MockedProvider } from '@apollo/client/testing'; import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock'; import { OverviewHost } from '.'; import { createStore, State } from '../../../../store'; import { overviewHostQuery } from '../../../../containers/overview/overview_host/index.gql_query'; -import { GetOverviewHostQuery } from '../../../../graphql/types'; -import { MockedProvider } from 'react-apollo/test-utils'; import { wait } from '../../../../lib/helpers'; jest.mock('../../../../lib/kibana'); @@ -22,12 +21,7 @@ jest.mock('../../../../lib/kibana'); const startDate = 1579553397080; const endDate = 1579639797080; -interface MockedProvidedQuery { - request: { - query: GetOverviewHostQuery.Query; - fetchPolicy: string; - variables: GetOverviewHostQuery.Variables; - }; +interface MockedProvidedQuery extends MockedResponse { result: { data: { source: unknown; @@ -39,7 +33,6 @@ const mockOpenTimelineQueryResults: MockedProvidedQuery[] = [ { request: { query: overviewHostQuery, - fetchPolicy: 'cache-and-network', variables: { sourceId: 'default', timerange: { interval: '12h', from: startDate, to: endDate }, diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.test.tsx index 151bb444cfe75..9cefddd3c41a2 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.test.tsx @@ -7,14 +7,13 @@ import { cloneDeep } from 'lodash/fp'; import { mount } from 'enzyme'; import React from 'react'; +import { MockedProvider, MockedResponse } from '@apollo/client/testing'; import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock'; import { OverviewNetwork } from '.'; import { createStore, State } from '../../../../store'; import { overviewNetworkQuery } from '../../../../containers/overview/overview_network/index.gql_query'; -import { GetOverviewHostQuery } from '../../../../graphql/types'; -import { MockedProvider } from 'react-apollo/test-utils'; import { wait } from '../../../../lib/helpers'; jest.mock('../../../../lib/kibana'); @@ -22,12 +21,7 @@ jest.mock('../../../../lib/kibana'); const startDate = 1579553397080; const endDate = 1579639797080; -interface MockedProvidedQuery { - request: { - query: GetOverviewHostQuery.Query; - fetchPolicy: string; - variables: GetOverviewHostQuery.Variables; - }; +interface MockedProvidedQuery extends MockedResponse { result: { data: { source: unknown; @@ -39,7 +33,6 @@ const mockOpenTimelineQueryResults: MockedProvidedQuery[] = [ { request: { query: overviewNetworkQuery, - fetchPolicy: 'cache-and-network', variables: { sourceId: 'default', timerange: { interval: '12h', from: startDate, to: endDate }, diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.tsx index 100abd997ee6b..8c6c96f6e233b 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network/index.tsx @@ -50,6 +50,9 @@ const OverviewNetworkComponent: React.FC = ({ setQuery, }) => { const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); + const title = ( + + ); return ( @@ -89,12 +92,7 @@ const OverviewNetworkComponent: React.FC = ({ <>{''} ) } - title={ - - } + title={title} > ; filterBy: FilterMode; } export type Props = OwnProps & PropsFromRedux; const StatefulRecentTimelinesComponent = React.memo( - ({ apolloClient, filterBy, updateIsLoading, updateTimeline }) => { + ({ filterBy, updateIsLoading, updateTimeline }) => { + const apolloClient = useApolloClient(); const actionDispatcher = updateIsLoading as ActionCreator<{ id: string; isLoading: boolean }>; const onOpenTimeline: OnOpenTimeline = useCallback( ({ duplicate, timelineId }: { duplicate: boolean; timelineId: string }) => { diff --git a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx index 2513004af84dd..7f6c157fcabd6 100644 --- a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx @@ -372,7 +372,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ dispatch(inputsActions.setSearchBarFilter({ id, filters })), }); -export const connector = connect(makeMapStateToProps, mapDispatchToProps); +const connector = connect(makeMapStateToProps, mapDispatchToProps); type PropsFromRedux = ConnectedProps; diff --git a/x-pack/legacy/plugins/siem/public/components/stat_items/index.tsx b/x-pack/legacy/plugins/siem/public/components/stat_items/index.tsx index 3ebcba0a85a40..17a8e961836ce 100644 --- a/x-pack/legacy/plugins/siem/public/components/stat_items/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/stat_items/index.tsx @@ -18,7 +18,7 @@ import { get, getOr } from 'lodash/fp'; import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; -import { KpiHostsData, KpiNetworkData } from '../../graphql/types'; +import { KpiHostsData, KpiHostDetailsData, KpiNetworkData } from '../../graphql/types'; import { AreaChart } from '../charts/areachart'; import { BarChart } from '../charts/barchart'; import { ChartSeriesData, ChartData, ChartSeriesConfigs, UpdateDateRange } from '../charts/common'; @@ -112,12 +112,12 @@ export const barchartConfigs = (config?: { onElementClick?: ElementClickListener export const addValueToFields = ( fields: StatItem[], - data: KpiHostsData | KpiNetworkData + data: KpiHostsData | KpiHostDetailsData | KpiNetworkData ): StatItem[] => fields.map(field => ({ ...field, value: get(field.key, data) })); export const addValueToAreaChart = ( fields: StatItem[], - data: KpiHostsData | KpiNetworkData + data: KpiHostsData | KpiHostDetailsData | KpiNetworkData ): ChartSeriesData[] => fields .filter(field => get(`${field.key}Histogram`, data) != null) @@ -129,7 +129,7 @@ export const addValueToAreaChart = ( export const addValueToBarChart = ( fields: StatItem[], - data: KpiHostsData | KpiNetworkData + data: KpiHostsData | KpiHostDetailsData | KpiNetworkData ): ChartSeriesData[] => { if (fields.length === 0) return []; return fields.reduce((acc: ChartSeriesData[], field: StatItem, idx: number) => { @@ -158,7 +158,7 @@ export const addValueToBarChart = ( export const useKpiMatrixStatus = ( mappings: Readonly, - data: KpiHostsData | KpiNetworkData, + data: KpiHostsData | KpiHostDetailsData | KpiNetworkData, id: string, from: number, to: number, diff --git a/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx b/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx index ad38a7d61bcba..ff79351271cca 100644 --- a/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx @@ -306,7 +306,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateReduxTime: dispatchUpdateReduxTime(dispatch), }); -export const connector = connect(makeMapStateToProps, mapDispatchToProps); +const connector = connect(makeMapStateToProps, mapDispatchToProps); type PropsFromRedux = ConnectedProps; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/helpers.test.ts b/x-pack/legacy/plugins/siem/public/components/timeline/body/helpers.test.ts index f021bf38b56c2..ced2f3f76f9f0 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/helpers.test.ts +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/helpers.test.ts @@ -11,7 +11,7 @@ import { eventHasNotes, eventIsPinned, getPinTooltip, stringifyEvent } from './h describe('helpers', () => { describe('stringifyEvent', () => { test('it omits __typename when it appears at arbitrary levels', () => { - const toStringify: Ecs = { + const toStringify: Ecs = ({ __typename: 'level 0', _id: '4', timestamp: '2018-11-08T19:03:25.937Z', @@ -54,7 +54,7 @@ describe('helpers', () => { region_name: ['neither'], country_iso_code: ['sasquatch'], }, - } as Ecs; // as cast so that `__typename` can be added for the tests even though it is not part of ECS + } as unknown) as Ecs; // as cast so that `__typename` can be added for the tests even though it is not part of ECS const expected: Ecs = { _id: '4', timestamp: '2018-11-08T19:03:25.937Z', diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap index 6b866aeecc831..e1b7de34e4004 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap @@ -1299,86 +1299,791 @@ tr:hover .c3:focus::before { ( return ( prevProps.browserFields === nextProps.browserFields && prevProps.columnHeaders === nextProps.columnHeaders && - prevProps.data === nextProps.data && + deepEqual(prevProps.data, nextProps.data) && prevProps.eventIdToNoteIds === nextProps.eventIdToNoteIds && prevProps.notesById === nextProps.notesById && prevProps.height === nextProps.height && diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx index 65c539d77a16b..0689472cd5b96 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx @@ -7,6 +7,7 @@ import { memo, useEffect } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { IIndexPattern } from 'src/plugins/data/public'; +import deepEqual from 'fast-deep-equal'; import { timelineSelectors, State } from '../../store'; import { inputsActions } from '../../store/actions'; @@ -39,7 +40,14 @@ const TimelineKqlFetchComponent = memo( }); }, [kueryFilterQueryDraft, kueryFilterQuery, id]); return null; - } + }, + (prevProps, nextProps) => + prevProps.id === nextProps.id && + deepEqual(prevProps.indexPattern, nextProps.indexPattern) && + prevProps.inputId === nextProps.inputId && + prevProps.kueryFilterQuery === nextProps.kueryFilterQuery && + prevProps.kueryFilterQueryDraft === nextProps.kueryFilterQueryDraft && + prevProps.setTimelineQuery === nextProps.setTimelineQuery ); const makeMapStateToProps = () => { @@ -58,7 +66,7 @@ const mapDispatchToProps = { setTimelineQuery: inputsActions.setQuery, }; -export const connector = connect(makeMapStateToProps, mapDispatchToProps); +const connector = connect(makeMapStateToProps, mapDispatchToProps); type PropsFromRedux = ConnectedProps; 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 1fcc4382c1798..efcc6a2b71dc9 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 @@ -177,7 +177,6 @@ interface FooterProps { getUpdatedAt: () => number; hasNextPage: boolean; height: number; - isEventViewer?: boolean; isLive: boolean; isLoading: boolean; itemsCount: number; @@ -196,7 +195,6 @@ export const FooterComponent = ({ getUpdatedAt, hasNextPage, height, - isEventViewer, isLive, isLoading, itemsCount, @@ -345,7 +343,6 @@ export const Footer = React.memo( prevProps.compact === nextProps.compact && prevProps.hasNextPage === nextProps.hasNextPage && prevProps.height === nextProps.height && - prevProps.isEventViewer === nextProps.isEventViewer && prevProps.isLive === nextProps.isLive && prevProps.isLoading === nextProps.isLoading && prevProps.itemsCount === nextProps.itemsCount && diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/header/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/header/index.tsx index 81eef0efbfa5b..bb9ee6efb9c78 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/header/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/header/index.tsx @@ -8,6 +8,7 @@ import { EuiCallOut } from '@elastic/eui'; import React from 'react'; import styled from 'styled-components'; import { IIndexPattern } from 'src/plugins/data/public'; +import deepEqual from 'fast-deep-equal'; import { Sort } from '../body/sort'; import { DataProviders } from '../data_providers'; @@ -91,4 +92,19 @@ export const TimelineHeaderComponent: React.FC = ({ ); -export const TimelineHeader = React.memo(TimelineHeaderComponent); +export const TimelineHeader = React.memo( + TimelineHeaderComponent, + (prevProps, nextProps) => + deepEqual(prevProps.browserFields, nextProps.browserFields) && + prevProps.id === nextProps.id && + deepEqual(prevProps.indexPattern, nextProps.indexPattern) && + deepEqual(prevProps.dataProviders, nextProps.dataProviders) && + prevProps.onChangeDataProviderKqlQuery === nextProps.onChangeDataProviderKqlQuery && + prevProps.onChangeDroppableAndProvider === nextProps.onChangeDroppableAndProvider && + prevProps.onDataProviderEdited === nextProps.onDataProviderEdited && + prevProps.onDataProviderRemoved === nextProps.onDataProviderRemoved && + prevProps.onToggleDataProviderEnabled === nextProps.onToggleDataProviderEnabled && + prevProps.onToggleDataProviderExcluded === nextProps.onToggleDataProviderExcluded && + prevProps.show === nextProps.show && + prevProps.showCallOutUnauthorizedMsg === nextProps.showCallOutUnauthorizedMsg +); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx index 611d08e61be22..c2a571d8086a7 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx @@ -6,6 +6,7 @@ import { isEmpty, isNumber, get } from 'lodash/fp'; import memoizeOne from 'memoize-one'; +import deepEqual from 'fast-deep-equal'; import { escapeQueryValue, convertToBuildEsQuery } from '../../lib/keury'; @@ -93,65 +94,68 @@ export const buildGlobalQuery = (dataProviders: DataProvider[], browserFields: B }, '') .trim(); -export const combineQueries = ({ - config, - dataProviders, - indexPattern, - browserFields, - filters = [], - kqlQuery, - kqlMode, - start, - end, - isEventViewer, -}: { - config: EsQueryConfig; - dataProviders: DataProvider[]; - indexPattern: IIndexPattern; - browserFields: BrowserFields; - filters: Filter[]; - kqlQuery: Query; - kqlMode: string; - start: number; - end: number; - isEventViewer?: boolean; -}): { filterQuery: string } | null => { - const kuery: Query = { query: '', language: kqlQuery.language }; - if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && isEmpty(filters) && !isEventViewer) { - return null; - } else if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && isEventViewer) { - kuery.query = `@timestamp >= ${start} and @timestamp <= ${end}`; - return { - filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), - }; - } else if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && !isEmpty(filters)) { - kuery.query = `@timestamp >= ${start} and @timestamp <= ${end}`; - return { - filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), - }; - } else if (isEmpty(dataProviders) && !isEmpty(kqlQuery.query)) { - kuery.query = `(${kqlQuery.query}) and @timestamp >= ${start} and @timestamp <= ${end}`; - return { - filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), - }; - } else if (!isEmpty(dataProviders) && isEmpty(kqlQuery)) { - kuery.query = `(${buildGlobalQuery( - dataProviders, - browserFields +export const combineQueries = memoizeOne( + ({ + config, + dataProviders, + indexPattern, + browserFields, + filters = [], + kqlQuery, + kqlMode, + start, + end, + isEventViewer, + }: { + config: EsQueryConfig; + dataProviders: DataProvider[]; + indexPattern: IIndexPattern; + browserFields: BrowserFields; + filters: Filter[]; + kqlQuery: Query; + kqlMode: string; + start: number; + end: number; + isEventViewer?: boolean; + }): { filterQuery: string } | null => { + const kuery: Query = { query: '', language: kqlQuery.language }; + if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && isEmpty(filters) && !isEventViewer) { + return null; + } else if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && isEventViewer) { + kuery.query = `@timestamp >= ${start} and @timestamp <= ${end}`; + return { + filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), + }; + } else if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && !isEmpty(filters)) { + kuery.query = `@timestamp >= ${start} and @timestamp <= ${end}`; + return { + filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), + }; + } else if (isEmpty(dataProviders) && !isEmpty(kqlQuery.query)) { + kuery.query = `(${kqlQuery.query}) and @timestamp >= ${start} and @timestamp <= ${end}`; + return { + filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), + }; + } else if (!isEmpty(dataProviders) && isEmpty(kqlQuery)) { + kuery.query = `(${buildGlobalQuery( + dataProviders, + browserFields + )}) and @timestamp >= ${start} and @timestamp <= ${end}`; + return { + filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), + }; + } + const operatorKqlQuery = kqlMode === 'filter' ? 'and' : 'or'; + const postpend = (q: string) => `${!isEmpty(q) ? ` ${operatorKqlQuery} (${q})` : ''}`; + kuery.query = `((${buildGlobalQuery(dataProviders, browserFields)})${postpend( + kqlQuery.query as string )}) and @timestamp >= ${start} and @timestamp <= ${end}`; return { filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), }; - } - const operatorKqlQuery = kqlMode === 'filter' ? 'and' : 'or'; - const postpend = (q: string) => `${!isEmpty(q) ? ` ${operatorKqlQuery} (${q})` : ''}`; - kuery.query = `((${buildGlobalQuery(dataProviders, browserFields)})${postpend( - kqlQuery.query as string - )}) and @timestamp >= ${start} and @timestamp <= ${end}`; - return { - filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), - }; -}; + }, + deepEqual +); interface CalculateBodyHeightParams { /** The the height of the flyout container, which is typically the entire "page", not including the standard Kibana navigation */ @@ -164,13 +168,15 @@ interface CalculateBodyHeightParams { timelineFooterHeight?: number; } -export const calculateBodyHeight = ({ - flyoutHeight = 0, - flyoutHeaderHeight = 0, - timelineHeaderHeight = 0, - timelineFooterHeight = 0, -}: CalculateBodyHeightParams): number => - flyoutHeight - (flyoutHeaderHeight + timelineHeaderHeight + timelineFooterHeight); +export const calculateBodyHeight = memoizeOne( + ({ + flyoutHeight = 0, + flyoutHeaderHeight = 0, + timelineHeaderHeight = 0, + timelineFooterHeight = 0, + }: CalculateBodyHeightParams): number => + flyoutHeight - (flyoutHeaderHeight + timelineHeaderHeight + timelineFooterHeight) +); /** * The CSS class name of a "stateful event", which appears in both 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 0ce6bc16f1325..24bf36b954afe 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx @@ -8,7 +8,7 @@ import React, { useEffect, useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import deepEqual from 'fast-deep-equal'; -import { WithSource } from '../../containers/source'; +import { useWithSource } from '../../containers/source'; import { useSignalIndex } from '../../containers/detection_engine/signals/use_signal_index'; import { inputsModel, inputsSelectors, State, timelineSelectors } from '../../store'; import { timelineActions } from '../../store/actions'; @@ -34,6 +34,8 @@ export interface OwnProps { type Props = OwnProps & PropsFromRedux; +const EMPTY_INDEX_TO_ADD: string[] = []; + const StatefulTimelineComponent = React.memo( ({ columns, @@ -75,7 +77,7 @@ const StatefulTimelineComponent = React.memo( ) { return [signalIndexName]; } - return []; + return EMPTY_INDEX_TO_ADD; }, [eventType, signalIndexExists, signalIndexName]); const onDataProviderRemoved: OnDataProviderRemoved = useCallback( @@ -163,42 +165,40 @@ const StatefulTimelineComponent = React.memo( } }, []); + const { indexPattern, browserFields } = useWithSource(indexToAdd); + return ( - - {({ indexPattern, browserFields }) => ( - - )} - + ); }, (prevProps, nextProps) => { 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 87061bdbb5d02..614085d87c76e 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 @@ -228,7 +228,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateReduxTime: dispatchUpdateReduxTime(dispatch), }); -export const connector = connect(makeMapStateToProps, mapDispatchToProps); +const connector = connect(makeMapStateToProps, mapDispatchToProps); type PropsFromRedux = ConnectedProps; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx index 4c5238d213e43..6bfb775496396 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx @@ -6,7 +6,7 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; import useResizeObserver from 'use-resize-observer/polyfilled'; import { timelineQuery } from '../../containers/timeline/index.gql_query'; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx index 58bbbef328ddf..fe6fad6ed0bca 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx @@ -6,7 +6,7 @@ import { EuiFlexGroup } from '@elastic/eui'; import { getOr, isEmpty } from 'lodash/fp'; -import React from 'react'; +import React, { useMemo } from 'react'; import styled from 'styled-components'; import useResizeObserver from 'use-resize-observer/polyfilled'; @@ -121,6 +121,12 @@ export const TimelineComponent: React.FC = ({ const { ref: measureRef, width = 0, height: timelineHeaderHeight = 0 } = useResizeObserver< HTMLDivElement >({}); + const bodyHeight = calculateBodyHeight({ + flyoutHeight, + flyoutHeaderHeight, + timelineHeaderHeight, + timelineFooterHeight: footerHeight, + }); const kibana = useKibana(); const combinedQueries = combineQueries({ config: esQuery.getEsQueryConfig(kibana.services.uiSettings), @@ -133,7 +139,14 @@ export const TimelineComponent: React.FC = ({ start, end, }); - const columnsHeader = isEmpty(columns) ? defaultHeaders : columns; + const sortField = { + sortFieldId: sort.columnId, + direction: sort.sortDirection as Direction, + }; + const timelineQueryFields = useMemo(() => { + const columnsHeader = isEmpty(columns) ? defaultHeaders : columns; + return columnsHeader.map(c => c.id); + }, [columns]); return ( = ({ eventType={eventType} id={id} indexToAdd={indexToAdd} - fields={columnsHeader.map(c => c.id)} + fields={timelineQueryFields} sourceId="default" limit={itemsPerPage} filterQuery={combinedQueries.filterQuery} - sortField={{ - sortFieldId: sort.columnId, - direction: sort.sortDirection as Direction, - }} + sortField={sortField} > {({ events, @@ -196,12 +206,7 @@ export const TimelineComponent: React.FC = ({ browserFields={browserFields} data={events} id={id} - height={calculateBodyHeight({ - flyoutHeight, - flyoutHeaderHeight, - timelineHeaderHeight, - timelineFooterHeight: footerHeight, - })} + height={bodyHeight} sort={sort} toggleColumn={toggleColumn} /> diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/url_state/index.test.tsx index 10aa388449d91..879c7f4553bc6 100644 --- a/x-pack/legacy/plugins/siem/public/components/url_state/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/url_state/index.test.tsx @@ -6,6 +6,7 @@ import { mount } from 'enzyme'; import React from 'react'; +import { MockedProvider } from '@apollo/client/testing'; import { HookWrapper } from '../../mock'; import { SiemPageName } from '../../pages/home/types'; @@ -72,7 +73,11 @@ describe('UrlStateContainer', () => { pageName, detailName, }).relativeTimeSearch.undefinedQuery; - mount( useUrlStateHooks(args)} />); + mount( + + useUrlStateHooks(args)} /> + + ); expect(mockSetRelativeRangeDatePicker.mock.calls[1][0]).toEqual({ from: 11223344556677, @@ -101,7 +106,11 @@ describe('UrlStateContainer', () => { (page, namespaceLower, namespaceUpper, examplePath, type, pageName, detailName) => { mockProps = getMockPropsObj({ page, examplePath, namespaceLower, pageName, detailName }) .absoluteTimeSearch.undefinedQuery; - mount( useUrlStateHooks(args)} />); + mount( + + useUrlStateHooks(args)} /> + + ); expect(mockSetAbsoluteRangeDatePicker.mock.calls[1][0]).toEqual({ from: 1556736012685, @@ -126,7 +135,11 @@ describe('UrlStateContainer', () => { (page, namespaceLower, namespaceUpper, examplePath, type, pageName, detailName) => { mockProps = getMockPropsObj({ page, examplePath, namespaceLower, pageName, detailName }) .relativeTimeSearch.undefinedQuery; - mount( useUrlStateHooks(args)} />); + mount( + + useUrlStateHooks(args)} /> + + ); expect(mockSetFilterQuery.mock.calls[0][0]).toEqual({ id: 'global', @@ -150,7 +163,11 @@ describe('UrlStateContainer', () => { pageName, detailName, }).noSearch.definedQuery; - mount( useUrlStateHooks(args)} />); + mount( + + useUrlStateHooks(args)} /> + + ); expect( mockHistory.replace.mock.calls[mockHistory.replace.mock.calls.length - 1][0] @@ -180,7 +197,9 @@ describe('UrlStateContainer', () => { detailName, }).relativeTimeSearch.undefinedQuery; const wrapper = mount( - useUrlStateHooks(args)} /> + + useUrlStateHooks(args)} /> + ); wrapper.setProps({ diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx b/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx index 294e41a1faa7b..362a398999393 100644 --- a/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx @@ -52,4 +52,4 @@ const UseUrlStateComponent: React.FC = props => { return ; }; -export const UseUrlState = React.memo(UseUrlStateComponent); +export const UseUrlState = React.memo(UseUrlStateComponent, deepEqual); diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/index_mocked.test.tsx b/x-pack/legacy/plugins/siem/public/components/url_state/index_mocked.test.tsx index 4adc17b32e189..60c253dcaf936 100644 --- a/x-pack/legacy/plugins/siem/public/components/url_state/index_mocked.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/url_state/index_mocked.test.tsx @@ -6,6 +6,7 @@ import { mount } from 'enzyme'; import React from 'react'; +import { MockedProvider } from '@apollo/client/testing'; import { HookWrapper } from '../../mock/hook_wrapper'; import { SiemPageName } from '../../pages/home/types'; @@ -46,7 +47,8 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => detailName: undefined, }).noSearch.definedQuery; const wrapper = mount( - useUrlStateHooks(args)} /> + useUrlStateHooks(args)} />, + { wrappingComponent: MockedProvider } ); const newUrlState = { @@ -97,7 +99,8 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => detailName: undefined, }).noSearch.undefinedQuery; const wrapper = mount( - useUrlStateHooks(args)} /> + useUrlStateHooks(args)} />, + { wrappingComponent: MockedProvider } ); const newUrlState = { ...mockProps.urlState, @@ -129,7 +132,8 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => }).noSearch.undefinedQuery; const wrapper = mount( - useUrlStateHooks(args)} /> + useUrlStateHooks(args)} />, + { wrappingComponent: MockedProvider } ); const newUrlState = { ...mockProps.urlState, @@ -161,7 +165,9 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => (page, namespaceLower, namespaceUpper, examplePath, type, pageName, detailName) => { mockProps = getMockPropsObj({ page, examplePath, namespaceLower, pageName, detailName }) .noSearch.undefinedQuery; - mount( useUrlStateHooks(args)} />); + mount( useUrlStateHooks(args)} />, { + wrappingComponent: MockedProvider, + }); expect(mockHistory.replace.mock.calls[0][0]).toEqual({ hash: '', @@ -198,7 +204,8 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => detailName: undefined, }).noSearch.definedQuery; const wrapper = mount( - useUrlStateHooks(args)} /> + useUrlStateHooks(args)} />, + { wrappingComponent: MockedProvider } ); expect( diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/types.ts b/x-pack/legacy/plugins/siem/public/components/url_state/types.ts index 2cb1b0c96ad79..ebd18cdd31732 100644 --- a/x-pack/legacy/plugins/siem/public/components/url_state/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/url_state/types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import ApolloClient from 'apollo-client'; +import { ApolloClient } from '@apollo/client'; import * as H from 'history'; import { ActionCreator } from 'typescript-fsa'; import { @@ -88,9 +88,6 @@ export type KeyUrlState = keyof UrlState; export interface UrlStateProps { navTabs: Record; indexPattern?: IIndexPattern; - mapToUrlState?: (value: string) => UrlState; - onChange?: (urlState: UrlState, previousUrlState: UrlState) => void; - onInitialize?: (urlState: UrlState) => void; } export interface UrlStateStateToPropsType { diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx b/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx index a7704e0e86970..9d4d42e681a75 100644 --- a/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx +++ b/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx @@ -6,10 +6,10 @@ import { difference, isEmpty } from 'lodash/fp'; import { useEffect, useRef, useState } from 'react'; +import { useApolloClient } from '@apollo/client'; import deepEqual from 'fast-deep-equal'; import { useKibana } from '../../lib/kibana'; -import { useApolloClient } from '../../utils/apollo_context'; import { CONSTANTS, UrlStateType } from './constants'; import { getQueryStringFromLocation, diff --git a/x-pack/legacy/plugins/siem/public/containers/authentications/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/authentications/index.gql_query.ts index eee35730cfdbb..1e0b080af4cf1 100644 --- a/x-pack/legacy/plugins/siem/public/containers/authentications/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/authentications/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const authenticationsQuery = gql` query GetAuthenticationsQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/authentications/index.tsx b/x-pack/legacy/plugins/siem/public/containers/authentications/index.tsx index 6d4a88c45a768..5ada3f171e96c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/authentications/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/authentications/index.tsx @@ -6,7 +6,6 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect } from 'react-redux'; import { compose } from 'redux'; @@ -14,6 +13,7 @@ import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { AuthenticationsEdges, GetAuthenticationsQuery, + GetAuthenticationsQueryComponent, PageInfoPaginated, } from '../../graphql/types'; import { hostsModel, hostsSelectors, inputsModel, State, inputsSelectors } from '../../store'; @@ -22,8 +22,6 @@ import { generateTablePaginationOptions } from '../../components/paginated_table import { withKibana, WithKibanaProps } from '../../lib/kibana'; import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; -import { authenticationsQuery } from './index.gql_query'; - const ID = 'authenticationQuery'; export interface AuthenticationArgs { @@ -39,7 +37,7 @@ export interface AuthenticationArgs { } export interface OwnProps extends QueryTemplatePaginatedProps { - children: (args: AuthenticationArgs) => React.ReactNode; + children: (args: AuthenticationArgs) => React.ReactElement; type: hostsModel.HostsType; } @@ -83,8 +81,7 @@ class AuthenticationsComponentQuery extends QueryTemplatePaginated< inspect: isInspected, }; return ( - - query={authenticationsQuery} + + ); } } diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.test.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.test.tsx index cad78ac565903..bf5e60847a045 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.test.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.test.tsx @@ -5,15 +5,15 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; +import { useApolloClient } from '@apollo/client'; import { defaultIndexPattern } from '../../../../default_index_pattern'; -import { useApolloClient } from '../../../utils/apollo_context'; import { mocksSource } from '../../source/mock'; import { useFetchIndexPatterns, Return } from './fetch_index_patterns'; const mockUseApolloClient = useApolloClient as jest.Mock; -jest.mock('../../../utils/apollo_context'); +jest.mock('@apollo/client'); describe('useFetchIndexPatterns', () => { beforeEach(() => { diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx index 06c4d1054bca4..1aee0e4c36807 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx @@ -6,6 +6,7 @@ import { isEmpty, get } from 'lodash/fp'; import { useEffect, useState, Dispatch, SetStateAction } from 'react'; +import { useApolloClient } from '@apollo/client'; import deepEqual from 'fast-deep-equal'; import { IIndexPattern } from '../../../../../../../../src/plugins/data/public'; @@ -18,7 +19,6 @@ import { import { useStateToaster } from '../../../components/toasters'; import { errorToToaster } from '../../../components/ml/api/error_to_toaster'; import { SourceQuery } from '../../../graphql/types'; -import { useApolloClient } from '../../../utils/apollo_context'; import * as i18n from './translations'; diff --git a/x-pack/legacy/plugins/siem/public/containers/errors/index.test.tsx b/x-pack/legacy/plugins/siem/public/containers/errors/index.test.tsx index e1b192df104d7..81ccb76c83fb5 100644 --- a/x-pack/legacy/plugins/siem/public/containers/errors/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/errors/index.test.tsx @@ -5,8 +5,7 @@ */ import { reTryOneTimeOnErrorHandler, errorLinkHandler } from '.'; -import { ServerError } from 'apollo-link-http-common'; -import { Operation } from 'apollo-link'; +import { ServerError, Operation } from '@apollo/client'; import { GraphQLError } from 'graphql'; import * as store from '../../store'; import { onError } from 'apollo-link-error'; diff --git a/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/index.ts b/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/index.ts index 9cae503d30940..b4ec108c69922 100644 --- a/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/index.ts +++ b/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/index.ts @@ -5,16 +5,18 @@ */ import { get } from 'lodash/fp'; -import React, { useEffect, useState } from 'react'; +import { FetchPolicy } from '@apollo/client'; import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; -import { GetLastEventTimeQuery, LastEventIndexKey, LastTimeDetails } from '../../../graphql/types'; +import { + LastEventIndexKey, + LastTimeDetails, + useGetLastEventTimeQueryQuery, +} from '../../../graphql/types'; import { inputsModel } from '../../../store'; -import { QueryTemplateProps } from '../../query_template'; import { useUiSetting$ } from '../../../lib/kibana'; import { LastEventTimeGqlQuery } from './last_event_time.gql_query'; -import { useApolloClient } from '../../../utils/apollo_context'; export interface LastEventTimeArgs { id: string; @@ -24,63 +26,29 @@ export interface LastEventTimeArgs { refetch: inputsModel.Refetch; } -export interface OwnProps extends QueryTemplateProps { - children: (args: LastEventTimeArgs) => React.ReactNode; - indexKey: LastEventIndexKey; -} - -export function useLastEventTimeQuery( +export const useLastEventTimeQuery = ( indexKey: LastEventIndexKey, details: LastTimeDetails, sourceId: string -) { - const [loading, updateLoading] = useState(false); - const [lastSeen, updateLastSeen] = useState(null); - const [errorMessage, updateErrorMessage] = useState(null); - const [currentIndexKey, updateCurrentIndexKey] = useState(null); +) => { const [defaultIndex] = useUiSetting$(DEFAULT_INDEX_KEY); - const apolloClient = useApolloClient(); - async function fetchLastEventTime(signal: AbortSignal) { - updateLoading(true); - if (apolloClient) { - apolloClient - .query({ - query: LastEventTimeGqlQuery, - fetchPolicy: 'cache-first', - variables: { - sourceId, - indexKey, - details, - defaultIndex, - }, - context: { - fetchOptions: { - signal, - }, - }, - }) - .then( - result => { - updateLoading(false); - updateLastSeen(get('data.source.LastEventTime.lastSeen', result)); - updateErrorMessage(null); - updateCurrentIndexKey(currentIndexKey); - }, - error => { - updateLoading(false); - updateLastSeen(null); - updateErrorMessage(error.message); - } - ); - } - } - - useEffect(() => { - const abortCtrl = new AbortController(); - const signal = abortCtrl.signal; - fetchLastEventTime(signal); - return () => abortCtrl.abort(); - }, [apolloClient, indexKey, details.hostName, details.ip]); - - return { lastSeen, loading, errorMessage }; -} + const options = { + query: LastEventTimeGqlQuery, + fetchPolicy: 'cache-first' as FetchPolicy, + variables: { + sourceId, + indexKey, + details, + defaultIndex, + }, + }; + + const { data, loading, error } = useGetLastEventTimeQueryQuery(options); + const lastSeen = get('source.LastEventTime.lastSeen', data); + + return { + lastSeen, + loading, + errorMessage: error?.message, + }; +}; diff --git a/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/last_event_time.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/last_event_time.gql_query.ts index 049c73b607b7e..22f56014cfb46 100644 --- a/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/last_event_time.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/last_event_time.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const LastEventTimeGqlQuery = gql` query GetLastEventTimeQuery( 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 ca8786077851f..5e7f473b87748 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 @@ -4,16 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +import { MockedResponse } from '@apollo/client/testing'; + import { defaultIndexPattern } from '../../../../default_index_pattern'; -import { GetLastEventTimeQuery, LastEventIndexKey } from '../../../graphql/types'; +import { LastEventIndexKey } from '../../../graphql/types'; import { LastEventTimeGqlQuery } from './last_event_time.gql_query'; -interface MockLastEventTimeQuery { - request: { - query: GetLastEventTimeQuery.Query; - variables: GetLastEventTimeQuery.Variables; - }; +interface MockLastEventTimeQuery extends MockedResponse { result: { data?: { source: { @@ -24,7 +22,6 @@ interface MockLastEventTimeQuery { }; }; }; - errors?: [{ message: string }]; }; } diff --git a/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx b/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx index 4632e9aee3fdd..14cdc65ee7bb0 100644 --- a/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useCallback, useState, useEffect } from 'react'; -import { connect, ConnectedProps } from 'react-redux'; +import { useCallback, useState, useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; -import { inputsModel, inputsSelectors, State } from '../../store'; +import { inputsModel, inputsSelectors } from '../../store'; import { inputsActions } from '../../store/actions'; interface SetQuery { @@ -25,31 +25,24 @@ export interface GlobalTimeArgs { isInitializing: boolean; } -interface OwnProps { - children: (args: GlobalTimeArgs) => React.ReactNode; -} - -type GlobalTimeProps = OwnProps & PropsFromRedux; - -export const GlobalTimeComponent: React.FC = ({ - children, - deleteAllQuery, - deleteOneQuery, - from, - to, - setGlobalQuery, -}) => { +export const useGlobalTime = () => { const [isInitializing, setIsInitializing] = useState(true); + const dispatch = useDispatch(); + const { from, to } = useSelector(inputsSelectors.globalTimeRangeSelector); + + const deleteAllQuery = useCallback(props => dispatch(inputsActions.deleteAllQuery(props)), [ + dispatch, + ]); const setQuery = useCallback( ({ id, inspect, loading, refetch }: SetQuery) => - setGlobalQuery({ inputId: 'global', id, inspect, loading, refetch }), - [setGlobalQuery] + dispatch(inputsActions.setQuery({ inputId: 'global', id, inspect, loading, refetch })), + [dispatch] ); const deleteQuery = useCallback( - ({ id }: { id: string }) => deleteOneQuery({ inputId: 'global', id }), - [deleteOneQuery] + ({ id }: { id: string }) => dispatch(inputsActions.deleteOneQuery({ inputId: 'global', id })), + [dispatch] ); useEffect(() => { @@ -59,37 +52,13 @@ export const GlobalTimeComponent: React.FC = ({ return () => { deleteAllQuery({ id: 'global' }); }; - }, []); - - return ( - <> - {children({ - isInitializing, - from, - to, - setQuery, - deleteQuery, - })} - - ); -}; + }, [isInitializing, deleteAllQuery]); -const mapStateToProps = (state: State) => { - const timerange: inputsModel.TimeRange = inputsSelectors.globalTimeRangeSelector(state); return { - from: timerange.from, - to: timerange.to, + isInitializing, + from, + to, + setQuery, + deleteQuery, }; }; - -const mapDispatchToProps = { - deleteAllQuery: inputsActions.deleteAllQuery, - deleteOneQuery: inputsActions.deleteOneQuery, - setGlobalQuery: inputsActions.setQuery, -}; - -export const connector = connect(mapStateToProps, mapDispatchToProps); - -type PropsFromRedux = ConnectedProps; - -export const GlobalTime = connector(React.memo(GlobalTimeComponent)); diff --git a/x-pack/legacy/plugins/siem/public/containers/helpers.ts b/x-pack/legacy/plugins/siem/public/containers/helpers.ts index 5f66e3f4b88d4..a43c1c066db73 100644 --- a/x-pack/legacy/plugins/siem/public/containers/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/containers/helpers.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { FetchPolicy } from 'apollo-client'; +import { WatchQueryFetchPolicy } from '@apollo/client'; import { isString } from 'lodash/fp'; import { ESQuery } from '../../common/typed_json'; @@ -12,4 +12,4 @@ import { ESQuery } from '../../common/typed_json'; export const createFilter = (filterQuery: ESQuery | string | undefined) => isString(filterQuery) ? filterQuery : JSON.stringify(filterQuery); -export const getDefaultFetchPolicy = (): FetchPolicy => 'cache-and-network'; +export const getDefaultFetchPolicy = (): WatchQueryFetchPolicy => 'cache-and-network'; diff --git a/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/first_last_seen.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/first_last_seen.gql_query.ts index 7db4f138c7794..1a794bb53bdf7 100644 --- a/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/first_last_seen.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/first_last_seen.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const HostFirstLastSeenGqlQuery = gql` query GetHostFirstLastSeenQuery($sourceId: ID!, $hostName: String!, $defaultIndex: [String!]!) { diff --git a/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/index.ts b/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/index.ts index e36da5bfbe4ee..2fb60ebce86f7 100644 --- a/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/index.ts +++ b/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import ApolloClient from 'apollo-client'; +import { useApolloClient } from '@apollo/client'; import { get } from 'lodash/fp'; import React, { useEffect, useState } from 'react'; @@ -26,19 +26,16 @@ export interface FirstLastSeenHostArgs { } export interface OwnProps extends QueryTemplateProps { - children: (args: FirstLastSeenHostArgs) => React.ReactNode; + children: (args: FirstLastSeenHostArgs) => React.ReactElement; hostName: string; } -export function useFirstLastSeenHostQuery( - hostName: string, - sourceId: string, - apolloClient: ApolloClient -) { +export function useFirstLastSeenHostQuery(hostName: string, sourceId: string) { const [loading, updateLoading] = useState(false); const [firstSeen, updateFirstSeen] = useState(null); const [lastSeen, updateLastSeen] = useState(null); const [errorMessage, updateErrorMessage] = useState(null); + const apolloClient = useApolloClient(); const [defaultIndex] = useUiSetting$(DEFAULT_INDEX_KEY); async function fetchFirstLastSeenHost(signal: AbortSignal) { diff --git a/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/mock.ts b/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/mock.ts index 2c9d418763e8e..22080c7a86101 100644 --- a/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/mock.ts +++ b/x-pack/legacy/plugins/siem/public/containers/hosts/first_last_seen/mock.ts @@ -4,16 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ +import { MockedResponse } from '@apollo/client/testing'; import { defaultIndexPattern } from '../../../../default_index_pattern'; -import { GetHostFirstLastSeenQuery } from '../../../graphql/types'; import { HostFirstLastSeenGqlQuery } from './first_last_seen.gql_query'; -interface MockedProvidedQuery { - request: { - query: GetHostFirstLastSeenQuery.Query; - variables: GetHostFirstLastSeenQuery.Variables; - }; +interface MockedProvidedQuery extends MockedResponse { result: { data?: { source: { @@ -24,9 +20,9 @@ interface MockedProvidedQuery { }; }; }; - errors?: [{ message: string }]; }; } + export const mockFirstLastSeenHostQuery: MockedProvidedQuery[] = [ { request: { diff --git a/x-pack/legacy/plugins/siem/public/containers/hosts/hosts_table.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/hosts/hosts_table.gql_query.ts index 672ea70b09ad2..555d4ede5bfcd 100644 --- a/x-pack/legacy/plugins/siem/public/containers/hosts/hosts_table.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/hosts/hosts_table.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const HostsTableQuery = gql` query GetHostsTableQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/hosts/index.tsx b/x-pack/legacy/plugins/siem/public/containers/hosts/index.tsx index 733c2224d840a..ccd51534ec794 100644 --- a/x-pack/legacy/plugins/siem/public/containers/hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/hosts/index.tsx @@ -7,7 +7,6 @@ import { get, getOr } from 'lodash/fp'; import memoizeOne from 'memoize-one'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect } from 'react-redux'; import { compose } from 'redux'; @@ -15,6 +14,7 @@ import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { Direction, GetHostsTableQuery, + GetHostsTableQueryComponent, HostsEdges, HostsFields, PageInfoPaginated, @@ -24,7 +24,6 @@ import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; import { withKibana, WithKibanaProps } from '../../lib/kibana'; -import { HostsTableQuery } from './hosts_table.gql_query'; import { generateTablePaginationOptions } from '../../components/paginated_table/helpers'; const ID = 'hostsQuery'; @@ -44,7 +43,7 @@ export interface HostsArgs { } export interface OwnProps extends QueryTemplatePaginatedProps { - children: (args: HostsArgs) => React.ReactNode; + children: (args: HostsArgs) => React.ReactElement; type: hostsModel.HostsType; startDate: number; endDate: number; @@ -110,8 +109,7 @@ class HostsComponentQuery extends QueryTemplatePaginated< inspect: isInspected, }; return ( - - query={HostsTableQuery} + + ); } diff --git a/x-pack/legacy/plugins/siem/public/containers/hosts/overview/host_overview.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/hosts/overview/host_overview.gql_query.ts index 46794816dbf2a..7427352b49523 100644 --- a/x-pack/legacy/plugins/siem/public/containers/hosts/overview/host_overview.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/hosts/overview/host_overview.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const HostOverviewQuery = gql` query GetHostOverviewQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/hosts/overview/index.tsx b/x-pack/legacy/plugins/siem/public/containers/hosts/overview/index.tsx index 5057e872b5313..14e2591f5650b 100644 --- a/x-pack/legacy/plugins/siem/public/containers/hosts/overview/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/hosts/overview/index.tsx @@ -6,7 +6,6 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect } from 'react-redux'; import { compose } from 'redux'; @@ -16,8 +15,11 @@ import { getDefaultFetchPolicy } from '../../helpers'; import { QueryTemplate, QueryTemplateProps } from '../../query_template'; import { withKibana, WithKibanaProps } from '../../../lib/kibana'; -import { HostOverviewQuery } from './host_overview.gql_query'; -import { GetHostOverviewQuery, HostItem } from '../../../graphql/types'; +import { + GetHostOverviewQuery, + GetHostOverviewQueryComponent, + HostItem, +} from '../../../graphql/types'; const ID = 'hostOverviewQuery'; @@ -36,7 +38,7 @@ export interface HostOverviewReduxProps { } export interface OwnProps extends QueryTemplateProps { - children: (args: HostOverviewArgs) => React.ReactNode; + children: (args: HostOverviewArgs) => React.ReactElement; hostName: string; startDate: number; endDate: number; @@ -62,8 +64,7 @@ class HostOverviewByNameComponentQuery extends QueryTemplate< endDate, } = this.props; return ( - - query={HostOverviewQuery} + + ); } } diff --git a/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.gql_query.ts index 3733cd780a4f7..875413f4cac0d 100644 --- a/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const ipOverviewQuery = gql` query GetIpOverviewQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx b/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx index ade94c430c6ef..9d83af620b730 100644 --- a/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx @@ -6,18 +6,15 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; -import { GetIpOverviewQuery, IpOverviewData } from '../../graphql/types'; +import { GetIpOverviewQueryComponent, IpOverviewData } from '../../graphql/types'; import { networkModel, inputsModel, inputsSelectors, State } from '../../store'; import { useUiSetting } from '../../lib/kibana'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplateProps } from '../query_template'; -import { ipOverviewQuery } from './index.gql_query'; - const ID = 'ipOverviewQuery'; export interface IpOverviewArgs { @@ -29,15 +26,14 @@ export interface IpOverviewArgs { } export interface IpOverviewProps extends QueryTemplateProps { - children: (args: IpOverviewArgs) => React.ReactNode; + children: (args: IpOverviewArgs) => React.ReactElement; type: networkModel.NetworkType; ip: string; } const IpOverviewComponentQuery = React.memo( ({ id = ID, isInspected, children, filterQuery, skip, sourceId, ip }) => ( - - query={ipOverviewQuery} + ( refetch, }); }} - + ) ); diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.gql_query.tsx b/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.gql_query.ts similarity index 97% rename from x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.gql_query.tsx rename to x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.gql_query.ts index 077f49c4bdfa6..3b847d1b71560 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.gql_query.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const kpiHostDetailsQuery = gql` fragment KpiHostDetailsChartFields on KpiHostHistogramData { diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx b/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx index de9d54b1a185c..1568cf60586d7 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx @@ -6,18 +6,15 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; -import { KpiHostDetailsData, GetKpiHostDetailsQuery } from '../../graphql/types'; +import { KpiHostDetailsData, GetKpiHostDetailsQueryComponent } from '../../graphql/types'; import { inputsModel, inputsSelectors, State } from '../../store'; import { useUiSetting } from '../../lib/kibana'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplateProps } from '../query_template'; -import { kpiHostDetailsQuery } from './index.gql_query'; - const ID = 'kpiHostDetailsQuery'; export interface KpiHostDetailsArgs { @@ -29,13 +26,12 @@ export interface KpiHostDetailsArgs { } export interface QueryKpiHostDetailsProps extends QueryTemplateProps { - children: (args: KpiHostDetailsArgs) => React.ReactNode; + children: (args: KpiHostDetailsArgs) => React.ReactElement; } const KpiHostDetailsComponentQuery = React.memo( ({ id = ID, children, endDate, filterQuery, isInspected, skip, sourceId, startDate }) => ( - - query={kpiHostDetailsQuery} + + ) ); diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.gql_query.ts index 37d54455db1fd..e359adf2a354f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const kpiHostsQuery = gql` fragment KpiHostChartFields on KpiHostHistogramData { diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx b/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx index 5be2423e8a162..543a2b6035b81 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx @@ -6,18 +6,15 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; -import { GetKpiHostsQuery, KpiHostsData } from '../../graphql/types'; +import { GetKpiHostsQueryComponent, KpiHostsData } from '../../graphql/types'; import { inputsModel, inputsSelectors, State } from '../../store'; import { useUiSetting } from '../../lib/kibana'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplateProps } from '../query_template'; -import { kpiHostsQuery } from './index.gql_query'; - const ID = 'kpiHostsQuery'; export interface KpiHostsArgs { @@ -29,13 +26,12 @@ export interface KpiHostsArgs { } export interface KpiHostsProps extends QueryTemplateProps { - children: (args: KpiHostsArgs) => React.ReactNode; + children: (args: KpiHostsArgs) => React.ReactElement; } const KpiHostsComponentQuery = React.memo( ({ id = ID, children, endDate, filterQuery, isInspected, skip, sourceId, startDate }) => ( - - query={kpiHostsQuery} + ( refetch, }); }} - + ) ); diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.gql_query.ts index 3c693f08b45f2..90f773fad229c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const kpiNetworkQuery = gql` fragment KpiNetworkChartFields on KpiNetworkHistogramData { diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx b/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx index 338cdc39b178c..019cc718fd5be 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx @@ -6,18 +6,15 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; -import { GetKpiNetworkQuery, KpiNetworkData } from '../../graphql/types'; +import { GetKpiNetworkQueryComponent, KpiNetworkData } from '../../graphql/types'; import { inputsModel, inputsSelectors, State } from '../../store'; import { useUiSetting } from '../../lib/kibana'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplateProps } from '../query_template'; -import { kpiNetworkQuery } from './index.gql_query'; - const ID = 'kpiNetworkQuery'; export interface KpiNetworkArgs { @@ -29,13 +26,12 @@ export interface KpiNetworkArgs { } export interface KpiNetworkProps extends QueryTemplateProps { - children: (args: KpiNetworkArgs) => React.ReactNode; + children: (args: KpiNetworkArgs) => React.ReactElement; } const KpiNetworkComponentQuery = React.memo( ({ id = ID, children, filterQuery, isInspected, skip, sourceId, startDate, endDate }) => ( - - query={kpiNetworkQuery} + ( refetch, }); }} - + ) ); diff --git a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.gql_query.ts index 6fb729ca7e9a0..8c032c17a6b95 100644 --- a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const MatrixHistogramGqlQuery = gql` query GetMatrixHistogramQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.test.tsx b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.test.tsx index 06367ab8657a8..141d986c5188b 100644 --- a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.test.tsx @@ -7,7 +7,8 @@ import { useQuery } from '.'; import { mount } from 'enzyme'; import React from 'react'; -import { useApolloClient } from '../../utils/apollo_context'; +import { useApolloClient } from '@apollo/client'; + import { errorToToaster } from '../../components/ml/api/error_to_toaster'; import { MatrixOverTimeHistogramData, HistogramType } from '../../graphql/types'; import { InspectQuery, Refetch } from '../../store/inputs/model'; @@ -25,7 +26,7 @@ const mockQuery = jest.fn().mockResolvedValue({ }); const mockRejectQuery = jest.fn().mockRejectedValue(new Error()); -jest.mock('../../utils/apollo_context', () => ({ +jest.mock('@apollo/client', () => ({ useApolloClient: jest.fn(), })); diff --git a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.ts b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.ts index 683d5b68c305b..c995e5065a3ec 100644 --- a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.ts +++ b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.ts @@ -4,13 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ import { useEffect, useState, useRef } from 'react'; +import { useApolloClient } from '@apollo/client'; + import { MatrixHistogramQueryProps } from '../../components/matrix_histogram/types'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { useStateToaster } from '../../components/toasters'; import { errorToToaster } from '../../components/ml/api/error_to_toaster'; import { useUiSetting$ } from '../../lib/kibana'; import { createFilter } from '../helpers'; -import { useApolloClient } from '../../utils/apollo_context'; import { inputsModel } from '../../store'; import { MatrixHistogramGqlQuery } from './index.gql_query'; import { GetMatrixHistogramQuery, MatrixOverTimeHistogramData } from '../../graphql/types'; diff --git a/x-pack/legacy/plugins/siem/public/containers/network_dns/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/network_dns/index.gql_query.ts index a81d112fa4c50..ad272466d2370 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_dns/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/network_dns/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const networkDnsQuery = gql` query GetNetworkDnsQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/network_dns/index.tsx b/x-pack/legacy/plugins/siem/public/containers/network_dns/index.tsx index 04c8783c30a0f..da6aeb34d33c6 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_dns/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/network_dns/index.tsx @@ -6,7 +6,6 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect } from 'react-redux'; import { compose } from 'redux'; @@ -15,6 +14,7 @@ import { ScaleType } from '@elastic/charts'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetNetworkDnsQuery, + GetNetworkDnsQueryComponent, NetworkDnsEdges, NetworkDnsSortField, PageInfoPaginated, @@ -25,7 +25,6 @@ import { withKibana, WithKibanaProps } from '../../lib/kibana'; import { generateTablePaginationOptions } from '../../components/paginated_table/helpers'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; -import { networkDnsQuery } from './index.gql_query'; import { DEFAULT_TABLE_ACTIVE_PAGE, DEFAULT_TABLE_LIMIT } from '../../store/constants'; import { MatrixHistogram } from '../../components/matrix_histogram'; import { MatrixHistogramOption, GetSubTitle } from '../../components/matrix_histogram/types'; @@ -49,7 +48,7 @@ export interface NetworkDnsArgs { } export interface OwnProps extends QueryTemplatePaginatedProps { - children: (args: NetworkDnsArgs) => React.ReactNode; + children: (args: NetworkDnsArgs) => React.ReactElement; type: networkModel.NetworkType; } @@ -117,10 +116,9 @@ export class NetworkDnsComponentQuery extends QueryTemplatePaginated< }; return ( - + @@ -161,7 +159,7 @@ export class NetworkDnsComponentQuery extends QueryTemplatePaginated< histogram: getOr(null, 'source.NetworkDns.histogram', data), }); }} - + ); } } diff --git a/x-pack/legacy/plugins/siem/public/containers/network_http/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/network_http/index.gql_query.ts index bedf13dfa9849..b084fe846dca2 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_http/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/network_http/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const networkHttpQuery = gql` query GetNetworkHttpQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/network_http/index.tsx b/x-pack/legacy/plugins/siem/public/containers/network_http/index.tsx index bf4e64f63d559..1f0759d25e870 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_http/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/network_http/index.tsx @@ -6,13 +6,13 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect } from 'react-redux'; import { compose } from 'redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetNetworkHttpQuery, + GetNetworkHttpQueryComponent, NetworkHttpEdges, NetworkHttpSortField, PageInfoPaginated, @@ -22,7 +22,6 @@ import { withKibana, WithKibanaProps } from '../../lib/kibana'; import { generateTablePaginationOptions } from '../../components/paginated_table/helpers'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; -import { networkHttpQuery } from './index.gql_query'; const ID = 'networkHttpQuery'; @@ -40,7 +39,7 @@ export interface NetworkHttpArgs { } export interface OwnProps extends QueryTemplatePaginatedProps { - children: (args: NetworkHttpArgs) => React.ReactNode; + children: (args: NetworkHttpArgs) => React.ReactElement; ip?: string; type: networkModel.NetworkType; } @@ -90,10 +89,9 @@ class NetworkHttpComponentQuery extends QueryTemplatePaginated< }, }; return ( - + @@ -133,7 +131,7 @@ class NetworkHttpComponentQuery extends QueryTemplatePaginated< totalCount: getOr(-1, 'source.NetworkHttp.totalCount', data), }); }} - + ); } } diff --git a/x-pack/legacy/plugins/siem/public/containers/network_top_countries/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/network_top_countries/index.gql_query.ts index 5850246ceecec..4c647d910ebd6 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_top_countries/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/network_top_countries/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const networkTopCountriesQuery = gql` query GetNetworkTopCountriesQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/network_top_countries/index.tsx b/x-pack/legacy/plugins/siem/public/containers/network_top_countries/index.tsx index bd1e1a002bbcd..43f3616b79924 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_top_countries/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/network_top_countries/index.tsx @@ -6,7 +6,6 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect } from 'react-redux'; import { compose } from 'redux'; @@ -14,6 +13,7 @@ import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { FlowTargetSourceDest, GetNetworkTopCountriesQuery, + GetNetworkTopCountriesQueryComponent, NetworkTopCountriesEdges, NetworkTopTablesSortField, PageInfoPaginated, @@ -23,7 +23,6 @@ import { withKibana, WithKibanaProps } from '../../lib/kibana'; import { generateTablePaginationOptions } from '../../components/paginated_table/helpers'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; -import { networkTopCountriesQuery } from './index.gql_query'; const ID = 'networkTopCountriesQuery'; @@ -41,7 +40,7 @@ export interface NetworkTopCountriesArgs { } export interface OwnProps extends QueryTemplatePaginatedProps { - children: (args: NetworkTopCountriesArgs) => React.ReactNode; + children: (args: NetworkTopCountriesArgs) => React.ReactElement; flowTarget: FlowTargetSourceDest; ip?: string; type: networkModel.NetworkType; @@ -94,10 +93,9 @@ class NetworkTopCountriesComponentQuery extends QueryTemplatePaginated< }, }; return ( - + @@ -137,7 +135,7 @@ class NetworkTopCountriesComponentQuery extends QueryTemplatePaginated< totalCount: getOr(-1, 'source.NetworkTopCountries.totalCount', data), }); }} - + ); } } diff --git a/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.gql_query.ts index a73f9ff9256ff..ba852e042016c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const networkTopNFlowQuery = gql` query GetNetworkTopNFlowQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.tsx b/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.tsx index f0f1f8257f29f..3121ab9d8433c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.tsx @@ -6,7 +6,6 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect } from 'react-redux'; import { compose } from 'redux'; @@ -14,6 +13,7 @@ import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { FlowTargetSourceDest, GetNetworkTopNFlowQuery, + GetNetworkTopNFlowQueryComponent, NetworkTopNFlowEdges, NetworkTopTablesSortField, PageInfoPaginated, @@ -23,7 +23,6 @@ import { inputsModel, inputsSelectors, networkModel, networkSelectors, State } f import { generateTablePaginationOptions } from '../../components/paginated_table/helpers'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; -import { networkTopNFlowQuery } from './index.gql_query'; const ID = 'networkTopNFlowQuery'; @@ -41,7 +40,7 @@ export interface NetworkTopNFlowArgs { } export interface OwnProps extends QueryTemplatePaginatedProps { - children: (args: NetworkTopNFlowArgs) => React.ReactNode; + children: (args: NetworkTopNFlowArgs) => React.ReactElement; flowTarget: FlowTargetSourceDest; ip?: string; type: networkModel.NetworkType; @@ -94,10 +93,9 @@ class NetworkTopNFlowComponentQuery extends QueryTemplatePaginated< }, }; return ( - + @@ -137,7 +135,7 @@ class NetworkTopNFlowComponentQuery extends QueryTemplatePaginated< totalCount: getOr(-1, 'source.NetworkTopNFlow.totalCount', data), }); }} - + ); } } diff --git a/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.gql_query.ts index 6f17bf6915aa4..a1b6998ec2e75 100644 --- a/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const overviewHostQuery = gql` query GetOverviewHostQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx b/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx index 2dd9ccf24d802..8d7028e3f6bd7 100644 --- a/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx @@ -6,19 +6,16 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; -import { GetOverviewHostQuery, OverviewHostData } from '../../../graphql/types'; +import { GetOverviewHostQueryComponent, OverviewHostData } from '../../../graphql/types'; import { useUiSetting } from '../../../lib/kibana'; import { inputsModel, inputsSelectors } from '../../../store/inputs'; import { State } from '../../../store'; import { createFilter, getDefaultFetchPolicy } from '../../helpers'; import { QueryTemplateProps } from '../../query_template'; -import { overviewHostQuery } from './index.gql_query'; - export const ID = 'overviewHostQuery'; export interface OverviewHostArgs { @@ -30,43 +27,40 @@ export interface OverviewHostArgs { } export interface OverviewHostProps extends QueryTemplateProps { - children: (args: OverviewHostArgs) => React.ReactNode; + children: (args: OverviewHostArgs) => React.ReactElement; sourceId: string; endDate: number; startDate: number; } const OverviewHostComponentQuery = React.memo( - ({ id = ID, children, filterQuery, isInspected, sourceId, startDate, endDate }) => { - return ( - - query={overviewHostQuery} - fetchPolicy={getDefaultFetchPolicy()} - variables={{ - sourceId, - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - filterQuery: createFilter(filterQuery), - defaultIndex: useUiSetting(DEFAULT_INDEX_KEY), - inspect: isInspected, - }} - > - {({ data, loading, refetch }) => { - const overviewHost = getOr({}, `source.OverviewHost`, data); - return children({ - id, - inspect: getOr(null, 'source.OverviewHost.inspect', data), - overviewHost, - loading, - refetch, - }); - }} - - ); - } + ({ id = ID, children, filterQuery, isInspected, sourceId, startDate, endDate }) => ( + (DEFAULT_INDEX_KEY), + inspect: isInspected, + }} + > + {({ data, loading, refetch }) => { + const overviewHost = getOr({}, `source.OverviewHost`, data); + return children({ + id, + inspect: getOr(null, 'source.OverviewHost.inspect', data), + overviewHost, + loading, + refetch, + }); + }} + + ) ); OverviewHostComponentQuery.displayName = 'OverviewHostComponentQuery'; diff --git a/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.gql_query.ts index d40ab900b91a7..6eb8dc9dcdaec 100644 --- a/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const overviewNetworkQuery = gql` query GetOverviewNetworkQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx b/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx index d0acd41c224a5..5ae8741c2545e 100644 --- a/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx @@ -6,19 +6,16 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; -import { GetOverviewNetworkQuery, OverviewNetworkData } from '../../../graphql/types'; +import { GetOverviewNetworkQueryComponent, OverviewNetworkData } from '../../../graphql/types'; import { useUiSetting } from '../../../lib/kibana'; import { State } from '../../../store'; import { inputsModel, inputsSelectors } from '../../../store/inputs'; import { createFilter, getDefaultFetchPolicy } from '../../helpers'; import { QueryTemplateProps } from '../../query_template'; -import { overviewNetworkQuery } from './index.gql_query'; - export const ID = 'overviewNetworkQuery'; export interface OverviewNetworkArgs { @@ -30,7 +27,7 @@ export interface OverviewNetworkArgs { } export interface OverviewNetworkProps extends QueryTemplateProps { - children: (args: OverviewNetworkArgs) => React.ReactNode; + children: (args: OverviewNetworkArgs) => React.ReactElement; sourceId: string; endDate: number; startDate: number; @@ -38,8 +35,7 @@ export interface OverviewNetworkProps extends QueryTemplateProps { export const OverviewNetworkComponentQuery = React.memo( ({ id = ID, children, filterQuery, isInspected, sourceId, startDate, endDate }) => ( - - query={overviewNetworkQuery} + + ) ); 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 dfb452c24b86e..43b9237bf0cb7 100644 --- a/x-pack/legacy/plugins/siem/public/containers/query_template.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/query_template.tsx @@ -4,9 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ApolloQueryResult } from 'apollo-client'; +import { + ApolloQueryResult, + FetchMoreOptions, + FetchMoreQueryOptions, + OperationVariables, +} from '@apollo/client'; import React from 'react'; -import { FetchMoreOptions, FetchMoreQueryOptions, OperationVariables } from 'react-apollo'; import { ESQuery } from '../../common/typed_json'; diff --git a/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx b/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx index db618f216d83e..c01289bf61f6c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx @@ -4,10 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ApolloQueryResult, NetworkStatus } from 'apollo-client'; -import memoizeOne from 'memoize-one'; +import { + ApolloQueryResult, + NetworkStatus, + FetchMoreOptions, + FetchMoreQueryOptions, + OperationVariables, +} from '@apollo/client'; import React from 'react'; -import { FetchMoreOptions, FetchMoreQueryOptions, OperationVariables } from 'react-apollo'; +import memoizeOne from 'memoize-one'; import deepEqual from 'fast-deep-equal'; import { ESQuery } from '../../common/typed_json'; diff --git a/x-pack/legacy/plugins/siem/public/containers/source/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/source/index.gql_query.ts index 1f9ba09167e1e..6c84ee7f29c41 100644 --- a/x-pack/legacy/plugins/siem/public/containers/source/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/source/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const sourceQuery = gql` query SourceQuery($sourceId: ID = "default", $defaultIndex: [String!]!) { diff --git a/x-pack/legacy/plugins/siem/public/containers/source/index.test.tsx b/x-pack/legacy/plugins/siem/public/containers/source/index.test.tsx index d1a183a402e37..d64a7ebab44f4 100644 --- a/x-pack/legacy/plugins/siem/public/containers/source/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/source/index.test.tsx @@ -4,55 +4,39 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; -import { mount } from 'enzyme'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { MockedProvider } from '@apollo/client/testing'; +import { renderHook } from '@testing-library/react-hooks'; -import { wait } from '../../lib/helpers'; - -import { WithSource, indicesExistOrDataTemporarilyUnavailable } from '.'; +import { useWithSource, indicesExistOrDataTemporarilyUnavailable } from '.'; import { mockBrowserFields, mockIndexFields, mocksSource } from './mock'; jest.mock('../../lib/kibana'); describe('Index Fields & Browser Fields', () => { test('Index Fields', async () => { - mount( + const wrapper: React.ComponentType = ({ children }) => ( - - {({ indexPattern }) => { - if (!isEqual(indexPattern.fields, [])) { - expect(indexPattern.fields).toEqual(mockIndexFields); - } - - return null; - }} - + {(children as unknown) as undefined} ); + const { result, waitForNextUpdate } = renderHook(() => useWithSource(), { wrapper }); - // Why => https://github.com/apollographql/react-apollo/issues/1711 - await wait(); + await waitForNextUpdate(); + + expect(result.current.indexPattern.fields).toEqual(mockIndexFields); }); test('Browser Fields', async () => { - mount( + const wrapper: React.ComponentType = ({ children }) => ( - - {({ browserFields }) => { - if (!isEqual(browserFields, {})) { - expect(browserFields).toEqual(mockBrowserFields); - } - - return null; - }} - + {(children as unknown) as undefined} ); + const { result, waitForNextUpdate } = renderHook(() => useWithSource(), { wrapper }); + await waitForNextUpdate(); - // Why => https://github.com/apollographql/react-apollo/issues/1711 - await wait(); + expect(result.current.browserFields).toEqual(mockBrowserFields); }); describe('indicesExistOrDataTemporarilyUnavailable', () => { 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 e454421ca955d..f8f85f0fccc04 100644 --- a/x-pack/legacy/plugins/siem/public/containers/source/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/source/index.tsx @@ -6,18 +6,16 @@ import { isUndefined } from 'lodash'; import { get, keyBy, pick, set, isEmpty } from 'lodash/fp'; -import { Query } from 'react-apollo'; -import React, { useEffect, useMemo, useState } from 'react'; +import { useMemo } from 'react'; import memoizeOne from 'memoize-one'; import { IIndexPattern } from 'src/plugins/data/public'; import { useUiSetting$ } from '../../lib/kibana'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; -import { IndexField, SourceQuery } from '../../graphql/types'; +import { IndexField, useSourceQueryQuery } from '../../graphql/types'; import { sourceQuery } from './index.gql_query'; -import { useApolloClient } from '../../utils/apollo_context'; export { sourceQuery }; @@ -50,18 +48,6 @@ export const getAllFieldsByName = ( ): { [fieldName: string]: Partial } => keyBy('name', getAllBrowserFields(browserFields)); -interface WithSourceArgs { - indicesExist: boolean; - browserFields: BrowserFields; - indexPattern: IIndexPattern; -} - -interface WithSourceProps { - children: (args: WithSourceArgs) => React.ReactNode; - indexToAdd?: string[] | null; - sourceId: string; -} - export const getIndexFields = memoizeOne( (title: string, fields: IndexField[]): IIndexPattern => fields && fields.length > 0 @@ -83,7 +69,10 @@ export const getBrowserFields = memoizeOne( : {} ); -export const WithSource = React.memo(({ children, indexToAdd, sourceId }) => { +export const indicesExistOrDataTemporarilyUnavailable = (indicesExist: boolean | undefined) => + indicesExist || isUndefined(indicesExist); + +export const useWithSource = (indexToAdd?: string[] | null, sourceId: string = 'default') => { const [configIndex] = useUiSetting$(DEFAULT_INDEX_KEY); const defaultIndex = useMemo(() => { if (indexToAdd != null && !isEmpty(indexToAdd)) { @@ -92,86 +81,28 @@ export const WithSource = React.memo(({ children, indexToAdd, s return configIndex; }, [configIndex, indexToAdd]); - return ( - - query={sourceQuery} - fetchPolicy="cache-first" - notifyOnNetworkStatusChange - variables={{ - sourceId, - defaultIndex, - }} - > - {({ data }) => - children({ - indicesExist: get('source.status.indicesExist', data), - browserFields: getBrowserFields( - defaultIndex.join(), - get('source.status.indexFields', data) - ), - indexPattern: getIndexFields(defaultIndex.join(), get('source.status.indexFields', data)), - }) - } - + const variables = { + sourceId, + defaultIndex, + }; + + const { data } = useSourceQueryQuery({ + fetchPolicy: 'cache-first', + notifyOnNetworkStatusChange: true, + variables, + }); + + const indicesExist = get('source.status.indicesExist', data); + const browserFields = getBrowserFields( + defaultIndex.join(), + get('source.status.indexFields', data) ); -}); - -WithSource.displayName = 'WithSource'; - -export const indicesExistOrDataTemporarilyUnavailable = (indicesExist: boolean | undefined) => - indicesExist || isUndefined(indicesExist); - -export const useWithSource = (sourceId: string, indices: string[]) => { - const [loading, updateLoading] = useState(false); - const [indicesExist, setIndicesExist] = useState(undefined); - const [browserFields, setBrowserFields] = useState(null); - const [indexPattern, setIndexPattern] = useState(null); - const [errorMessage, updateErrorMessage] = useState(null); - - const apolloClient = useApolloClient(); - async function fetchSource(signal: AbortSignal) { - updateLoading(true); - if (apolloClient) { - apolloClient - .query({ - query: sourceQuery, - fetchPolicy: 'cache-first', - variables: { - sourceId, - defaultIndex: indices, - }, - context: { - fetchOptions: { - signal, - }, - }, - }) - .then( - result => { - updateLoading(false); - updateErrorMessage(null); - setIndicesExist(get('data.source.status.indicesExist', result)); - setBrowserFields( - getBrowserFields(indices.join(), get('data.source.status.indexFields', result)) - ); - setIndexPattern( - getIndexFields(indices.join(), get('data.source.status.indexFields', result)) - ); - }, - error => { - updateLoading(false); - updateErrorMessage(error.message); - } - ); - } - } - - useEffect(() => { - const abortCtrl = new AbortController(); - const signal = abortCtrl.signal; - fetchSource(signal); - return () => abortCtrl.abort(); - }, [apolloClient, sourceId, indices]); - - return { indicesExist, browserFields, indexPattern, loading, errorMessage }; + const indexPattern = getIndexFields(defaultIndex.join(), get('source.status.indexFields', data)); + const contentAvailable = indicesExistOrDataTemporarilyUnavailable(indicesExist); + + return { + browserFields, + indexPattern, + contentAvailable, + }; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/all/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/all/index.gql_query.ts index e380e46e77070..055c7203ef78e 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/all/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/all/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const allTimelinesQuery = gql` query GetAllTimeline( 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 22c7b03f34dd5..1da4404146a44 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 @@ -8,16 +8,14 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import memoizeOne from 'memoize-one'; -import { Query } from 'react-apollo'; - import { OpenTimelineResult } from '../../../components/open_timeline/types'; import { GetAllTimeline, + GetAllTimelineComponent, PageInfoTimeline, SortTimeline, TimelineResult, } from '../../../graphql/types'; -import { allTimelinesQuery } from './index.gql_query'; export interface AllTimelinesArgs { timelines: OpenTimelineResult[]; @@ -33,7 +31,7 @@ export interface AllTimelinesVariables { } interface OwnProps extends AllTimelinesVariables { - children?: (args: AllTimelinesArgs) => React.ReactNode; + children?: (args: AllTimelinesArgs) => React.ReactElement; } const getAllTimeline = memoizeOne( @@ -85,8 +83,7 @@ const AllTimelinesQueryComponent: React.FC = ({ sort, }; return ( - - query={allTimelinesQuery} + = ({ ), }) } - + ); }; diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/delete/persist.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/delete/persist.gql_query.ts index 4096d7245e89b..1cdd4a4c66c32 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/delete/persist.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/delete/persist.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const deleteTimelineMutation = gql` mutation DeleteTimelineMutation($id: [ID!]!) { diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/details/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/details/index.gql_query.ts index 4677d2328be87..2618fe8565536 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/details/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/details/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const timelineDetailsQuery = gql` query GetTimelineDetailsQuery( 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 cf1b8954307e7..4c5e0f7940449 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 @@ -7,14 +7,15 @@ import { getOr } from 'lodash/fp'; import memoizeOne from 'memoize-one'; import React from 'react'; -import { Query } from 'react-apollo'; import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; -import { DetailItem, GetTimelineDetailsQuery } from '../../../graphql/types'; +import { + DetailItem, + GetTimelineDetailsQuery, + GetTimelineDetailsQueryComponent, +} from '../../../graphql/types'; import { useUiSetting } from '../../../lib/kibana'; -import { timelineDetailsQuery } from './index.gql_query'; - export interface EventsArgs { detailsData: DetailItem[] | null; loading: boolean; @@ -46,8 +47,7 @@ const TimelineDetailsQueryComponent: React.FC = ({ defaultIndex: useUiSetting(DEFAULT_INDEX_KEY), }; return executeQuery ? ( - - query={timelineDetailsQuery} + = ({ ), }) } - + ) : ( children!({ loading: false, detailsData: null }) ); diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/favorite/persist.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/favorite/persist.gql_query.ts index 27d3fdd342e19..d11c87df8332f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/favorite/persist.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/favorite/persist.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const persistTimelineFavoriteMutation = gql` mutation PersistTimelineFavoriteMutation($timelineId: ID) { diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/index.gql_query.ts index c54238c5d8687..3d9026085f7f5 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const timelineQuery = gql` query GetTimelineQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx b/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx index ccd8babd41e68..5ee36f3a75f98 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx @@ -7,7 +7,6 @@ import { getOr } from 'lodash/fp'; import memoizeOne from 'memoize-one'; import React from 'react'; -import { Query } from 'react-apollo'; import { compose, Dispatch } from 'redux'; import { connect, ConnectedProps } from 'react-redux'; @@ -15,6 +14,7 @@ import { IIndexPattern } from '../../../../../../../src/plugins/data/common/inde import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetTimelineQuery, + GetTimelineQueryComponent, PageInfo, SortField, TimelineEdges, @@ -25,7 +25,6 @@ import { withKibana, WithKibanaProps } from '../../lib/kibana'; import { createFilter } from '../helpers'; import { QueryTemplate, QueryTemplateProps } from '../query_template'; import { EventType } from '../../store/timeline/model'; -import { timelineQuery } from './index.gql_query'; import { timelineActions } from '../../store/timeline'; import { SIGNALS_PAGE_TIMELINE_ID } from '../../pages/detection_engine/components/signals'; @@ -41,12 +40,8 @@ export interface TimelineArgs { getUpdatedAt: () => number; } -export interface CustomReduxProps { - clearSignalsState: ({ id }: { id?: string }) => void; -} - export interface OwnProps extends QueryTemplateProps { - children?: (args: TimelineArgs) => React.ReactNode; + children?: (args: TimelineArgs) => React.ReactElement; eventType?: EventType; id: string; indexPattern?: IIndexPattern; @@ -56,7 +51,7 @@ export interface OwnProps extends QueryTemplateProps { fields: string[]; } -type TimelineQueryProps = OwnProps & PropsFromRedux & WithKibanaProps & CustomReduxProps; +type TimelineQueryProps = OwnProps & PropsFromRedux & WithKibanaProps; class TimelineQueryComponent extends QueryTemplate< TimelineQueryProps, @@ -106,8 +101,7 @@ class TimelineQueryComponent extends QueryTemplate< }; return ( - - query={timelineQuery} + + ); } diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/notes/persist.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/notes/persist.gql_query.ts index ff9ea164acee4..fbb3c4cd8b3f7 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/notes/persist.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/notes/persist.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const persistTimelineNoteMutation = gql` mutation PersistTimelineNoteMutation($noteId: ID, $version: String, $note: NoteInput!) { diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/one/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/one/index.gql_query.ts index e68db445a5cbb..8e5af210ddfd4 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/one/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/one/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const oneTimelineQuery = gql` query GetOneTimeline($id: ID!) { diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/persist.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/persist.gql_query.ts index 6a0609f9158f3..787a8027e5fef 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/persist.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/persist.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const persistTimelineMutation = gql` mutation PersistTimelineMutation($timelineId: ID, $version: String, $timeline: TimelineInput!) { diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/pinned_event/persist.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/pinned_event/persist.gql_query.ts index 7257dcb404011..d66dc4fb28a00 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/pinned_event/persist.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/pinned_event/persist.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const persistTimelinePinnedEventMutation = gql` mutation PersistTimelinePinnedEventMutation($pinnedEventId: ID, $eventId: ID!, $timelineId: ID) { diff --git a/x-pack/legacy/plugins/siem/public/containers/tls/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/tls/index.gql_query.ts index bbb92282bee83..68b79adcbcf55 100644 --- a/x-pack/legacy/plugins/siem/public/containers/tls/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/tls/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const tlsQuery = gql` query GetTlsQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/tls/index.tsx b/x-pack/legacy/plugins/siem/public/containers/tls/index.tsx index 3738355c8846e..77aa79c29fb81 100644 --- a/x-pack/legacy/plugins/siem/public/containers/tls/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/tls/index.tsx @@ -6,7 +6,6 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect } from 'react-redux'; import { compose } from 'redux'; @@ -16,6 +15,7 @@ import { TlsEdges, TlsSortField, GetTlsQuery, + GetTlsQueryComponent, FlowTargetSourceDest, } from '../../graphql/types'; import { inputsModel, networkModel, networkSelectors, State, inputsSelectors } from '../../store'; @@ -23,7 +23,6 @@ import { withKibana, WithKibanaProps } from '../../lib/kibana'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { generateTablePaginationOptions } from '../../components/paginated_table/helpers'; import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; -import { tlsQuery } from './index.gql_query'; const ID = 'tlsQuery'; @@ -40,7 +39,7 @@ export interface TlsArgs { } export interface OwnProps extends QueryTemplatePaginatedProps { - children: (args: TlsArgs) => React.ReactNode; + children: (args: TlsArgs) => React.ReactElement; flowTarget: FlowTargetSourceDest; ip: string; type: networkModel.NetworkType; @@ -93,8 +92,7 @@ class TlsComponentQuery extends QueryTemplatePaginated< }, }; return ( - - query={tlsQuery} + + ); } } diff --git a/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.gql_query.ts index d984de020faa1..6ab980e338e32 100644 --- a/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const uncommonProcessesQuery = gql` query GetUncommonProcessesQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx b/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx index 0a2ce67d9be80..06b6306bd1140 100644 --- a/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx @@ -6,13 +6,13 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect, ConnectedProps } from 'react-redux'; import { compose } from 'redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetUncommonProcessesQuery, + GetUncommonProcessesQueryComponent, PageInfoPaginated, UncommonProcessesEdges, } from '../../graphql/types'; @@ -22,8 +22,6 @@ import { generateTablePaginationOptions } from '../../components/paginated_table import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; -import { uncommonProcessesQuery } from './index.gql_query'; - const ID = 'uncommonProcessesQuery'; export interface UncommonProcessesArgs { @@ -39,7 +37,7 @@ export interface UncommonProcessesArgs { } export interface OwnProps extends QueryTemplatePaginatedProps { - children: (args: UncommonProcessesArgs) => React.ReactNode; + children: (args: UncommonProcessesArgs) => React.ReactElement; type: hostsModel.HostsType; } @@ -77,8 +75,7 @@ class UncommonProcessesComponentQuery extends QueryTemplatePaginated< }, }; return ( - - query={uncommonProcessesQuery} + + ); } } diff --git a/x-pack/legacy/plugins/siem/public/containers/users/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/users/index.gql_query.ts index 3fc1cdfd160db..a1ddff1a60e64 100644 --- a/x-pack/legacy/plugins/siem/public/containers/users/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/users/index.gql_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const usersQuery = gql` query GetUsersQuery( diff --git a/x-pack/legacy/plugins/siem/public/containers/users/index.tsx b/x-pack/legacy/plugins/siem/public/containers/users/index.tsx index 5f71449c52460..f1e0351ef2fe3 100644 --- a/x-pack/legacy/plugins/siem/public/containers/users/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/users/index.tsx @@ -6,20 +6,23 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { Query } from 'react-apollo'; import { connect, ConnectedProps } from 'react-redux'; import { compose } from 'redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; -import { GetUsersQuery, FlowTarget, PageInfoPaginated, UsersEdges } from '../../graphql/types'; +import { + GetUsersQuery, + FlowTarget, + PageInfoPaginated, + UsersEdges, + GetUsersQueryComponent, +} from '../../graphql/types'; import { inputsModel, networkModel, networkSelectors, State, inputsSelectors } from '../../store'; import { withKibana, WithKibanaProps } from '../../lib/kibana'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { generateTablePaginationOptions } from '../../components/paginated_table/helpers'; import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; -import { usersQuery } from './index.gql_query'; - const ID = 'usersQuery'; export interface UsersArgs { @@ -35,7 +38,7 @@ export interface UsersArgs { } export interface OwnProps extends QueryTemplatePaginatedProps { - children: (args: UsersArgs) => React.ReactNode; + children: (args: UsersArgs) => React.ReactElement; flowTarget: FlowTarget; ip: string; type: networkModel.NetworkType; @@ -81,8 +84,7 @@ class UsersComponentQuery extends QueryTemplatePaginated< }, }; return ( - - query={usersQuery} + + ); } } diff --git a/x-pack/legacy/plugins/siem/public/graphql/introspection.json b/x-pack/legacy/plugins/siem/public/graphql/introspection.json deleted file mode 100644 index 9802a5f5bd3bf..0000000000000 --- a/x-pack/legacy/plugins/siem/public/graphql/introspection.json +++ /dev/null @@ -1,12556 +0,0 @@ -{ - "__schema": { - "queryType": { "name": "Query" }, - "mutationType": { "name": "Mutation" }, - "subscriptionType": null, - "types": [ - { - "kind": "OBJECT", - "name": "Query", - "description": "", - "fields": [ - { - "name": "getNote", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NoteResult", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "getNotesByTimelineId", - "description": "", - "args": [ - { - "name": "timelineId", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NoteResult", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "getNotesByEventId", - "description": "", - "args": [ - { - "name": "eventId", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NoteResult", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "getAllNotes", - "description": "", - "args": [ - { - "name": "pageInfo", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "PageInfoNote", "ofType": null }, - "defaultValue": null - }, - { - "name": "search", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "SortNote", "ofType": null }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ResponseNotes", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "getAllPinnedEventsByTimelineId", - "description": "", - "args": [ - { - "name": "timelineId", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PinnedEvent", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source", - "description": "Get a security data source by id", - "args": [ - { - "name": "id", - "description": "The id of the source", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "Source", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "allSources", - "description": "Get a list of all security data sources", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "Source", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "getOneTimeline", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TimelineResult", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "getAllTimeline", - "description": "", - "args": [ - { - "name": "pageInfo", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "PageInfoTimeline", "ofType": null }, - "defaultValue": null - }, - { - "name": "search", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "SortTimeline", "ofType": null }, - "defaultValue": null - }, - { - "name": "onlyUserFavorite", - "description": "", - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ResponseTimelines", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ID", - "description": "The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"4\"`) or integer (such as `4`) input value will be accepted as an ID.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NoteResult", - "description": "", - "fields": [ - { - "name": "eventId", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "note", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timelineId", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "noteId", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "created", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdBy", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timelineVersion", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updated", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updatedBy", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "String", - "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Float", - "description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "PageInfoNote", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "pageIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pageSize", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "SortNote", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "sortField", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "SortFieldNote", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "sortOrder", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "SortFieldNote", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "updatedBy", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "updated", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "Direction", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { "name": "asc", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "desc", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ResponseNotes", - "description": "", - "fields": [ - { - "name": "notes", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NoteResult", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "PinnedEvent", - "description": "", - "fields": [ - { - "name": "code", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "message", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pinnedEventId", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "eventId", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ID", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timelineId", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ID", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timelineVersion", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "created", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdBy", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updated", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updatedBy", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Source", - "description": "", - "fields": [ - { - "name": "id", - "description": "The id of the source", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "configuration", - "description": "The raw configuration of the source", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "SourceConfiguration", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "status", - "description": "The status of the source", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "SourceStatus", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "Authentications", - "description": "Gets Authentication success and failures based on a timerange", - "args": [ - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "AuthenticationsData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "Timeline", - "description": "", - "args": [ - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "PaginationInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "sortField", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "SortField", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "fieldRequested", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TimelineData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "TimelineDetails", - "description": "", - "args": [ - { - "name": "eventId", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "indexName", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TimelineDetailsData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "LastEventTime", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "indexKey", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "LastEventIndexKey", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "details", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "LastTimeDetails", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "LastEventTimeData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "Hosts", - "description": "Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "HostsSortField", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "HostsData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "HostOverview", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "hostName", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "HostItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "HostFirstLastSeen", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "hostName", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "FirstLastSeenHost", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "IpOverview", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "ip", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { "kind": "OBJECT", "name": "IpOverviewData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "Users", - "description": "", - "args": [ - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "ip", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "UsersSortField", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "flowTarget", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "FlowTarget", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UsersData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "KpiNetwork", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { "kind": "OBJECT", "name": "KpiNetworkData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "KpiHosts", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostsData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "KpiHostDetails", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostDetailsData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "MatrixHistogram", - "description": "", - "args": [ - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "stackByField", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "histogramType", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "HistogramType", "ofType": null } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "MatrixHistogramOverTimeData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NetworkTopCountries", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "ip", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "flowTarget", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "FlowTargetSourceDest", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "NetworkTopTablesSortField", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkTopCountriesData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NetworkTopNFlow", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "ip", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "flowTarget", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "FlowTargetSourceDest", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "NetworkTopTablesSortField", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkTopNFlowData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NetworkDns", - "description": "", - "args": [ - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "isPtrIncluded", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "NetworkDnsSortField", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "stackByField", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkDnsData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NetworkDnsHistogram", - "description": "", - "args": [ - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "stackByField", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkDsOverTimeData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NetworkHttp", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "ip", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "NetworkHttpSortField", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkHttpData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OverviewNetwork", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { "kind": "OBJECT", "name": "OverviewNetworkData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OverviewHost", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { "kind": "OBJECT", "name": "OverviewHostData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "Tls", - "description": "", - "args": [ - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "ip", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TlsSortField", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "flowTarget", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "FlowTargetSourceDest", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TlsData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UncommonProcesses", - "description": "Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified", - "args": [ - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UncommonProcessesData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "whoAmI", - "description": "Just a simple example to get the app name", - "args": [], - "type": { "kind": "OBJECT", "name": "SayMyName", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SourceConfiguration", - "description": "A set of configuration options for a security data source", - "fields": [ - { - "name": "fields", - "description": "The field mapping to use for this source", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "SourceFields", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SourceFields", - "description": "A mapping of semantic fields to their document counterparts", - "fields": [ - { - "name": "container", - "description": "The field to identify a container by", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "host", - "description": "The fields to identify a host by", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "message", - "description": "The fields that may contain the log event message. The first field found win.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pod", - "description": "The field to identify a pod by", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "tiebreaker", - "description": "The field to use as a tiebreaker for log events that have identical timestamps", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timestamp", - "description": "The field to use as a timestamp for metrics and logs", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SourceStatus", - "description": "The status of an infrastructure data source", - "fields": [ - { - "name": "indicesExist", - "description": "Whether the configured alias or wildcard pattern resolve to any auditbeat indices", - "args": [ - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "indexFields", - "description": "The list of fields defined in the index mappings", - "args": [ - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "IndexField", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Boolean", - "description": "The `Boolean` scalar type represents `true` or `false`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "IndexField", - "description": "A descriptor of a field in an index", - "fields": [ - { - "name": "category", - "description": "Where the field belong", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "example", - "description": "Example of field's value", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "indexes", - "description": "whether the field's belong to an alias index", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "The name of the field", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "The type of the field's values as recognized by Kibana", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "searchable", - "description": "Whether the field's values can be efficiently searched for", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "aggregatable", - "description": "Whether the field's values can be aggregated", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "Description of the field", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "format", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "TimerangeInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "interval", - "description": "The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "to", - "description": "The end of the timerange", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "from", - "description": "The beginning of the timerange", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "activePage", - "description": "The activePage parameter defines the page of results you want to fetch", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "cursorStart", - "description": "The cursorStart parameter defines the start of the results to be displayed", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "fakePossibleCount", - "description": "The fakePossibleCount parameter determines the total count in order to show 5 additional pages", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "querySize", - "description": "The querySize parameter is the number of items to be returned", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AuthenticationsData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "AuthenticationsEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AuthenticationsEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "AuthenticationItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AuthenticationItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "failures", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "successes", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "user", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UserEcsFields", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastSuccess", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "LastSourceHost", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastFailure", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "LastSourceHost", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UserEcsFields", - "description": "", - "fields": [ - { - "name": "domain", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "full_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "email", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "hash", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "group", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ToStringArray", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "LastSourceHost", - "description": "", - "fields": [ - { - "name": "timestamp", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SourceEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "host", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "HostEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Date", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SourceEcsFields", - "description": "", - "fields": [ - { - "name": "bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ip", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "port", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "domain", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "geo", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "packets", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ToNumberArray", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "GeoEcsFields", - "description": "", - "fields": [ - { - "name": "city_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "continent_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "country_iso_code", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "country_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "location", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Location", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "region_iso_code", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "region_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Location", - "description": "", - "fields": [ - { - "name": "lon", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lat", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HostEcsFields", - "description": "", - "fields": [ - { - "name": "architecture", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ip", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mac", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "os", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "OsEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "OsEcsFields", - "description": "", - "fields": [ - { - "name": "platform", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "full", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "family", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "kernel", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "CursorType", - "description": "", - "fields": [ - { - "name": "value", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "tiebreaker", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "PageInfoPaginated", - "description": "", - "fields": [ - { - "name": "activePage", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fakeTotalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "showMorePagesIndicator", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Inspect", - "description": "", - "fields": [ - { - "name": "dsl", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "response", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "PaginationInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "limit", - "description": "The limit parameter allows you to configure the maximum amount of items to be returned", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "cursor", - "description": "The cursor parameter defines the next result you want to fetch", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "tiebreaker", - "description": "The tiebreaker parameter allow to be more precise to fetch the next item", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "SortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "sortFieldId", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "direction", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TimelineData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TimelineEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfo", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TimelineEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TimelineItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TimelineItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "_index", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "data", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TimelineNonEcsData", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ecs", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ECS", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TimelineNonEcsData", - "description": "", - "fields": [ - { - "name": "field", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "value", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ECS", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "_index", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "auditd", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "AuditdEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "DestinationEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dns", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "DnsEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "endgame", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "EndgameEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "event", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "EventEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "geo", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "host", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "HostEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "network", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "NetworkEcsField", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "rule", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "RuleEcsField", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "signal", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SignalField", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SourceEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "suricata", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SuricataEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "tls", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TlsEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "zeek", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "ZeekEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "http", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "HttpEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "url", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "UrlEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timestamp", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "message", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "user", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "UserEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "winlog", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "WinlogEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "process", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "ProcessEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "file", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "FileFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "system", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SystemEcsField", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AuditdEcsFields", - "description": "", - "fields": [ - { - "name": "result", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "session", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "data", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "AuditdData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "summary", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Summary", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "sequence", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AuditdData", - "description": "", - "fields": [ - { - "name": "acct", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "terminal", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "op", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Summary", - "description": "", - "fields": [ - { - "name": "actor", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "PrimarySecondary", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "object", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "PrimarySecondary", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "how", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "message_type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "sequence", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "PrimarySecondary", - "description": "", - "fields": [ - { - "name": "primary", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "secondary", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "DestinationEcsFields", - "description": "", - "fields": [ - { - "name": "bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ip", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "port", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "domain", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "geo", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "packets", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "DnsEcsFields", - "description": "", - "fields": [ - { - "name": "question", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "DnsQuestionData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "resolved_ip", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "response_code", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "DnsQuestionData", - "description": "", - "fields": [ - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "EndgameEcsFields", - "description": "", - "fields": [ - { - "name": "exit_code", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "file_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "file_path", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "logon_type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "parent_process_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pid", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "process_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subject_domain_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subject_logon_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subject_user_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "target_domain_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "target_logon_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "target_user_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "EventEcsFields", - "description": "", - "fields": [ - { - "name": "action", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "category", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "code", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "created", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToDateArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dataset", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "duration", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "end", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToDateArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "hash", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "kind", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "module", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "original", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "outcome", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "risk_score", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "risk_score_norm", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "severity", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "start", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToDateArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timezone", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ToDateArray", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkEcsField", - "description": "", - "fields": [ - { - "name": "bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "community_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "direction", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "packets", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "protocol", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "transport", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "RuleEcsField", - "description": "", - "fields": [ - { - "name": "reference", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SignalField", - "description": "", - "fields": [ - { - "name": "rule", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "RuleField", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "original_time", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "RuleField", - "description": "", - "fields": [ - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "rule_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "false_positives", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "saved_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timeline_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timeline_title", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "max_signals", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "risk_score", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "output_index", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "from", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "immutable", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "index", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "interval", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "language", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "query", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "references", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "severity", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "tags", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "threat", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToAny", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "size", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "to", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "enabled", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "filters", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToAny", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "created_at", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updated_at", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "created_by", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updated_by", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ToBooleanArray", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ToAny", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SuricataEcsFields", - "description": "", - "fields": [ - { - "name": "eve", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SuricataEveData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SuricataEveData", - "description": "", - "fields": [ - { - "name": "alert", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SuricataAlertData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "flow_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "proto", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SuricataAlertData", - "description": "", - "fields": [ - { - "name": "signature", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "signature_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsEcsFields", - "description": "", - "fields": [ - { - "name": "client_certificate", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TlsClientCertificateData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fingerprints", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TlsFingerprintsData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "server_certificate", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TlsServerCertificateData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsClientCertificateData", - "description": "", - "fields": [ - { - "name": "fingerprint", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "FingerprintData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "FingerprintData", - "description": "", - "fields": [ - { - "name": "sha1", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsFingerprintsData", - "description": "", - "fields": [ - { - "name": "ja3", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TlsJa3Data", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsJa3Data", - "description": "", - "fields": [ - { - "name": "hash", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsServerCertificateData", - "description": "", - "fields": [ - { - "name": "fingerprint", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "FingerprintData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ZeekEcsFields", - "description": "", - "fields": [ - { - "name": "session_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "connection", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "ZeekConnectionData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "notice", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "ZeekNoticeData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dns", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "ZeekDnsData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "http", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "ZeekHttpData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "files", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "ZeekFileData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ssl", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "ZeekSslData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ZeekConnectionData", - "description": "", - "fields": [ - { - "name": "local_resp", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "local_orig", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "missed_bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "state", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "history", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ZeekNoticeData", - "description": "", - "fields": [ - { - "name": "suppress_for", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "msg", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "note", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "sub", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dst", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dropped", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "peer_descr", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ZeekDnsData", - "description": "", - "fields": [ - { - "name": "AA", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "qclass_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "RD", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "qtype_name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "rejected", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "qtype", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "query", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "trans_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "qclass", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "RA", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "TC", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ZeekHttpData", - "description": "", - "fields": [ - { - "name": "resp_mime_types", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "trans_depth", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "status_msg", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "resp_fuids", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "tags", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ZeekFileData", - "description": "", - "fields": [ - { - "name": "session_ids", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timedout", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "local_orig", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "tx_host", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "is_orig", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "overflow_bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "sha1", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "duration", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "depth", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "analyzers", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mime_type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "rx_host", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "total_bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fuid", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "seen_bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "missing_bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "md5", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ZeekSslData", - "description": "", - "fields": [ - { - "name": "cipher", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "established", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "resumed", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToBooleanArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HttpEcsFields", - "description": "", - "fields": [ - { - "name": "version", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "request", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "HttpRequestData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "response", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "HttpResponseData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HttpRequestData", - "description": "", - "fields": [ - { - "name": "method", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "body", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "HttpBodyData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "referrer", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HttpBodyData", - "description": "", - "fields": [ - { - "name": "content", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HttpResponseData", - "description": "", - "fields": [ - { - "name": "status_code", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "body", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "HttpBodyData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UrlEcsFields", - "description": "", - "fields": [ - { - "name": "domain", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "original", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "username", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "password", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "WinlogEcsFields", - "description": "", - "fields": [ - { - "name": "event_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ProcessEcsFields", - "description": "", - "fields": [ - { - "name": "hash", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "ProcessHashData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pid", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ppid", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "executable", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "title", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "thread", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Thread", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "working_directory", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ProcessHashData", - "description": "", - "fields": [ - { - "name": "md5", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "sha1", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "sha256", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Thread", - "description": "", - "fields": [ - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "start", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "FileFields", - "description": "", - "fields": [ - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "path", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "target_path", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "extension", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "device", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inode", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uid", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "owner", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "gid", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "group", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mode", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "size", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mtime", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToDateArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ctime", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToDateArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SystemEcsField", - "description": "", - "fields": [ - { - "name": "audit", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "AuditEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "auth", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "AuthEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AuditEcsFields", - "description": "", - "fields": [ - { - "name": "package", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "PackageEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "PackageEcsFields", - "description": "", - "fields": [ - { - "name": "arch", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "entity_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "size", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToNumberArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "summary", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AuthEcsFields", - "description": "", - "fields": [ - { - "name": "ssh", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SshEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SshEcsFields", - "description": "", - "fields": [ - { - "name": "method", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "signature", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "PageInfo", - "description": "", - "fields": [ - { - "name": "endCursor", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "CursorType", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "hasNextPage", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TimelineDetailsData", - "description": "", - "fields": [ - { - "name": "data", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "DetailItem", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "DetailItem", - "description": "", - "fields": [ - { - "name": "field", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "values", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "originalValue", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "EsValue", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "EsValue", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "LastEventIndexKey", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "hostDetails", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "hosts", "description": "", "isDeprecated": false, "deprecationReason": null }, - { - "name": "ipDetails", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "network", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "LastTimeDetails", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "hostName", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "ip", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "LastEventTimeData", - "description": "", - "fields": [ - { - "name": "lastSeen", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "HostsSortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "HostsFields", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "direction", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "HostsFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "hostName", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastSeen", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HostsData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "HostsEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HostsEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "HostItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HostItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastSeen", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "host", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "HostEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cloud", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "CloudFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "CloudFields", - "description": "", - "fields": [ - { - "name": "instance", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "CloudInstance", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "machine", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "CloudMachine", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "provider", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "region", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "CloudInstance", - "description": "", - "fields": [ - { - "name": "id", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "CloudMachine", - "description": "", - "fields": [ - { - "name": "type", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "FirstLastSeenHost", - "description": "", - "fields": [ - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "firstSeen", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastSeen", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "IpOverviewData", - "description": "", - "fields": [ - { - "name": "client", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Overview", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Overview", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "host", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "HostEcsFields", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "server", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Overview", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Overview", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Overview", - "description": "", - "fields": [ - { - "name": "firstSeen", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastSeen", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "autonomousSystem", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "AutonomousSystem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "geo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "GeoEcsFields", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AutonomousSystem", - "description": "", - "fields": [ - { - "name": "number", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "organization", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "AutonomousSystemOrganization", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AutonomousSystemOrganization", - "description": "", - "fields": [ - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "UsersSortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "UsersFields", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "direction", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "UsersFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { "name": "name", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "count", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "FlowTarget", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { "name": "client", "description": "", "isDeprecated": false, "deprecationReason": null }, - { - "name": "destination", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "server", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "source", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UsersData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UsersEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UsersEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UsersNode", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UsersNode", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timestamp", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "user", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "UsersItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UsersItem", - "description": "", - "fields": [ - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "groupId", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "groupName", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "count", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "KpiNetworkData", - "description": "", - "fields": [ - { - "name": "networkEvents", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueFlowId", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueSourcePrivateIps", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueSourcePrivateIpsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiNetworkHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDestinationPrivateIps", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDestinationPrivateIpsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiNetworkHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dnsQueries", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "tlsHandshakes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "KpiNetworkHistogramData", - "description": "", - "fields": [ - { - "name": "x", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "y", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "KpiHostsData", - "description": "", - "fields": [ - { - "name": "hosts", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "hostsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authSuccess", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authSuccessHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authFailure", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authFailureHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueSourceIps", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueSourceIpsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDestinationIps", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDestinationIpsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "KpiHostHistogramData", - "description": "", - "fields": [ - { - "name": "x", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "y", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "KpiHostDetailsData", - "description": "", - "fields": [ - { - "name": "authSuccess", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authSuccessHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authFailure", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authFailureHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueSourceIps", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueSourceIpsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDestinationIps", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDestinationIpsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "HistogramType", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "authentications", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "anomalies", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "events", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "alerts", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "dns", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "MatrixHistogramOverTimeData", - "description": "", - "fields": [ - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "matrixHistogramData", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "MatrixOverTimeHistogramData", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "MatrixOverTimeHistogramData", - "description": "", - "fields": [ - { - "name": "x", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "y", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "g", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "FlowTargetSourceDest", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "destination", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "source", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "NetworkTopTablesSortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "NetworkTopTablesFields", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "direction", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "NetworkTopTablesFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "bytes_in", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "bytes_out", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "flows", "description": "", "isDeprecated": false, "deprecationReason": null }, - { - "name": "destination_ips", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source_ips", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopCountriesData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkTopCountriesEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopCountriesEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkTopCountriesItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopCountriesItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopCountriesItemSource", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopCountriesItemDestination", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "network", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopNetworkTablesEcsField", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TopCountriesItemSource", - "description": "", - "fields": [ - { - "name": "country", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "flows", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "location", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "GeoItem", - "description": "", - "fields": [ - { - "name": "geo", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "flowTarget", - "description": "", - "args": [], - "type": { "kind": "ENUM", "name": "FlowTargetSourceDest", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TopCountriesItemDestination", - "description": "", - "fields": [ - { - "name": "country", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "flows", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "location", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TopNetworkTablesEcsField", - "description": "", - "fields": [ - { - "name": "bytes_in", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "bytes_out", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopNFlowData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkTopNFlowEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopNFlowEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkTopNFlowItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopNFlowItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopNFlowItemSource", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopNFlowItemDestination", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "network", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopNetworkTablesEcsField", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TopNFlowItemSource", - "description": "", - "fields": [ - { - "name": "autonomous_system", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "AutonomousSystemItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "domain", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ip", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "location", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "flows", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AutonomousSystemItem", - "description": "", - "fields": [ - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "number", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TopNFlowItemDestination", - "description": "", - "fields": [ - { - "name": "autonomous_system", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "AutonomousSystemItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "domain", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ip", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "location", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "flows", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "NetworkDnsSortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "NetworkDnsFields", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "direction", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "NetworkDnsFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "dnsName", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryCount", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDomains", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dnsBytesIn", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dnsBytesOut", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkDnsData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkDnsEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "histogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "MatrixOverOrdinalHistogramData", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkDnsEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkDnsItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkDnsItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dnsBytesIn", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dnsBytesOut", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dnsName", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryCount", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDomains", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "MatrixOverOrdinalHistogramData", - "description": "", - "fields": [ - { - "name": "x", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "y", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "g", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkDsOverTimeData", - "description": "", - "fields": [ - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "matrixHistogramData", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "MatrixOverTimeHistogramData", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "NetworkHttpSortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "direction", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkHttpData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkHttpEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkHttpEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkHttpItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkHttpItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "domains", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastHost", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastSourceIp", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "methods", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "path", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "requestCount", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "statuses", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "OverviewNetworkData", - "description": "", - "fields": [ - { - "name": "auditbeatSocket", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "filebeatCisco", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "filebeatNetflow", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "filebeatPanw", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "filebeatSuricata", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "filebeatZeek", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "packetbeatDNS", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "packetbeatFlow", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "packetbeatTLS", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "OverviewHostData", - "description": "", - "fields": [ - { - "name": "auditbeatAuditd", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "auditbeatFIM", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "auditbeatLogin", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "auditbeatPackage", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "auditbeatProcess", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "auditbeatUser", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "endgameDns", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "endgameFile", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "endgameImageLoad", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "endgameNetwork", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "endgameProcess", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "endgameRegistry", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "endgameSecurity", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "filebeatSystemModule", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "winlogbeatSecurity", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "winlogbeatMWSysmonOperational", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "TlsSortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "TlsFields", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "direction", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "TlsFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { "name": "_id", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TlsEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TlsNode", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsNode", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timestamp", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "alternativeNames", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "notAfter", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "commonNames", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ja3", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "issuerNames", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UncommonProcessesData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UncommonProcessesEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UncommonProcessesEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UncommonProcessItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UncommonProcessItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "instances", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "process", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ProcessEcsFields", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "hosts", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "HostEcsFields", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "user", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "UserEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SayMyName", - "description": "", - "fields": [ - { - "name": "appName", - "description": "The id of the source", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TimelineResult", - "description": "", - "fields": [ - { - "name": "columns", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ColumnHeaderResult", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "created", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdBy", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dataProviders", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "DataProviderResult", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "dateRange", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "DateRangePickerResult", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "eventIdToNoteIds", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NoteResult", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "eventType", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "favorite", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "FavoriteTimelineResult", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "filters", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "FilterTimelineResult", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "kqlMode", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "kqlQuery", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SerializedFilterQueryResult", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "notes", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NoteResult", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "noteIds", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pinnedEventIds", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pinnedEventsSaveObject", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PinnedEvent", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "savedQueryId", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "savedObjectId", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "sort", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SortTimelineResult", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "title", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updated", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updatedBy", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ColumnHeaderResult", - "description": "", - "fields": [ - { - "name": "aggregatable", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "category", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "columnHeaderType", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "example", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "indexes", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "placeholder", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "searchable", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "DataProviderResult", - "description": "", - "fields": [ - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "enabled", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "excluded", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "kqlQuery", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryMatch", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "QueryMatchResult", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "and", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "DataProviderResult", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "QueryMatchResult", - "description": "", - "fields": [ - { - "name": "field", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "displayField", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "value", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "displayValue", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "operator", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "DateRangePickerResult", - "description": "", - "fields": [ - { - "name": "start", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "end", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "FavoriteTimelineResult", - "description": "", - "fields": [ - { - "name": "fullName", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "userName", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "favoriteDate", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "FilterTimelineResult", - "description": "", - "fields": [ - { - "name": "exists", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "meta", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "FilterMetaTimelineResult", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "match_all", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "missing", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "query", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "range", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "script", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "FilterMetaTimelineResult", - "description": "", - "fields": [ - { - "name": "alias", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "controlledBy", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "disabled", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "field", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "formattedValue", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "index", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "key", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "negate", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "params", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "value", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SerializedFilterQueryResult", - "description": "", - "fields": [ - { - "name": "filterQuery", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "SerializedKueryQueryResult", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SerializedKueryQueryResult", - "description": "", - "fields": [ - { - "name": "kuery", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "KueryFilterQueryResult", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "serializedQuery", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "KueryFilterQueryResult", - "description": "", - "fields": [ - { - "name": "kind", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "expression", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SortTimelineResult", - "description": "", - "fields": [ - { - "name": "columnId", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "sortDirection", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "PageInfoTimeline", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "pageIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pageSize", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "SortTimeline", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "sortField", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "SortFieldTimeline", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "sortOrder", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "SortFieldTimeline", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { "name": "title", "description": "", "isDeprecated": false, "deprecationReason": null }, - { - "name": "description", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updated", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "created", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ResponseTimelines", - "description": "", - "fields": [ - { - "name": "timeline", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TimelineResult", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Mutation", - "description": "", - "fields": [ - { - "name": "persistNote", - "description": "Persists a note", - "args": [ - { - "name": "noteId", - "description": "", - "type": { "kind": "SCALAR", "name": "ID", "ofType": null }, - "defaultValue": null - }, - { - "name": "version", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "note", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "NoteInput", "ofType": null } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ResponseNote", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deleteNote", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deleteNoteByTimelineId", - "description": "", - "args": [ - { - "name": "timelineId", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "version", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "persistPinnedEventOnTimeline", - "description": "Persists a pinned event in a timeline", - "args": [ - { - "name": "pinnedEventId", - "description": "", - "type": { "kind": "SCALAR", "name": "ID", "ofType": null }, - "defaultValue": null - }, - { - "name": "eventId", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "timelineId", - "description": "", - "type": { "kind": "SCALAR", "name": "ID", "ofType": null }, - "defaultValue": null - } - ], - "type": { "kind": "OBJECT", "name": "PinnedEvent", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deletePinnedEventOnTimeline", - "description": "Remove a pinned events in a timeline", - "args": [ - { - "name": "id", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deleteAllPinnedEventsOnTimeline", - "description": "Remove all pinned events in a timeline", - "args": [ - { - "name": "timelineId", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "persistTimeline", - "description": "Persists a timeline", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "ID", "ofType": null }, - "defaultValue": null - }, - { - "name": "version", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timeline", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimelineInput", "ofType": null } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ResponseTimeline", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "persistFavorite", - "description": "", - "args": [ - { - "name": "timelineId", - "description": "", - "type": { "kind": "SCALAR", "name": "ID", "ofType": null }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ResponseFavoriteTimeline", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deleteTimeline", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "NoteInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "eventId", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "note", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timelineId", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ResponseNote", - "description": "", - "fields": [ - { - "name": "code", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "message", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "note", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NoteResult", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "TimelineInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "columns", - "description": "", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "ColumnHeaderInput", "ofType": null } - } - }, - "defaultValue": null - }, - { - "name": "dataProviders", - "description": "", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "DataProviderInput", "ofType": null } - } - }, - "defaultValue": null - }, - { - "name": "description", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "eventType", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "filters", - "description": "", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "FilterTimelineInput", "ofType": null } - } - }, - "defaultValue": null - }, - { - "name": "kqlMode", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "kqlQuery", - "description": "", - "type": { - "kind": "INPUT_OBJECT", - "name": "SerializedFilterQueryInput", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "title", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "dateRange", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "DateRangePickerInput", "ofType": null }, - "defaultValue": null - }, - { - "name": "savedQueryId", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "SortTimelineInput", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "ColumnHeaderInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "aggregatable", - "description": "", - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "defaultValue": null - }, - { - "name": "category", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "columnHeaderType", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "description", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "example", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "indexes", - "description": "", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "defaultValue": null - }, - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "name", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "placeholder", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "searchable", - "description": "", - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "defaultValue": null - }, - { - "name": "type", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "DataProviderInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "name", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "enabled", - "description": "", - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "defaultValue": null - }, - { - "name": "excluded", - "description": "", - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "defaultValue": null - }, - { - "name": "kqlQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "queryMatch", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "QueryMatchInput", "ofType": null }, - "defaultValue": null - }, - { - "name": "and", - "description": "", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "DataProviderInput", "ofType": null } - } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "QueryMatchInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "displayField", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "value", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "displayValue", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "operator", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "FilterTimelineInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "exists", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "meta", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "FilterMetaTimelineInput", "ofType": null }, - "defaultValue": null - }, - { - "name": "match_all", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "missing", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "query", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "range", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "script", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "FilterMetaTimelineInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "alias", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "controlledBy", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "disabled", - "description": "", - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "defaultValue": null - }, - { - "name": "field", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "formattedValue", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "index", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "key", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "negate", - "description": "", - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "defaultValue": null - }, - { - "name": "params", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "type", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "value", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "SerializedFilterQueryInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "filterQuery", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "SerializedKueryQueryInput", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "SerializedKueryQueryInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "kuery", - "description": "", - "type": { "kind": "INPUT_OBJECT", "name": "KueryFilterQueryInput", "ofType": null }, - "defaultValue": null - }, - { - "name": "serializedQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "KueryFilterQueryInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "kind", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "expression", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "DateRangePickerInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "start", - "description": "", - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "defaultValue": null - }, - { - "name": "end", - "description": "", - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "SortTimelineInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "columnId", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "sortDirection", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ResponseTimeline", - "description": "", - "fields": [ - { - "name": "code", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "message", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timeline", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TimelineResult", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ResponseFavoriteTimeline", - "description": "", - "fields": [ - { - "name": "code", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "message", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "savedObjectId", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "favorite", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "FavoriteTimelineResult", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Schema", - "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.", - "fields": [ - { - "name": "types", - "description": "A list of all types supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__Type", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryType", - "description": "The type that query operations will be rooted at.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__Type", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mutationType", - "description": "If this server supports mutation, the type that mutation operations will be rooted at.", - "args": [], - "type": { "kind": "OBJECT", "name": "__Type", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subscriptionType", - "description": "If this server support subscription, the type that subscription operations will be rooted at.", - "args": [], - "type": { "kind": "OBJECT", "name": "__Type", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "directives", - "description": "A list of all directives supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__Directive", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Type", - "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.", - "fields": [ - { - "name": "kind", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "__TypeKind", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": null, - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fields", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__Field", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "interfaces", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__Type", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "possibleTypes", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__Type", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "enumValues", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__EnumValue", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inputFields", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__InputValue", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ofType", - "description": null, - "args": [], - "type": { "kind": "OBJECT", "name": "__Type", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__TypeKind", - "description": "An enum describing what kind of type a given `__Type` is.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "SCALAR", - "description": "Indicates this type is a scalar.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Indicates this type is a union. `possibleTypes` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Indicates this type is an enum. `enumValues` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Indicates this type is an input object. `inputFields` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "LIST", - "description": "Indicates this type is a list. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NON_NULL", - "description": "Indicates this type is a non-null. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Field", - "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__InputValue", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__Type", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__InputValue", - "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__Type", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "defaultValue", - "description": "A GraphQL-formatted string representing the default value for this input value.", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__EnumValue", - "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Directive", - "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "locations", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "__DirectiveLocation", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "__InputValue", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "onOperation", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onFragment", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onField", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__DirectiveLocation", - "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "QUERY", - "description": "Location adjacent to a query operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "MUTATION", - "description": "Location adjacent to a mutation operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SUBSCRIPTION", - "description": "Location adjacent to a subscription operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD", - "description": "Location adjacent to a field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_DEFINITION", - "description": "Location adjacent to a fragment definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_SPREAD", - "description": "Location adjacent to a fragment spread.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INLINE_FRAGMENT", - "description": "Location adjacent to an inline fragment.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCHEMA", - "description": "Location adjacent to a schema definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCALAR", - "description": "Location adjacent to a scalar definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Location adjacent to an object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD_DEFINITION", - "description": "Location adjacent to a field definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ARGUMENT_DEFINITION", - "description": "Location adjacent to an argument definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Location adjacent to an interface definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Location adjacent to a union definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Location adjacent to an enum definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM_VALUE", - "description": "Location adjacent to an enum value definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Location adjacent to an input object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_FIELD_DEFINITION", - "description": "Location adjacent to an input object field definition.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "EcsEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ECS", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "EventsTimelineData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "EcsEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfo", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "OsFields", - "description": "", - "fields": [ - { - "name": "platform", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "full", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "family", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "kernel", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HostFields", - "description": "", - "fields": [ - { - "name": "architecture", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ip", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mac", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "os", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "OsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "NetworkDirectionEcs", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "inbound", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "outbound", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "internal", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "external", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "incoming", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "outgoing", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "listening", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "unknown", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "NetworkHttpFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "domains", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastHost", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastSourceIp", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "methods", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "path", "description": "", "isDeprecated": false, "deprecationReason": null }, - { - "name": "requestCount", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "statuses", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "FlowDirection", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "uniDirectional", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "biDirectional", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "FavoriteTimelineInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "fullName", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "userName", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "favoriteDate", - "description": "", - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - } - ], - "directives": [ - { - "name": "skip", - "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [ - { - "name": "if", - "description": "Skipped when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "defaultValue": null - } - ] - }, - { - "name": "include", - "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [ - { - "name": "if", - "description": "Included when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "defaultValue": null - } - ] - }, - { - "name": "deprecated", - "description": "Marks an element of a GraphQL schema as no longer supported.", - "locations": ["FIELD_DEFINITION", "ENUM_VALUE"], - "args": [ - { - "name": "reason", - "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/).", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": "\"No longer supported\"" - } - ] - } - ] - } -} diff --git a/x-pack/legacy/plugins/siem/public/graphql/types.ts b/x-pack/legacy/plugins/siem/public/graphql/types.ts deleted file mode 100644 index 3528ee6e13a38..0000000000000 --- a/x-pack/legacy/plugins/siem/public/graphql/types.ts +++ /dev/null @@ -1,5943 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/* - * 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 type Maybe = T | null; - -export interface PageInfoNote { - pageIndex: number; - - pageSize: number; -} - -export interface SortNote { - sortField: SortFieldNote; - - sortOrder: Direction; -} - -export interface TimerangeInput { - /** The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan. */ - interval: string; - /** The end of the timerange */ - to: number; - /** The beginning of the timerange */ - from: number; -} - -export interface PaginationInputPaginated { - /** The activePage parameter defines the page of results you want to fetch */ - activePage: number; - /** The cursorStart parameter defines the start of the results to be displayed */ - cursorStart: number; - /** The fakePossibleCount parameter determines the total count in order to show 5 additional pages */ - fakePossibleCount: number; - /** The querySize parameter is the number of items to be returned */ - querySize: number; -} - -export interface PaginationInput { - /** The limit parameter allows you to configure the maximum amount of items to be returned */ - limit: number; - /** The cursor parameter defines the next result you want to fetch */ - cursor?: Maybe; - /** The tiebreaker parameter allow to be more precise to fetch the next item */ - tiebreaker?: Maybe; -} - -export interface SortField { - sortFieldId: string; - - direction: Direction; -} - -export interface LastTimeDetails { - hostName?: Maybe; - - ip?: Maybe; -} - -export interface HostsSortField { - field: HostsFields; - - direction: Direction; -} - -export interface UsersSortField { - field: UsersFields; - - direction: Direction; -} - -export interface NetworkTopTablesSortField { - field: NetworkTopTablesFields; - - direction: Direction; -} - -export interface NetworkDnsSortField { - field: NetworkDnsFields; - - direction: Direction; -} - -export interface NetworkHttpSortField { - direction: Direction; -} - -export interface TlsSortField { - field: TlsFields; - - direction: Direction; -} - -export interface PageInfoTimeline { - pageIndex: number; - - pageSize: number; -} - -export interface SortTimeline { - sortField: SortFieldTimeline; - - sortOrder: Direction; -} - -export interface NoteInput { - eventId?: Maybe; - - note?: Maybe; - - timelineId?: Maybe; -} - -export interface TimelineInput { - columns?: Maybe; - - dataProviders?: Maybe; - - description?: Maybe; - - eventType?: Maybe; - - filters?: Maybe; - - kqlMode?: Maybe; - - kqlQuery?: Maybe; - - title?: Maybe; - - dateRange?: Maybe; - - savedQueryId?: Maybe; - - sort?: Maybe; -} - -export interface ColumnHeaderInput { - aggregatable?: Maybe; - - category?: Maybe; - - columnHeaderType?: Maybe; - - description?: Maybe; - - example?: Maybe; - - indexes?: Maybe; - - id?: Maybe; - - name?: Maybe; - - placeholder?: Maybe; - - searchable?: Maybe; - - type?: Maybe; -} - -export interface DataProviderInput { - id?: Maybe; - - name?: Maybe; - - enabled?: Maybe; - - excluded?: Maybe; - - kqlQuery?: Maybe; - - queryMatch?: Maybe; - - and?: Maybe; -} - -export interface QueryMatchInput { - field?: Maybe; - - displayField?: Maybe; - - value?: Maybe; - - displayValue?: Maybe; - - operator?: Maybe; -} - -export interface FilterTimelineInput { - exists?: Maybe; - - meta?: Maybe; - - match_all?: Maybe; - - missing?: Maybe; - - query?: Maybe; - - range?: Maybe; - - script?: Maybe; -} - -export interface FilterMetaTimelineInput { - alias?: Maybe; - - controlledBy?: Maybe; - - disabled?: Maybe; - - field?: Maybe; - - formattedValue?: Maybe; - - index?: Maybe; - - key?: Maybe; - - negate?: Maybe; - - params?: Maybe; - - type?: Maybe; - - value?: Maybe; -} - -export interface SerializedFilterQueryInput { - filterQuery?: Maybe; -} - -export interface SerializedKueryQueryInput { - kuery?: Maybe; - - serializedQuery?: Maybe; -} - -export interface KueryFilterQueryInput { - kind?: Maybe; - - expression?: Maybe; -} - -export interface DateRangePickerInput { - start?: Maybe; - - end?: Maybe; -} - -export interface SortTimelineInput { - columnId?: Maybe; - - sortDirection?: Maybe; -} - -export interface FavoriteTimelineInput { - fullName?: Maybe; - - userName?: Maybe; - - favoriteDate?: Maybe; -} - -export enum SortFieldNote { - updatedBy = 'updatedBy', - updated = 'updated', -} - -export enum Direction { - asc = 'asc', - desc = 'desc', -} - -export enum LastEventIndexKey { - hostDetails = 'hostDetails', - hosts = 'hosts', - ipDetails = 'ipDetails', - network = 'network', -} - -export enum HostsFields { - hostName = 'hostName', - lastSeen = 'lastSeen', -} - -export enum UsersFields { - name = 'name', - count = 'count', -} - -export enum FlowTarget { - client = 'client', - destination = 'destination', - server = 'server', - source = 'source', -} - -export enum HistogramType { - authentications = 'authentications', - anomalies = 'anomalies', - events = 'events', - alerts = 'alerts', - dns = 'dns', -} - -export enum FlowTargetSourceDest { - destination = 'destination', - source = 'source', -} - -export enum NetworkTopTablesFields { - bytes_in = 'bytes_in', - bytes_out = 'bytes_out', - flows = 'flows', - destination_ips = 'destination_ips', - source_ips = 'source_ips', -} - -export enum NetworkDnsFields { - dnsName = 'dnsName', - queryCount = 'queryCount', - uniqueDomains = 'uniqueDomains', - dnsBytesIn = 'dnsBytesIn', - dnsBytesOut = 'dnsBytesOut', -} - -export enum TlsFields { - _id = '_id', -} - -export enum SortFieldTimeline { - title = 'title', - description = 'description', - updated = 'updated', - created = 'created', -} - -export enum NetworkDirectionEcs { - inbound = 'inbound', - outbound = 'outbound', - internal = 'internal', - external = 'external', - incoming = 'incoming', - outgoing = 'outgoing', - listening = 'listening', - unknown = 'unknown', -} - -export enum NetworkHttpFields { - domains = 'domains', - lastHost = 'lastHost', - lastSourceIp = 'lastSourceIp', - methods = 'methods', - path = 'path', - requestCount = 'requestCount', - statuses = 'statuses', -} - -export enum FlowDirection { - uniDirectional = 'uniDirectional', - biDirectional = 'biDirectional', -} - -export type ToStringArray = string[]; - -export type Date = string; - -export type ToNumberArray = number[]; - -export type ToDateArray = string[]; - -export type ToBooleanArray = boolean[]; - -export type ToAny = any; - -export type EsValue = any; - -// ==================================================== -// Scalars -// ==================================================== - -// ==================================================== -// Types -// ==================================================== - -export interface Query { - getNote: NoteResult; - - getNotesByTimelineId: NoteResult[]; - - getNotesByEventId: NoteResult[]; - - getAllNotes: ResponseNotes; - - getAllPinnedEventsByTimelineId: PinnedEvent[]; - /** Get a security data source by id */ - source: Source; - /** Get a list of all security data sources */ - allSources: Source[]; - - getOneTimeline: TimelineResult; - - getAllTimeline: ResponseTimelines; -} - -export interface NoteResult { - eventId?: Maybe; - - note?: Maybe; - - timelineId?: Maybe; - - noteId: string; - - created?: Maybe; - - createdBy?: Maybe; - - timelineVersion?: Maybe; - - updated?: Maybe; - - updatedBy?: Maybe; - - version?: Maybe; -} - -export interface ResponseNotes { - notes: NoteResult[]; - - totalCount?: Maybe; -} - -export interface PinnedEvent { - code?: Maybe; - - message?: Maybe; - - pinnedEventId: string; - - eventId?: Maybe; - - timelineId?: Maybe; - - timelineVersion?: Maybe; - - created?: Maybe; - - createdBy?: Maybe; - - updated?: Maybe; - - updatedBy?: Maybe; - - version?: Maybe; -} - -export interface Source { - /** The id of the source */ - id: string; - /** The raw configuration of the source */ - configuration: SourceConfiguration; - /** The status of the source */ - status: SourceStatus; - /** Gets Authentication success and failures based on a timerange */ - Authentications: AuthenticationsData; - - Timeline: TimelineData; - - TimelineDetails: TimelineDetailsData; - - LastEventTime: LastEventTimeData; - /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ - Hosts: HostsData; - - HostOverview: HostItem; - - HostFirstLastSeen: FirstLastSeenHost; - - IpOverview?: Maybe; - - Users: UsersData; - - KpiNetwork?: Maybe; - - KpiHosts: KpiHostsData; - - KpiHostDetails: KpiHostDetailsData; - - MatrixHistogram: MatrixHistogramOverTimeData; - - NetworkTopCountries: NetworkTopCountriesData; - - NetworkTopNFlow: NetworkTopNFlowData; - - NetworkDns: NetworkDnsData; - - NetworkDnsHistogram: NetworkDsOverTimeData; - - NetworkHttp: NetworkHttpData; - - OverviewNetwork?: Maybe; - - OverviewHost?: Maybe; - - Tls: TlsData; - /** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */ - UncommonProcesses: UncommonProcessesData; - /** Just a simple example to get the app name */ - whoAmI?: Maybe; -} - -/** A set of configuration options for a security data source */ -export interface SourceConfiguration { - /** The field mapping to use for this source */ - fields: SourceFields; -} - -/** A mapping of semantic fields to their document counterparts */ -export interface SourceFields { - /** The field to identify a container by */ - container: string; - /** The fields to identify a host by */ - host: string; - /** The fields that may contain the log event message. The first field found win. */ - message: string[]; - /** The field to identify a pod by */ - pod: string; - /** The field to use as a tiebreaker for log events that have identical timestamps */ - tiebreaker: string; - /** The field to use as a timestamp for metrics and logs */ - timestamp: string; -} - -/** The status of an infrastructure data source */ -export interface SourceStatus { - /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ - indicesExist: boolean; - /** The list of fields defined in the index mappings */ - indexFields: IndexField[]; -} - -/** A descriptor of a field in an index */ -export interface IndexField { - /** Where the field belong */ - category: string; - /** Example of field's value */ - example?: Maybe; - /** whether the field's belong to an alias index */ - indexes: (Maybe)[]; - /** The name of the field */ - name: string; - /** The type of the field's values as recognized by Kibana */ - type: string; - /** Whether the field's values can be efficiently searched for */ - searchable: boolean; - /** Whether the field's values can be aggregated */ - aggregatable: boolean; - /** Description of the field */ - description?: Maybe; - - format?: Maybe; -} - -export interface AuthenticationsData { - edges: AuthenticationsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface AuthenticationsEdges { - node: AuthenticationItem; - - cursor: CursorType; -} - -export interface AuthenticationItem { - _id: string; - - failures: number; - - successes: number; - - user: UserEcsFields; - - lastSuccess?: Maybe; - - lastFailure?: Maybe; -} - -export interface UserEcsFields { - domain?: Maybe; - - id?: Maybe; - - name?: Maybe; - - full_name?: Maybe; - - email?: Maybe; - - hash?: Maybe; - - group?: Maybe; -} - -export interface LastSourceHost { - timestamp?: Maybe; - - source?: Maybe; - - host?: Maybe; -} - -export interface SourceEcsFields { - bytes?: Maybe; - - ip?: Maybe; - - port?: Maybe; - - domain?: Maybe; - - geo?: Maybe; - - packets?: Maybe; -} - -export interface GeoEcsFields { - city_name?: Maybe; - - continent_name?: Maybe; - - country_iso_code?: Maybe; - - country_name?: Maybe; - - location?: Maybe; - - region_iso_code?: Maybe; - - region_name?: Maybe; -} - -export interface Location { - lon?: Maybe; - - lat?: Maybe; -} - -export interface HostEcsFields { - architecture?: Maybe; - - id?: Maybe; - - ip?: Maybe; - - mac?: Maybe; - - name?: Maybe; - - os?: Maybe; - - type?: Maybe; -} - -export interface OsEcsFields { - platform?: Maybe; - - name?: Maybe; - - full?: Maybe; - - family?: Maybe; - - version?: Maybe; - - kernel?: Maybe; -} - -export interface CursorType { - value?: Maybe; - - tiebreaker?: Maybe; -} - -export interface PageInfoPaginated { - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; -} - -export interface Inspect { - dsl: string[]; - - response: string[]; -} - -export interface TimelineData { - edges: TimelineEdges[]; - - totalCount: number; - - pageInfo: PageInfo; - - inspect?: Maybe; -} - -export interface TimelineEdges { - node: TimelineItem; - - cursor: CursorType; -} - -export interface TimelineItem { - _id: string; - - _index?: Maybe; - - data: TimelineNonEcsData[]; - - ecs: Ecs; -} - -export interface TimelineNonEcsData { - field: string; - - value?: Maybe; -} - -export interface Ecs { - _id: string; - - _index?: Maybe; - - auditd?: Maybe; - - destination?: Maybe; - - dns?: Maybe; - - endgame?: Maybe; - - event?: Maybe; - - geo?: Maybe; - - host?: Maybe; - - network?: Maybe; - - rule?: Maybe; - - signal?: Maybe; - - source?: Maybe; - - suricata?: Maybe; - - tls?: Maybe; - - zeek?: Maybe; - - http?: Maybe; - - url?: Maybe; - - timestamp?: Maybe; - - message?: Maybe; - - user?: Maybe; - - winlog?: Maybe; - - process?: Maybe; - - file?: Maybe; - - system?: Maybe; -} - -export interface AuditdEcsFields { - result?: Maybe; - - session?: Maybe; - - data?: Maybe; - - summary?: Maybe; - - sequence?: Maybe; -} - -export interface AuditdData { - acct?: Maybe; - - terminal?: Maybe; - - op?: Maybe; -} - -export interface Summary { - actor?: Maybe; - - object?: Maybe; - - how?: Maybe; - - message_type?: Maybe; - - sequence?: Maybe; -} - -export interface PrimarySecondary { - primary?: Maybe; - - secondary?: Maybe; - - type?: Maybe; -} - -export interface DestinationEcsFields { - bytes?: Maybe; - - ip?: Maybe; - - port?: Maybe; - - domain?: Maybe; - - geo?: Maybe; - - packets?: Maybe; -} - -export interface DnsEcsFields { - question?: Maybe; - - resolved_ip?: Maybe; - - response_code?: Maybe; -} - -export interface DnsQuestionData { - name?: Maybe; - - type?: Maybe; -} - -export interface EndgameEcsFields { - exit_code?: Maybe; - - file_name?: Maybe; - - file_path?: Maybe; - - logon_type?: Maybe; - - parent_process_name?: Maybe; - - pid?: Maybe; - - process_name?: Maybe; - - subject_domain_name?: Maybe; - - subject_logon_id?: Maybe; - - subject_user_name?: Maybe; - - target_domain_name?: Maybe; - - target_logon_id?: Maybe; - - target_user_name?: Maybe; -} - -export interface EventEcsFields { - action?: Maybe; - - category?: Maybe; - - code?: Maybe; - - created?: Maybe; - - dataset?: Maybe; - - duration?: Maybe; - - end?: Maybe; - - hash?: Maybe; - - id?: Maybe; - - kind?: Maybe; - - module?: Maybe; - - original?: Maybe; - - outcome?: Maybe; - - risk_score?: Maybe; - - risk_score_norm?: Maybe; - - severity?: Maybe; - - start?: Maybe; - - timezone?: Maybe; - - type?: Maybe; -} - -export interface NetworkEcsField { - bytes?: Maybe; - - community_id?: Maybe; - - direction?: Maybe; - - packets?: Maybe; - - protocol?: Maybe; - - transport?: Maybe; -} - -export interface RuleEcsField { - reference?: Maybe; -} - -export interface SignalField { - rule?: Maybe; - - original_time?: Maybe; -} - -export interface RuleField { - id?: Maybe; - - rule_id?: Maybe; - - false_positives: string[]; - - saved_id?: Maybe; - - timeline_id?: Maybe; - - timeline_title?: Maybe; - - max_signals?: Maybe; - - risk_score?: Maybe; - - output_index?: Maybe; - - description?: Maybe; - - from?: Maybe; - - immutable?: Maybe; - - index?: Maybe; - - interval?: Maybe; - - language?: Maybe; - - query?: Maybe; - - references?: Maybe; - - severity?: Maybe; - - tags?: Maybe; - - threat?: Maybe; - - type?: Maybe; - - size?: Maybe; - - to?: Maybe; - - enabled?: Maybe; - - filters?: Maybe; - - created_at?: Maybe; - - updated_at?: Maybe; - - created_by?: Maybe; - - updated_by?: Maybe; - - version?: Maybe; -} - -export interface SuricataEcsFields { - eve?: Maybe; -} - -export interface SuricataEveData { - alert?: Maybe; - - flow_id?: Maybe; - - proto?: Maybe; -} - -export interface SuricataAlertData { - signature?: Maybe; - - signature_id?: Maybe; -} - -export interface TlsEcsFields { - client_certificate?: Maybe; - - fingerprints?: Maybe; - - server_certificate?: Maybe; -} - -export interface TlsClientCertificateData { - fingerprint?: Maybe; -} - -export interface FingerprintData { - sha1?: Maybe; -} - -export interface TlsFingerprintsData { - ja3?: Maybe; -} - -export interface TlsJa3Data { - hash?: Maybe; -} - -export interface TlsServerCertificateData { - fingerprint?: Maybe; -} - -export interface ZeekEcsFields { - session_id?: Maybe; - - connection?: Maybe; - - notice?: Maybe; - - dns?: Maybe; - - http?: Maybe; - - files?: Maybe; - - ssl?: Maybe; -} - -export interface ZeekConnectionData { - local_resp?: Maybe; - - local_orig?: Maybe; - - missed_bytes?: Maybe; - - state?: Maybe; - - history?: Maybe; -} - -export interface ZeekNoticeData { - suppress_for?: Maybe; - - msg?: Maybe; - - note?: Maybe; - - sub?: Maybe; - - dst?: Maybe; - - dropped?: Maybe; - - peer_descr?: Maybe; -} - -export interface ZeekDnsData { - AA?: Maybe; - - qclass_name?: Maybe; - - RD?: Maybe; - - qtype_name?: Maybe; - - rejected?: Maybe; - - qtype?: Maybe; - - query?: Maybe; - - trans_id?: Maybe; - - qclass?: Maybe; - - RA?: Maybe; - - TC?: Maybe; -} - -export interface ZeekHttpData { - resp_mime_types?: Maybe; - - trans_depth?: Maybe; - - status_msg?: Maybe; - - resp_fuids?: Maybe; - - tags?: Maybe; -} - -export interface ZeekFileData { - session_ids?: Maybe; - - timedout?: Maybe; - - local_orig?: Maybe; - - tx_host?: Maybe; - - source?: Maybe; - - is_orig?: Maybe; - - overflow_bytes?: Maybe; - - sha1?: Maybe; - - duration?: Maybe; - - depth?: Maybe; - - analyzers?: Maybe; - - mime_type?: Maybe; - - rx_host?: Maybe; - - total_bytes?: Maybe; - - fuid?: Maybe; - - seen_bytes?: Maybe; - - missing_bytes?: Maybe; - - md5?: Maybe; -} - -export interface ZeekSslData { - cipher?: Maybe; - - established?: Maybe; - - resumed?: Maybe; - - version?: Maybe; -} - -export interface HttpEcsFields { - version?: Maybe; - - request?: Maybe; - - response?: Maybe; -} - -export interface HttpRequestData { - method?: Maybe; - - body?: Maybe; - - referrer?: Maybe; - - bytes?: Maybe; -} - -export interface HttpBodyData { - content?: Maybe; - - bytes?: Maybe; -} - -export interface HttpResponseData { - status_code?: Maybe; - - body?: Maybe; - - bytes?: Maybe; -} - -export interface UrlEcsFields { - domain?: Maybe; - - original?: Maybe; - - username?: Maybe; - - password?: Maybe; -} - -export interface WinlogEcsFields { - event_id?: Maybe; -} - -export interface ProcessEcsFields { - hash?: Maybe; - - pid?: Maybe; - - name?: Maybe; - - ppid?: Maybe; - - args?: Maybe; - - executable?: Maybe; - - title?: Maybe; - - thread?: Maybe; - - working_directory?: Maybe; -} - -export interface ProcessHashData { - md5?: Maybe; - - sha1?: Maybe; - - sha256?: Maybe; -} - -export interface Thread { - id?: Maybe; - - start?: Maybe; -} - -export interface FileFields { - name?: Maybe; - - path?: Maybe; - - target_path?: Maybe; - - extension?: Maybe; - - type?: Maybe; - - device?: Maybe; - - inode?: Maybe; - - uid?: Maybe; - - owner?: Maybe; - - gid?: Maybe; - - group?: Maybe; - - mode?: Maybe; - - size?: Maybe; - - mtime?: Maybe; - - ctime?: Maybe; -} - -export interface SystemEcsField { - audit?: Maybe; - - auth?: Maybe; -} - -export interface AuditEcsFields { - package?: Maybe; -} - -export interface PackageEcsFields { - arch?: Maybe; - - entity_id?: Maybe; - - name?: Maybe; - - size?: Maybe; - - summary?: Maybe; - - version?: Maybe; -} - -export interface AuthEcsFields { - ssh?: Maybe; -} - -export interface SshEcsFields { - method?: Maybe; - - signature?: Maybe; -} - -export interface PageInfo { - endCursor?: Maybe; - - hasNextPage?: Maybe; -} - -export interface TimelineDetailsData { - data?: Maybe; - - inspect?: Maybe; -} - -export interface DetailItem { - field: string; - - values?: Maybe; - - originalValue?: Maybe; -} - -export interface LastEventTimeData { - lastSeen?: Maybe; - - inspect?: Maybe; -} - -export interface HostsData { - edges: HostsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface HostsEdges { - node: HostItem; - - cursor: CursorType; -} - -export interface HostItem { - _id?: Maybe; - - lastSeen?: Maybe; - - host?: Maybe; - - cloud?: Maybe; - - inspect?: Maybe; -} - -export interface CloudFields { - instance?: Maybe; - - machine?: Maybe; - - provider?: Maybe<(Maybe)[]>; - - region?: Maybe<(Maybe)[]>; -} - -export interface CloudInstance { - id?: Maybe<(Maybe)[]>; -} - -export interface CloudMachine { - type?: Maybe<(Maybe)[]>; -} - -export interface FirstLastSeenHost { - inspect?: Maybe; - - firstSeen?: Maybe; - - lastSeen?: Maybe; -} - -export interface IpOverviewData { - client?: Maybe; - - destination?: Maybe; - - host: HostEcsFields; - - server?: Maybe; - - source?: Maybe; - - inspect?: Maybe; -} - -export interface Overview { - firstSeen?: Maybe; - - lastSeen?: Maybe; - - autonomousSystem: AutonomousSystem; - - geo: GeoEcsFields; -} - -export interface AutonomousSystem { - number?: Maybe; - - organization?: Maybe; -} - -export interface AutonomousSystemOrganization { - name?: Maybe; -} - -export interface UsersData { - edges: UsersEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface UsersEdges { - node: UsersNode; - - cursor: CursorType; -} - -export interface UsersNode { - _id?: Maybe; - - timestamp?: Maybe; - - user?: Maybe; -} - -export interface UsersItem { - name?: Maybe; - - id?: Maybe; - - groupId?: Maybe; - - groupName?: Maybe; - - count?: Maybe; -} - -export interface KpiNetworkData { - networkEvents?: Maybe; - - uniqueFlowId?: Maybe; - - uniqueSourcePrivateIps?: Maybe; - - uniqueSourcePrivateIpsHistogram?: Maybe; - - uniqueDestinationPrivateIps?: Maybe; - - uniqueDestinationPrivateIpsHistogram?: Maybe; - - dnsQueries?: Maybe; - - tlsHandshakes?: Maybe; - - inspect?: Maybe; -} - -export interface KpiNetworkHistogramData { - x?: Maybe; - - y?: Maybe; -} - -export interface KpiHostsData { - hosts?: Maybe; - - hostsHistogram?: Maybe; - - authSuccess?: Maybe; - - authSuccessHistogram?: Maybe; - - authFailure?: Maybe; - - authFailureHistogram?: Maybe; - - uniqueSourceIps?: Maybe; - - uniqueSourceIpsHistogram?: Maybe; - - uniqueDestinationIps?: Maybe; - - uniqueDestinationIpsHistogram?: Maybe; - - inspect?: Maybe; -} - -export interface KpiHostHistogramData { - x?: Maybe; - - y?: Maybe; -} - -export interface KpiHostDetailsData { - authSuccess?: Maybe; - - authSuccessHistogram?: Maybe; - - authFailure?: Maybe; - - authFailureHistogram?: Maybe; - - uniqueSourceIps?: Maybe; - - uniqueSourceIpsHistogram?: Maybe; - - uniqueDestinationIps?: Maybe; - - uniqueDestinationIpsHistogram?: Maybe; - - inspect?: Maybe; -} - -export interface MatrixHistogramOverTimeData { - inspect?: Maybe; - - matrixHistogramData: MatrixOverTimeHistogramData[]; - - totalCount: number; -} - -export interface MatrixOverTimeHistogramData { - x?: Maybe; - - y?: Maybe; - - g?: Maybe; -} - -export interface NetworkTopCountriesData { - edges: NetworkTopCountriesEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface NetworkTopCountriesEdges { - node: NetworkTopCountriesItem; - - cursor: CursorType; -} - -export interface NetworkTopCountriesItem { - _id?: Maybe; - - source?: Maybe; - - destination?: Maybe; - - network?: Maybe; -} - -export interface TopCountriesItemSource { - country?: Maybe; - - destination_ips?: Maybe; - - flows?: Maybe; - - location?: Maybe; - - source_ips?: Maybe; -} - -export interface GeoItem { - geo?: Maybe; - - flowTarget?: Maybe; -} - -export interface TopCountriesItemDestination { - country?: Maybe; - - destination_ips?: Maybe; - - flows?: Maybe; - - location?: Maybe; - - source_ips?: Maybe; -} - -export interface TopNetworkTablesEcsField { - bytes_in?: Maybe; - - bytes_out?: Maybe; -} - -export interface NetworkTopNFlowData { - edges: NetworkTopNFlowEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface NetworkTopNFlowEdges { - node: NetworkTopNFlowItem; - - cursor: CursorType; -} - -export interface NetworkTopNFlowItem { - _id?: Maybe; - - source?: Maybe; - - destination?: Maybe; - - network?: Maybe; -} - -export interface TopNFlowItemSource { - autonomous_system?: Maybe; - - domain?: Maybe; - - ip?: Maybe; - - location?: Maybe; - - flows?: Maybe; - - destination_ips?: Maybe; -} - -export interface AutonomousSystemItem { - name?: Maybe; - - number?: Maybe; -} - -export interface TopNFlowItemDestination { - autonomous_system?: Maybe; - - domain?: Maybe; - - ip?: Maybe; - - location?: Maybe; - - flows?: Maybe; - - source_ips?: Maybe; -} - -export interface NetworkDnsData { - edges: NetworkDnsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; - - histogram?: Maybe; -} - -export interface NetworkDnsEdges { - node: NetworkDnsItem; - - cursor: CursorType; -} - -export interface NetworkDnsItem { - _id?: Maybe; - - dnsBytesIn?: Maybe; - - dnsBytesOut?: Maybe; - - dnsName?: Maybe; - - queryCount?: Maybe; - - uniqueDomains?: Maybe; -} - -export interface MatrixOverOrdinalHistogramData { - x: string; - - y: number; - - g: string; -} - -export interface NetworkDsOverTimeData { - inspect?: Maybe; - - matrixHistogramData: MatrixOverTimeHistogramData[]; - - totalCount: number; -} - -export interface NetworkHttpData { - edges: NetworkHttpEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface NetworkHttpEdges { - node: NetworkHttpItem; - - cursor: CursorType; -} - -export interface NetworkHttpItem { - _id?: Maybe; - - domains: string[]; - - lastHost?: Maybe; - - lastSourceIp?: Maybe; - - methods: string[]; - - path?: Maybe; - - requestCount?: Maybe; - - statuses: string[]; -} - -export interface OverviewNetworkData { - auditbeatSocket?: Maybe; - - filebeatCisco?: Maybe; - - filebeatNetflow?: Maybe; - - filebeatPanw?: Maybe; - - filebeatSuricata?: Maybe; - - filebeatZeek?: Maybe; - - packetbeatDNS?: Maybe; - - packetbeatFlow?: Maybe; - - packetbeatTLS?: Maybe; - - inspect?: Maybe; -} - -export interface OverviewHostData { - auditbeatAuditd?: Maybe; - - auditbeatFIM?: Maybe; - - auditbeatLogin?: Maybe; - - auditbeatPackage?: Maybe; - - auditbeatProcess?: Maybe; - - auditbeatUser?: Maybe; - - endgameDns?: Maybe; - - endgameFile?: Maybe; - - endgameImageLoad?: Maybe; - - endgameNetwork?: Maybe; - - endgameProcess?: Maybe; - - endgameRegistry?: Maybe; - - endgameSecurity?: Maybe; - - filebeatSystemModule?: Maybe; - - winlogbeatSecurity?: Maybe; - - winlogbeatMWSysmonOperational?: Maybe; - - inspect?: Maybe; -} - -export interface TlsData { - edges: TlsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface TlsEdges { - node: TlsNode; - - cursor: CursorType; -} - -export interface TlsNode { - _id?: Maybe; - - timestamp?: Maybe; - - alternativeNames?: Maybe; - - notAfter?: Maybe; - - commonNames?: Maybe; - - ja3?: Maybe; - - issuerNames?: Maybe; -} - -export interface UncommonProcessesData { - edges: UncommonProcessesEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface UncommonProcessesEdges { - node: UncommonProcessItem; - - cursor: CursorType; -} - -export interface UncommonProcessItem { - _id: string; - - instances: number; - - process: ProcessEcsFields; - - hosts: HostEcsFields[]; - - user?: Maybe; -} - -export interface SayMyName { - /** The id of the source */ - appName: string; -} - -export interface TimelineResult { - columns?: Maybe; - - created?: Maybe; - - createdBy?: Maybe; - - dataProviders?: Maybe; - - dateRange?: Maybe; - - description?: Maybe; - - eventIdToNoteIds?: Maybe; - - eventType?: Maybe; - - favorite?: Maybe; - - filters?: Maybe; - - kqlMode?: Maybe; - - kqlQuery?: Maybe; - - notes?: Maybe; - - noteIds?: Maybe; - - pinnedEventIds?: Maybe; - - pinnedEventsSaveObject?: Maybe; - - savedQueryId?: Maybe; - - savedObjectId: string; - - sort?: Maybe; - - title?: Maybe; - - updated?: Maybe; - - updatedBy?: Maybe; - - version: string; -} - -export interface ColumnHeaderResult { - aggregatable?: Maybe; - - category?: Maybe; - - columnHeaderType?: Maybe; - - description?: Maybe; - - example?: Maybe; - - indexes?: Maybe; - - id?: Maybe; - - name?: Maybe; - - placeholder?: Maybe; - - searchable?: Maybe; - - type?: Maybe; -} - -export interface DataProviderResult { - id?: Maybe; - - name?: Maybe; - - enabled?: Maybe; - - excluded?: Maybe; - - kqlQuery?: Maybe; - - queryMatch?: Maybe; - - and?: Maybe; -} - -export interface QueryMatchResult { - field?: Maybe; - - displayField?: Maybe; - - value?: Maybe; - - displayValue?: Maybe; - - operator?: Maybe; -} - -export interface DateRangePickerResult { - start?: Maybe; - - end?: Maybe; -} - -export interface FavoriteTimelineResult { - fullName?: Maybe; - - userName?: Maybe; - - favoriteDate?: Maybe; -} - -export interface FilterTimelineResult { - exists?: Maybe; - - meta?: Maybe; - - match_all?: Maybe; - - missing?: Maybe; - - query?: Maybe; - - range?: Maybe; - - script?: Maybe; -} - -export interface FilterMetaTimelineResult { - alias?: Maybe; - - controlledBy?: Maybe; - - disabled?: Maybe; - - field?: Maybe; - - formattedValue?: Maybe; - - index?: Maybe; - - key?: Maybe; - - negate?: Maybe; - - params?: Maybe; - - type?: Maybe; - - value?: Maybe; -} - -export interface SerializedFilterQueryResult { - filterQuery?: Maybe; -} - -export interface SerializedKueryQueryResult { - kuery?: Maybe; - - serializedQuery?: Maybe; -} - -export interface KueryFilterQueryResult { - kind?: Maybe; - - expression?: Maybe; -} - -export interface SortTimelineResult { - columnId?: Maybe; - - sortDirection?: Maybe; -} - -export interface ResponseTimelines { - timeline: (Maybe)[]; - - totalCount?: Maybe; -} - -export interface Mutation { - /** Persists a note */ - persistNote: ResponseNote; - - deleteNote?: Maybe; - - deleteNoteByTimelineId?: Maybe; - /** Persists a pinned event in a timeline */ - persistPinnedEventOnTimeline?: Maybe; - /** Remove a pinned events in a timeline */ - deletePinnedEventOnTimeline: boolean; - /** Remove all pinned events in a timeline */ - deleteAllPinnedEventsOnTimeline: boolean; - /** Persists a timeline */ - persistTimeline: ResponseTimeline; - - persistFavorite: ResponseFavoriteTimeline; - - deleteTimeline: boolean; -} - -export interface ResponseNote { - code?: Maybe; - - message?: Maybe; - - note: NoteResult; -} - -export interface ResponseTimeline { - code?: Maybe; - - message?: Maybe; - - timeline: TimelineResult; -} - -export interface ResponseFavoriteTimeline { - code?: Maybe; - - message?: Maybe; - - savedObjectId: string; - - version: string; - - favorite?: Maybe; -} - -export interface EcsEdges { - node: Ecs; - - cursor: CursorType; -} - -export interface EventsTimelineData { - edges: EcsEdges[]; - - totalCount: number; - - pageInfo: PageInfo; - - inspect?: Maybe; -} - -export interface OsFields { - platform?: Maybe; - - name?: Maybe; - - full?: Maybe; - - family?: Maybe; - - version?: Maybe; - - kernel?: Maybe; -} - -export interface HostFields { - architecture?: Maybe; - - id?: Maybe; - - ip?: Maybe<(Maybe)[]>; - - mac?: Maybe<(Maybe)[]>; - - name?: Maybe; - - os?: Maybe; - - type?: Maybe; -} - -// ==================================================== -// Arguments -// ==================================================== - -export interface GetNoteQueryArgs { - id: string; -} -export interface GetNotesByTimelineIdQueryArgs { - timelineId: string; -} -export interface GetNotesByEventIdQueryArgs { - eventId: string; -} -export interface GetAllNotesQueryArgs { - pageInfo?: Maybe; - - search?: Maybe; - - sort?: Maybe; -} -export interface GetAllPinnedEventsByTimelineIdQueryArgs { - timelineId: string; -} -export interface SourceQueryArgs { - /** The id of the source */ - id: string; -} -export interface GetOneTimelineQueryArgs { - id: string; -} -export interface GetAllTimelineQueryArgs { - pageInfo?: Maybe; - - search?: Maybe; - - sort?: Maybe; - - onlyUserFavorite?: Maybe; -} -export interface AuthenticationsSourceArgs { - timerange: TimerangeInput; - - pagination: PaginationInputPaginated; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface TimelineSourceArgs { - pagination: PaginationInput; - - sortField: SortField; - - fieldRequested: string[]; - - timerange?: Maybe; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface TimelineDetailsSourceArgs { - eventId: string; - - indexName: string; - - defaultIndex: string[]; -} -export interface LastEventTimeSourceArgs { - id?: Maybe; - - indexKey: LastEventIndexKey; - - details: LastTimeDetails; - - defaultIndex: string[]; -} -export interface HostsSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - pagination: PaginationInputPaginated; - - sort: HostsSortField; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface HostOverviewSourceArgs { - id?: Maybe; - - hostName: string; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} -export interface HostFirstLastSeenSourceArgs { - id?: Maybe; - - hostName: string; - - defaultIndex: string[]; -} -export interface IpOverviewSourceArgs { - id?: Maybe; - - filterQuery?: Maybe; - - ip: string; - - defaultIndex: string[]; -} -export interface UsersSourceArgs { - filterQuery?: Maybe; - - id?: Maybe; - - ip: string; - - pagination: PaginationInputPaginated; - - sort: UsersSortField; - - flowTarget: FlowTarget; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} -export interface KpiNetworkSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface KpiHostsSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface KpiHostDetailsSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface MatrixHistogramSourceArgs { - filterQuery?: Maybe; - - defaultIndex: string[]; - - timerange: TimerangeInput; - - stackByField: string; - - histogramType: HistogramType; -} -export interface NetworkTopCountriesSourceArgs { - id?: Maybe; - - filterQuery?: Maybe; - - ip?: Maybe; - - flowTarget: FlowTargetSourceDest; - - pagination: PaginationInputPaginated; - - sort: NetworkTopTablesSortField; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} -export interface NetworkTopNFlowSourceArgs { - id?: Maybe; - - filterQuery?: Maybe; - - ip?: Maybe; - - flowTarget: FlowTargetSourceDest; - - pagination: PaginationInputPaginated; - - sort: NetworkTopTablesSortField; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} -export interface NetworkDnsSourceArgs { - filterQuery?: Maybe; - - id?: Maybe; - - isPtrIncluded: boolean; - - pagination: PaginationInputPaginated; - - sort: NetworkDnsSortField; - - stackByField?: Maybe; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} -export interface NetworkDnsHistogramSourceArgs { - filterQuery?: Maybe; - - defaultIndex: string[]; - - timerange: TimerangeInput; - - stackByField?: Maybe; -} -export interface NetworkHttpSourceArgs { - id?: Maybe; - - filterQuery?: Maybe; - - ip?: Maybe; - - pagination: PaginationInputPaginated; - - sort: NetworkHttpSortField; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} -export interface OverviewNetworkSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface OverviewHostSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface TlsSourceArgs { - filterQuery?: Maybe; - - id?: Maybe; - - ip: string; - - pagination: PaginationInputPaginated; - - sort: TlsSortField; - - flowTarget: FlowTargetSourceDest; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} -export interface UncommonProcessesSourceArgs { - timerange: TimerangeInput; - - pagination: PaginationInputPaginated; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface IndicesExistSourceStatusArgs { - defaultIndex: string[]; -} -export interface IndexFieldsSourceStatusArgs { - defaultIndex: string[]; -} -export interface PersistNoteMutationArgs { - noteId?: Maybe; - - version?: Maybe; - - note: NoteInput; -} -export interface DeleteNoteMutationArgs { - id: string[]; -} -export interface DeleteNoteByTimelineIdMutationArgs { - timelineId: string; - - version?: Maybe; -} -export interface PersistPinnedEventOnTimelineMutationArgs { - pinnedEventId?: Maybe; - - eventId: string; - - timelineId?: Maybe; -} -export interface DeletePinnedEventOnTimelineMutationArgs { - id: string[]; -} -export interface DeleteAllPinnedEventsOnTimelineMutationArgs { - timelineId: string; -} -export interface PersistTimelineMutationArgs { - id?: Maybe; - - version?: Maybe; - - timeline: TimelineInput; -} -export interface PersistFavoriteMutationArgs { - timelineId?: Maybe; -} -export interface DeleteTimelineMutationArgs { - id: string[]; -} - -// ==================================================== -// Documents -// ==================================================== - -export namespace GetAuthenticationsQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - pagination: PaginationInputPaginated; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - Authentications: Authentications; - }; - - export type Authentications = { - __typename?: 'AuthenticationsData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'AuthenticationsEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'AuthenticationItem'; - - _id: string; - - failures: number; - - successes: number; - - user: User; - - lastSuccess: Maybe; - - lastFailure: Maybe; - }; - - export type User = { - __typename?: 'UserEcsFields'; - - name: Maybe; - }; - - export type LastSuccess = { - __typename?: 'LastSourceHost'; - - timestamp: Maybe; - - source: Maybe<_Source>; - - host: Maybe; - }; - - export type _Source = { - __typename?: 'SourceEcsFields'; - - ip: Maybe; - }; - - export type Host = { - __typename?: 'HostEcsFields'; - - id: Maybe; - - name: Maybe; - }; - - export type LastFailure = { - __typename?: 'LastSourceHost'; - - timestamp: Maybe; - - source: Maybe<__Source>; - - host: Maybe<_Host>; - }; - - export type __Source = { - __typename?: 'SourceEcsFields'; - - ip: Maybe; - }; - - export type _Host = { - __typename?: 'HostEcsFields'; - - id: Maybe; - - name: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetLastEventTimeQuery { - export type Variables = { - sourceId: string; - indexKey: LastEventIndexKey; - details: LastTimeDetails; - defaultIndex: string[]; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - LastEventTime: LastEventTime; - }; - - export type LastEventTime = { - __typename?: 'LastEventTimeData'; - - lastSeen: Maybe; - }; -} - -export namespace GetHostFirstLastSeenQuery { - export type Variables = { - sourceId: string; - hostName: string; - defaultIndex: string[]; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - HostFirstLastSeen: HostFirstLastSeen; - }; - - export type HostFirstLastSeen = { - __typename?: 'FirstLastSeenHost'; - - firstSeen: Maybe; - - lastSeen: Maybe; - }; -} - -export namespace GetHostsTableQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - pagination: PaginationInputPaginated; - sort: HostsSortField; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - Hosts: Hosts; - }; - - export type Hosts = { - __typename?: 'HostsData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'HostsEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'HostItem'; - - _id: Maybe; - - lastSeen: Maybe; - - host: Maybe; - }; - - export type Host = { - __typename?: 'HostEcsFields'; - - id: Maybe; - - name: Maybe; - - os: Maybe; - }; - - export type Os = { - __typename?: 'OsEcsFields'; - - name: Maybe; - - version: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetHostOverviewQuery { - export type Variables = { - sourceId: string; - hostName: string; - timerange: TimerangeInput; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - HostOverview: HostOverview; - }; - - export type HostOverview = { - __typename?: 'HostItem'; - - _id: Maybe; - - host: Maybe; - - cloud: Maybe; - - inspect: Maybe; - }; - - export type Host = { - __typename?: 'HostEcsFields'; - - architecture: Maybe; - - id: Maybe; - - ip: Maybe; - - mac: Maybe; - - name: Maybe; - - os: Maybe; - - type: Maybe; - }; - - export type Os = { - __typename?: 'OsEcsFields'; - - family: Maybe; - - name: Maybe; - - platform: Maybe; - - version: Maybe; - }; - - export type Cloud = { - __typename?: 'CloudFields'; - - instance: Maybe; - - machine: Maybe; - - provider: Maybe<(Maybe)[]>; - - region: Maybe<(Maybe)[]>; - }; - - export type Instance = { - __typename?: 'CloudInstance'; - - id: Maybe<(Maybe)[]>; - }; - - export type Machine = { - __typename?: 'CloudMachine'; - - type: Maybe<(Maybe)[]>; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetIpOverviewQuery { - export type Variables = { - sourceId: string; - filterQuery?: Maybe; - ip: string; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - IpOverview: Maybe; - }; - - export type IpOverview = { - __typename?: 'IpOverviewData'; - - source: Maybe<_Source>; - - destination: Maybe; - - host: Host; - - inspect: Maybe; - }; - - export type _Source = { - __typename?: 'Overview'; - - firstSeen: Maybe; - - lastSeen: Maybe; - - autonomousSystem: AutonomousSystem; - - geo: Geo; - }; - - export type AutonomousSystem = { - __typename?: 'AutonomousSystem'; - - number: Maybe; - - organization: Maybe; - }; - - export type Organization = { - __typename?: 'AutonomousSystemOrganization'; - - name: Maybe; - }; - - export type Geo = { - __typename?: 'GeoEcsFields'; - - continent_name: Maybe; - - city_name: Maybe; - - country_iso_code: Maybe; - - country_name: Maybe; - - location: Maybe; - - region_iso_code: Maybe; - - region_name: Maybe; - }; - - export type Location = { - __typename?: 'Location'; - - lat: Maybe; - - lon: Maybe; - }; - - export type Destination = { - __typename?: 'Overview'; - - firstSeen: Maybe; - - lastSeen: Maybe; - - autonomousSystem: _AutonomousSystem; - - geo: _Geo; - }; - - export type _AutonomousSystem = { - __typename?: 'AutonomousSystem'; - - number: Maybe; - - organization: Maybe<_Organization>; - }; - - export type _Organization = { - __typename?: 'AutonomousSystemOrganization'; - - name: Maybe; - }; - - export type _Geo = { - __typename?: 'GeoEcsFields'; - - continent_name: Maybe; - - city_name: Maybe; - - country_iso_code: Maybe; - - country_name: Maybe; - - location: Maybe<_Location>; - - region_iso_code: Maybe; - - region_name: Maybe; - }; - - export type _Location = { - __typename?: 'Location'; - - lat: Maybe; - - lon: Maybe; - }; - - export type Host = { - __typename?: 'HostEcsFields'; - - architecture: Maybe; - - id: Maybe; - - ip: Maybe; - - mac: Maybe; - - name: Maybe; - - os: Maybe; - - type: Maybe; - }; - - export type Os = { - __typename?: 'OsEcsFields'; - - family: Maybe; - - name: Maybe; - - platform: Maybe; - - version: Maybe; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetKpiHostDetailsQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - KpiHostDetails: KpiHostDetails; - }; - - export type KpiHostDetails = { - __typename?: 'KpiHostDetailsData'; - - authSuccess: Maybe; - - authSuccessHistogram: Maybe; - - authFailure: Maybe; - - authFailureHistogram: Maybe; - - uniqueSourceIps: Maybe; - - uniqueSourceIpsHistogram: Maybe; - - uniqueDestinationIps: Maybe; - - uniqueDestinationIpsHistogram: Maybe; - - inspect: Maybe; - }; - - export type AuthSuccessHistogram = KpiHostDetailsChartFields.Fragment; - - export type AuthFailureHistogram = KpiHostDetailsChartFields.Fragment; - - export type UniqueSourceIpsHistogram = KpiHostDetailsChartFields.Fragment; - - export type UniqueDestinationIpsHistogram = KpiHostDetailsChartFields.Fragment; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetKpiHostsQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - KpiHosts: KpiHosts; - }; - - export type KpiHosts = { - __typename?: 'KpiHostsData'; - - hosts: Maybe; - - hostsHistogram: Maybe; - - authSuccess: Maybe; - - authSuccessHistogram: Maybe; - - authFailure: Maybe; - - authFailureHistogram: Maybe; - - uniqueSourceIps: Maybe; - - uniqueSourceIpsHistogram: Maybe; - - uniqueDestinationIps: Maybe; - - uniqueDestinationIpsHistogram: Maybe; - - inspect: Maybe; - }; - - export type HostsHistogram = KpiHostChartFields.Fragment; - - export type AuthSuccessHistogram = KpiHostChartFields.Fragment; - - export type AuthFailureHistogram = KpiHostChartFields.Fragment; - - export type UniqueSourceIpsHistogram = KpiHostChartFields.Fragment; - - export type UniqueDestinationIpsHistogram = KpiHostChartFields.Fragment; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetKpiNetworkQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - KpiNetwork: Maybe; - }; - - export type KpiNetwork = { - __typename?: 'KpiNetworkData'; - - networkEvents: Maybe; - - uniqueFlowId: Maybe; - - uniqueSourcePrivateIps: Maybe; - - uniqueSourcePrivateIpsHistogram: Maybe; - - uniqueDestinationPrivateIps: Maybe; - - uniqueDestinationPrivateIpsHistogram: Maybe; - - dnsQueries: Maybe; - - tlsHandshakes: Maybe; - - inspect: Maybe; - }; - - export type UniqueSourcePrivateIpsHistogram = KpiNetworkChartFields.Fragment; - - export type UniqueDestinationPrivateIpsHistogram = KpiNetworkChartFields.Fragment; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetMatrixHistogramQuery { - export type Variables = { - defaultIndex: string[]; - filterQuery?: Maybe; - histogramType: HistogramType; - inspect: boolean; - sourceId: string; - stackByField: string; - timerange: TimerangeInput; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - MatrixHistogram: MatrixHistogram; - }; - - export type MatrixHistogram = { - __typename?: 'MatrixHistogramOverTimeData'; - - matrixHistogramData: MatrixHistogramData[]; - - totalCount: number; - - inspect: Maybe; - }; - - export type MatrixHistogramData = { - __typename?: 'MatrixOverTimeHistogramData'; - - x: Maybe; - - y: Maybe; - - g: Maybe; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetNetworkDnsQuery { - export type Variables = { - defaultIndex: string[]; - filterQuery?: Maybe; - inspect: boolean; - isPtrIncluded: boolean; - pagination: PaginationInputPaginated; - sort: NetworkDnsSortField; - sourceId: string; - stackByField?: Maybe; - timerange: TimerangeInput; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - NetworkDns: NetworkDns; - }; - - export type NetworkDns = { - __typename?: 'NetworkDnsData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'NetworkDnsEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'NetworkDnsItem'; - - _id: Maybe; - - dnsBytesIn: Maybe; - - dnsBytesOut: Maybe; - - dnsName: Maybe; - - queryCount: Maybe; - - uniqueDomains: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetNetworkHttpQuery { - export type Variables = { - sourceId: string; - ip?: Maybe; - filterQuery?: Maybe; - pagination: PaginationInputPaginated; - sort: NetworkHttpSortField; - timerange: TimerangeInput; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - NetworkHttp: NetworkHttp; - }; - - export type NetworkHttp = { - __typename?: 'NetworkHttpData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'NetworkHttpEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'NetworkHttpItem'; - - domains: string[]; - - lastHost: Maybe; - - lastSourceIp: Maybe; - - methods: string[]; - - path: Maybe; - - requestCount: Maybe; - - statuses: string[]; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetNetworkTopCountriesQuery { - export type Variables = { - sourceId: string; - ip?: Maybe; - filterQuery?: Maybe; - pagination: PaginationInputPaginated; - sort: NetworkTopTablesSortField; - flowTarget: FlowTargetSourceDest; - timerange: TimerangeInput; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - NetworkTopCountries: NetworkTopCountries; - }; - - export type NetworkTopCountries = { - __typename?: 'NetworkTopCountriesData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'NetworkTopCountriesEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'NetworkTopCountriesItem'; - - source: Maybe<_Source>; - - destination: Maybe; - - network: Maybe; - }; - - export type _Source = { - __typename?: 'TopCountriesItemSource'; - - country: Maybe; - - destination_ips: Maybe; - - flows: Maybe; - - source_ips: Maybe; - }; - - export type Destination = { - __typename?: 'TopCountriesItemDestination'; - - country: Maybe; - - destination_ips: Maybe; - - flows: Maybe; - - source_ips: Maybe; - }; - - export type Network = { - __typename?: 'TopNetworkTablesEcsField'; - - bytes_in: Maybe; - - bytes_out: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetNetworkTopNFlowQuery { - export type Variables = { - sourceId: string; - ip?: Maybe; - filterQuery?: Maybe; - pagination: PaginationInputPaginated; - sort: NetworkTopTablesSortField; - flowTarget: FlowTargetSourceDest; - timerange: TimerangeInput; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - NetworkTopNFlow: NetworkTopNFlow; - }; - - export type NetworkTopNFlow = { - __typename?: 'NetworkTopNFlowData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'NetworkTopNFlowEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'NetworkTopNFlowItem'; - - source: Maybe<_Source>; - - destination: Maybe; - - network: Maybe; - }; - - export type _Source = { - __typename?: 'TopNFlowItemSource'; - - autonomous_system: Maybe; - - domain: Maybe; - - ip: Maybe; - - location: Maybe; - - flows: Maybe; - - destination_ips: Maybe; - }; - - export type AutonomousSystem = { - __typename?: 'AutonomousSystemItem'; - - name: Maybe; - - number: Maybe; - }; - - export type Location = { - __typename?: 'GeoItem'; - - geo: Maybe; - - flowTarget: Maybe; - }; - - export type Geo = { - __typename?: 'GeoEcsFields'; - - continent_name: Maybe; - - country_name: Maybe; - - country_iso_code: Maybe; - - city_name: Maybe; - - region_iso_code: Maybe; - - region_name: Maybe; - }; - - export type Destination = { - __typename?: 'TopNFlowItemDestination'; - - autonomous_system: Maybe<_AutonomousSystem>; - - domain: Maybe; - - ip: Maybe; - - location: Maybe<_Location>; - - flows: Maybe; - - source_ips: Maybe; - }; - - export type _AutonomousSystem = { - __typename?: 'AutonomousSystemItem'; - - name: Maybe; - - number: Maybe; - }; - - export type _Location = { - __typename?: 'GeoItem'; - - geo: Maybe<_Geo>; - - flowTarget: Maybe; - }; - - export type _Geo = { - __typename?: 'GeoEcsFields'; - - continent_name: Maybe; - - country_name: Maybe; - - country_iso_code: Maybe; - - city_name: Maybe; - - region_iso_code: Maybe; - - region_name: Maybe; - }; - - export type Network = { - __typename?: 'TopNetworkTablesEcsField'; - - bytes_in: Maybe; - - bytes_out: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetOverviewHostQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - OverviewHost: Maybe; - }; - - export type OverviewHost = { - __typename?: 'OverviewHostData'; - - auditbeatAuditd: Maybe; - - auditbeatFIM: Maybe; - - auditbeatLogin: Maybe; - - auditbeatPackage: Maybe; - - auditbeatProcess: Maybe; - - auditbeatUser: Maybe; - - endgameDns: Maybe; - - endgameFile: Maybe; - - endgameImageLoad: Maybe; - - endgameNetwork: Maybe; - - endgameProcess: Maybe; - - endgameRegistry: Maybe; - - endgameSecurity: Maybe; - - filebeatSystemModule: Maybe; - - winlogbeatSecurity: Maybe; - - winlogbeatMWSysmonOperational: Maybe; - - inspect: Maybe; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetOverviewNetworkQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - OverviewNetwork: Maybe; - }; - - export type OverviewNetwork = { - __typename?: 'OverviewNetworkData'; - - auditbeatSocket: Maybe; - - filebeatCisco: Maybe; - - filebeatNetflow: Maybe; - - filebeatPanw: Maybe; - - filebeatSuricata: Maybe; - - filebeatZeek: Maybe; - - packetbeatDNS: Maybe; - - packetbeatFlow: Maybe; - - packetbeatTLS: Maybe; - - inspect: Maybe; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace SourceQuery { - export type Variables = { - sourceId?: Maybe; - defaultIndex: string[]; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - status: Status; - }; - - export type Status = { - __typename?: 'SourceStatus'; - - indicesExist: boolean; - - indexFields: IndexFields[]; - }; - - export type IndexFields = { - __typename?: 'IndexField'; - - category: string; - - description: Maybe; - - example: Maybe; - - indexes: (Maybe)[]; - - name: string; - - searchable: boolean; - - type: string; - - aggregatable: boolean; - - format: Maybe; - }; -} - -export namespace GetAllTimeline { - export type Variables = { - pageInfo: PageInfoTimeline; - search?: Maybe; - sort?: Maybe; - onlyUserFavorite?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - getAllTimeline: GetAllTimeline; - }; - - export type GetAllTimeline = { - __typename?: 'ResponseTimelines'; - - totalCount: Maybe; - - timeline: (Maybe)[]; - }; - - export type Timeline = { - __typename?: 'TimelineResult'; - - savedObjectId: string; - - description: Maybe; - - favorite: Maybe; - - eventIdToNoteIds: Maybe; - - notes: Maybe; - - noteIds: Maybe; - - pinnedEventIds: Maybe; - - title: Maybe; - - created: Maybe; - - createdBy: Maybe; - - updated: Maybe; - - updatedBy: Maybe; - - version: string; - }; - - export type Favorite = { - __typename?: 'FavoriteTimelineResult'; - - fullName: Maybe; - - userName: Maybe; - - favoriteDate: Maybe; - }; - - export type EventIdToNoteIds = { - __typename?: 'NoteResult'; - - eventId: Maybe; - - note: Maybe; - - timelineId: Maybe; - - noteId: string; - - created: Maybe; - - createdBy: Maybe; - - timelineVersion: Maybe; - - updated: Maybe; - - updatedBy: Maybe; - - version: Maybe; - }; - - export type Notes = { - __typename?: 'NoteResult'; - - eventId: Maybe; - - note: Maybe; - - timelineId: Maybe; - - timelineVersion: Maybe; - - noteId: string; - - created: Maybe; - - createdBy: Maybe; - - updated: Maybe; - - updatedBy: Maybe; - - version: Maybe; - }; -} - -export namespace DeleteTimelineMutation { - export type Variables = { - id: string[]; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - deleteTimeline: boolean; - }; -} - -export namespace GetTimelineDetailsQuery { - export type Variables = { - sourceId: string; - eventId: string; - indexName: string; - defaultIndex: string[]; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - TimelineDetails: TimelineDetails; - }; - - export type TimelineDetails = { - __typename?: 'TimelineDetailsData'; - - data: Maybe; - }; - - export type Data = { - __typename?: 'DetailItem'; - - field: string; - - values: Maybe; - - originalValue: Maybe; - }; -} - -export namespace PersistTimelineFavoriteMutation { - export type Variables = { - timelineId?: Maybe; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - persistFavorite: PersistFavorite; - }; - - export type PersistFavorite = { - __typename?: 'ResponseFavoriteTimeline'; - - savedObjectId: string; - - version: string; - - favorite: Maybe; - }; - - export type Favorite = { - __typename?: 'FavoriteTimelineResult'; - - fullName: Maybe; - - userName: Maybe; - - favoriteDate: Maybe; - }; -} - -export namespace GetTimelineQuery { - export type Variables = { - sourceId: string; - fieldRequested: string[]; - pagination: PaginationInput; - sortField: SortField; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - Timeline: Timeline; - }; - - export type Timeline = { - __typename?: 'TimelineData'; - - totalCount: number; - - inspect: Maybe; - - pageInfo: PageInfo; - - edges: Edges[]; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; - - export type PageInfo = { - __typename?: 'PageInfo'; - - endCursor: Maybe; - - hasNextPage: Maybe; - }; - - export type EndCursor = { - __typename?: 'CursorType'; - - value: Maybe; - - tiebreaker: Maybe; - }; - - export type Edges = { - __typename?: 'TimelineEdges'; - - node: Node; - }; - - export type Node = { - __typename?: 'TimelineItem'; - - _id: string; - - _index: Maybe; - - data: Data[]; - - ecs: Ecs; - }; - - export type Data = { - __typename?: 'TimelineNonEcsData'; - - field: string; - - value: Maybe; - }; - - export type Ecs = { - __typename?: 'ECS'; - - _id: string; - - _index: Maybe; - - timestamp: Maybe; - - message: Maybe; - - system: Maybe; - - event: Maybe; - - auditd: Maybe; - - file: Maybe; - - host: Maybe; - - rule: Maybe; - - source: Maybe<_Source>; - - destination: Maybe; - - dns: Maybe; - - endgame: Maybe; - - geo: Maybe<__Geo>; - - signal: Maybe; - - suricata: Maybe; - - network: Maybe; - - http: Maybe; - - tls: Maybe; - - url: Maybe; - - user: Maybe; - - winlog: Maybe; - - process: Maybe; - - zeek: Maybe; - }; - - export type System = { - __typename?: 'SystemEcsField'; - - auth: Maybe; - - audit: Maybe; - }; - - export type Auth = { - __typename?: 'AuthEcsFields'; - - ssh: Maybe; - }; - - export type Ssh = { - __typename?: 'SshEcsFields'; - - signature: Maybe; - - method: Maybe; - }; - - export type Audit = { - __typename?: 'AuditEcsFields'; - - package: Maybe; - }; - - export type Package = { - __typename?: 'PackageEcsFields'; - - arch: Maybe; - - entity_id: Maybe; - - name: Maybe; - - size: Maybe; - - summary: Maybe; - - version: Maybe; - }; - - export type Event = { - __typename?: 'EventEcsFields'; - - action: Maybe; - - category: Maybe; - - code: Maybe; - - created: Maybe; - - dataset: Maybe; - - duration: Maybe; - - end: Maybe; - - hash: Maybe; - - id: Maybe; - - kind: Maybe; - - module: Maybe; - - original: Maybe; - - outcome: Maybe; - - risk_score: Maybe; - - risk_score_norm: Maybe; - - severity: Maybe; - - start: Maybe; - - timezone: Maybe; - - type: Maybe; - }; - - export type Auditd = { - __typename?: 'AuditdEcsFields'; - - result: Maybe; - - session: Maybe; - - data: Maybe<_Data>; - - summary: Maybe; - }; - - export type _Data = { - __typename?: 'AuditdData'; - - acct: Maybe; - - terminal: Maybe; - - op: Maybe; - }; - - export type Summary = { - __typename?: 'Summary'; - - actor: Maybe; - - object: Maybe; - - how: Maybe; - - message_type: Maybe; - - sequence: Maybe; - }; - - export type Actor = { - __typename?: 'PrimarySecondary'; - - primary: Maybe; - - secondary: Maybe; - }; - - export type Object = { - __typename?: 'PrimarySecondary'; - - primary: Maybe; - - secondary: Maybe; - - type: Maybe; - }; - - export type File = { - __typename?: 'FileFields'; - - name: Maybe; - - path: Maybe; - - target_path: Maybe; - - extension: Maybe; - - type: Maybe; - - device: Maybe; - - inode: Maybe; - - uid: Maybe; - - owner: Maybe; - - gid: Maybe; - - group: Maybe; - - mode: Maybe; - - size: Maybe; - - mtime: Maybe; - - ctime: Maybe; - }; - - export type Host = { - __typename?: 'HostEcsFields'; - - id: Maybe; - - name: Maybe; - - ip: Maybe; - }; - - export type Rule = { - __typename?: 'RuleEcsField'; - - reference: Maybe; - }; - - export type _Source = { - __typename?: 'SourceEcsFields'; - - bytes: Maybe; - - ip: Maybe; - - packets: Maybe; - - port: Maybe; - - geo: Maybe; - }; - - export type Geo = { - __typename?: 'GeoEcsFields'; - - continent_name: Maybe; - - country_name: Maybe; - - country_iso_code: Maybe; - - city_name: Maybe; - - region_iso_code: Maybe; - - region_name: Maybe; - }; - - export type Destination = { - __typename?: 'DestinationEcsFields'; - - bytes: Maybe; - - ip: Maybe; - - packets: Maybe; - - port: Maybe; - - geo: Maybe<_Geo>; - }; - - export type _Geo = { - __typename?: 'GeoEcsFields'; - - continent_name: Maybe; - - country_name: Maybe; - - country_iso_code: Maybe; - - city_name: Maybe; - - region_iso_code: Maybe; - - region_name: Maybe; - }; - - export type Dns = { - __typename?: 'DnsEcsFields'; - - question: Maybe; - - resolved_ip: Maybe; - - response_code: Maybe; - }; - - export type Question = { - __typename?: 'DnsQuestionData'; - - name: Maybe; - - type: Maybe; - }; - - export type Endgame = { - __typename?: 'EndgameEcsFields'; - - exit_code: Maybe; - - file_name: Maybe; - - file_path: Maybe; - - logon_type: Maybe; - - parent_process_name: Maybe; - - pid: Maybe; - - process_name: Maybe; - - subject_domain_name: Maybe; - - subject_logon_id: Maybe; - - subject_user_name: Maybe; - - target_domain_name: Maybe; - - target_logon_id: Maybe; - - target_user_name: Maybe; - }; - - export type __Geo = { - __typename?: 'GeoEcsFields'; - - region_name: Maybe; - - country_iso_code: Maybe; - }; - - export type Signal = { - __typename?: 'SignalField'; - - original_time: Maybe; - - rule: Maybe<_Rule>; - }; - - export type _Rule = { - __typename?: 'RuleField'; - - id: Maybe; - - saved_id: Maybe; - - timeline_id: Maybe; - - timeline_title: Maybe; - - output_index: Maybe; - - from: Maybe; - - index: Maybe; - - language: Maybe; - - query: Maybe; - - to: Maybe; - - filters: Maybe; - }; - - export type Suricata = { - __typename?: 'SuricataEcsFields'; - - eve: Maybe; - }; - - export type Eve = { - __typename?: 'SuricataEveData'; - - proto: Maybe; - - flow_id: Maybe; - - alert: Maybe; - }; - - export type Alert = { - __typename?: 'SuricataAlertData'; - - signature: Maybe; - - signature_id: Maybe; - }; - - export type Network = { - __typename?: 'NetworkEcsField'; - - bytes: Maybe; - - community_id: Maybe; - - direction: Maybe; - - packets: Maybe; - - protocol: Maybe; - - transport: Maybe; - }; - - export type Http = { - __typename?: 'HttpEcsFields'; - - version: Maybe; - - request: Maybe; - - response: Maybe; - }; - - export type Request = { - __typename?: 'HttpRequestData'; - - method: Maybe; - - body: Maybe; - - referrer: Maybe; - }; - - export type Body = { - __typename?: 'HttpBodyData'; - - bytes: Maybe; - - content: Maybe; - }; - - export type Response = { - __typename?: 'HttpResponseData'; - - status_code: Maybe; - - body: Maybe<_Body>; - }; - - export type _Body = { - __typename?: 'HttpBodyData'; - - bytes: Maybe; - - content: Maybe; - }; - - export type Tls = { - __typename?: 'TlsEcsFields'; - - client_certificate: Maybe; - - fingerprints: Maybe; - - server_certificate: Maybe; - }; - - export type ClientCertificate = { - __typename?: 'TlsClientCertificateData'; - - fingerprint: Maybe; - }; - - export type Fingerprint = { - __typename?: 'FingerprintData'; - - sha1: Maybe; - }; - - export type Fingerprints = { - __typename?: 'TlsFingerprintsData'; - - ja3: Maybe; - }; - - export type Ja3 = { - __typename?: 'TlsJa3Data'; - - hash: Maybe; - }; - - export type ServerCertificate = { - __typename?: 'TlsServerCertificateData'; - - fingerprint: Maybe<_Fingerprint>; - }; - - export type _Fingerprint = { - __typename?: 'FingerprintData'; - - sha1: Maybe; - }; - - export type Url = { - __typename?: 'UrlEcsFields'; - - original: Maybe; - - domain: Maybe; - - username: Maybe; - - password: Maybe; - }; - - export type User = { - __typename?: 'UserEcsFields'; - - domain: Maybe; - - name: Maybe; - }; - - export type Winlog = { - __typename?: 'WinlogEcsFields'; - - event_id: Maybe; - }; - - export type Process = { - __typename?: 'ProcessEcsFields'; - - hash: Maybe; - - pid: Maybe; - - name: Maybe; - - ppid: Maybe; - - args: Maybe; - - executable: Maybe; - - title: Maybe; - - working_directory: Maybe; - }; - - export type Hash = { - __typename?: 'ProcessHashData'; - - md5: Maybe; - - sha1: Maybe; - - sha256: Maybe; - }; - - export type Zeek = { - __typename?: 'ZeekEcsFields'; - - session_id: Maybe; - - connection: Maybe; - - notice: Maybe; - - dns: Maybe<_Dns>; - - http: Maybe<_Http>; - - files: Maybe; - - ssl: Maybe; - }; - - export type Connection = { - __typename?: 'ZeekConnectionData'; - - local_resp: Maybe; - - local_orig: Maybe; - - missed_bytes: Maybe; - - state: Maybe; - - history: Maybe; - }; - - export type Notice = { - __typename?: 'ZeekNoticeData'; - - suppress_for: Maybe; - - msg: Maybe; - - note: Maybe; - - sub: Maybe; - - dst: Maybe; - - dropped: Maybe; - - peer_descr: Maybe; - }; - - export type _Dns = { - __typename?: 'ZeekDnsData'; - - AA: Maybe; - - qclass_name: Maybe; - - RD: Maybe; - - qtype_name: Maybe; - - rejected: Maybe; - - qtype: Maybe; - - query: Maybe; - - trans_id: Maybe; - - qclass: Maybe; - - RA: Maybe; - - TC: Maybe; - }; - - export type _Http = { - __typename?: 'ZeekHttpData'; - - resp_mime_types: Maybe; - - trans_depth: Maybe; - - status_msg: Maybe; - - resp_fuids: Maybe; - - tags: Maybe; - }; - - export type Files = { - __typename?: 'ZeekFileData'; - - session_ids: Maybe; - - timedout: Maybe; - - local_orig: Maybe; - - tx_host: Maybe; - - source: Maybe; - - is_orig: Maybe; - - overflow_bytes: Maybe; - - sha1: Maybe; - - duration: Maybe; - - depth: Maybe; - - analyzers: Maybe; - - mime_type: Maybe; - - rx_host: Maybe; - - total_bytes: Maybe; - - fuid: Maybe; - - seen_bytes: Maybe; - - missing_bytes: Maybe; - - md5: Maybe; - }; - - export type Ssl = { - __typename?: 'ZeekSslData'; - - cipher: Maybe; - - established: Maybe; - - resumed: Maybe; - - version: Maybe; - }; -} - -export namespace PersistTimelineNoteMutation { - export type Variables = { - noteId?: Maybe; - version?: Maybe; - note: NoteInput; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - persistNote: PersistNote; - }; - - export type PersistNote = { - __typename?: 'ResponseNote'; - - code: Maybe; - - message: Maybe; - - note: Note; - }; - - export type Note = { - __typename?: 'NoteResult'; - - eventId: Maybe; - - note: Maybe; - - timelineId: Maybe; - - timelineVersion: Maybe; - - noteId: string; - - created: Maybe; - - createdBy: Maybe; - - updated: Maybe; - - updatedBy: Maybe; - - version: Maybe; - }; -} - -export namespace GetOneTimeline { - export type Variables = { - id: string; - }; - - export type Query = { - __typename?: 'Query'; - - getOneTimeline: GetOneTimeline; - }; - - export type GetOneTimeline = { - __typename?: 'TimelineResult'; - - savedObjectId: string; - - columns: Maybe; - - dataProviders: Maybe; - - dateRange: Maybe; - - description: Maybe; - - eventType: Maybe; - - eventIdToNoteIds: Maybe; - - favorite: Maybe; - - filters: Maybe; - - kqlMode: Maybe; - - kqlQuery: Maybe; - - notes: Maybe; - - noteIds: Maybe; - - pinnedEventIds: Maybe; - - pinnedEventsSaveObject: Maybe; - - title: Maybe; - - savedQueryId: Maybe; - - sort: Maybe; - - created: Maybe; - - createdBy: Maybe; - - updated: Maybe; - - updatedBy: Maybe; - - version: string; - }; - - export type Columns = { - __typename?: 'ColumnHeaderResult'; - - aggregatable: Maybe; - - category: Maybe; - - columnHeaderType: Maybe; - - description: Maybe; - - example: Maybe; - - indexes: Maybe; - - id: Maybe; - - name: Maybe; - - searchable: Maybe; - - type: Maybe; - }; - - export type DataProviders = { - __typename?: 'DataProviderResult'; - - id: Maybe; - - name: Maybe; - - enabled: Maybe; - - excluded: Maybe; - - kqlQuery: Maybe; - - queryMatch: Maybe; - - and: Maybe; - }; - - export type QueryMatch = { - __typename?: 'QueryMatchResult'; - - field: Maybe; - - displayField: Maybe; - - value: Maybe; - - displayValue: Maybe; - - operator: Maybe; - }; - - export type And = { - __typename?: 'DataProviderResult'; - - id: Maybe; - - name: Maybe; - - enabled: Maybe; - - excluded: Maybe; - - kqlQuery: Maybe; - - queryMatch: Maybe<_QueryMatch>; - }; - - export type _QueryMatch = { - __typename?: 'QueryMatchResult'; - - field: Maybe; - - displayField: Maybe; - - value: Maybe; - - displayValue: Maybe; - - operator: Maybe; - }; - - export type DateRange = { - __typename?: 'DateRangePickerResult'; - - start: Maybe; - - end: Maybe; - }; - - export type EventIdToNoteIds = { - __typename?: 'NoteResult'; - - eventId: Maybe; - - note: Maybe; - - timelineId: Maybe; - - noteId: string; - - created: Maybe; - - createdBy: Maybe; - - timelineVersion: Maybe; - - updated: Maybe; - - updatedBy: Maybe; - - version: Maybe; - }; - - export type Favorite = { - __typename?: 'FavoriteTimelineResult'; - - fullName: Maybe; - - userName: Maybe; - - favoriteDate: Maybe; - }; - - export type Filters = { - __typename?: 'FilterTimelineResult'; - - meta: Maybe; - - query: Maybe; - - exists: Maybe; - - match_all: Maybe; - - missing: Maybe; - - range: Maybe; - - script: Maybe; - }; - - export type Meta = { - __typename?: 'FilterMetaTimelineResult'; - - alias: Maybe; - - controlledBy: Maybe; - - disabled: Maybe; - - field: Maybe; - - formattedValue: Maybe; - - index: Maybe; - - key: Maybe; - - negate: Maybe; - - params: Maybe; - - type: Maybe; - - value: Maybe; - }; - - export type KqlQuery = { - __typename?: 'SerializedFilterQueryResult'; - - filterQuery: Maybe; - }; - - export type FilterQuery = { - __typename?: 'SerializedKueryQueryResult'; - - kuery: Maybe; - - serializedQuery: Maybe; - }; - - export type Kuery = { - __typename?: 'KueryFilterQueryResult'; - - kind: Maybe; - - expression: Maybe; - }; - - export type Notes = { - __typename?: 'NoteResult'; - - eventId: Maybe; - - note: Maybe; - - timelineId: Maybe; - - timelineVersion: Maybe; - - noteId: string; - - created: Maybe; - - createdBy: Maybe; - - updated: Maybe; - - updatedBy: Maybe; - - version: Maybe; - }; - - export type PinnedEventsSaveObject = { - __typename?: 'PinnedEvent'; - - pinnedEventId: string; - - eventId: Maybe; - - timelineId: Maybe; - - created: Maybe; - - createdBy: Maybe; - - updated: Maybe; - - updatedBy: Maybe; - - version: Maybe; - }; - - export type Sort = { - __typename?: 'SortTimelineResult'; - - columnId: Maybe; - - sortDirection: Maybe; - }; -} - -export namespace PersistTimelineMutation { - export type Variables = { - timelineId?: Maybe; - version?: Maybe; - timeline: TimelineInput; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - persistTimeline: PersistTimeline; - }; - - export type PersistTimeline = { - __typename?: 'ResponseTimeline'; - - code: Maybe; - - message: Maybe; - - timeline: Timeline; - }; - - export type Timeline = { - __typename?: 'TimelineResult'; - - savedObjectId: string; - - version: string; - - columns: Maybe; - - dataProviders: Maybe; - - description: Maybe; - - eventType: Maybe; - - favorite: Maybe; - - filters: Maybe; - - kqlMode: Maybe; - - kqlQuery: Maybe; - - title: Maybe; - - dateRange: Maybe; - - savedQueryId: Maybe; - - sort: Maybe; - - created: Maybe; - - createdBy: Maybe; - - updated: Maybe; - - updatedBy: Maybe; - }; - - export type Columns = { - __typename?: 'ColumnHeaderResult'; - - aggregatable: Maybe; - - category: Maybe; - - columnHeaderType: Maybe; - - description: Maybe; - - example: Maybe; - - indexes: Maybe; - - id: Maybe; - - name: Maybe; - - searchable: Maybe; - - type: Maybe; - }; - - export type DataProviders = { - __typename?: 'DataProviderResult'; - - id: Maybe; - - name: Maybe; - - enabled: Maybe; - - excluded: Maybe; - - kqlQuery: Maybe; - - queryMatch: Maybe; - - and: Maybe; - }; - - export type QueryMatch = { - __typename?: 'QueryMatchResult'; - - field: Maybe; - - displayField: Maybe; - - value: Maybe; - - displayValue: Maybe; - - operator: Maybe; - }; - - export type And = { - __typename?: 'DataProviderResult'; - - id: Maybe; - - name: Maybe; - - enabled: Maybe; - - excluded: Maybe; - - kqlQuery: Maybe; - - queryMatch: Maybe<_QueryMatch>; - }; - - export type _QueryMatch = { - __typename?: 'QueryMatchResult'; - - field: Maybe; - - displayField: Maybe; - - value: Maybe; - - displayValue: Maybe; - - operator: Maybe; - }; - - export type Favorite = { - __typename?: 'FavoriteTimelineResult'; - - fullName: Maybe; - - userName: Maybe; - - favoriteDate: Maybe; - }; - - export type Filters = { - __typename?: 'FilterTimelineResult'; - - meta: Maybe; - - query: Maybe; - - exists: Maybe; - - match_all: Maybe; - - missing: Maybe; - - range: Maybe; - - script: Maybe; - }; - - export type Meta = { - __typename?: 'FilterMetaTimelineResult'; - - alias: Maybe; - - controlledBy: Maybe; - - disabled: Maybe; - - field: Maybe; - - formattedValue: Maybe; - - index: Maybe; - - key: Maybe; - - negate: Maybe; - - params: Maybe; - - type: Maybe; - - value: Maybe; - }; - - export type KqlQuery = { - __typename?: 'SerializedFilterQueryResult'; - - filterQuery: Maybe; - }; - - export type FilterQuery = { - __typename?: 'SerializedKueryQueryResult'; - - kuery: Maybe; - - serializedQuery: Maybe; - }; - - export type Kuery = { - __typename?: 'KueryFilterQueryResult'; - - kind: Maybe; - - expression: Maybe; - }; - - export type DateRange = { - __typename?: 'DateRangePickerResult'; - - start: Maybe; - - end: Maybe; - }; - - export type Sort = { - __typename?: 'SortTimelineResult'; - - columnId: Maybe; - - sortDirection: Maybe; - }; -} - -export namespace PersistTimelinePinnedEventMutation { - export type Variables = { - pinnedEventId?: Maybe; - eventId: string; - timelineId?: Maybe; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - persistPinnedEventOnTimeline: Maybe; - }; - - export type PersistPinnedEventOnTimeline = { - __typename?: 'PinnedEvent'; - - pinnedEventId: string; - - eventId: Maybe; - - timelineId: Maybe; - - timelineVersion: Maybe; - - created: Maybe; - - createdBy: Maybe; - - updated: Maybe; - - updatedBy: Maybe; - - version: Maybe; - }; -} - -export namespace GetTlsQuery { - export type Variables = { - sourceId: string; - filterQuery?: Maybe; - flowTarget: FlowTargetSourceDest; - ip: string; - pagination: PaginationInputPaginated; - sort: TlsSortField; - timerange: TimerangeInput; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - Tls: Tls; - }; - - export type Tls = { - __typename?: 'TlsData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'TlsEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'TlsNode'; - - _id: Maybe; - - alternativeNames: Maybe; - - commonNames: Maybe; - - ja3: Maybe; - - issuerNames: Maybe; - - notAfter: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetUncommonProcessesQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - pagination: PaginationInputPaginated; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - UncommonProcesses: UncommonProcesses; - }; - - export type UncommonProcesses = { - __typename?: 'UncommonProcessesData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'UncommonProcessesEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'UncommonProcessItem'; - - _id: string; - - instances: number; - - process: Process; - - user: Maybe; - - hosts: Hosts[]; - }; - - export type Process = { - __typename?: 'ProcessEcsFields'; - - args: Maybe; - - name: Maybe; - }; - - export type User = { - __typename?: 'UserEcsFields'; - - id: Maybe; - - name: Maybe; - }; - - export type Hosts = { - __typename?: 'HostEcsFields'; - - name: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetUsersQuery { - export type Variables = { - sourceId: string; - filterQuery?: Maybe; - flowTarget: FlowTarget; - ip: string; - pagination: PaginationInputPaginated; - sort: UsersSortField; - timerange: TimerangeInput; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - Users: Users; - }; - - export type Users = { - __typename?: 'UsersData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'UsersEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'UsersNode'; - - user: Maybe; - }; - - export type User = { - __typename?: 'UsersItem'; - - name: Maybe; - - id: Maybe; - - groupId: Maybe; - - groupName: Maybe; - - count: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace KpiHostDetailsChartFields { - export type Fragment = { - __typename?: 'KpiHostHistogramData'; - - x: Maybe; - - y: Maybe; - }; -} - -export namespace KpiHostChartFields { - export type Fragment = { - __typename?: 'KpiHostHistogramData'; - - x: Maybe; - - y: Maybe; - }; -} - -export namespace KpiNetworkChartFields { - export type Fragment = { - __typename?: 'KpiNetworkHistogramData'; - - x: Maybe; - - y: Maybe; - }; -} diff --git a/x-pack/legacy/plugins/siem/public/graphql/types.tsx b/x-pack/legacy/plugins/siem/public/graphql/types.tsx new file mode 100644 index 0000000000000..6bf0e89ff5b8d --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/graphql/types.tsx @@ -0,0 +1,5314 @@ +/* + * 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. + */ + +/* tslint:disable */ +/* eslint-disable */ + +import gql from 'graphql-tag'; +import * as React from 'react'; +import * as ApolloReactCommon from '@apollo/client'; +import * as ApolloReactComponents from '@apollo/react-components'; +import * as ApolloReactHooks from '@apollo/client'; +export type Maybe = T | null; +export type Omit = Pick>; + +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: string, + String: string, + Boolean: boolean, + Int: number, + Float: number, + ToStringArray: string[], + Date: string, + ToNumberArray: number[], + ToDateArray: string[], + ToBooleanArray: boolean[], + ToAny: any, + EsValue: any, +}; + +export type AuditdData = { + __typename?: 'AuditdData', + acct?: Maybe, + terminal?: Maybe, + op?: Maybe, +}; + +export type AuditdEcsFields = { + __typename?: 'AuditdEcsFields', + result?: Maybe, + session?: Maybe, + data?: Maybe, + summary?: Maybe, + sequence?: Maybe, +}; + +export type AuditEcsFields = { + __typename?: 'AuditEcsFields', + package?: Maybe, +}; + +export type AuthEcsFields = { + __typename?: 'AuthEcsFields', + ssh?: Maybe, +}; + +export type AuthenticationItem = { + __typename?: 'AuthenticationItem', + _id: Scalars['String'], + failures: Scalars['Float'], + successes: Scalars['Float'], + user: UserEcsFields, + lastSuccess?: Maybe, + lastFailure?: Maybe, +}; + +export type AuthenticationsData = { + __typename?: 'AuthenticationsData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +}; + +export type AuthenticationsEdges = { + __typename?: 'AuthenticationsEdges', + node: AuthenticationItem, + cursor: CursorType, +}; + +export type AutonomousSystem = { + __typename?: 'AutonomousSystem', + number?: Maybe, + organization?: Maybe, +}; + +export type AutonomousSystemItem = { + __typename?: 'AutonomousSystemItem', + name?: Maybe, + number?: Maybe, +}; + +export type AutonomousSystemOrganization = { + __typename?: 'AutonomousSystemOrganization', + name?: Maybe, +}; + +export type CloudFields = { + __typename?: 'CloudFields', + instance?: Maybe, + machine?: Maybe, + provider?: Maybe>>, + region?: Maybe>>, +}; + +export type CloudInstance = { + __typename?: 'CloudInstance', + id?: Maybe>>, +}; + +export type CloudMachine = { + __typename?: 'CloudMachine', + type?: Maybe>>, +}; + +export type ColumnHeaderInput = { + aggregatable?: Maybe, + category?: Maybe, + columnHeaderType?: Maybe, + description?: Maybe, + example?: Maybe, + indexes?: Maybe>, + id?: Maybe, + name?: Maybe, + placeholder?: Maybe, + searchable?: Maybe, + type?: Maybe, +}; + +export type ColumnHeaderResult = { + __typename?: 'ColumnHeaderResult', + aggregatable?: Maybe, + category?: Maybe, + columnHeaderType?: Maybe, + description?: Maybe, + example?: Maybe, + indexes?: Maybe>, + id?: Maybe, + name?: Maybe, + placeholder?: Maybe, + searchable?: Maybe, + type?: Maybe, +}; + +export type CursorType = { + __typename?: 'CursorType', + value?: Maybe, + tiebreaker?: Maybe, +}; + +export type DataProviderInput = { + id?: Maybe, + name?: Maybe, + enabled?: Maybe, + excluded?: Maybe, + kqlQuery?: Maybe, + queryMatch?: Maybe, + and?: Maybe>, +}; + +export type DataProviderResult = { + __typename?: 'DataProviderResult', + id?: Maybe, + name?: Maybe, + enabled?: Maybe, + excluded?: Maybe, + kqlQuery?: Maybe, + queryMatch?: Maybe, + and?: Maybe>, +}; + + +export type DateRangePickerInput = { + start?: Maybe, + end?: Maybe, +}; + +export type DateRangePickerResult = { + __typename?: 'DateRangePickerResult', + start?: Maybe, + end?: Maybe, +}; + +export type DestinationEcsFields = { + __typename?: 'DestinationEcsFields', + bytes?: Maybe, + ip?: Maybe, + port?: Maybe, + domain?: Maybe, + geo?: Maybe, + packets?: Maybe, +}; + +export type DetailItem = { + __typename?: 'DetailItem', + field: Scalars['String'], + values?: Maybe, + originalValue?: Maybe, +}; + +export enum Direction { + asc = 'asc', + desc = 'desc' +} + +export type DnsEcsFields = { + __typename?: 'DnsEcsFields', + question?: Maybe, + resolved_ip?: Maybe, + response_code?: Maybe, +}; + +export type DnsQuestionData = { + __typename?: 'DnsQuestionData', + name?: Maybe, + type?: Maybe, +}; + +export type Ecs = { + __typename?: 'ECS', + _id: Scalars['String'], + _index?: Maybe, + auditd?: Maybe, + destination?: Maybe, + dns?: Maybe, + endgame?: Maybe, + event?: Maybe, + geo?: Maybe, + host?: Maybe, + network?: Maybe, + rule?: Maybe, + signal?: Maybe, + source?: Maybe, + suricata?: Maybe, + tls?: Maybe, + zeek?: Maybe, + http?: Maybe, + url?: Maybe, + timestamp?: Maybe, + message?: Maybe, + user?: Maybe, + winlog?: Maybe, + process?: Maybe, + file?: Maybe, + system?: Maybe, +}; + +export type EcsEdges = { + __typename?: 'EcsEdges', + node: Ecs, + cursor: CursorType, +}; + +export type EndgameEcsFields = { + __typename?: 'EndgameEcsFields', + exit_code?: Maybe, + file_name?: Maybe, + file_path?: Maybe, + logon_type?: Maybe, + parent_process_name?: Maybe, + pid?: Maybe, + process_name?: Maybe, + subject_domain_name?: Maybe, + subject_logon_id?: Maybe, + subject_user_name?: Maybe, + target_domain_name?: Maybe, + target_logon_id?: Maybe, + target_user_name?: Maybe, +}; + + +export type EventEcsFields = { + __typename?: 'EventEcsFields', + action?: Maybe, + category?: Maybe, + code?: Maybe, + created?: Maybe, + dataset?: Maybe, + duration?: Maybe, + end?: Maybe, + hash?: Maybe, + id?: Maybe, + kind?: Maybe, + module?: Maybe, + original?: Maybe, + outcome?: Maybe, + risk_score?: Maybe, + risk_score_norm?: Maybe, + severity?: Maybe, + start?: Maybe, + timezone?: Maybe, + type?: Maybe, +}; + +export type EventsTimelineData = { + __typename?: 'EventsTimelineData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfo, + inspect?: Maybe, +}; + +export type FavoriteTimelineInput = { + fullName?: Maybe, + userName?: Maybe, + favoriteDate?: Maybe, +}; + +export type FavoriteTimelineResult = { + __typename?: 'FavoriteTimelineResult', + fullName?: Maybe, + userName?: Maybe, + favoriteDate?: Maybe, +}; + +export type FileFields = { + __typename?: 'FileFields', + name?: Maybe, + path?: Maybe, + target_path?: Maybe, + extension?: Maybe, + type?: Maybe, + device?: Maybe, + inode?: Maybe, + uid?: Maybe, + owner?: Maybe, + gid?: Maybe, + group?: Maybe, + mode?: Maybe, + size?: Maybe, + mtime?: Maybe, + ctime?: Maybe, +}; + +export type FilterMetaTimelineInput = { + alias?: Maybe, + controlledBy?: Maybe, + disabled?: Maybe, + field?: Maybe, + formattedValue?: Maybe, + index?: Maybe, + key?: Maybe, + negate?: Maybe, + params?: Maybe, + type?: Maybe, + value?: Maybe, +}; + +export type FilterMetaTimelineResult = { + __typename?: 'FilterMetaTimelineResult', + alias?: Maybe, + controlledBy?: Maybe, + disabled?: Maybe, + field?: Maybe, + formattedValue?: Maybe, + index?: Maybe, + key?: Maybe, + negate?: Maybe, + params?: Maybe, + type?: Maybe, + value?: Maybe, +}; + +export type FilterTimelineInput = { + exists?: Maybe, + meta?: Maybe, + match_all?: Maybe, + missing?: Maybe, + query?: Maybe, + range?: Maybe, + script?: Maybe, +}; + +export type FilterTimelineResult = { + __typename?: 'FilterTimelineResult', + exists?: Maybe, + meta?: Maybe, + match_all?: Maybe, + missing?: Maybe, + query?: Maybe, + range?: Maybe, + script?: Maybe, +}; + +export type FingerprintData = { + __typename?: 'FingerprintData', + sha1?: Maybe, +}; + +export type FirstLastSeenHost = { + __typename?: 'FirstLastSeenHost', + inspect?: Maybe, + firstSeen?: Maybe, + lastSeen?: Maybe, +}; + +export enum FlowDirection { + uniDirectional = 'uniDirectional', + biDirectional = 'biDirectional' +} + +export enum FlowTarget { + client = 'client', + destination = 'destination', + server = 'server', + source = 'source' +} + +export enum FlowTargetSourceDest { + destination = 'destination', + source = 'source' +} + +export type GeoEcsFields = { + __typename?: 'GeoEcsFields', + city_name?: Maybe, + continent_name?: Maybe, + country_iso_code?: Maybe, + country_name?: Maybe, + location?: Maybe, + region_iso_code?: Maybe, + region_name?: Maybe, +}; + +export type GeoItem = { + __typename?: 'GeoItem', + geo?: Maybe, + flowTarget?: Maybe, +}; + +export enum HistogramType { + authentications = 'authentications', + anomalies = 'anomalies', + events = 'events', + alerts = 'alerts', + dns = 'dns' +} + +export type HostEcsFields = { + __typename?: 'HostEcsFields', + architecture?: Maybe, + id?: Maybe, + ip?: Maybe, + mac?: Maybe, + name?: Maybe, + os?: Maybe, + type?: Maybe, +}; + +export type HostFields = { + __typename?: 'HostFields', + architecture?: Maybe, + id?: Maybe, + ip?: Maybe>>, + mac?: Maybe>>, + name?: Maybe, + os?: Maybe, + type?: Maybe, +}; + +export type HostItem = { + __typename?: 'HostItem', + _id?: Maybe, + lastSeen?: Maybe, + host?: Maybe, + cloud?: Maybe, + inspect?: Maybe, +}; + +export type HostsData = { + __typename?: 'HostsData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +}; + +export type HostsEdges = { + __typename?: 'HostsEdges', + node: HostItem, + cursor: CursorType, +}; + +export enum HostsFields { + hostName = 'hostName', + lastSeen = 'lastSeen' +} + +export type HostsSortField = { + field: HostsFields, + direction: Direction, +}; + +export type HttpBodyData = { + __typename?: 'HttpBodyData', + content?: Maybe, + bytes?: Maybe, +}; + +export type HttpEcsFields = { + __typename?: 'HttpEcsFields', + version?: Maybe, + request?: Maybe, + response?: Maybe, +}; + +export type HttpRequestData = { + __typename?: 'HttpRequestData', + method?: Maybe, + body?: Maybe, + referrer?: Maybe, + bytes?: Maybe, +}; + +export type HttpResponseData = { + __typename?: 'HttpResponseData', + status_code?: Maybe, + body?: Maybe, + bytes?: Maybe, +}; + +/** A descriptor of a field in an index */ +export type IndexField = { + __typename?: 'IndexField', + /** Where the field belong */ + category: Scalars['String'], + /** Example of field's value */ + example?: Maybe, + /** whether the field's belong to an alias index */ + indexes: Array>, + /** The name of the field */ + name: Scalars['String'], + /** The type of the field's values as recognized by Kibana */ + type: Scalars['String'], + /** Whether the field's values can be efficiently searched for */ + searchable: Scalars['Boolean'], + /** Whether the field's values can be aggregated */ + aggregatable: Scalars['Boolean'], + /** Description of the field */ + description?: Maybe, + format?: Maybe, +}; + +export type Inspect = { + __typename?: 'Inspect', + dsl: Array, + response: Array, +}; + +export type IpOverviewData = { + __typename?: 'IpOverviewData', + client?: Maybe, + destination?: Maybe, + host: HostEcsFields, + server?: Maybe, + source?: Maybe, + inspect?: Maybe, +}; + +export type KpiHostDetailsData = { + __typename?: 'KpiHostDetailsData', + authSuccess?: Maybe, + authSuccessHistogram?: Maybe>, + authFailure?: Maybe, + authFailureHistogram?: Maybe>, + uniqueSourceIps?: Maybe, + uniqueSourceIpsHistogram?: Maybe>, + uniqueDestinationIps?: Maybe, + uniqueDestinationIpsHistogram?: Maybe>, + inspect?: Maybe, +}; + +export type KpiHostHistogramData = { + __typename?: 'KpiHostHistogramData', + x?: Maybe, + y?: Maybe, +}; + +export type KpiHostsData = { + __typename?: 'KpiHostsData', + hosts?: Maybe, + hostsHistogram?: Maybe>, + authSuccess?: Maybe, + authSuccessHistogram?: Maybe>, + authFailure?: Maybe, + authFailureHistogram?: Maybe>, + uniqueSourceIps?: Maybe, + uniqueSourceIpsHistogram?: Maybe>, + uniqueDestinationIps?: Maybe, + uniqueDestinationIpsHistogram?: Maybe>, + inspect?: Maybe, +}; + +export type KpiNetworkData = { + __typename?: 'KpiNetworkData', + networkEvents?: Maybe, + uniqueFlowId?: Maybe, + uniqueSourcePrivateIps?: Maybe, + uniqueSourcePrivateIpsHistogram?: Maybe>, + uniqueDestinationPrivateIps?: Maybe, + uniqueDestinationPrivateIpsHistogram?: Maybe>, + dnsQueries?: Maybe, + tlsHandshakes?: Maybe, + inspect?: Maybe, +}; + +export type KpiNetworkHistogramData = { + __typename?: 'KpiNetworkHistogramData', + x?: Maybe, + y?: Maybe, +}; + +export type KueryFilterQueryInput = { + kind?: Maybe, + expression?: Maybe, +}; + +export type KueryFilterQueryResult = { + __typename?: 'KueryFilterQueryResult', + kind?: Maybe, + expression?: Maybe, +}; + +export enum LastEventIndexKey { + hostDetails = 'hostDetails', + hosts = 'hosts', + ipDetails = 'ipDetails', + network = 'network' +} + +export type LastEventTimeData = { + __typename?: 'LastEventTimeData', + lastSeen?: Maybe, + inspect?: Maybe, +}; + +export type LastSourceHost = { + __typename?: 'LastSourceHost', + timestamp?: Maybe, + source?: Maybe, + host?: Maybe, +}; + +export type LastTimeDetails = { + hostName?: Maybe, + ip?: Maybe, +}; + +export type Location = { + __typename?: 'Location', + lon?: Maybe, + lat?: Maybe, +}; + +export type MatrixHistogramOverTimeData = { + __typename?: 'MatrixHistogramOverTimeData', + inspect?: Maybe, + matrixHistogramData: Array, + totalCount: Scalars['Float'], +}; + +export type MatrixOverOrdinalHistogramData = { + __typename?: 'MatrixOverOrdinalHistogramData', + x: Scalars['String'], + y: Scalars['Float'], + g: Scalars['String'], +}; + +export type MatrixOverTimeHistogramData = { + __typename?: 'MatrixOverTimeHistogramData', + x?: Maybe, + y?: Maybe, + g?: Maybe, +}; + +export type Mutation = { + __typename?: 'Mutation', + /** Persists a note */ + persistNote: ResponseNote, + deleteNote?: Maybe, + deleteNoteByTimelineId?: Maybe, + /** Persists a pinned event in a timeline */ + persistPinnedEventOnTimeline?: Maybe, + /** Remove a pinned events in a timeline */ + deletePinnedEventOnTimeline: Scalars['Boolean'], + /** Remove all pinned events in a timeline */ + deleteAllPinnedEventsOnTimeline: Scalars['Boolean'], + /** Persists a timeline */ + persistTimeline: ResponseTimeline, + persistFavorite: ResponseFavoriteTimeline, + deleteTimeline: Scalars['Boolean'], +}; + + +export type MutationPersistNoteArgs = { + noteId?: Maybe, + version?: Maybe, + note: NoteInput +}; + + +export type MutationDeleteNoteArgs = { + id: Array +}; + + +export type MutationDeleteNoteByTimelineIdArgs = { + timelineId: Scalars['ID'], + version?: Maybe +}; + + +export type MutationPersistPinnedEventOnTimelineArgs = { + pinnedEventId?: Maybe, + eventId: Scalars['ID'], + timelineId?: Maybe +}; + + +export type MutationDeletePinnedEventOnTimelineArgs = { + id: Array +}; + + +export type MutationDeleteAllPinnedEventsOnTimelineArgs = { + timelineId: Scalars['ID'] +}; + + +export type MutationPersistTimelineArgs = { + id?: Maybe, + version?: Maybe, + timeline: TimelineInput +}; + + +export type MutationPersistFavoriteArgs = { + timelineId?: Maybe +}; + + +export type MutationDeleteTimelineArgs = { + id: Array +}; + +export enum NetworkDirectionEcs { + inbound = 'inbound', + outbound = 'outbound', + internal = 'internal', + external = 'external', + incoming = 'incoming', + outgoing = 'outgoing', + listening = 'listening', + unknown = 'unknown' +} + +export type NetworkDnsData = { + __typename?: 'NetworkDnsData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, + histogram?: Maybe>, +}; + +export type NetworkDnsEdges = { + __typename?: 'NetworkDnsEdges', + node: NetworkDnsItem, + cursor: CursorType, +}; + +export enum NetworkDnsFields { + dnsName = 'dnsName', + queryCount = 'queryCount', + uniqueDomains = 'uniqueDomains', + dnsBytesIn = 'dnsBytesIn', + dnsBytesOut = 'dnsBytesOut' +} + +export type NetworkDnsItem = { + __typename?: 'NetworkDnsItem', + _id?: Maybe, + dnsBytesIn?: Maybe, + dnsBytesOut?: Maybe, + dnsName?: Maybe, + queryCount?: Maybe, + uniqueDomains?: Maybe, +}; + +export type NetworkDnsSortField = { + field: NetworkDnsFields, + direction: Direction, +}; + +export type NetworkDsOverTimeData = { + __typename?: 'NetworkDsOverTimeData', + inspect?: Maybe, + matrixHistogramData: Array, + totalCount: Scalars['Float'], +}; + +export type NetworkEcsField = { + __typename?: 'NetworkEcsField', + bytes?: Maybe, + community_id?: Maybe, + direction?: Maybe, + packets?: Maybe, + protocol?: Maybe, + transport?: Maybe, +}; + +export type NetworkHttpData = { + __typename?: 'NetworkHttpData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +}; + +export type NetworkHttpEdges = { + __typename?: 'NetworkHttpEdges', + node: NetworkHttpItem, + cursor: CursorType, +}; + +export enum NetworkHttpFields { + domains = 'domains', + lastHost = 'lastHost', + lastSourceIp = 'lastSourceIp', + methods = 'methods', + path = 'path', + requestCount = 'requestCount', + statuses = 'statuses' +} + +export type NetworkHttpItem = { + __typename?: 'NetworkHttpItem', + _id?: Maybe, + domains: Array, + lastHost?: Maybe, + lastSourceIp?: Maybe, + methods: Array, + path?: Maybe, + requestCount?: Maybe, + statuses: Array, +}; + +export type NetworkHttpSortField = { + direction: Direction, +}; + +export type NetworkTopCountriesData = { + __typename?: 'NetworkTopCountriesData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +}; + +export type NetworkTopCountriesEdges = { + __typename?: 'NetworkTopCountriesEdges', + node: NetworkTopCountriesItem, + cursor: CursorType, +}; + +export type NetworkTopCountriesItem = { + __typename?: 'NetworkTopCountriesItem', + _id?: Maybe, + source?: Maybe, + destination?: Maybe, + network?: Maybe, +}; + +export type NetworkTopNFlowData = { + __typename?: 'NetworkTopNFlowData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +}; + +export type NetworkTopNFlowEdges = { + __typename?: 'NetworkTopNFlowEdges', + node: NetworkTopNFlowItem, + cursor: CursorType, +}; + +export type NetworkTopNFlowItem = { + __typename?: 'NetworkTopNFlowItem', + _id?: Maybe, + source?: Maybe, + destination?: Maybe, + network?: Maybe, +}; + +export enum NetworkTopTablesFields { + bytes_in = 'bytes_in', + bytes_out = 'bytes_out', + flows = 'flows', + destination_ips = 'destination_ips', + source_ips = 'source_ips' +} + +export type NetworkTopTablesSortField = { + field: NetworkTopTablesFields, + direction: Direction, +}; + +export type NoteInput = { + eventId?: Maybe, + note?: Maybe, + timelineId?: Maybe, +}; + +export type NoteResult = { + __typename?: 'NoteResult', + eventId?: Maybe, + note?: Maybe, + timelineId?: Maybe, + noteId: Scalars['String'], + created?: Maybe, + createdBy?: Maybe, + timelineVersion?: Maybe, + updated?: Maybe, + updatedBy?: Maybe, + version?: Maybe, +}; + +export type OsEcsFields = { + __typename?: 'OsEcsFields', + platform?: Maybe, + name?: Maybe, + full?: Maybe, + family?: Maybe, + version?: Maybe, + kernel?: Maybe, +}; + +export type OsFields = { + __typename?: 'OsFields', + platform?: Maybe, + name?: Maybe, + full?: Maybe, + family?: Maybe, + version?: Maybe, + kernel?: Maybe, +}; + +export type Overview = { + __typename?: 'Overview', + firstSeen?: Maybe, + lastSeen?: Maybe, + autonomousSystem: AutonomousSystem, + geo: GeoEcsFields, +}; + +export type OverviewHostData = { + __typename?: 'OverviewHostData', + auditbeatAuditd?: Maybe, + auditbeatFIM?: Maybe, + auditbeatLogin?: Maybe, + auditbeatPackage?: Maybe, + auditbeatProcess?: Maybe, + auditbeatUser?: Maybe, + endgameDns?: Maybe, + endgameFile?: Maybe, + endgameImageLoad?: Maybe, + endgameNetwork?: Maybe, + endgameProcess?: Maybe, + endgameRegistry?: Maybe, + endgameSecurity?: Maybe, + filebeatSystemModule?: Maybe, + winlogbeatSecurity?: Maybe, + winlogbeatMWSysmonOperational?: Maybe, + inspect?: Maybe, +}; + +export type OverviewNetworkData = { + __typename?: 'OverviewNetworkData', + auditbeatSocket?: Maybe, + filebeatCisco?: Maybe, + filebeatNetflow?: Maybe, + filebeatPanw?: Maybe, + filebeatSuricata?: Maybe, + filebeatZeek?: Maybe, + packetbeatDNS?: Maybe, + packetbeatFlow?: Maybe, + packetbeatTLS?: Maybe, + inspect?: Maybe, +}; + +export type PackageEcsFields = { + __typename?: 'PackageEcsFields', + arch?: Maybe, + entity_id?: Maybe, + name?: Maybe, + size?: Maybe, + summary?: Maybe, + version?: Maybe, +}; + +export type PageInfo = { + __typename?: 'PageInfo', + endCursor?: Maybe, + hasNextPage?: Maybe, +}; + +export type PageInfoNote = { + pageIndex: Scalars['Float'], + pageSize: Scalars['Float'], +}; + +export type PageInfoPaginated = { + __typename?: 'PageInfoPaginated', + activePage: Scalars['Float'], + fakeTotalCount: Scalars['Float'], + showMorePagesIndicator: Scalars['Boolean'], +}; + +export type PageInfoTimeline = { + pageIndex: Scalars['Float'], + pageSize: Scalars['Float'], +}; + +export type PaginationInput = { + /** The limit parameter allows you to configure the maximum amount of items to be returned */ + limit: Scalars['Float'], + /** The cursor parameter defines the next result you want to fetch */ + cursor?: Maybe, + /** The tiebreaker parameter allow to be more precise to fetch the next item */ + tiebreaker?: Maybe, +}; + +export type PaginationInputPaginated = { + /** The activePage parameter defines the page of results you want to fetch */ + activePage: Scalars['Float'], + /** The cursorStart parameter defines the start of the results to be displayed */ + cursorStart: Scalars['Float'], + /** The fakePossibleCount parameter determines the total count in order to show 5 additional pages */ + fakePossibleCount: Scalars['Float'], + /** The querySize parameter is the number of items to be returned */ + querySize: Scalars['Float'], +}; + +export type PinnedEvent = { + __typename?: 'PinnedEvent', + code?: Maybe, + message?: Maybe, + pinnedEventId: Scalars['ID'], + eventId?: Maybe, + timelineId?: Maybe, + timelineVersion?: Maybe, + created?: Maybe, + createdBy?: Maybe, + updated?: Maybe, + updatedBy?: Maybe, + version?: Maybe, +}; + +export type PrimarySecondary = { + __typename?: 'PrimarySecondary', + primary?: Maybe, + secondary?: Maybe, + type?: Maybe, +}; + +export type ProcessEcsFields = { + __typename?: 'ProcessEcsFields', + hash?: Maybe, + pid?: Maybe, + name?: Maybe, + ppid?: Maybe, + args?: Maybe, + executable?: Maybe, + title?: Maybe, + thread?: Maybe, + working_directory?: Maybe, +}; + +export type ProcessHashData = { + __typename?: 'ProcessHashData', + md5?: Maybe, + sha1?: Maybe, + sha256?: Maybe, +}; + +export type Query = { + __typename?: 'Query', + getNote: NoteResult, + getNotesByTimelineId: Array, + getNotesByEventId: Array, + getAllNotes: ResponseNotes, + getAllPinnedEventsByTimelineId: Array, + /** Get a security data source by id */ + source: Source, + /** Get a list of all security data sources */ + allSources: Array, + getOneTimeline: TimelineResult, + getAllTimeline: ResponseTimelines, +}; + + +export type QueryGetNoteArgs = { + id: Scalars['ID'] +}; + + +export type QueryGetNotesByTimelineIdArgs = { + timelineId: Scalars['ID'] +}; + + +export type QueryGetNotesByEventIdArgs = { + eventId: Scalars['ID'] +}; + + +export type QueryGetAllNotesArgs = { + pageInfo?: Maybe, + search?: Maybe, + sort?: Maybe +}; + + +export type QueryGetAllPinnedEventsByTimelineIdArgs = { + timelineId: Scalars['ID'] +}; + + +export type QuerySourceArgs = { + id: Scalars['ID'] +}; + + +export type QueryGetOneTimelineArgs = { + id: Scalars['ID'] +}; + + +export type QueryGetAllTimelineArgs = { + pageInfo?: Maybe, + search?: Maybe, + sort?: Maybe, + onlyUserFavorite?: Maybe +}; + +export type QueryMatchInput = { + field?: Maybe, + displayField?: Maybe, + value?: Maybe, + displayValue?: Maybe, + operator?: Maybe, +}; + +export type QueryMatchResult = { + __typename?: 'QueryMatchResult', + field?: Maybe, + displayField?: Maybe, + value?: Maybe, + displayValue?: Maybe, + operator?: Maybe, +}; + +export type ResponseFavoriteTimeline = { + __typename?: 'ResponseFavoriteTimeline', + code?: Maybe, + message?: Maybe, + savedObjectId: Scalars['String'], + version: Scalars['String'], + favorite?: Maybe>, +}; + +export type ResponseNote = { + __typename?: 'ResponseNote', + code?: Maybe, + message?: Maybe, + note: NoteResult, +}; + +export type ResponseNotes = { + __typename?: 'ResponseNotes', + notes: Array, + totalCount?: Maybe, +}; + +export type ResponseTimeline = { + __typename?: 'ResponseTimeline', + code?: Maybe, + message?: Maybe, + timeline: TimelineResult, +}; + +export type ResponseTimelines = { + __typename?: 'ResponseTimelines', + timeline: Array>, + totalCount?: Maybe, +}; + +export type RuleEcsField = { + __typename?: 'RuleEcsField', + reference?: Maybe, +}; + +export type RuleField = { + __typename?: 'RuleField', + id?: Maybe, + rule_id?: Maybe, + false_positives: Array, + saved_id?: Maybe, + timeline_id?: Maybe, + timeline_title?: Maybe, + max_signals?: Maybe, + risk_score?: Maybe, + output_index?: Maybe, + description?: Maybe, + from?: Maybe, + immutable?: Maybe, + index?: Maybe, + interval?: Maybe, + language?: Maybe, + query?: Maybe, + references?: Maybe, + severity?: Maybe, + tags?: Maybe, + threat?: Maybe, + type?: Maybe, + size?: Maybe, + to?: Maybe, + enabled?: Maybe, + filters?: Maybe, + created_at?: Maybe, + updated_at?: Maybe, + created_by?: Maybe, + updated_by?: Maybe, + version?: Maybe, +}; + +export type SayMyName = { + __typename?: 'SayMyName', + /** The id of the source */ + appName: Scalars['String'], +}; + +export type SerializedFilterQueryInput = { + filterQuery?: Maybe, +}; + +export type SerializedFilterQueryResult = { + __typename?: 'SerializedFilterQueryResult', + filterQuery?: Maybe, +}; + +export type SerializedKueryQueryInput = { + kuery?: Maybe, + serializedQuery?: Maybe, +}; + +export type SerializedKueryQueryResult = { + __typename?: 'SerializedKueryQueryResult', + kuery?: Maybe, + serializedQuery?: Maybe, +}; + +export type SignalField = { + __typename?: 'SignalField', + rule?: Maybe, + original_time?: Maybe, +}; + +export type SortField = { + sortFieldId: Scalars['String'], + direction: Direction, +}; + +export enum SortFieldNote { + updatedBy = 'updatedBy', + updated = 'updated' +} + +export enum SortFieldTimeline { + title = 'title', + description = 'description', + updated = 'updated', + created = 'created' +} + +export type SortNote = { + sortField: SortFieldNote, + sortOrder: Direction, +}; + +export type SortTimeline = { + sortField: SortFieldTimeline, + sortOrder: Direction, +}; + +export type SortTimelineInput = { + columnId?: Maybe, + sortDirection?: Maybe, +}; + +export type SortTimelineResult = { + __typename?: 'SortTimelineResult', + columnId?: Maybe, + sortDirection?: Maybe, +}; + +export type Source = { + __typename?: 'Source', + /** The id of the source */ + id: Scalars['ID'], + /** The raw configuration of the source */ + configuration: SourceConfiguration, + /** The status of the source */ + status: SourceStatus, + /** Gets Authentication success and failures based on a timerange */ + Authentications: AuthenticationsData, + Timeline: TimelineData, + TimelineDetails: TimelineDetailsData, + LastEventTime: LastEventTimeData, + /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ + Hosts: HostsData, + HostOverview: HostItem, + HostFirstLastSeen: FirstLastSeenHost, + IpOverview?: Maybe, + Users: UsersData, + KpiNetwork?: Maybe, + KpiHosts: KpiHostsData, + KpiHostDetails: KpiHostDetailsData, + MatrixHistogram: MatrixHistogramOverTimeData, + NetworkTopCountries: NetworkTopCountriesData, + NetworkTopNFlow: NetworkTopNFlowData, + NetworkDns: NetworkDnsData, + NetworkDnsHistogram: NetworkDsOverTimeData, + NetworkHttp: NetworkHttpData, + OverviewNetwork?: Maybe, + OverviewHost?: Maybe, + Tls: TlsData, + /** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */ + UncommonProcesses: UncommonProcessesData, + /** Just a simple example to get the app name */ + whoAmI?: Maybe, +}; + + +export type SourceAuthenticationsArgs = { + timerange: TimerangeInput, + pagination: PaginationInputPaginated, + filterQuery?: Maybe, + defaultIndex: Array +}; + + +export type SourceTimelineArgs = { + pagination: PaginationInput, + sortField: SortField, + fieldRequested: Array, + timerange?: Maybe, + filterQuery?: Maybe, + defaultIndex: Array +}; + + +export type SourceTimelineDetailsArgs = { + eventId: Scalars['String'], + indexName: Scalars['String'], + defaultIndex: Array +}; + + +export type SourceLastEventTimeArgs = { + id?: Maybe, + indexKey: LastEventIndexKey, + details: LastTimeDetails, + defaultIndex: Array +}; + + +export type SourceHostsArgs = { + id?: Maybe, + timerange: TimerangeInput, + pagination: PaginationInputPaginated, + sort: HostsSortField, + filterQuery?: Maybe, + defaultIndex: Array +}; + + +export type SourceHostOverviewArgs = { + id?: Maybe, + hostName: Scalars['String'], + timerange: TimerangeInput, + defaultIndex: Array +}; + + +export type SourceHostFirstLastSeenArgs = { + id?: Maybe, + hostName: Scalars['String'], + defaultIndex: Array +}; + + +export type SourceIpOverviewArgs = { + id?: Maybe, + filterQuery?: Maybe, + ip: Scalars['String'], + defaultIndex: Array +}; + + +export type SourceUsersArgs = { + filterQuery?: Maybe, + id?: Maybe, + ip: Scalars['String'], + pagination: PaginationInputPaginated, + sort: UsersSortField, + flowTarget: FlowTarget, + timerange: TimerangeInput, + defaultIndex: Array +}; + + +export type SourceKpiNetworkArgs = { + id?: Maybe, + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array +}; + + +export type SourceKpiHostsArgs = { + id?: Maybe, + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array +}; + + +export type SourceKpiHostDetailsArgs = { + id?: Maybe, + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array +}; + + +export type SourceMatrixHistogramArgs = { + filterQuery?: Maybe, + defaultIndex: Array, + timerange: TimerangeInput, + stackByField: Scalars['String'], + histogramType: HistogramType +}; + + +export type SourceNetworkTopCountriesArgs = { + id?: Maybe, + filterQuery?: Maybe, + ip?: Maybe, + flowTarget: FlowTargetSourceDest, + pagination: PaginationInputPaginated, + sort: NetworkTopTablesSortField, + timerange: TimerangeInput, + defaultIndex: Array +}; + + +export type SourceNetworkTopNFlowArgs = { + id?: Maybe, + filterQuery?: Maybe, + ip?: Maybe, + flowTarget: FlowTargetSourceDest, + pagination: PaginationInputPaginated, + sort: NetworkTopTablesSortField, + timerange: TimerangeInput, + defaultIndex: Array +}; + + +export type SourceNetworkDnsArgs = { + filterQuery?: Maybe, + id?: Maybe, + isPtrIncluded: Scalars['Boolean'], + pagination: PaginationInputPaginated, + sort: NetworkDnsSortField, + stackByField?: Maybe, + timerange: TimerangeInput, + defaultIndex: Array +}; + + +export type SourceNetworkDnsHistogramArgs = { + filterQuery?: Maybe, + defaultIndex: Array, + timerange: TimerangeInput, + stackByField?: Maybe +}; + + +export type SourceNetworkHttpArgs = { + id?: Maybe, + filterQuery?: Maybe, + ip?: Maybe, + pagination: PaginationInputPaginated, + sort: NetworkHttpSortField, + timerange: TimerangeInput, + defaultIndex: Array +}; + + +export type SourceOverviewNetworkArgs = { + id?: Maybe, + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array +}; + + +export type SourceOverviewHostArgs = { + id?: Maybe, + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array +}; + + +export type SourceTlsArgs = { + filterQuery?: Maybe, + id?: Maybe, + ip: Scalars['String'], + pagination: PaginationInputPaginated, + sort: TlsSortField, + flowTarget: FlowTargetSourceDest, + timerange: TimerangeInput, + defaultIndex: Array +}; + + +export type SourceUncommonProcessesArgs = { + timerange: TimerangeInput, + pagination: PaginationInputPaginated, + filterQuery?: Maybe, + defaultIndex: Array +}; + +/** A set of configuration options for a security data source */ +export type SourceConfiguration = { + __typename?: 'SourceConfiguration', + /** The field mapping to use for this source */ + fields: SourceFields, +}; + +export type SourceEcsFields = { + __typename?: 'SourceEcsFields', + bytes?: Maybe, + ip?: Maybe, + port?: Maybe, + domain?: Maybe, + geo?: Maybe, + packets?: Maybe, +}; + +/** A mapping of semantic fields to their document counterparts */ +export type SourceFields = { + __typename?: 'SourceFields', + /** The field to identify a container by */ + container: Scalars['String'], + /** The fields to identify a host by */ + host: Scalars['String'], + /** The fields that may contain the log event message. The first field found win. */ + message: Array, + /** The field to identify a pod by */ + pod: Scalars['String'], + /** The field to use as a tiebreaker for log events that have identical timestamps */ + tiebreaker: Scalars['String'], + /** The field to use as a timestamp for metrics and logs */ + timestamp: Scalars['String'], +}; + +/** The status of an infrastructure data source */ +export type SourceStatus = { + __typename?: 'SourceStatus', + /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ + indicesExist: Scalars['Boolean'], + /** The list of fields defined in the index mappings */ + indexFields: Array, +}; + + +/** The status of an infrastructure data source */ +export type SourceStatusIndicesExistArgs = { + defaultIndex: Array +}; + + +/** The status of an infrastructure data source */ +export type SourceStatusIndexFieldsArgs = { + defaultIndex: Array +}; + +export type SshEcsFields = { + __typename?: 'SshEcsFields', + method?: Maybe, + signature?: Maybe, +}; + +export type Summary = { + __typename?: 'Summary', + actor?: Maybe, + object?: Maybe, + how?: Maybe, + message_type?: Maybe, + sequence?: Maybe, +}; + +export type SuricataAlertData = { + __typename?: 'SuricataAlertData', + signature?: Maybe, + signature_id?: Maybe, +}; + +export type SuricataEcsFields = { + __typename?: 'SuricataEcsFields', + eve?: Maybe, +}; + +export type SuricataEveData = { + __typename?: 'SuricataEveData', + alert?: Maybe, + flow_id?: Maybe, + proto?: Maybe, +}; + +export type SystemEcsField = { + __typename?: 'SystemEcsField', + audit?: Maybe, + auth?: Maybe, +}; + +export type Thread = { + __typename?: 'Thread', + id?: Maybe, + start?: Maybe, +}; + +export type TimelineData = { + __typename?: 'TimelineData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfo, + inspect?: Maybe, +}; + +export type TimelineDetailsData = { + __typename?: 'TimelineDetailsData', + data?: Maybe>, + inspect?: Maybe, +}; + +export type TimelineEdges = { + __typename?: 'TimelineEdges', + node: TimelineItem, + cursor: CursorType, +}; + +export type TimelineInput = { + columns?: Maybe>, + dataProviders?: Maybe>, + description?: Maybe, + eventType?: Maybe, + filters?: Maybe>, + kqlMode?: Maybe, + kqlQuery?: Maybe, + title?: Maybe, + dateRange?: Maybe, + savedQueryId?: Maybe, + sort?: Maybe, +}; + +export type TimelineItem = { + __typename?: 'TimelineItem', + _id: Scalars['String'], + _index?: Maybe, + data: Array, + ecs: Ecs, +}; + +export type TimelineNonEcsData = { + __typename?: 'TimelineNonEcsData', + field: Scalars['String'], + value?: Maybe, +}; + +export type TimelineResult = { + __typename?: 'TimelineResult', + columns?: Maybe>, + created?: Maybe, + createdBy?: Maybe, + dataProviders?: Maybe>, + dateRange?: Maybe, + description?: Maybe, + eventIdToNoteIds?: Maybe>, + eventType?: Maybe, + favorite?: Maybe>, + filters?: Maybe>, + kqlMode?: Maybe, + kqlQuery?: Maybe, + notes?: Maybe>, + noteIds?: Maybe>, + pinnedEventIds?: Maybe>, + pinnedEventsSaveObject?: Maybe>, + savedQueryId?: Maybe, + savedObjectId: Scalars['String'], + sort?: Maybe, + title?: Maybe, + updated?: Maybe, + updatedBy?: Maybe, + version: Scalars['String'], +}; + +export type TimerangeInput = { + /** + * The interval string to use for last bucket. The format is '{value}{unit}'. For + * example '5m' would return the metrics for the last 5 minutes of the timespan. + */ + interval: Scalars['String'], + /** The end of the timerange */ + to: Scalars['Float'], + /** The beginning of the timerange */ + from: Scalars['Float'], +}; + +export type TlsClientCertificateData = { + __typename?: 'TlsClientCertificateData', + fingerprint?: Maybe, +}; + +export type TlsData = { + __typename?: 'TlsData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +}; + +export type TlsEcsFields = { + __typename?: 'TlsEcsFields', + client_certificate?: Maybe, + fingerprints?: Maybe, + server_certificate?: Maybe, +}; + +export type TlsEdges = { + __typename?: 'TlsEdges', + node: TlsNode, + cursor: CursorType, +}; + +export enum TlsFields { + _id = '_id' +} + +export type TlsFingerprintsData = { + __typename?: 'TlsFingerprintsData', + ja3?: Maybe, +}; + +export type TlsJa3Data = { + __typename?: 'TlsJa3Data', + hash?: Maybe, +}; + +export type TlsNode = { + __typename?: 'TlsNode', + _id?: Maybe, + timestamp?: Maybe, + alternativeNames?: Maybe>, + notAfter?: Maybe>, + commonNames?: Maybe>, + ja3?: Maybe>, + issuerNames?: Maybe>, +}; + +export type TlsServerCertificateData = { + __typename?: 'TlsServerCertificateData', + fingerprint?: Maybe, +}; + +export type TlsSortField = { + field: TlsFields, + direction: Direction, +}; + + + + + +export type TopCountriesItemDestination = { + __typename?: 'TopCountriesItemDestination', + country?: Maybe, + destination_ips?: Maybe, + flows?: Maybe, + location?: Maybe, + source_ips?: Maybe, +}; + +export type TopCountriesItemSource = { + __typename?: 'TopCountriesItemSource', + country?: Maybe, + destination_ips?: Maybe, + flows?: Maybe, + location?: Maybe, + source_ips?: Maybe, +}; + +export type TopNetworkTablesEcsField = { + __typename?: 'TopNetworkTablesEcsField', + bytes_in?: Maybe, + bytes_out?: Maybe, +}; + +export type TopNFlowItemDestination = { + __typename?: 'TopNFlowItemDestination', + autonomous_system?: Maybe, + domain?: Maybe>, + ip?: Maybe, + location?: Maybe, + flows?: Maybe, + source_ips?: Maybe, +}; + +export type TopNFlowItemSource = { + __typename?: 'TopNFlowItemSource', + autonomous_system?: Maybe, + domain?: Maybe>, + ip?: Maybe, + location?: Maybe, + flows?: Maybe, + destination_ips?: Maybe, +}; + + +export type UncommonProcessesData = { + __typename?: 'UncommonProcessesData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +}; + +export type UncommonProcessesEdges = { + __typename?: 'UncommonProcessesEdges', + node: UncommonProcessItem, + cursor: CursorType, +}; + +export type UncommonProcessItem = { + __typename?: 'UncommonProcessItem', + _id: Scalars['String'], + instances: Scalars['Float'], + process: ProcessEcsFields, + hosts: Array, + user?: Maybe, +}; + +export type UrlEcsFields = { + __typename?: 'UrlEcsFields', + domain?: Maybe, + original?: Maybe, + username?: Maybe, + password?: Maybe, +}; + +export type UserEcsFields = { + __typename?: 'UserEcsFields', + domain?: Maybe, + id?: Maybe, + name?: Maybe, + full_name?: Maybe, + email?: Maybe, + hash?: Maybe, + group?: Maybe, +}; + +export type UsersData = { + __typename?: 'UsersData', + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +}; + +export type UsersEdges = { + __typename?: 'UsersEdges', + node: UsersNode, + cursor: CursorType, +}; + +export enum UsersFields { + name = 'name', + count = 'count' +} + +export type UsersItem = { + __typename?: 'UsersItem', + name?: Maybe, + id?: Maybe, + groupId?: Maybe, + groupName?: Maybe, + count?: Maybe, +}; + +export type UsersNode = { + __typename?: 'UsersNode', + _id?: Maybe, + timestamp?: Maybe, + user?: Maybe, +}; + +export type UsersSortField = { + field: UsersFields, + direction: Direction, +}; + +export type WinlogEcsFields = { + __typename?: 'WinlogEcsFields', + event_id?: Maybe, +}; + +export type ZeekConnectionData = { + __typename?: 'ZeekConnectionData', + local_resp?: Maybe, + local_orig?: Maybe, + missed_bytes?: Maybe, + state?: Maybe, + history?: Maybe, +}; + +export type ZeekDnsData = { + __typename?: 'ZeekDnsData', + AA?: Maybe, + qclass_name?: Maybe, + RD?: Maybe, + qtype_name?: Maybe, + rejected?: Maybe, + qtype?: Maybe, + query?: Maybe, + trans_id?: Maybe, + qclass?: Maybe, + RA?: Maybe, + TC?: Maybe, +}; + +export type ZeekEcsFields = { + __typename?: 'ZeekEcsFields', + session_id?: Maybe, + connection?: Maybe, + notice?: Maybe, + dns?: Maybe, + http?: Maybe, + files?: Maybe, + ssl?: Maybe, +}; + +export type ZeekFileData = { + __typename?: 'ZeekFileData', + session_ids?: Maybe, + timedout?: Maybe, + local_orig?: Maybe, + tx_host?: Maybe, + source?: Maybe, + is_orig?: Maybe, + overflow_bytes?: Maybe, + sha1?: Maybe, + duration?: Maybe, + depth?: Maybe, + analyzers?: Maybe, + mime_type?: Maybe, + rx_host?: Maybe, + total_bytes?: Maybe, + fuid?: Maybe, + seen_bytes?: Maybe, + missing_bytes?: Maybe, + md5?: Maybe, +}; + +export type ZeekHttpData = { + __typename?: 'ZeekHttpData', + resp_mime_types?: Maybe, + trans_depth?: Maybe, + status_msg?: Maybe, + resp_fuids?: Maybe, + tags?: Maybe, +}; + +export type ZeekNoticeData = { + __typename?: 'ZeekNoticeData', + suppress_for?: Maybe, + msg?: Maybe, + note?: Maybe, + sub?: Maybe, + dst?: Maybe, + dropped?: Maybe, + peer_descr?: Maybe, +}; + +export type ZeekSslData = { + __typename?: 'ZeekSslData', + cipher?: Maybe, + established?: Maybe, + resumed?: Maybe, + version?: Maybe, +}; + +export type GetAuthenticationsQueryQueryVariables = { + sourceId: Scalars['ID'], + timerange: TimerangeInput, + pagination: PaginationInputPaginated, + filterQuery?: Maybe, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetAuthenticationsQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, Authentications: { __typename?: 'AuthenticationsData', totalCount: number, edges: Array<{ __typename?: 'AuthenticationsEdges', node: { __typename?: 'AuthenticationItem', _id: string, failures: number, successes: number, user: { __typename?: 'UserEcsFields', name: Maybe }, lastSuccess: Maybe<{ __typename?: 'LastSourceHost', timestamp: Maybe, source: Maybe<{ __typename?: 'SourceEcsFields', ip: Maybe }>, host: Maybe<{ __typename?: 'HostEcsFields', id: Maybe, name: Maybe }> }>, lastFailure: Maybe<{ __typename?: 'LastSourceHost', timestamp: Maybe, source: Maybe<{ __typename?: 'SourceEcsFields', ip: Maybe }>, host: Maybe<{ __typename?: 'HostEcsFields', id: Maybe, name: Maybe }> }> }, cursor: { __typename?: 'CursorType', value: Maybe } }>, pageInfo: { __typename?: 'PageInfoPaginated', activePage: number, fakeTotalCount: number, showMorePagesIndicator: boolean }, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type GetLastEventTimeQueryQueryVariables = { + sourceId: Scalars['ID'], + indexKey: LastEventIndexKey, + details: LastTimeDetails, + defaultIndex: Array +}; + + +export type GetLastEventTimeQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, LastEventTime: { __typename?: 'LastEventTimeData', lastSeen: Maybe } } }; + +export type GetHostFirstLastSeenQueryQueryVariables = { + sourceId: Scalars['ID'], + hostName: Scalars['String'], + defaultIndex: Array +}; + + +export type GetHostFirstLastSeenQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, HostFirstLastSeen: { __typename?: 'FirstLastSeenHost', firstSeen: Maybe, lastSeen: Maybe } } }; + +export type GetHostsTableQueryQueryVariables = { + sourceId: Scalars['ID'], + timerange: TimerangeInput, + pagination: PaginationInputPaginated, + sort: HostsSortField, + filterQuery?: Maybe, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetHostsTableQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, Hosts: { __typename?: 'HostsData', totalCount: number, edges: Array<{ __typename?: 'HostsEdges', node: { __typename?: 'HostItem', _id: Maybe, lastSeen: Maybe, host: Maybe<{ __typename?: 'HostEcsFields', id: Maybe, name: Maybe, os: Maybe<{ __typename?: 'OsEcsFields', name: Maybe, version: Maybe }> }> }, cursor: { __typename?: 'CursorType', value: Maybe } }>, pageInfo: { __typename?: 'PageInfoPaginated', activePage: number, fakeTotalCount: number, showMorePagesIndicator: boolean }, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type GetHostOverviewQueryQueryVariables = { + sourceId: Scalars['ID'], + hostName: Scalars['String'], + timerange: TimerangeInput, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetHostOverviewQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, HostOverview: { __typename?: 'HostItem', _id: Maybe, host: Maybe<{ __typename?: 'HostEcsFields', architecture: Maybe, id: Maybe, ip: Maybe, mac: Maybe, name: Maybe, type: Maybe, os: Maybe<{ __typename?: 'OsEcsFields', family: Maybe, name: Maybe, platform: Maybe, version: Maybe }> }>, cloud: Maybe<{ __typename?: 'CloudFields', provider: Maybe>>, region: Maybe>>, instance: Maybe<{ __typename?: 'CloudInstance', id: Maybe>> }>, machine: Maybe<{ __typename?: 'CloudMachine', type: Maybe>> }> }>, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type GetIpOverviewQueryQueryVariables = { + sourceId: Scalars['ID'], + filterQuery?: Maybe, + ip: Scalars['String'], + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetIpOverviewQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, IpOverview: Maybe<{ __typename?: 'IpOverviewData', source: Maybe<{ __typename?: 'Overview', firstSeen: Maybe, lastSeen: Maybe, autonomousSystem: { __typename?: 'AutonomousSystem', number: Maybe, organization: Maybe<{ __typename?: 'AutonomousSystemOrganization', name: Maybe }> }, geo: { __typename?: 'GeoEcsFields', continent_name: Maybe, city_name: Maybe, country_iso_code: Maybe, country_name: Maybe, region_iso_code: Maybe, region_name: Maybe, location: Maybe<{ __typename?: 'Location', lat: Maybe, lon: Maybe }> } }>, destination: Maybe<{ __typename?: 'Overview', firstSeen: Maybe, lastSeen: Maybe, autonomousSystem: { __typename?: 'AutonomousSystem', number: Maybe, organization: Maybe<{ __typename?: 'AutonomousSystemOrganization', name: Maybe }> }, geo: { __typename?: 'GeoEcsFields', continent_name: Maybe, city_name: Maybe, country_iso_code: Maybe, country_name: Maybe, region_iso_code: Maybe, region_name: Maybe, location: Maybe<{ __typename?: 'Location', lat: Maybe, lon: Maybe }> } }>, host: { __typename?: 'HostEcsFields', architecture: Maybe, id: Maybe, ip: Maybe, mac: Maybe, name: Maybe, type: Maybe, os: Maybe<{ __typename?: 'OsEcsFields', family: Maybe, name: Maybe, platform: Maybe, version: Maybe }> }, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> }> } }; + +export type KpiHostDetailsChartFieldsFragment = { __typename?: 'KpiHostHistogramData', x: Maybe, y: Maybe }; + +export type GetKpiHostDetailsQueryQueryVariables = { + sourceId: Scalars['ID'], + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetKpiHostDetailsQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, KpiHostDetails: { __typename?: 'KpiHostDetailsData', authSuccess: Maybe, authFailure: Maybe, uniqueSourceIps: Maybe, uniqueDestinationIps: Maybe, authSuccessHistogram: Maybe>, authFailureHistogram: Maybe>, uniqueSourceIpsHistogram: Maybe>, uniqueDestinationIpsHistogram: Maybe>, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type KpiHostChartFieldsFragment = { __typename?: 'KpiHostHistogramData', x: Maybe, y: Maybe }; + +export type GetKpiHostsQueryQueryVariables = { + sourceId: Scalars['ID'], + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetKpiHostsQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, KpiHosts: { __typename?: 'KpiHostsData', hosts: Maybe, authSuccess: Maybe, authFailure: Maybe, uniqueSourceIps: Maybe, uniqueDestinationIps: Maybe, hostsHistogram: Maybe>, authSuccessHistogram: Maybe>, authFailureHistogram: Maybe>, uniqueSourceIpsHistogram: Maybe>, uniqueDestinationIpsHistogram: Maybe>, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type KpiNetworkChartFieldsFragment = { __typename?: 'KpiNetworkHistogramData', x: Maybe, y: Maybe }; + +export type GetKpiNetworkQueryQueryVariables = { + sourceId: Scalars['ID'], + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetKpiNetworkQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, KpiNetwork: Maybe<{ __typename?: 'KpiNetworkData', networkEvents: Maybe, uniqueFlowId: Maybe, uniqueSourcePrivateIps: Maybe, uniqueDestinationPrivateIps: Maybe, dnsQueries: Maybe, tlsHandshakes: Maybe, uniqueSourcePrivateIpsHistogram: Maybe>, uniqueDestinationPrivateIpsHistogram: Maybe>, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> }> } }; + +export type GetMatrixHistogramQueryQueryVariables = { + defaultIndex: Array, + filterQuery?: Maybe, + histogramType: HistogramType, + inspect: Scalars['Boolean'], + sourceId: Scalars['ID'], + stackByField: Scalars['String'], + timerange: TimerangeInput +}; + + +export type GetMatrixHistogramQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, MatrixHistogram: { __typename?: 'MatrixHistogramOverTimeData', totalCount: number, matrixHistogramData: Array<{ __typename?: 'MatrixOverTimeHistogramData', x: Maybe, y: Maybe, g: Maybe }>, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type GetNetworkDnsQueryQueryVariables = { + defaultIndex: Array, + filterQuery?: Maybe, + inspect: Scalars['Boolean'], + isPtrIncluded: Scalars['Boolean'], + pagination: PaginationInputPaginated, + sort: NetworkDnsSortField, + sourceId: Scalars['ID'], + stackByField?: Maybe, + timerange: TimerangeInput +}; + + +export type GetNetworkDnsQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, NetworkDns: { __typename?: 'NetworkDnsData', totalCount: number, edges: Array<{ __typename?: 'NetworkDnsEdges', node: { __typename?: 'NetworkDnsItem', _id: Maybe, dnsBytesIn: Maybe, dnsBytesOut: Maybe, dnsName: Maybe, queryCount: Maybe, uniqueDomains: Maybe }, cursor: { __typename?: 'CursorType', value: Maybe } }>, pageInfo: { __typename?: 'PageInfoPaginated', activePage: number, fakeTotalCount: number, showMorePagesIndicator: boolean }, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type GetNetworkHttpQueryQueryVariables = { + sourceId: Scalars['ID'], + ip?: Maybe, + filterQuery?: Maybe, + pagination: PaginationInputPaginated, + sort: NetworkHttpSortField, + timerange: TimerangeInput, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetNetworkHttpQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, NetworkHttp: { __typename?: 'NetworkHttpData', totalCount: number, edges: Array<{ __typename?: 'NetworkHttpEdges', node: { __typename?: 'NetworkHttpItem', domains: Array, lastHost: Maybe, lastSourceIp: Maybe, methods: Array, path: Maybe, requestCount: Maybe, statuses: Array }, cursor: { __typename?: 'CursorType', value: Maybe } }>, pageInfo: { __typename?: 'PageInfoPaginated', activePage: number, fakeTotalCount: number, showMorePagesIndicator: boolean }, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type GetNetworkTopCountriesQueryQueryVariables = { + sourceId: Scalars['ID'], + ip?: Maybe, + filterQuery?: Maybe, + pagination: PaginationInputPaginated, + sort: NetworkTopTablesSortField, + flowTarget: FlowTargetSourceDest, + timerange: TimerangeInput, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetNetworkTopCountriesQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, NetworkTopCountries: { __typename?: 'NetworkTopCountriesData', totalCount: number, edges: Array<{ __typename?: 'NetworkTopCountriesEdges', node: { __typename?: 'NetworkTopCountriesItem', source: Maybe<{ __typename?: 'TopCountriesItemSource', country: Maybe, destination_ips: Maybe, flows: Maybe, source_ips: Maybe }>, destination: Maybe<{ __typename?: 'TopCountriesItemDestination', country: Maybe, destination_ips: Maybe, flows: Maybe, source_ips: Maybe }>, network: Maybe<{ __typename?: 'TopNetworkTablesEcsField', bytes_in: Maybe, bytes_out: Maybe }> }, cursor: { __typename?: 'CursorType', value: Maybe } }>, pageInfo: { __typename?: 'PageInfoPaginated', activePage: number, fakeTotalCount: number, showMorePagesIndicator: boolean }, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type GetNetworkTopNFlowQueryQueryVariables = { + sourceId: Scalars['ID'], + ip?: Maybe, + filterQuery?: Maybe, + pagination: PaginationInputPaginated, + sort: NetworkTopTablesSortField, + flowTarget: FlowTargetSourceDest, + timerange: TimerangeInput, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetNetworkTopNFlowQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, NetworkTopNFlow: { __typename?: 'NetworkTopNFlowData', totalCount: number, edges: Array<{ __typename?: 'NetworkTopNFlowEdges', node: { __typename?: 'NetworkTopNFlowItem', source: Maybe<{ __typename?: 'TopNFlowItemSource', domain: Maybe>, ip: Maybe, flows: Maybe, destination_ips: Maybe, autonomous_system: Maybe<{ __typename?: 'AutonomousSystemItem', name: Maybe, number: Maybe }>, location: Maybe<{ __typename?: 'GeoItem', flowTarget: Maybe, geo: Maybe<{ __typename?: 'GeoEcsFields', continent_name: Maybe, country_name: Maybe, country_iso_code: Maybe, city_name: Maybe, region_iso_code: Maybe, region_name: Maybe }> }> }>, destination: Maybe<{ __typename?: 'TopNFlowItemDestination', domain: Maybe>, ip: Maybe, flows: Maybe, source_ips: Maybe, autonomous_system: Maybe<{ __typename?: 'AutonomousSystemItem', name: Maybe, number: Maybe }>, location: Maybe<{ __typename?: 'GeoItem', flowTarget: Maybe, geo: Maybe<{ __typename?: 'GeoEcsFields', continent_name: Maybe, country_name: Maybe, country_iso_code: Maybe, city_name: Maybe, region_iso_code: Maybe, region_name: Maybe }> }> }>, network: Maybe<{ __typename?: 'TopNetworkTablesEcsField', bytes_in: Maybe, bytes_out: Maybe }> }, cursor: { __typename?: 'CursorType', value: Maybe } }>, pageInfo: { __typename?: 'PageInfoPaginated', activePage: number, fakeTotalCount: number, showMorePagesIndicator: boolean }, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type GetOverviewHostQueryQueryVariables = { + sourceId: Scalars['ID'], + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetOverviewHostQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, OverviewHost: Maybe<{ __typename?: 'OverviewHostData', auditbeatAuditd: Maybe, auditbeatFIM: Maybe, auditbeatLogin: Maybe, auditbeatPackage: Maybe, auditbeatProcess: Maybe, auditbeatUser: Maybe, endgameDns: Maybe, endgameFile: Maybe, endgameImageLoad: Maybe, endgameNetwork: Maybe, endgameProcess: Maybe, endgameRegistry: Maybe, endgameSecurity: Maybe, filebeatSystemModule: Maybe, winlogbeatSecurity: Maybe, winlogbeatMWSysmonOperational: Maybe, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> }> } }; + +export type GetOverviewNetworkQueryQueryVariables = { + sourceId: Scalars['ID'], + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetOverviewNetworkQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, OverviewNetwork: Maybe<{ __typename?: 'OverviewNetworkData', auditbeatSocket: Maybe, filebeatCisco: Maybe, filebeatNetflow: Maybe, filebeatPanw: Maybe, filebeatSuricata: Maybe, filebeatZeek: Maybe, packetbeatDNS: Maybe, packetbeatFlow: Maybe, packetbeatTLS: Maybe, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> }> } }; + +export type SourceQueryQueryVariables = { + sourceId?: Maybe, + defaultIndex: Array +}; + + +export type SourceQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, status: { __typename?: 'SourceStatus', indicesExist: boolean, indexFields: Array<{ __typename?: 'IndexField', category: string, description: Maybe, example: Maybe, indexes: Array>, name: string, searchable: boolean, type: string, aggregatable: boolean, format: Maybe }> } } }; + +export type GetAllTimelineQueryVariables = { + pageInfo: PageInfoTimeline, + search?: Maybe, + sort?: Maybe, + onlyUserFavorite?: Maybe +}; + + +export type GetAllTimelineQuery = { __typename?: 'Query', getAllTimeline: { __typename?: 'ResponseTimelines', totalCount: Maybe, timeline: Array, noteIds: Maybe>, pinnedEventIds: Maybe>, title: Maybe, created: Maybe, createdBy: Maybe, updated: Maybe, updatedBy: Maybe, version: string, favorite: Maybe, userName: Maybe, favoriteDate: Maybe }>>, eventIdToNoteIds: Maybe, note: Maybe, timelineId: Maybe, noteId: string, created: Maybe, createdBy: Maybe, timelineVersion: Maybe, updated: Maybe, updatedBy: Maybe, version: Maybe }>>, notes: Maybe, note: Maybe, timelineId: Maybe, timelineVersion: Maybe, noteId: string, created: Maybe, createdBy: Maybe, updated: Maybe, updatedBy: Maybe, version: Maybe }>> }>> } }; + +export type DeleteTimelineMutationMutationVariables = { + id: Array +}; + + +export type DeleteTimelineMutationMutation = { __typename?: 'Mutation', deleteTimeline: boolean }; + +export type GetTimelineDetailsQueryQueryVariables = { + sourceId: Scalars['ID'], + eventId: Scalars['String'], + indexName: Scalars['String'], + defaultIndex: Array +}; + + +export type GetTimelineDetailsQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, TimelineDetails: { __typename?: 'TimelineDetailsData', data: Maybe, originalValue: Maybe }>> } } }; + +export type PersistTimelineFavoriteMutationMutationVariables = { + timelineId?: Maybe +}; + + +export type PersistTimelineFavoriteMutationMutation = { __typename?: 'Mutation', persistFavorite: { __typename?: 'ResponseFavoriteTimeline', savedObjectId: string, version: string, favorite: Maybe, userName: Maybe, favoriteDate: Maybe }>> } }; + +export type GetTimelineQueryQueryVariables = { + sourceId: Scalars['ID'], + fieldRequested: Array, + pagination: PaginationInput, + sortField: SortField, + filterQuery?: Maybe, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetTimelineQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, Timeline: { __typename?: 'TimelineData', totalCount: number, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }>, pageInfo: { __typename?: 'PageInfo', hasNextPage: Maybe, endCursor: Maybe<{ __typename?: 'CursorType', value: Maybe, tiebreaker: Maybe }> }, edges: Array<{ __typename?: 'TimelineEdges', node: { __typename?: 'TimelineItem', _id: string, _index: Maybe, data: Array<{ __typename?: 'TimelineNonEcsData', field: string, value: Maybe }>, ecs: { __typename?: 'ECS', _id: string, _index: Maybe, timestamp: Maybe, message: Maybe, system: Maybe<{ __typename?: 'SystemEcsField', auth: Maybe<{ __typename?: 'AuthEcsFields', ssh: Maybe<{ __typename?: 'SshEcsFields', signature: Maybe, method: Maybe }> }>, audit: Maybe<{ __typename?: 'AuditEcsFields', package: Maybe<{ __typename?: 'PackageEcsFields', arch: Maybe, entity_id: Maybe, name: Maybe, size: Maybe, summary: Maybe, version: Maybe }> }> }>, event: Maybe<{ __typename?: 'EventEcsFields', action: Maybe, category: Maybe, code: Maybe, created: Maybe, dataset: Maybe, duration: Maybe, end: Maybe, hash: Maybe, id: Maybe, kind: Maybe, module: Maybe, original: Maybe, outcome: Maybe, risk_score: Maybe, risk_score_norm: Maybe, severity: Maybe, start: Maybe, timezone: Maybe, type: Maybe }>, auditd: Maybe<{ __typename?: 'AuditdEcsFields', result: Maybe, session: Maybe, data: Maybe<{ __typename?: 'AuditdData', acct: Maybe, terminal: Maybe, op: Maybe }>, summary: Maybe<{ __typename?: 'Summary', how: Maybe, message_type: Maybe, sequence: Maybe, actor: Maybe<{ __typename?: 'PrimarySecondary', primary: Maybe, secondary: Maybe }>, object: Maybe<{ __typename?: 'PrimarySecondary', primary: Maybe, secondary: Maybe, type: Maybe }> }> }>, file: Maybe<{ __typename?: 'FileFields', name: Maybe, path: Maybe, target_path: Maybe, extension: Maybe, type: Maybe, device: Maybe, inode: Maybe, uid: Maybe, owner: Maybe, gid: Maybe, group: Maybe, mode: Maybe, size: Maybe, mtime: Maybe, ctime: Maybe }>, host: Maybe<{ __typename?: 'HostEcsFields', id: Maybe, name: Maybe, ip: Maybe }>, rule: Maybe<{ __typename?: 'RuleEcsField', reference: Maybe }>, source: Maybe<{ __typename?: 'SourceEcsFields', bytes: Maybe, ip: Maybe, packets: Maybe, port: Maybe, geo: Maybe<{ __typename?: 'GeoEcsFields', continent_name: Maybe, country_name: Maybe, country_iso_code: Maybe, city_name: Maybe, region_iso_code: Maybe, region_name: Maybe }> }>, destination: Maybe<{ __typename?: 'DestinationEcsFields', bytes: Maybe, ip: Maybe, packets: Maybe, port: Maybe, geo: Maybe<{ __typename?: 'GeoEcsFields', continent_name: Maybe, country_name: Maybe, country_iso_code: Maybe, city_name: Maybe, region_iso_code: Maybe, region_name: Maybe }> }>, dns: Maybe<{ __typename?: 'DnsEcsFields', resolved_ip: Maybe, response_code: Maybe, question: Maybe<{ __typename?: 'DnsQuestionData', name: Maybe, type: Maybe }> }>, endgame: Maybe<{ __typename?: 'EndgameEcsFields', exit_code: Maybe, file_name: Maybe, file_path: Maybe, logon_type: Maybe, parent_process_name: Maybe, pid: Maybe, process_name: Maybe, subject_domain_name: Maybe, subject_logon_id: Maybe, subject_user_name: Maybe, target_domain_name: Maybe, target_logon_id: Maybe, target_user_name: Maybe }>, geo: Maybe<{ __typename?: 'GeoEcsFields', region_name: Maybe, country_iso_code: Maybe }>, signal: Maybe<{ __typename?: 'SignalField', original_time: Maybe, rule: Maybe<{ __typename?: 'RuleField', id: Maybe, saved_id: Maybe, timeline_id: Maybe, timeline_title: Maybe, output_index: Maybe, from: Maybe, index: Maybe, language: Maybe, query: Maybe, to: Maybe, filters: Maybe }> }>, suricata: Maybe<{ __typename?: 'SuricataEcsFields', eve: Maybe<{ __typename?: 'SuricataEveData', proto: Maybe, flow_id: Maybe, alert: Maybe<{ __typename?: 'SuricataAlertData', signature: Maybe, signature_id: Maybe }> }> }>, network: Maybe<{ __typename?: 'NetworkEcsField', bytes: Maybe, community_id: Maybe, direction: Maybe, packets: Maybe, protocol: Maybe, transport: Maybe }>, http: Maybe<{ __typename?: 'HttpEcsFields', version: Maybe, request: Maybe<{ __typename?: 'HttpRequestData', method: Maybe, referrer: Maybe, body: Maybe<{ __typename?: 'HttpBodyData', bytes: Maybe, content: Maybe }> }>, response: Maybe<{ __typename?: 'HttpResponseData', status_code: Maybe, body: Maybe<{ __typename?: 'HttpBodyData', bytes: Maybe, content: Maybe }> }> }>, tls: Maybe<{ __typename?: 'TlsEcsFields', client_certificate: Maybe<{ __typename?: 'TlsClientCertificateData', fingerprint: Maybe<{ __typename?: 'FingerprintData', sha1: Maybe }> }>, fingerprints: Maybe<{ __typename?: 'TlsFingerprintsData', ja3: Maybe<{ __typename?: 'TlsJa3Data', hash: Maybe }> }>, server_certificate: Maybe<{ __typename?: 'TlsServerCertificateData', fingerprint: Maybe<{ __typename?: 'FingerprintData', sha1: Maybe }> }> }>, url: Maybe<{ __typename?: 'UrlEcsFields', original: Maybe, domain: Maybe, username: Maybe, password: Maybe }>, user: Maybe<{ __typename?: 'UserEcsFields', domain: Maybe, name: Maybe }>, winlog: Maybe<{ __typename?: 'WinlogEcsFields', event_id: Maybe }>, process: Maybe<{ __typename?: 'ProcessEcsFields', pid: Maybe, name: Maybe, ppid: Maybe, args: Maybe, executable: Maybe, title: Maybe, working_directory: Maybe, hash: Maybe<{ __typename?: 'ProcessHashData', md5: Maybe, sha1: Maybe, sha256: Maybe }> }>, zeek: Maybe<{ __typename?: 'ZeekEcsFields', session_id: Maybe, connection: Maybe<{ __typename?: 'ZeekConnectionData', local_resp: Maybe, local_orig: Maybe, missed_bytes: Maybe, state: Maybe, history: Maybe }>, notice: Maybe<{ __typename?: 'ZeekNoticeData', suppress_for: Maybe, msg: Maybe, note: Maybe, sub: Maybe, dst: Maybe, dropped: Maybe, peer_descr: Maybe }>, dns: Maybe<{ __typename?: 'ZeekDnsData', AA: Maybe, qclass_name: Maybe, RD: Maybe, qtype_name: Maybe, rejected: Maybe, qtype: Maybe, query: Maybe, trans_id: Maybe, qclass: Maybe, RA: Maybe, TC: Maybe }>, http: Maybe<{ __typename?: 'ZeekHttpData', resp_mime_types: Maybe, trans_depth: Maybe, status_msg: Maybe, resp_fuids: Maybe, tags: Maybe }>, files: Maybe<{ __typename?: 'ZeekFileData', session_ids: Maybe, timedout: Maybe, local_orig: Maybe, tx_host: Maybe, source: Maybe, is_orig: Maybe, overflow_bytes: Maybe, sha1: Maybe, duration: Maybe, depth: Maybe, analyzers: Maybe, mime_type: Maybe, rx_host: Maybe, total_bytes: Maybe, fuid: Maybe, seen_bytes: Maybe, missing_bytes: Maybe, md5: Maybe }>, ssl: Maybe<{ __typename?: 'ZeekSslData', cipher: Maybe, established: Maybe, resumed: Maybe, version: Maybe }> }> } } }> } } }; + +export type PersistTimelineNoteMutationMutationVariables = { + noteId?: Maybe, + version?: Maybe, + note: NoteInput +}; + + +export type PersistTimelineNoteMutationMutation = { __typename?: 'Mutation', persistNote: { __typename?: 'ResponseNote', code: Maybe, message: Maybe, note: { __typename?: 'NoteResult', eventId: Maybe, note: Maybe, timelineId: Maybe, timelineVersion: Maybe, noteId: string, created: Maybe, createdBy: Maybe, updated: Maybe, updatedBy: Maybe, version: Maybe } } }; + +export type GetOneTimelineQueryVariables = { + id: Scalars['ID'] +}; + + +export type GetOneTimelineQuery = { __typename?: 'Query', getOneTimeline: { __typename?: 'TimelineResult', savedObjectId: string, description: Maybe, eventType: Maybe, kqlMode: Maybe, noteIds: Maybe>, pinnedEventIds: Maybe>, title: Maybe, savedQueryId: Maybe, created: Maybe, createdBy: Maybe, updated: Maybe, updatedBy: Maybe, version: string, columns: Maybe, category: Maybe, columnHeaderType: Maybe, description: Maybe, example: Maybe, indexes: Maybe>, id: Maybe, name: Maybe, searchable: Maybe, type: Maybe }>>, dataProviders: Maybe, name: Maybe, enabled: Maybe, excluded: Maybe, kqlQuery: Maybe, queryMatch: Maybe<{ __typename?: 'QueryMatchResult', field: Maybe, displayField: Maybe, value: Maybe, displayValue: Maybe, operator: Maybe }>, and: Maybe, name: Maybe, enabled: Maybe, excluded: Maybe, kqlQuery: Maybe, queryMatch: Maybe<{ __typename?: 'QueryMatchResult', field: Maybe, displayField: Maybe, value: Maybe, displayValue: Maybe, operator: Maybe }> }>> }>>, dateRange: Maybe<{ __typename?: 'DateRangePickerResult', start: Maybe, end: Maybe }>, eventIdToNoteIds: Maybe, note: Maybe, timelineId: Maybe, noteId: string, created: Maybe, createdBy: Maybe, timelineVersion: Maybe, updated: Maybe, updatedBy: Maybe, version: Maybe }>>, favorite: Maybe, userName: Maybe, favoriteDate: Maybe }>>, filters: Maybe, exists: Maybe, match_all: Maybe, missing: Maybe, range: Maybe, script: Maybe, meta: Maybe<{ __typename?: 'FilterMetaTimelineResult', alias: Maybe, controlledBy: Maybe, disabled: Maybe, field: Maybe, formattedValue: Maybe, index: Maybe, key: Maybe, negate: Maybe, params: Maybe, type: Maybe, value: Maybe }> }>>, kqlQuery: Maybe<{ __typename?: 'SerializedFilterQueryResult', filterQuery: Maybe<{ __typename?: 'SerializedKueryQueryResult', serializedQuery: Maybe, kuery: Maybe<{ __typename?: 'KueryFilterQueryResult', kind: Maybe, expression: Maybe }> }> }>, notes: Maybe, note: Maybe, timelineId: Maybe, timelineVersion: Maybe, noteId: string, created: Maybe, createdBy: Maybe, updated: Maybe, updatedBy: Maybe, version: Maybe }>>, pinnedEventsSaveObject: Maybe, timelineId: Maybe, created: Maybe, createdBy: Maybe, updated: Maybe, updatedBy: Maybe, version: Maybe }>>, sort: Maybe<{ __typename?: 'SortTimelineResult', columnId: Maybe, sortDirection: Maybe }> } }; + +export type PersistTimelineMutationMutationVariables = { + timelineId?: Maybe, + version?: Maybe, + timeline: TimelineInput +}; + + +export type PersistTimelineMutationMutation = { __typename?: 'Mutation', persistTimeline: { __typename?: 'ResponseTimeline', code: Maybe, message: Maybe, timeline: { __typename?: 'TimelineResult', savedObjectId: string, version: string, description: Maybe, eventType: Maybe, kqlMode: Maybe, title: Maybe, savedQueryId: Maybe, created: Maybe, createdBy: Maybe, updated: Maybe, updatedBy: Maybe, columns: Maybe, category: Maybe, columnHeaderType: Maybe, description: Maybe, example: Maybe, indexes: Maybe>, id: Maybe, name: Maybe, searchable: Maybe, type: Maybe }>>, dataProviders: Maybe, name: Maybe, enabled: Maybe, excluded: Maybe, kqlQuery: Maybe, queryMatch: Maybe<{ __typename?: 'QueryMatchResult', field: Maybe, displayField: Maybe, value: Maybe, displayValue: Maybe, operator: Maybe }>, and: Maybe, name: Maybe, enabled: Maybe, excluded: Maybe, kqlQuery: Maybe, queryMatch: Maybe<{ __typename?: 'QueryMatchResult', field: Maybe, displayField: Maybe, value: Maybe, displayValue: Maybe, operator: Maybe }> }>> }>>, favorite: Maybe, userName: Maybe, favoriteDate: Maybe }>>, filters: Maybe, exists: Maybe, match_all: Maybe, missing: Maybe, range: Maybe, script: Maybe, meta: Maybe<{ __typename?: 'FilterMetaTimelineResult', alias: Maybe, controlledBy: Maybe, disabled: Maybe, field: Maybe, formattedValue: Maybe, index: Maybe, key: Maybe, negate: Maybe, params: Maybe, type: Maybe, value: Maybe }> }>>, kqlQuery: Maybe<{ __typename?: 'SerializedFilterQueryResult', filterQuery: Maybe<{ __typename?: 'SerializedKueryQueryResult', serializedQuery: Maybe, kuery: Maybe<{ __typename?: 'KueryFilterQueryResult', kind: Maybe, expression: Maybe }> }> }>, dateRange: Maybe<{ __typename?: 'DateRangePickerResult', start: Maybe, end: Maybe }>, sort: Maybe<{ __typename?: 'SortTimelineResult', columnId: Maybe, sortDirection: Maybe }> } } }; + +export type PersistTimelinePinnedEventMutationMutationVariables = { + pinnedEventId?: Maybe, + eventId: Scalars['ID'], + timelineId?: Maybe +}; + + +export type PersistTimelinePinnedEventMutationMutation = { __typename?: 'Mutation', persistPinnedEventOnTimeline: Maybe<{ __typename?: 'PinnedEvent', pinnedEventId: string, eventId: Maybe, timelineId: Maybe, timelineVersion: Maybe, created: Maybe, createdBy: Maybe, updated: Maybe, updatedBy: Maybe, version: Maybe }> }; + +export type GetTlsQueryQueryVariables = { + sourceId: Scalars['ID'], + filterQuery?: Maybe, + flowTarget: FlowTargetSourceDest, + ip: Scalars['String'], + pagination: PaginationInputPaginated, + sort: TlsSortField, + timerange: TimerangeInput, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetTlsQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, Tls: { __typename?: 'TlsData', totalCount: number, edges: Array<{ __typename?: 'TlsEdges', node: { __typename?: 'TlsNode', _id: Maybe, alternativeNames: Maybe>, commonNames: Maybe>, ja3: Maybe>, issuerNames: Maybe>, notAfter: Maybe> }, cursor: { __typename?: 'CursorType', value: Maybe } }>, pageInfo: { __typename?: 'PageInfoPaginated', activePage: number, fakeTotalCount: number, showMorePagesIndicator: boolean }, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type GetUncommonProcessesQueryQueryVariables = { + sourceId: Scalars['ID'], + timerange: TimerangeInput, + pagination: PaginationInputPaginated, + filterQuery?: Maybe, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetUncommonProcessesQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, UncommonProcesses: { __typename?: 'UncommonProcessesData', totalCount: number, edges: Array<{ __typename?: 'UncommonProcessesEdges', node: { __typename?: 'UncommonProcessItem', _id: string, instances: number, process: { __typename?: 'ProcessEcsFields', args: Maybe, name: Maybe }, user: Maybe<{ __typename?: 'UserEcsFields', id: Maybe, name: Maybe }>, hosts: Array<{ __typename?: 'HostEcsFields', name: Maybe }> }, cursor: { __typename?: 'CursorType', value: Maybe } }>, pageInfo: { __typename?: 'PageInfoPaginated', activePage: number, fakeTotalCount: number, showMorePagesIndicator: boolean }, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export type GetUsersQueryQueryVariables = { + sourceId: Scalars['ID'], + filterQuery?: Maybe, + flowTarget: FlowTarget, + ip: Scalars['String'], + pagination: PaginationInputPaginated, + sort: UsersSortField, + timerange: TimerangeInput, + defaultIndex: Array, + inspect: Scalars['Boolean'] +}; + + +export type GetUsersQueryQuery = { __typename?: 'Query', source: { __typename?: 'Source', id: string, Users: { __typename?: 'UsersData', totalCount: number, edges: Array<{ __typename?: 'UsersEdges', node: { __typename?: 'UsersNode', user: Maybe<{ __typename?: 'UsersItem', name: Maybe, id: Maybe, groupId: Maybe, groupName: Maybe, count: Maybe }> }, cursor: { __typename?: 'CursorType', value: Maybe } }>, pageInfo: { __typename?: 'PageInfoPaginated', activePage: number, fakeTotalCount: number, showMorePagesIndicator: boolean }, inspect: Maybe<{ __typename?: 'Inspect', dsl: Array, response: Array }> } } }; + +export const KpiHostDetailsChartFieldsFragmentDoc = gql` + fragment KpiHostDetailsChartFields on KpiHostHistogramData { + x + y +} + `; +export const KpiHostChartFieldsFragmentDoc = gql` + fragment KpiHostChartFields on KpiHostHistogramData { + x + y +} + `; +export const KpiNetworkChartFieldsFragmentDoc = gql` + fragment KpiNetworkChartFields on KpiNetworkHistogramData { + x + y +} + `; +export const GetAuthenticationsQueryDocument = gql` + query GetAuthenticationsQuery($sourceId: ID!, $timerange: TimerangeInput!, $pagination: PaginationInputPaginated!, $filterQuery: String, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + Authentications(timerange: $timerange, pagination: $pagination, filterQuery: $filterQuery, defaultIndex: $defaultIndex) { + totalCount + edges { + node { + _id + failures + successes + user { + name + } + lastSuccess { + timestamp + source { + ip + } + host { + id + name + } + } + lastFailure { + timestamp + source { + ip + } + host { + id + name + } + } + } + cursor { + value + } + } + pageInfo { + activePage + fakeTotalCount + showMorePagesIndicator + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetAuthenticationsQueryComponentProps = Omit, 'query'> & ({ variables: GetAuthenticationsQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetAuthenticationsQueryComponent = (props: GetAuthenticationsQueryComponentProps) => ( + query={GetAuthenticationsQueryDocument} {...props} /> + ); + + +/** + * __useGetAuthenticationsQueryQuery__ + * + * To run a query within a React component, call `useGetAuthenticationsQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetAuthenticationsQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetAuthenticationsQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * timerange: // value for 'timerange' + * pagination: // value for 'pagination' + * filterQuery: // value for 'filterQuery' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetAuthenticationsQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetAuthenticationsQueryDocument, baseOptions); + } +export function useGetAuthenticationsQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetAuthenticationsQueryDocument, baseOptions); + } +export type GetAuthenticationsQueryQueryHookResult = ReturnType; +export type GetAuthenticationsQueryLazyQueryHookResult = ReturnType; +export type GetAuthenticationsQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetLastEventTimeQueryDocument = gql` + query GetLastEventTimeQuery($sourceId: ID!, $indexKey: LastEventIndexKey!, $details: LastTimeDetails!, $defaultIndex: [String!]!) { + source(id: $sourceId) { + id + LastEventTime(indexKey: $indexKey, details: $details, defaultIndex: $defaultIndex) { + lastSeen + } + } +} + `; +export type GetLastEventTimeQueryComponentProps = Omit, 'query'> & ({ variables: GetLastEventTimeQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetLastEventTimeQueryComponent = (props: GetLastEventTimeQueryComponentProps) => ( + query={GetLastEventTimeQueryDocument} {...props} /> + ); + + +/** + * __useGetLastEventTimeQueryQuery__ + * + * To run a query within a React component, call `useGetLastEventTimeQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetLastEventTimeQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetLastEventTimeQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * indexKey: // value for 'indexKey' + * details: // value for 'details' + * defaultIndex: // value for 'defaultIndex' + * }, + * }); + */ +export function useGetLastEventTimeQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetLastEventTimeQueryDocument, baseOptions); + } +export function useGetLastEventTimeQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetLastEventTimeQueryDocument, baseOptions); + } +export type GetLastEventTimeQueryQueryHookResult = ReturnType; +export type GetLastEventTimeQueryLazyQueryHookResult = ReturnType; +export type GetLastEventTimeQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetHostFirstLastSeenQueryDocument = gql` + query GetHostFirstLastSeenQuery($sourceId: ID!, $hostName: String!, $defaultIndex: [String!]!) { + source(id: $sourceId) { + id + HostFirstLastSeen(hostName: $hostName, defaultIndex: $defaultIndex) { + firstSeen + lastSeen + } + } +} + `; +export type GetHostFirstLastSeenQueryComponentProps = Omit, 'query'> & ({ variables: GetHostFirstLastSeenQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetHostFirstLastSeenQueryComponent = (props: GetHostFirstLastSeenQueryComponentProps) => ( + query={GetHostFirstLastSeenQueryDocument} {...props} /> + ); + + +/** + * __useGetHostFirstLastSeenQueryQuery__ + * + * To run a query within a React component, call `useGetHostFirstLastSeenQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetHostFirstLastSeenQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetHostFirstLastSeenQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * hostName: // value for 'hostName' + * defaultIndex: // value for 'defaultIndex' + * }, + * }); + */ +export function useGetHostFirstLastSeenQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetHostFirstLastSeenQueryDocument, baseOptions); + } +export function useGetHostFirstLastSeenQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetHostFirstLastSeenQueryDocument, baseOptions); + } +export type GetHostFirstLastSeenQueryQueryHookResult = ReturnType; +export type GetHostFirstLastSeenQueryLazyQueryHookResult = ReturnType; +export type GetHostFirstLastSeenQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetHostsTableQueryDocument = gql` + query GetHostsTableQuery($sourceId: ID!, $timerange: TimerangeInput!, $pagination: PaginationInputPaginated!, $sort: HostsSortField!, $filterQuery: String, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + Hosts(timerange: $timerange, pagination: $pagination, sort: $sort, filterQuery: $filterQuery, defaultIndex: $defaultIndex) { + totalCount + edges { + node { + _id + lastSeen + host { + id + name + os { + name + version + } + } + } + cursor { + value + } + } + pageInfo { + activePage + fakeTotalCount + showMorePagesIndicator + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetHostsTableQueryComponentProps = Omit, 'query'> & ({ variables: GetHostsTableQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetHostsTableQueryComponent = (props: GetHostsTableQueryComponentProps) => ( + query={GetHostsTableQueryDocument} {...props} /> + ); + + +/** + * __useGetHostsTableQueryQuery__ + * + * To run a query within a React component, call `useGetHostsTableQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetHostsTableQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetHostsTableQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * timerange: // value for 'timerange' + * pagination: // value for 'pagination' + * sort: // value for 'sort' + * filterQuery: // value for 'filterQuery' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetHostsTableQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetHostsTableQueryDocument, baseOptions); + } +export function useGetHostsTableQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetHostsTableQueryDocument, baseOptions); + } +export type GetHostsTableQueryQueryHookResult = ReturnType; +export type GetHostsTableQueryLazyQueryHookResult = ReturnType; +export type GetHostsTableQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetHostOverviewQueryDocument = gql` + query GetHostOverviewQuery($sourceId: ID!, $hostName: String!, $timerange: TimerangeInput!, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + HostOverview(hostName: $hostName, timerange: $timerange, defaultIndex: $defaultIndex) { + _id + host { + architecture + id + ip + mac + name + os { + family + name + platform + version + } + type + } + cloud { + instance { + id + } + machine { + type + } + provider + region + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetHostOverviewQueryComponentProps = Omit, 'query'> & ({ variables: GetHostOverviewQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetHostOverviewQueryComponent = (props: GetHostOverviewQueryComponentProps) => ( + query={GetHostOverviewQueryDocument} {...props} /> + ); + + +/** + * __useGetHostOverviewQueryQuery__ + * + * To run a query within a React component, call `useGetHostOverviewQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetHostOverviewQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetHostOverviewQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * hostName: // value for 'hostName' + * timerange: // value for 'timerange' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetHostOverviewQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetHostOverviewQueryDocument, baseOptions); + } +export function useGetHostOverviewQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetHostOverviewQueryDocument, baseOptions); + } +export type GetHostOverviewQueryQueryHookResult = ReturnType; +export type GetHostOverviewQueryLazyQueryHookResult = ReturnType; +export type GetHostOverviewQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetIpOverviewQueryDocument = gql` + query GetIpOverviewQuery($sourceId: ID!, $filterQuery: String, $ip: String!, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + IpOverview(filterQuery: $filterQuery, ip: $ip, defaultIndex: $defaultIndex) { + source { + firstSeen + lastSeen + autonomousSystem { + number + organization { + name + } + } + geo { + continent_name + city_name + country_iso_code + country_name + location { + lat + lon + } + region_iso_code + region_name + } + } + destination { + firstSeen + lastSeen + autonomousSystem { + number + organization { + name + } + } + geo { + continent_name + city_name + country_iso_code + country_name + location { + lat + lon + } + region_iso_code + region_name + } + } + host { + architecture + id + ip + mac + name + os { + family + name + platform + version + } + type + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetIpOverviewQueryComponentProps = Omit, 'query'> & ({ variables: GetIpOverviewQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetIpOverviewQueryComponent = (props: GetIpOverviewQueryComponentProps) => ( + query={GetIpOverviewQueryDocument} {...props} /> + ); + + +/** + * __useGetIpOverviewQueryQuery__ + * + * To run a query within a React component, call `useGetIpOverviewQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetIpOverviewQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetIpOverviewQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * filterQuery: // value for 'filterQuery' + * ip: // value for 'ip' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetIpOverviewQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetIpOverviewQueryDocument, baseOptions); + } +export function useGetIpOverviewQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetIpOverviewQueryDocument, baseOptions); + } +export type GetIpOverviewQueryQueryHookResult = ReturnType; +export type GetIpOverviewQueryLazyQueryHookResult = ReturnType; +export type GetIpOverviewQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetKpiHostDetailsQueryDocument = gql` + query GetKpiHostDetailsQuery($sourceId: ID!, $timerange: TimerangeInput!, $filterQuery: String, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + KpiHostDetails(timerange: $timerange, filterQuery: $filterQuery, defaultIndex: $defaultIndex) { + authSuccess + authSuccessHistogram { + ...KpiHostDetailsChartFields + } + authFailure + authFailureHistogram { + ...KpiHostDetailsChartFields + } + uniqueSourceIps + uniqueSourceIpsHistogram { + ...KpiHostDetailsChartFields + } + uniqueDestinationIps + uniqueDestinationIpsHistogram { + ...KpiHostDetailsChartFields + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + ${KpiHostDetailsChartFieldsFragmentDoc}`; +export type GetKpiHostDetailsQueryComponentProps = Omit, 'query'> & ({ variables: GetKpiHostDetailsQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetKpiHostDetailsQueryComponent = (props: GetKpiHostDetailsQueryComponentProps) => ( + query={GetKpiHostDetailsQueryDocument} {...props} /> + ); + + +/** + * __useGetKpiHostDetailsQueryQuery__ + * + * To run a query within a React component, call `useGetKpiHostDetailsQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetKpiHostDetailsQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetKpiHostDetailsQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * timerange: // value for 'timerange' + * filterQuery: // value for 'filterQuery' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetKpiHostDetailsQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetKpiHostDetailsQueryDocument, baseOptions); + } +export function useGetKpiHostDetailsQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetKpiHostDetailsQueryDocument, baseOptions); + } +export type GetKpiHostDetailsQueryQueryHookResult = ReturnType; +export type GetKpiHostDetailsQueryLazyQueryHookResult = ReturnType; +export type GetKpiHostDetailsQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetKpiHostsQueryDocument = gql` + query GetKpiHostsQuery($sourceId: ID!, $timerange: TimerangeInput!, $filterQuery: String, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + KpiHosts(timerange: $timerange, filterQuery: $filterQuery, defaultIndex: $defaultIndex) { + hosts + hostsHistogram { + ...KpiHostChartFields + } + authSuccess + authSuccessHistogram { + ...KpiHostChartFields + } + authFailure + authFailureHistogram { + ...KpiHostChartFields + } + uniqueSourceIps + uniqueSourceIpsHistogram { + ...KpiHostChartFields + } + uniqueDestinationIps + uniqueDestinationIpsHistogram { + ...KpiHostChartFields + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + ${KpiHostChartFieldsFragmentDoc}`; +export type GetKpiHostsQueryComponentProps = Omit, 'query'> & ({ variables: GetKpiHostsQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetKpiHostsQueryComponent = (props: GetKpiHostsQueryComponentProps) => ( + query={GetKpiHostsQueryDocument} {...props} /> + ); + + +/** + * __useGetKpiHostsQueryQuery__ + * + * To run a query within a React component, call `useGetKpiHostsQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetKpiHostsQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetKpiHostsQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * timerange: // value for 'timerange' + * filterQuery: // value for 'filterQuery' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetKpiHostsQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetKpiHostsQueryDocument, baseOptions); + } +export function useGetKpiHostsQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetKpiHostsQueryDocument, baseOptions); + } +export type GetKpiHostsQueryQueryHookResult = ReturnType; +export type GetKpiHostsQueryLazyQueryHookResult = ReturnType; +export type GetKpiHostsQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetKpiNetworkQueryDocument = gql` + query GetKpiNetworkQuery($sourceId: ID!, $timerange: TimerangeInput!, $filterQuery: String, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + KpiNetwork(timerange: $timerange, filterQuery: $filterQuery, defaultIndex: $defaultIndex) { + networkEvents + uniqueFlowId + uniqueSourcePrivateIps + uniqueSourcePrivateIpsHistogram { + ...KpiNetworkChartFields + } + uniqueDestinationPrivateIps + uniqueDestinationPrivateIpsHistogram { + ...KpiNetworkChartFields + } + dnsQueries + tlsHandshakes + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + ${KpiNetworkChartFieldsFragmentDoc}`; +export type GetKpiNetworkQueryComponentProps = Omit, 'query'> & ({ variables: GetKpiNetworkQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetKpiNetworkQueryComponent = (props: GetKpiNetworkQueryComponentProps) => ( + query={GetKpiNetworkQueryDocument} {...props} /> + ); + + +/** + * __useGetKpiNetworkQueryQuery__ + * + * To run a query within a React component, call `useGetKpiNetworkQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetKpiNetworkQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetKpiNetworkQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * timerange: // value for 'timerange' + * filterQuery: // value for 'filterQuery' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetKpiNetworkQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetKpiNetworkQueryDocument, baseOptions); + } +export function useGetKpiNetworkQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetKpiNetworkQueryDocument, baseOptions); + } +export type GetKpiNetworkQueryQueryHookResult = ReturnType; +export type GetKpiNetworkQueryLazyQueryHookResult = ReturnType; +export type GetKpiNetworkQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetMatrixHistogramQueryDocument = gql` + query GetMatrixHistogramQuery($defaultIndex: [String!]!, $filterQuery: String, $histogramType: HistogramType!, $inspect: Boolean!, $sourceId: ID!, $stackByField: String!, $timerange: TimerangeInput!) { + source(id: $sourceId) { + id + MatrixHistogram(timerange: $timerange, filterQuery: $filterQuery, defaultIndex: $defaultIndex, stackByField: $stackByField, histogramType: $histogramType) { + matrixHistogramData { + x + y + g + } + totalCount + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetMatrixHistogramQueryComponentProps = Omit, 'query'> & ({ variables: GetMatrixHistogramQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetMatrixHistogramQueryComponent = (props: GetMatrixHistogramQueryComponentProps) => ( + query={GetMatrixHistogramQueryDocument} {...props} /> + ); + + +/** + * __useGetMatrixHistogramQueryQuery__ + * + * To run a query within a React component, call `useGetMatrixHistogramQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetMatrixHistogramQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetMatrixHistogramQueryQuery({ + * variables: { + * defaultIndex: // value for 'defaultIndex' + * filterQuery: // value for 'filterQuery' + * histogramType: // value for 'histogramType' + * inspect: // value for 'inspect' + * sourceId: // value for 'sourceId' + * stackByField: // value for 'stackByField' + * timerange: // value for 'timerange' + * }, + * }); + */ +export function useGetMatrixHistogramQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetMatrixHistogramQueryDocument, baseOptions); + } +export function useGetMatrixHistogramQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetMatrixHistogramQueryDocument, baseOptions); + } +export type GetMatrixHistogramQueryQueryHookResult = ReturnType; +export type GetMatrixHistogramQueryLazyQueryHookResult = ReturnType; +export type GetMatrixHistogramQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetNetworkDnsQueryDocument = gql` + query GetNetworkDnsQuery($defaultIndex: [String!]!, $filterQuery: String, $inspect: Boolean!, $isPtrIncluded: Boolean!, $pagination: PaginationInputPaginated!, $sort: NetworkDnsSortField!, $sourceId: ID!, $stackByField: String, $timerange: TimerangeInput!) { + source(id: $sourceId) { + id + NetworkDns(isPtrIncluded: $isPtrIncluded, sort: $sort, timerange: $timerange, pagination: $pagination, filterQuery: $filterQuery, defaultIndex: $defaultIndex, stackByField: $stackByField) { + totalCount + edges { + node { + _id + dnsBytesIn + dnsBytesOut + dnsName + queryCount + uniqueDomains + } + cursor { + value + } + } + pageInfo { + activePage + fakeTotalCount + showMorePagesIndicator + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetNetworkDnsQueryComponentProps = Omit, 'query'> & ({ variables: GetNetworkDnsQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetNetworkDnsQueryComponent = (props: GetNetworkDnsQueryComponentProps) => ( + query={GetNetworkDnsQueryDocument} {...props} /> + ); + + +/** + * __useGetNetworkDnsQueryQuery__ + * + * To run a query within a React component, call `useGetNetworkDnsQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetNetworkDnsQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetNetworkDnsQueryQuery({ + * variables: { + * defaultIndex: // value for 'defaultIndex' + * filterQuery: // value for 'filterQuery' + * inspect: // value for 'inspect' + * isPtrIncluded: // value for 'isPtrIncluded' + * pagination: // value for 'pagination' + * sort: // value for 'sort' + * sourceId: // value for 'sourceId' + * stackByField: // value for 'stackByField' + * timerange: // value for 'timerange' + * }, + * }); + */ +export function useGetNetworkDnsQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetNetworkDnsQueryDocument, baseOptions); + } +export function useGetNetworkDnsQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetNetworkDnsQueryDocument, baseOptions); + } +export type GetNetworkDnsQueryQueryHookResult = ReturnType; +export type GetNetworkDnsQueryLazyQueryHookResult = ReturnType; +export type GetNetworkDnsQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetNetworkHttpQueryDocument = gql` + query GetNetworkHttpQuery($sourceId: ID!, $ip: String, $filterQuery: String, $pagination: PaginationInputPaginated!, $sort: NetworkHttpSortField!, $timerange: TimerangeInput!, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + NetworkHttp(filterQuery: $filterQuery, ip: $ip, pagination: $pagination, sort: $sort, timerange: $timerange, defaultIndex: $defaultIndex) { + totalCount + edges { + node { + domains + lastHost + lastSourceIp + methods + path + requestCount + statuses + } + cursor { + value + } + } + pageInfo { + activePage + fakeTotalCount + showMorePagesIndicator + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetNetworkHttpQueryComponentProps = Omit, 'query'> & ({ variables: GetNetworkHttpQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetNetworkHttpQueryComponent = (props: GetNetworkHttpQueryComponentProps) => ( + query={GetNetworkHttpQueryDocument} {...props} /> + ); + + +/** + * __useGetNetworkHttpQueryQuery__ + * + * To run a query within a React component, call `useGetNetworkHttpQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetNetworkHttpQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetNetworkHttpQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * ip: // value for 'ip' + * filterQuery: // value for 'filterQuery' + * pagination: // value for 'pagination' + * sort: // value for 'sort' + * timerange: // value for 'timerange' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetNetworkHttpQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetNetworkHttpQueryDocument, baseOptions); + } +export function useGetNetworkHttpQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetNetworkHttpQueryDocument, baseOptions); + } +export type GetNetworkHttpQueryQueryHookResult = ReturnType; +export type GetNetworkHttpQueryLazyQueryHookResult = ReturnType; +export type GetNetworkHttpQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetNetworkTopCountriesQueryDocument = gql` + query GetNetworkTopCountriesQuery($sourceId: ID!, $ip: String, $filterQuery: String, $pagination: PaginationInputPaginated!, $sort: NetworkTopTablesSortField!, $flowTarget: FlowTargetSourceDest!, $timerange: TimerangeInput!, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + NetworkTopCountries(filterQuery: $filterQuery, flowTarget: $flowTarget, ip: $ip, pagination: $pagination, sort: $sort, timerange: $timerange, defaultIndex: $defaultIndex) { + totalCount + edges { + node { + source { + country + destination_ips + flows + source_ips + } + destination { + country + destination_ips + flows + source_ips + } + network { + bytes_in + bytes_out + } + } + cursor { + value + } + } + pageInfo { + activePage + fakeTotalCount + showMorePagesIndicator + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetNetworkTopCountriesQueryComponentProps = Omit, 'query'> & ({ variables: GetNetworkTopCountriesQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetNetworkTopCountriesQueryComponent = (props: GetNetworkTopCountriesQueryComponentProps) => ( + query={GetNetworkTopCountriesQueryDocument} {...props} /> + ); + + +/** + * __useGetNetworkTopCountriesQueryQuery__ + * + * To run a query within a React component, call `useGetNetworkTopCountriesQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetNetworkTopCountriesQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetNetworkTopCountriesQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * ip: // value for 'ip' + * filterQuery: // value for 'filterQuery' + * pagination: // value for 'pagination' + * sort: // value for 'sort' + * flowTarget: // value for 'flowTarget' + * timerange: // value for 'timerange' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetNetworkTopCountriesQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetNetworkTopCountriesQueryDocument, baseOptions); + } +export function useGetNetworkTopCountriesQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetNetworkTopCountriesQueryDocument, baseOptions); + } +export type GetNetworkTopCountriesQueryQueryHookResult = ReturnType; +export type GetNetworkTopCountriesQueryLazyQueryHookResult = ReturnType; +export type GetNetworkTopCountriesQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetNetworkTopNFlowQueryDocument = gql` + query GetNetworkTopNFlowQuery($sourceId: ID!, $ip: String, $filterQuery: String, $pagination: PaginationInputPaginated!, $sort: NetworkTopTablesSortField!, $flowTarget: FlowTargetSourceDest!, $timerange: TimerangeInput!, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + NetworkTopNFlow(filterQuery: $filterQuery, flowTarget: $flowTarget, ip: $ip, pagination: $pagination, sort: $sort, timerange: $timerange, defaultIndex: $defaultIndex) { + totalCount + edges { + node { + source { + autonomous_system { + name + number + } + domain + ip + location { + geo { + continent_name + country_name + country_iso_code + city_name + region_iso_code + region_name + } + flowTarget + } + flows + destination_ips + } + destination { + autonomous_system { + name + number + } + domain + ip + location { + geo { + continent_name + country_name + country_iso_code + city_name + region_iso_code + region_name + } + flowTarget + } + flows + source_ips + } + network { + bytes_in + bytes_out + } + } + cursor { + value + } + } + pageInfo { + activePage + fakeTotalCount + showMorePagesIndicator + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetNetworkTopNFlowQueryComponentProps = Omit, 'query'> & ({ variables: GetNetworkTopNFlowQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetNetworkTopNFlowQueryComponent = (props: GetNetworkTopNFlowQueryComponentProps) => ( + query={GetNetworkTopNFlowQueryDocument} {...props} /> + ); + + +/** + * __useGetNetworkTopNFlowQueryQuery__ + * + * To run a query within a React component, call `useGetNetworkTopNFlowQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetNetworkTopNFlowQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetNetworkTopNFlowQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * ip: // value for 'ip' + * filterQuery: // value for 'filterQuery' + * pagination: // value for 'pagination' + * sort: // value for 'sort' + * flowTarget: // value for 'flowTarget' + * timerange: // value for 'timerange' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetNetworkTopNFlowQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetNetworkTopNFlowQueryDocument, baseOptions); + } +export function useGetNetworkTopNFlowQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetNetworkTopNFlowQueryDocument, baseOptions); + } +export type GetNetworkTopNFlowQueryQueryHookResult = ReturnType; +export type GetNetworkTopNFlowQueryLazyQueryHookResult = ReturnType; +export type GetNetworkTopNFlowQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetOverviewHostQueryDocument = gql` + query GetOverviewHostQuery($sourceId: ID!, $timerange: TimerangeInput!, $filterQuery: String, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + OverviewHost(timerange: $timerange, filterQuery: $filterQuery, defaultIndex: $defaultIndex) { + auditbeatAuditd + auditbeatFIM + auditbeatLogin + auditbeatPackage + auditbeatProcess + auditbeatUser + endgameDns + endgameFile + endgameImageLoad + endgameNetwork + endgameProcess + endgameRegistry + endgameSecurity + filebeatSystemModule + winlogbeatSecurity + winlogbeatMWSysmonOperational + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetOverviewHostQueryComponentProps = Omit, 'query'> & ({ variables: GetOverviewHostQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetOverviewHostQueryComponent = (props: GetOverviewHostQueryComponentProps) => ( + query={GetOverviewHostQueryDocument} {...props} /> + ); + + +/** + * __useGetOverviewHostQueryQuery__ + * + * To run a query within a React component, call `useGetOverviewHostQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetOverviewHostQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetOverviewHostQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * timerange: // value for 'timerange' + * filterQuery: // value for 'filterQuery' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetOverviewHostQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetOverviewHostQueryDocument, baseOptions); + } +export function useGetOverviewHostQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetOverviewHostQueryDocument, baseOptions); + } +export type GetOverviewHostQueryQueryHookResult = ReturnType; +export type GetOverviewHostQueryLazyQueryHookResult = ReturnType; +export type GetOverviewHostQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetOverviewNetworkQueryDocument = gql` + query GetOverviewNetworkQuery($sourceId: ID!, $timerange: TimerangeInput!, $filterQuery: String, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + OverviewNetwork(timerange: $timerange, filterQuery: $filterQuery, defaultIndex: $defaultIndex) { + auditbeatSocket + filebeatCisco + filebeatNetflow + filebeatPanw + filebeatSuricata + filebeatZeek + packetbeatDNS + packetbeatFlow + packetbeatTLS + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetOverviewNetworkQueryComponentProps = Omit, 'query'> & ({ variables: GetOverviewNetworkQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetOverviewNetworkQueryComponent = (props: GetOverviewNetworkQueryComponentProps) => ( + query={GetOverviewNetworkQueryDocument} {...props} /> + ); + + +/** + * __useGetOverviewNetworkQueryQuery__ + * + * To run a query within a React component, call `useGetOverviewNetworkQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetOverviewNetworkQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetOverviewNetworkQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * timerange: // value for 'timerange' + * filterQuery: // value for 'filterQuery' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetOverviewNetworkQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetOverviewNetworkQueryDocument, baseOptions); + } +export function useGetOverviewNetworkQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetOverviewNetworkQueryDocument, baseOptions); + } +export type GetOverviewNetworkQueryQueryHookResult = ReturnType; +export type GetOverviewNetworkQueryLazyQueryHookResult = ReturnType; +export type GetOverviewNetworkQueryQueryResult = ApolloReactCommon.QueryResult; +export const SourceQueryDocument = gql` + query SourceQuery($sourceId: ID = "default", $defaultIndex: [String!]!) { + source(id: $sourceId) { + id + status { + indicesExist(defaultIndex: $defaultIndex) + indexFields(defaultIndex: $defaultIndex) { + category + description + example + indexes + name + searchable + type + aggregatable + format + } + } + } +} + `; +export type SourceQueryComponentProps = Omit, 'query'> & ({ variables: SourceQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const SourceQueryComponent = (props: SourceQueryComponentProps) => ( + query={SourceQueryDocument} {...props} /> + ); + + +/** + * __useSourceQueryQuery__ + * + * To run a query within a React component, call `useSourceQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useSourceQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useSourceQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * defaultIndex: // value for 'defaultIndex' + * }, + * }); + */ +export function useSourceQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(SourceQueryDocument, baseOptions); + } +export function useSourceQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(SourceQueryDocument, baseOptions); + } +export type SourceQueryQueryHookResult = ReturnType; +export type SourceQueryLazyQueryHookResult = ReturnType; +export type SourceQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetAllTimelineDocument = gql` + query GetAllTimeline($pageInfo: PageInfoTimeline!, $search: String, $sort: SortTimeline, $onlyUserFavorite: Boolean) { + getAllTimeline(pageInfo: $pageInfo, search: $search, sort: $sort, onlyUserFavorite: $onlyUserFavorite) { + totalCount + timeline { + savedObjectId + description + favorite { + fullName + userName + favoriteDate + } + eventIdToNoteIds { + eventId + note + timelineId + noteId + created + createdBy + timelineVersion + updated + updatedBy + version + } + notes { + eventId + note + timelineId + timelineVersion + noteId + created + createdBy + updated + updatedBy + version + } + noteIds + pinnedEventIds + title + created + createdBy + updated + updatedBy + version + } + } +} + `; +export type GetAllTimelineComponentProps = Omit, 'query'> & ({ variables: GetAllTimelineQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetAllTimelineComponent = (props: GetAllTimelineComponentProps) => ( + query={GetAllTimelineDocument} {...props} /> + ); + + +/** + * __useGetAllTimelineQuery__ + * + * To run a query within a React component, call `useGetAllTimelineQuery` and pass it any options that fit your needs. + * When your component renders, `useGetAllTimelineQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetAllTimelineQuery({ + * variables: { + * pageInfo: // value for 'pageInfo' + * search: // value for 'search' + * sort: // value for 'sort' + * onlyUserFavorite: // value for 'onlyUserFavorite' + * }, + * }); + */ +export function useGetAllTimelineQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetAllTimelineDocument, baseOptions); + } +export function useGetAllTimelineLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetAllTimelineDocument, baseOptions); + } +export type GetAllTimelineQueryHookResult = ReturnType; +export type GetAllTimelineLazyQueryHookResult = ReturnType; +export type GetAllTimelineQueryResult = ApolloReactCommon.QueryResult; +export const DeleteTimelineMutationDocument = gql` + mutation DeleteTimelineMutation($id: [ID!]!) { + deleteTimeline(id: $id) +} + `; +export type DeleteTimelineMutationMutationFn = ApolloReactCommon.MutationFunction; +export type DeleteTimelineMutationComponentProps = Omit, 'mutation'>; + + export const DeleteTimelineMutationComponent = (props: DeleteTimelineMutationComponentProps) => ( + mutation={DeleteTimelineMutationDocument} {...props} /> + ); + + +/** + * __useDeleteTimelineMutationMutation__ + * + * To run a mutation, you first call `useDeleteTimelineMutationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteTimelineMutationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [deleteTimelineMutationMutation, { data, loading, error }] = useDeleteTimelineMutationMutation({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useDeleteTimelineMutationMutation(baseOptions?: ApolloReactHooks.MutationHookOptions) { + return ApolloReactHooks.useMutation(DeleteTimelineMutationDocument, baseOptions); + } +export type DeleteTimelineMutationMutationHookResult = ReturnType; +export type DeleteTimelineMutationMutationResult = ApolloReactCommon.MutationResult; +export type DeleteTimelineMutationMutationOptions = ApolloReactCommon.BaseMutationOptions; +export const GetTimelineDetailsQueryDocument = gql` + query GetTimelineDetailsQuery($sourceId: ID!, $eventId: String!, $indexName: String!, $defaultIndex: [String!]!) { + source(id: $sourceId) { + id + TimelineDetails(eventId: $eventId, indexName: $indexName, defaultIndex: $defaultIndex) { + data { + field + values + originalValue + } + } + } +} + `; +export type GetTimelineDetailsQueryComponentProps = Omit, 'query'> & ({ variables: GetTimelineDetailsQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetTimelineDetailsQueryComponent = (props: GetTimelineDetailsQueryComponentProps) => ( + query={GetTimelineDetailsQueryDocument} {...props} /> + ); + + +/** + * __useGetTimelineDetailsQueryQuery__ + * + * To run a query within a React component, call `useGetTimelineDetailsQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetTimelineDetailsQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetTimelineDetailsQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * eventId: // value for 'eventId' + * indexName: // value for 'indexName' + * defaultIndex: // value for 'defaultIndex' + * }, + * }); + */ +export function useGetTimelineDetailsQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetTimelineDetailsQueryDocument, baseOptions); + } +export function useGetTimelineDetailsQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetTimelineDetailsQueryDocument, baseOptions); + } +export type GetTimelineDetailsQueryQueryHookResult = ReturnType; +export type GetTimelineDetailsQueryLazyQueryHookResult = ReturnType; +export type GetTimelineDetailsQueryQueryResult = ApolloReactCommon.QueryResult; +export const PersistTimelineFavoriteMutationDocument = gql` + mutation PersistTimelineFavoriteMutation($timelineId: ID) { + persistFavorite(timelineId: $timelineId) { + savedObjectId + version + favorite { + fullName + userName + favoriteDate + } + } +} + `; +export type PersistTimelineFavoriteMutationMutationFn = ApolloReactCommon.MutationFunction; +export type PersistTimelineFavoriteMutationComponentProps = Omit, 'mutation'>; + + export const PersistTimelineFavoriteMutationComponent = (props: PersistTimelineFavoriteMutationComponentProps) => ( + mutation={PersistTimelineFavoriteMutationDocument} {...props} /> + ); + + +/** + * __usePersistTimelineFavoriteMutationMutation__ + * + * To run a mutation, you first call `usePersistTimelineFavoriteMutationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `usePersistTimelineFavoriteMutationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [persistTimelineFavoriteMutationMutation, { data, loading, error }] = usePersistTimelineFavoriteMutationMutation({ + * variables: { + * timelineId: // value for 'timelineId' + * }, + * }); + */ +export function usePersistTimelineFavoriteMutationMutation(baseOptions?: ApolloReactHooks.MutationHookOptions) { + return ApolloReactHooks.useMutation(PersistTimelineFavoriteMutationDocument, baseOptions); + } +export type PersistTimelineFavoriteMutationMutationHookResult = ReturnType; +export type PersistTimelineFavoriteMutationMutationResult = ApolloReactCommon.MutationResult; +export type PersistTimelineFavoriteMutationMutationOptions = ApolloReactCommon.BaseMutationOptions; +export const GetTimelineQueryDocument = gql` + query GetTimelineQuery($sourceId: ID!, $fieldRequested: [String!]!, $pagination: PaginationInput!, $sortField: SortField!, $filterQuery: String, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + Timeline(fieldRequested: $fieldRequested, pagination: $pagination, sortField: $sortField, filterQuery: $filterQuery, defaultIndex: $defaultIndex) { + totalCount + inspect @include(if: $inspect) { + dsl + response + } + pageInfo { + endCursor { + value + tiebreaker + } + hasNextPage + } + edges { + node { + _id + _index + data { + field + value + } + ecs { + _id + _index + timestamp + message + system { + auth { + ssh { + signature + method + } + } + audit { + package { + arch + entity_id + name + size + summary + version + } + } + } + event { + action + category + code + created + dataset + duration + end + hash + id + kind + module + original + outcome + risk_score + risk_score_norm + severity + start + timezone + type + } + auditd { + result + session + data { + acct + terminal + op + } + summary { + actor { + primary + secondary + } + object { + primary + secondary + type + } + how + message_type + sequence + } + } + file { + name + path + target_path + extension + type + device + inode + uid + owner + gid + group + mode + size + mtime + ctime + } + host { + id + name + ip + } + rule { + reference + } + source { + bytes + ip + packets + port + geo { + continent_name + country_name + country_iso_code + city_name + region_iso_code + region_name + } + } + destination { + bytes + ip + packets + port + geo { + continent_name + country_name + country_iso_code + city_name + region_iso_code + region_name + } + } + dns { + question { + name + type + } + resolved_ip + response_code + } + endgame { + exit_code + file_name + file_path + logon_type + parent_process_name + pid + process_name + subject_domain_name + subject_logon_id + subject_user_name + target_domain_name + target_logon_id + target_user_name + } + geo { + region_name + country_iso_code + } + signal { + original_time + rule { + id + saved_id + timeline_id + timeline_title + output_index + from + index + language + query + to + filters + } + } + suricata { + eve { + proto + flow_id + alert { + signature + signature_id + } + } + } + network { + bytes + community_id + direction + packets + protocol + transport + } + http { + version + request { + method + body { + bytes + content + } + referrer + } + response { + status_code + body { + bytes + content + } + } + } + tls { + client_certificate { + fingerprint { + sha1 + } + } + fingerprints { + ja3 { + hash + } + } + server_certificate { + fingerprint { + sha1 + } + } + } + url { + original + domain + username + password + } + user { + domain + name + } + winlog { + event_id + } + process { + hash { + md5 + sha1 + sha256 + } + pid + name + ppid + args + executable + title + working_directory + } + zeek { + session_id + connection { + local_resp + local_orig + missed_bytes + state + history + } + notice { + suppress_for + msg + note + sub + dst + dropped + peer_descr + } + dns { + AA + qclass_name + RD + qtype_name + rejected + qtype + query + trans_id + qclass + RA + TC + } + http { + resp_mime_types + trans_depth + status_msg + resp_fuids + tags + } + files { + session_ids + timedout + local_orig + tx_host + source + is_orig + overflow_bytes + sha1 + duration + depth + analyzers + mime_type + rx_host + total_bytes + fuid + seen_bytes + missing_bytes + md5 + } + ssl { + cipher + established + resumed + version + } + } + } + } + } + } + } +} + `; +export type GetTimelineQueryComponentProps = Omit, 'query'> & ({ variables: GetTimelineQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetTimelineQueryComponent = (props: GetTimelineQueryComponentProps) => ( + query={GetTimelineQueryDocument} {...props} /> + ); + + +/** + * __useGetTimelineQueryQuery__ + * + * To run a query within a React component, call `useGetTimelineQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetTimelineQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetTimelineQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * fieldRequested: // value for 'fieldRequested' + * pagination: // value for 'pagination' + * sortField: // value for 'sortField' + * filterQuery: // value for 'filterQuery' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetTimelineQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetTimelineQueryDocument, baseOptions); + } +export function useGetTimelineQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetTimelineQueryDocument, baseOptions); + } +export type GetTimelineQueryQueryHookResult = ReturnType; +export type GetTimelineQueryLazyQueryHookResult = ReturnType; +export type GetTimelineQueryQueryResult = ApolloReactCommon.QueryResult; +export const PersistTimelineNoteMutationDocument = gql` + mutation PersistTimelineNoteMutation($noteId: ID, $version: String, $note: NoteInput!) { + persistNote(noteId: $noteId, version: $version, note: $note) { + code + message + note { + eventId + note + timelineId + timelineVersion + noteId + created + createdBy + updated + updatedBy + version + } + } +} + `; +export type PersistTimelineNoteMutationMutationFn = ApolloReactCommon.MutationFunction; +export type PersistTimelineNoteMutationComponentProps = Omit, 'mutation'>; + + export const PersistTimelineNoteMutationComponent = (props: PersistTimelineNoteMutationComponentProps) => ( + mutation={PersistTimelineNoteMutationDocument} {...props} /> + ); + + +/** + * __usePersistTimelineNoteMutationMutation__ + * + * To run a mutation, you first call `usePersistTimelineNoteMutationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `usePersistTimelineNoteMutationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [persistTimelineNoteMutationMutation, { data, loading, error }] = usePersistTimelineNoteMutationMutation({ + * variables: { + * noteId: // value for 'noteId' + * version: // value for 'version' + * note: // value for 'note' + * }, + * }); + */ +export function usePersistTimelineNoteMutationMutation(baseOptions?: ApolloReactHooks.MutationHookOptions) { + return ApolloReactHooks.useMutation(PersistTimelineNoteMutationDocument, baseOptions); + } +export type PersistTimelineNoteMutationMutationHookResult = ReturnType; +export type PersistTimelineNoteMutationMutationResult = ApolloReactCommon.MutationResult; +export type PersistTimelineNoteMutationMutationOptions = ApolloReactCommon.BaseMutationOptions; +export const GetOneTimelineDocument = gql` + query GetOneTimeline($id: ID!) { + getOneTimeline(id: $id) { + savedObjectId + columns { + aggregatable + category + columnHeaderType + description + example + indexes + id + name + searchable + type + } + dataProviders { + id + name + enabled + excluded + kqlQuery + queryMatch { + field + displayField + value + displayValue + operator + } + and { + id + name + enabled + excluded + kqlQuery + queryMatch { + field + displayField + value + displayValue + operator + } + } + } + dateRange { + start + end + } + description + eventType + eventIdToNoteIds { + eventId + note + timelineId + noteId + created + createdBy + timelineVersion + updated + updatedBy + version + } + favorite { + fullName + userName + favoriteDate + } + filters { + meta { + alias + controlledBy + disabled + field + formattedValue + index + key + negate + params + type + value + } + query + exists + match_all + missing + range + script + } + kqlMode + kqlQuery { + filterQuery { + kuery { + kind + expression + } + serializedQuery + } + } + notes { + eventId + note + timelineId + timelineVersion + noteId + created + createdBy + updated + updatedBy + version + } + noteIds + pinnedEventIds + pinnedEventsSaveObject { + pinnedEventId + eventId + timelineId + created + createdBy + updated + updatedBy + version + } + title + savedQueryId + sort { + columnId + sortDirection + } + created + createdBy + updated + updatedBy + version + } +} + `; +export type GetOneTimelineComponentProps = Omit, 'query'> & ({ variables: GetOneTimelineQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetOneTimelineComponent = (props: GetOneTimelineComponentProps) => ( + query={GetOneTimelineDocument} {...props} /> + ); + + +/** + * __useGetOneTimelineQuery__ + * + * To run a query within a React component, call `useGetOneTimelineQuery` and pass it any options that fit your needs. + * When your component renders, `useGetOneTimelineQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetOneTimelineQuery({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useGetOneTimelineQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetOneTimelineDocument, baseOptions); + } +export function useGetOneTimelineLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetOneTimelineDocument, baseOptions); + } +export type GetOneTimelineQueryHookResult = ReturnType; +export type GetOneTimelineLazyQueryHookResult = ReturnType; +export type GetOneTimelineQueryResult = ApolloReactCommon.QueryResult; +export const PersistTimelineMutationDocument = gql` + mutation PersistTimelineMutation($timelineId: ID, $version: String, $timeline: TimelineInput!) { + persistTimeline(id: $timelineId, version: $version, timeline: $timeline) { + code + message + timeline { + savedObjectId + version + columns { + aggregatable + category + columnHeaderType + description + example + indexes + id + name + searchable + type + } + dataProviders { + id + name + enabled + excluded + kqlQuery + queryMatch { + field + displayField + value + displayValue + operator + } + and { + id + name + enabled + excluded + kqlQuery + queryMatch { + field + displayField + value + displayValue + operator + } + } + } + description + eventType + favorite { + fullName + userName + favoriteDate + } + filters { + meta { + alias + controlledBy + disabled + field + formattedValue + index + key + negate + params + type + value + } + query + exists + match_all + missing + range + script + } + kqlMode + kqlQuery { + filterQuery { + kuery { + kind + expression + } + serializedQuery + } + } + title + dateRange { + start + end + } + savedQueryId + sort { + columnId + sortDirection + } + created + createdBy + updated + updatedBy + } + } +} + `; +export type PersistTimelineMutationMutationFn = ApolloReactCommon.MutationFunction; +export type PersistTimelineMutationComponentProps = Omit, 'mutation'>; + + export const PersistTimelineMutationComponent = (props: PersistTimelineMutationComponentProps) => ( + mutation={PersistTimelineMutationDocument} {...props} /> + ); + + +/** + * __usePersistTimelineMutationMutation__ + * + * To run a mutation, you first call `usePersistTimelineMutationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `usePersistTimelineMutationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [persistTimelineMutationMutation, { data, loading, error }] = usePersistTimelineMutationMutation({ + * variables: { + * timelineId: // value for 'timelineId' + * version: // value for 'version' + * timeline: // value for 'timeline' + * }, + * }); + */ +export function usePersistTimelineMutationMutation(baseOptions?: ApolloReactHooks.MutationHookOptions) { + return ApolloReactHooks.useMutation(PersistTimelineMutationDocument, baseOptions); + } +export type PersistTimelineMutationMutationHookResult = ReturnType; +export type PersistTimelineMutationMutationResult = ApolloReactCommon.MutationResult; +export type PersistTimelineMutationMutationOptions = ApolloReactCommon.BaseMutationOptions; +export const PersistTimelinePinnedEventMutationDocument = gql` + mutation PersistTimelinePinnedEventMutation($pinnedEventId: ID, $eventId: ID!, $timelineId: ID) { + persistPinnedEventOnTimeline(pinnedEventId: $pinnedEventId, eventId: $eventId, timelineId: $timelineId) { + pinnedEventId + eventId + timelineId + timelineVersion + created + createdBy + updated + updatedBy + version + } +} + `; +export type PersistTimelinePinnedEventMutationMutationFn = ApolloReactCommon.MutationFunction; +export type PersistTimelinePinnedEventMutationComponentProps = Omit, 'mutation'>; + + export const PersistTimelinePinnedEventMutationComponent = (props: PersistTimelinePinnedEventMutationComponentProps) => ( + mutation={PersistTimelinePinnedEventMutationDocument} {...props} /> + ); + + +/** + * __usePersistTimelinePinnedEventMutationMutation__ + * + * To run a mutation, you first call `usePersistTimelinePinnedEventMutationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `usePersistTimelinePinnedEventMutationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [persistTimelinePinnedEventMutationMutation, { data, loading, error }] = usePersistTimelinePinnedEventMutationMutation({ + * variables: { + * pinnedEventId: // value for 'pinnedEventId' + * eventId: // value for 'eventId' + * timelineId: // value for 'timelineId' + * }, + * }); + */ +export function usePersistTimelinePinnedEventMutationMutation(baseOptions?: ApolloReactHooks.MutationHookOptions) { + return ApolloReactHooks.useMutation(PersistTimelinePinnedEventMutationDocument, baseOptions); + } +export type PersistTimelinePinnedEventMutationMutationHookResult = ReturnType; +export type PersistTimelinePinnedEventMutationMutationResult = ApolloReactCommon.MutationResult; +export type PersistTimelinePinnedEventMutationMutationOptions = ApolloReactCommon.BaseMutationOptions; +export const GetTlsQueryDocument = gql` + query GetTlsQuery($sourceId: ID!, $filterQuery: String, $flowTarget: FlowTargetSourceDest!, $ip: String!, $pagination: PaginationInputPaginated!, $sort: TlsSortField!, $timerange: TimerangeInput!, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + Tls(filterQuery: $filterQuery, flowTarget: $flowTarget, ip: $ip, pagination: $pagination, sort: $sort, timerange: $timerange, defaultIndex: $defaultIndex) { + totalCount + edges { + node { + _id + alternativeNames + commonNames + ja3 + issuerNames + notAfter + } + cursor { + value + } + } + pageInfo { + activePage + fakeTotalCount + showMorePagesIndicator + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetTlsQueryComponentProps = Omit, 'query'> & ({ variables: GetTlsQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetTlsQueryComponent = (props: GetTlsQueryComponentProps) => ( + query={GetTlsQueryDocument} {...props} /> + ); + + +/** + * __useGetTlsQueryQuery__ + * + * To run a query within a React component, call `useGetTlsQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetTlsQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetTlsQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * filterQuery: // value for 'filterQuery' + * flowTarget: // value for 'flowTarget' + * ip: // value for 'ip' + * pagination: // value for 'pagination' + * sort: // value for 'sort' + * timerange: // value for 'timerange' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetTlsQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetTlsQueryDocument, baseOptions); + } +export function useGetTlsQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetTlsQueryDocument, baseOptions); + } +export type GetTlsQueryQueryHookResult = ReturnType; +export type GetTlsQueryLazyQueryHookResult = ReturnType; +export type GetTlsQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetUncommonProcessesQueryDocument = gql` + query GetUncommonProcessesQuery($sourceId: ID!, $timerange: TimerangeInput!, $pagination: PaginationInputPaginated!, $filterQuery: String, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + UncommonProcesses(timerange: $timerange, pagination: $pagination, filterQuery: $filterQuery, defaultIndex: $defaultIndex) { + totalCount + edges { + node { + _id + instances + process { + args + name + } + user { + id + name + } + hosts { + name + } + } + cursor { + value + } + } + pageInfo { + activePage + fakeTotalCount + showMorePagesIndicator + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetUncommonProcessesQueryComponentProps = Omit, 'query'> & ({ variables: GetUncommonProcessesQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetUncommonProcessesQueryComponent = (props: GetUncommonProcessesQueryComponentProps) => ( + query={GetUncommonProcessesQueryDocument} {...props} /> + ); + + +/** + * __useGetUncommonProcessesQueryQuery__ + * + * To run a query within a React component, call `useGetUncommonProcessesQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetUncommonProcessesQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetUncommonProcessesQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * timerange: // value for 'timerange' + * pagination: // value for 'pagination' + * filterQuery: // value for 'filterQuery' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetUncommonProcessesQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetUncommonProcessesQueryDocument, baseOptions); + } +export function useGetUncommonProcessesQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetUncommonProcessesQueryDocument, baseOptions); + } +export type GetUncommonProcessesQueryQueryHookResult = ReturnType; +export type GetUncommonProcessesQueryLazyQueryHookResult = ReturnType; +export type GetUncommonProcessesQueryQueryResult = ApolloReactCommon.QueryResult; +export const GetUsersQueryDocument = gql` + query GetUsersQuery($sourceId: ID!, $filterQuery: String, $flowTarget: FlowTarget!, $ip: String!, $pagination: PaginationInputPaginated!, $sort: UsersSortField!, $timerange: TimerangeInput!, $defaultIndex: [String!]!, $inspect: Boolean!) { + source(id: $sourceId) { + id + Users(filterQuery: $filterQuery, flowTarget: $flowTarget, ip: $ip, pagination: $pagination, sort: $sort, timerange: $timerange, defaultIndex: $defaultIndex) { + totalCount + edges { + node { + user { + name + id + groupId + groupName + count + } + } + cursor { + value + } + } + pageInfo { + activePage + fakeTotalCount + showMorePagesIndicator + } + inspect @include(if: $inspect) { + dsl + response + } + } + } +} + `; +export type GetUsersQueryComponentProps = Omit, 'query'> & ({ variables: GetUsersQueryQueryVariables; skip?: boolean; } | { skip: boolean; }); + + export const GetUsersQueryComponent = (props: GetUsersQueryComponentProps) => ( + query={GetUsersQueryDocument} {...props} /> + ); + + +/** + * __useGetUsersQueryQuery__ + * + * To run a query within a React component, call `useGetUsersQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useGetUsersQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetUsersQueryQuery({ + * variables: { + * sourceId: // value for 'sourceId' + * filterQuery: // value for 'filterQuery' + * flowTarget: // value for 'flowTarget' + * ip: // value for 'ip' + * pagination: // value for 'pagination' + * sort: // value for 'sort' + * timerange: // value for 'timerange' + * defaultIndex: // value for 'defaultIndex' + * inspect: // value for 'inspect' + * }, + * }); + */ +export function useGetUsersQueryQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(GetUsersQueryDocument, baseOptions); + } +export function useGetUsersQueryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(GetUsersQueryDocument, baseOptions); + } +export type GetUsersQueryQueryHookResult = ReturnType; +export type GetUsersQueryLazyQueryHookResult = ReturnType; +export type GetUsersQueryQueryResult = ApolloReactCommon.QueryResult; +export namespace GetAuthenticationsQuery { + export type Variables = GetAuthenticationsQueryQueryVariables; + export type Query = GetAuthenticationsQueryQuery; + export type Source = GetAuthenticationsQueryQuery['source']; + export type Authentications = GetAuthenticationsQueryQuery['source']['Authentications']; + export type Edges = (NonNullable); + export type Node = (NonNullable)['node']; + export type User = (NonNullable)['node']['user']; + export type LastSuccess = (NonNullable<(NonNullable)['node']['lastSuccess']>); + export type _Source = (NonNullable<(NonNullable<(NonNullable)['node']['lastSuccess']>)['source']>); + export type Host = (NonNullable<(NonNullable<(NonNullable)['node']['lastSuccess']>)['host']>); + export type LastFailure = (NonNullable<(NonNullable)['node']['lastFailure']>); + export type __Source = (NonNullable<(NonNullable<(NonNullable)['node']['lastFailure']>)['source']>); + export type _Host = (NonNullable<(NonNullable<(NonNullable)['node']['lastFailure']>)['host']>); + export type Cursor = (NonNullable)['cursor']; + export type PageInfo = GetAuthenticationsQueryQuery['source']['Authentications']['pageInfo']; + export type Inspect = (NonNullable); + export const Document = GetAuthenticationsQueryDocument; + export const Component = GetAuthenticationsQueryComponent; + export const use = useGetAuthenticationsQueryQuery; +} + +export namespace GetLastEventTimeQuery { + export type Variables = GetLastEventTimeQueryQueryVariables; + export type Query = GetLastEventTimeQueryQuery; + export type Source = GetLastEventTimeQueryQuery['source']; + export type LastEventTime = GetLastEventTimeQueryQuery['source']['LastEventTime']; + export const Document = GetLastEventTimeQueryDocument; + export const Component = GetLastEventTimeQueryComponent; + export const use = useGetLastEventTimeQueryQuery; +} + +export namespace GetHostFirstLastSeenQuery { + export type Variables = GetHostFirstLastSeenQueryQueryVariables; + export type Query = GetHostFirstLastSeenQueryQuery; + export type Source = GetHostFirstLastSeenQueryQuery['source']; + export type HostFirstLastSeen = GetHostFirstLastSeenQueryQuery['source']['HostFirstLastSeen']; + export const Document = GetHostFirstLastSeenQueryDocument; + export const Component = GetHostFirstLastSeenQueryComponent; + export const use = useGetHostFirstLastSeenQueryQuery; +} + +export namespace GetHostsTableQuery { + export type Variables = GetHostsTableQueryQueryVariables; + export type Query = GetHostsTableQueryQuery; + export type Source = GetHostsTableQueryQuery['source']; + export type Hosts = GetHostsTableQueryQuery['source']['Hosts']; + export type Edges = (NonNullable); + export type Node = (NonNullable)['node']; + export type Host = (NonNullable<(NonNullable)['node']['host']>); + export type Os = (NonNullable<(NonNullable<(NonNullable)['node']['host']>)['os']>); + export type Cursor = (NonNullable)['cursor']; + export type PageInfo = GetHostsTableQueryQuery['source']['Hosts']['pageInfo']; + export type Inspect = (NonNullable); + export const Document = GetHostsTableQueryDocument; + export const Component = GetHostsTableQueryComponent; + export const use = useGetHostsTableQueryQuery; +} + +export namespace GetHostOverviewQuery { + export type Variables = GetHostOverviewQueryQueryVariables; + export type Query = GetHostOverviewQueryQuery; + export type Source = GetHostOverviewQueryQuery['source']; + export type HostOverview = GetHostOverviewQueryQuery['source']['HostOverview']; + export type Host = (NonNullable); + export type Os = (NonNullable<(NonNullable)['os']>); + export type Cloud = (NonNullable); + export type Instance = (NonNullable<(NonNullable)['instance']>); + export type Machine = (NonNullable<(NonNullable)['machine']>); + export type Inspect = (NonNullable); + export const Document = GetHostOverviewQueryDocument; + export const Component = GetHostOverviewQueryComponent; + export const use = useGetHostOverviewQueryQuery; +} + +export namespace GetIpOverviewQuery { + export type Variables = GetIpOverviewQueryQueryVariables; + export type Query = GetIpOverviewQueryQuery; + export type Source = GetIpOverviewQueryQuery['source']; + export type IpOverview = (NonNullable); + export type _Source = (NonNullable<(NonNullable)['source']>); + export type AutonomousSystem = (NonNullable<(NonNullable)['source']>)['autonomousSystem']; + export type Organization = (NonNullable<(NonNullable<(NonNullable)['source']>)['autonomousSystem']['organization']>); + export type Geo = (NonNullable<(NonNullable)['source']>)['geo']; + export type Location = (NonNullable<(NonNullable<(NonNullable)['source']>)['geo']['location']>); + export type Destination = (NonNullable<(NonNullable)['destination']>); + export type _AutonomousSystem = (NonNullable<(NonNullable)['destination']>)['autonomousSystem']; + export type _Organization = (NonNullable<(NonNullable<(NonNullable)['destination']>)['autonomousSystem']['organization']>); + export type _Geo = (NonNullable<(NonNullable)['destination']>)['geo']; + export type _Location = (NonNullable<(NonNullable<(NonNullable)['destination']>)['geo']['location']>); + export type Host = (NonNullable)['host']; + export type Os = (NonNullable<(NonNullable)['host']['os']>); + export type Inspect = (NonNullable<(NonNullable)['inspect']>); + export const Document = GetIpOverviewQueryDocument; + export const Component = GetIpOverviewQueryComponent; + export const use = useGetIpOverviewQueryQuery; +} + +export namespace KpiHostDetailsChartFields { + export type Fragment = KpiHostDetailsChartFieldsFragment; +} + +export namespace GetKpiHostDetailsQuery { + export type Variables = GetKpiHostDetailsQueryQueryVariables; + export type Query = GetKpiHostDetailsQueryQuery; + export type Source = GetKpiHostDetailsQueryQuery['source']; + export type KpiHostDetails = GetKpiHostDetailsQueryQuery['source']['KpiHostDetails']; + export type AuthSuccessHistogram = KpiHostDetailsChartFieldsFragment; + export type AuthFailureHistogram = KpiHostDetailsChartFieldsFragment; + export type UniqueSourceIpsHistogram = KpiHostDetailsChartFieldsFragment; + export type UniqueDestinationIpsHistogram = KpiHostDetailsChartFieldsFragment; + export type Inspect = (NonNullable); + export const Document = GetKpiHostDetailsQueryDocument; + export const Component = GetKpiHostDetailsQueryComponent; + export const use = useGetKpiHostDetailsQueryQuery; +} + +export namespace KpiHostChartFields { + export type Fragment = KpiHostChartFieldsFragment; +} + +export namespace GetKpiHostsQuery { + export type Variables = GetKpiHostsQueryQueryVariables; + export type Query = GetKpiHostsQueryQuery; + export type Source = GetKpiHostsQueryQuery['source']; + export type KpiHosts = GetKpiHostsQueryQuery['source']['KpiHosts']; + export type HostsHistogram = KpiHostChartFieldsFragment; + export type AuthSuccessHistogram = KpiHostChartFieldsFragment; + export type AuthFailureHistogram = KpiHostChartFieldsFragment; + export type UniqueSourceIpsHistogram = KpiHostChartFieldsFragment; + export type UniqueDestinationIpsHistogram = KpiHostChartFieldsFragment; + export type Inspect = (NonNullable); + export const Document = GetKpiHostsQueryDocument; + export const Component = GetKpiHostsQueryComponent; + export const use = useGetKpiHostsQueryQuery; +} + +export namespace KpiNetworkChartFields { + export type Fragment = KpiNetworkChartFieldsFragment; +} + +export namespace GetKpiNetworkQuery { + export type Variables = GetKpiNetworkQueryQueryVariables; + export type Query = GetKpiNetworkQueryQuery; + export type Source = GetKpiNetworkQueryQuery['source']; + export type KpiNetwork = (NonNullable); + export type UniqueSourcePrivateIpsHistogram = KpiNetworkChartFieldsFragment; + export type UniqueDestinationPrivateIpsHistogram = KpiNetworkChartFieldsFragment; + export type Inspect = (NonNullable<(NonNullable)['inspect']>); + export const Document = GetKpiNetworkQueryDocument; + export const Component = GetKpiNetworkQueryComponent; + export const use = useGetKpiNetworkQueryQuery; +} + +export namespace GetMatrixHistogramQuery { + export type Variables = GetMatrixHistogramQueryQueryVariables; + export type Query = GetMatrixHistogramQueryQuery; + export type Source = GetMatrixHistogramQueryQuery['source']; + export type MatrixHistogram = GetMatrixHistogramQueryQuery['source']['MatrixHistogram']; + export type MatrixHistogramData = (NonNullable); + export type Inspect = (NonNullable); + export const Document = GetMatrixHistogramQueryDocument; + export const Component = GetMatrixHistogramQueryComponent; + export const use = useGetMatrixHistogramQueryQuery; +} + +export namespace GetNetworkDnsQuery { + export type Variables = GetNetworkDnsQueryQueryVariables; + export type Query = GetNetworkDnsQueryQuery; + export type Source = GetNetworkDnsQueryQuery['source']; + export type NetworkDns = GetNetworkDnsQueryQuery['source']['NetworkDns']; + export type Edges = (NonNullable); + export type Node = (NonNullable)['node']; + export type Cursor = (NonNullable)['cursor']; + export type PageInfo = GetNetworkDnsQueryQuery['source']['NetworkDns']['pageInfo']; + export type Inspect = (NonNullable); + export const Document = GetNetworkDnsQueryDocument; + export const Component = GetNetworkDnsQueryComponent; + export const use = useGetNetworkDnsQueryQuery; +} + +export namespace GetNetworkHttpQuery { + export type Variables = GetNetworkHttpQueryQueryVariables; + export type Query = GetNetworkHttpQueryQuery; + export type Source = GetNetworkHttpQueryQuery['source']; + export type NetworkHttp = GetNetworkHttpQueryQuery['source']['NetworkHttp']; + export type Edges = (NonNullable); + export type Node = (NonNullable)['node']; + export type Cursor = (NonNullable)['cursor']; + export type PageInfo = GetNetworkHttpQueryQuery['source']['NetworkHttp']['pageInfo']; + export type Inspect = (NonNullable); + export const Document = GetNetworkHttpQueryDocument; + export const Component = GetNetworkHttpQueryComponent; + export const use = useGetNetworkHttpQueryQuery; +} + +export namespace GetNetworkTopCountriesQuery { + export type Variables = GetNetworkTopCountriesQueryQueryVariables; + export type Query = GetNetworkTopCountriesQueryQuery; + export type Source = GetNetworkTopCountriesQueryQuery['source']; + export type NetworkTopCountries = GetNetworkTopCountriesQueryQuery['source']['NetworkTopCountries']; + export type Edges = (NonNullable); + export type Node = (NonNullable)['node']; + export type _Source = (NonNullable<(NonNullable)['node']['source']>); + export type Destination = (NonNullable<(NonNullable)['node']['destination']>); + export type Network = (NonNullable<(NonNullable)['node']['network']>); + export type Cursor = (NonNullable)['cursor']; + export type PageInfo = GetNetworkTopCountriesQueryQuery['source']['NetworkTopCountries']['pageInfo']; + export type Inspect = (NonNullable); + export const Document = GetNetworkTopCountriesQueryDocument; + export const Component = GetNetworkTopCountriesQueryComponent; + export const use = useGetNetworkTopCountriesQueryQuery; +} + +export namespace GetNetworkTopNFlowQuery { + export type Variables = GetNetworkTopNFlowQueryQueryVariables; + export type Query = GetNetworkTopNFlowQueryQuery; + export type Source = GetNetworkTopNFlowQueryQuery['source']; + export type NetworkTopNFlow = GetNetworkTopNFlowQueryQuery['source']['NetworkTopNFlow']; + export type Edges = (NonNullable); + export type Node = (NonNullable)['node']; + export type _Source = (NonNullable<(NonNullable)['node']['source']>); + export type AutonomousSystem = (NonNullable<(NonNullable<(NonNullable)['node']['source']>)['autonomous_system']>); + export type Location = (NonNullable<(NonNullable<(NonNullable)['node']['source']>)['location']>); + export type Geo = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['source']>)['location']>)['geo']>); + export type Destination = (NonNullable<(NonNullable)['node']['destination']>); + export type _AutonomousSystem = (NonNullable<(NonNullable<(NonNullable)['node']['destination']>)['autonomous_system']>); + export type _Location = (NonNullable<(NonNullable<(NonNullable)['node']['destination']>)['location']>); + export type _Geo = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['destination']>)['location']>)['geo']>); + export type Network = (NonNullable<(NonNullable)['node']['network']>); + export type Cursor = (NonNullable)['cursor']; + export type PageInfo = GetNetworkTopNFlowQueryQuery['source']['NetworkTopNFlow']['pageInfo']; + export type Inspect = (NonNullable); + export const Document = GetNetworkTopNFlowQueryDocument; + export const Component = GetNetworkTopNFlowQueryComponent; + export const use = useGetNetworkTopNFlowQueryQuery; +} + +export namespace GetOverviewHostQuery { + export type Variables = GetOverviewHostQueryQueryVariables; + export type Query = GetOverviewHostQueryQuery; + export type Source = GetOverviewHostQueryQuery['source']; + export type OverviewHost = (NonNullable); + export type Inspect = (NonNullable<(NonNullable)['inspect']>); + export const Document = GetOverviewHostQueryDocument; + export const Component = GetOverviewHostQueryComponent; + export const use = useGetOverviewHostQueryQuery; +} + +export namespace GetOverviewNetworkQuery { + export type Variables = GetOverviewNetworkQueryQueryVariables; + export type Query = GetOverviewNetworkQueryQuery; + export type Source = GetOverviewNetworkQueryQuery['source']; + export type OverviewNetwork = (NonNullable); + export type Inspect = (NonNullable<(NonNullable)['inspect']>); + export const Document = GetOverviewNetworkQueryDocument; + export const Component = GetOverviewNetworkQueryComponent; + export const use = useGetOverviewNetworkQueryQuery; +} + +export namespace SourceQuery { + export type Variables = SourceQueryQueryVariables; + export type Query = SourceQueryQuery; + export type Source = SourceQueryQuery['source']; + export type Status = SourceQueryQuery['source']['status']; + export type IndexFields = (NonNullable); + export const Document = SourceQueryDocument; + export const Component = SourceQueryComponent; + export const use = useSourceQueryQuery; +} + +export namespace GetAllTimeline { + export type Variables = GetAllTimelineQueryVariables; + export type Query = GetAllTimelineQuery; + export type GetAllTimeline = GetAllTimelineQuery['getAllTimeline']; + export type Timeline = (NonNullable); + export type Favorite = (NonNullable<(NonNullable<(NonNullable)['favorite']>)[0]>); + export type EventIdToNoteIds = (NonNullable<(NonNullable<(NonNullable)['eventIdToNoteIds']>)[0]>); + export type Notes = (NonNullable<(NonNullable<(NonNullable)['notes']>)[0]>); + export const Document = GetAllTimelineDocument; + export const Component = GetAllTimelineComponent; + export const use = useGetAllTimelineQuery; +} + +export namespace DeleteTimelineMutation { + export type Variables = DeleteTimelineMutationMutationVariables; + export type Mutation = DeleteTimelineMutationMutation; + export const Document = DeleteTimelineMutationDocument; + export const Component = DeleteTimelineMutationComponent; + export const use = useDeleteTimelineMutationMutation; +} + +export namespace GetTimelineDetailsQuery { + export type Variables = GetTimelineDetailsQueryQueryVariables; + export type Query = GetTimelineDetailsQueryQuery; + export type Source = GetTimelineDetailsQueryQuery['source']; + export type TimelineDetails = GetTimelineDetailsQueryQuery['source']['TimelineDetails']; + export type Data = (NonNullable<(NonNullable)[0]>); + export const Document = GetTimelineDetailsQueryDocument; + export const Component = GetTimelineDetailsQueryComponent; + export const use = useGetTimelineDetailsQueryQuery; +} + +export namespace PersistTimelineFavoriteMutation { + export type Variables = PersistTimelineFavoriteMutationMutationVariables; + export type Mutation = PersistTimelineFavoriteMutationMutation; + export type PersistFavorite = PersistTimelineFavoriteMutationMutation['persistFavorite']; + export type Favorite = (NonNullable<(NonNullable)[0]>); + export const Document = PersistTimelineFavoriteMutationDocument; + export const Component = PersistTimelineFavoriteMutationComponent; + export const use = usePersistTimelineFavoriteMutationMutation; +} + +export namespace GetTimelineQuery { + export type Variables = GetTimelineQueryQueryVariables; + export type Query = GetTimelineQueryQuery; + export type Source = GetTimelineQueryQuery['source']; + export type Timeline = GetTimelineQueryQuery['source']['Timeline']; + export type Inspect = (NonNullable); + export type PageInfo = GetTimelineQueryQuery['source']['Timeline']['pageInfo']; + export type EndCursor = (NonNullable); + export type Edges = (NonNullable); + export type Node = (NonNullable)['node']; + export type Data = (NonNullable<(NonNullable)['node']['data'][0]>); + export type Ecs = (NonNullable)['node']['ecs']; + export type System = (NonNullable<(NonNullable)['node']['ecs']['system']>); + export type Auth = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['system']>)['auth']>); + export type Ssh = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['ecs']['system']>)['auth']>)['ssh']>); + export type Audit = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['system']>)['audit']>); + export type Package = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['ecs']['system']>)['audit']>)['package']>); + export type Event = (NonNullable<(NonNullable)['node']['ecs']['event']>); + export type Auditd = (NonNullable<(NonNullable)['node']['ecs']['auditd']>); + export type _Data = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['auditd']>)['data']>); + export type Summary = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['auditd']>)['summary']>); + export type Actor = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['ecs']['auditd']>)['summary']>)['actor']>); + export type Object = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['ecs']['auditd']>)['summary']>)['object']>); + export type File = (NonNullable<(NonNullable)['node']['ecs']['file']>); + export type Host = (NonNullable<(NonNullable)['node']['ecs']['host']>); + export type Rule = (NonNullable<(NonNullable)['node']['ecs']['rule']>); + export type _Source = (NonNullable<(NonNullable)['node']['ecs']['source']>); + export type Geo = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['source']>)['geo']>); + export type Destination = (NonNullable<(NonNullable)['node']['ecs']['destination']>); + export type _Geo = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['destination']>)['geo']>); + export type Dns = (NonNullable<(NonNullable)['node']['ecs']['dns']>); + export type Question = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['dns']>)['question']>); + export type Endgame = (NonNullable<(NonNullable)['node']['ecs']['endgame']>); + export type __Geo = (NonNullable<(NonNullable)['node']['ecs']['geo']>); + export type Signal = (NonNullable<(NonNullable)['node']['ecs']['signal']>); + export type _Rule = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['signal']>)['rule']>); + export type Suricata = (NonNullable<(NonNullable)['node']['ecs']['suricata']>); + export type Eve = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['suricata']>)['eve']>); + export type Alert = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['ecs']['suricata']>)['eve']>)['alert']>); + export type Network = (NonNullable<(NonNullable)['node']['ecs']['network']>); + export type Http = (NonNullable<(NonNullable)['node']['ecs']['http']>); + export type Request = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['http']>)['request']>); + export type Body = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['ecs']['http']>)['request']>)['body']>); + export type Response = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['http']>)['response']>); + export type _Body = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['ecs']['http']>)['response']>)['body']>); + export type Tls = (NonNullable<(NonNullable)['node']['ecs']['tls']>); + export type ClientCertificate = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['tls']>)['client_certificate']>); + export type Fingerprint = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['ecs']['tls']>)['client_certificate']>)['fingerprint']>); + export type Fingerprints = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['tls']>)['fingerprints']>); + export type Ja3 = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['ecs']['tls']>)['fingerprints']>)['ja3']>); + export type ServerCertificate = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['tls']>)['server_certificate']>); + export type _Fingerprint = (NonNullable<(NonNullable<(NonNullable<(NonNullable)['node']['ecs']['tls']>)['server_certificate']>)['fingerprint']>); + export type Url = (NonNullable<(NonNullable)['node']['ecs']['url']>); + export type User = (NonNullable<(NonNullable)['node']['ecs']['user']>); + export type Winlog = (NonNullable<(NonNullable)['node']['ecs']['winlog']>); + export type Process = (NonNullable<(NonNullable)['node']['ecs']['process']>); + export type Hash = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['process']>)['hash']>); + export type Zeek = (NonNullable<(NonNullable)['node']['ecs']['zeek']>); + export type Connection = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['zeek']>)['connection']>); + export type Notice = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['zeek']>)['notice']>); + export type _Dns = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['zeek']>)['dns']>); + export type _Http = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['zeek']>)['http']>); + export type Files = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['zeek']>)['files']>); + export type Ssl = (NonNullable<(NonNullable<(NonNullable)['node']['ecs']['zeek']>)['ssl']>); + export const Document = GetTimelineQueryDocument; + export const Component = GetTimelineQueryComponent; + export const use = useGetTimelineQueryQuery; +} + +export namespace PersistTimelineNoteMutation { + export type Variables = PersistTimelineNoteMutationMutationVariables; + export type Mutation = PersistTimelineNoteMutationMutation; + export type PersistNote = PersistTimelineNoteMutationMutation['persistNote']; + export type Note = PersistTimelineNoteMutationMutation['persistNote']['note']; + export const Document = PersistTimelineNoteMutationDocument; + export const Component = PersistTimelineNoteMutationComponent; + export const use = usePersistTimelineNoteMutationMutation; +} + +export namespace GetOneTimeline { + export type Variables = GetOneTimelineQueryVariables; + export type Query = GetOneTimelineQuery; + export type GetOneTimeline = GetOneTimelineQuery['getOneTimeline']; + export type Columns = (NonNullable<(NonNullable)[0]>); + export type DataProviders = (NonNullable<(NonNullable)[0]>); + export type QueryMatch = (NonNullable<(NonNullable<(NonNullable)[0]>)['queryMatch']>); + export type And = (NonNullable<(NonNullable<(NonNullable<(NonNullable)[0]>)['and']>)[0]>); + export type _QueryMatch = (NonNullable<(NonNullable<(NonNullable<(NonNullable<(NonNullable)[0]>)['and']>)[0]>)['queryMatch']>); + export type DateRange = (NonNullable); + export type EventIdToNoteIds = (NonNullable<(NonNullable)[0]>); + export type Favorite = (NonNullable<(NonNullable)[0]>); + export type Filters = (NonNullable<(NonNullable)[0]>); + export type Meta = (NonNullable<(NonNullable<(NonNullable)[0]>)['meta']>); + export type KqlQuery = (NonNullable); + export type FilterQuery = (NonNullable<(NonNullable)['filterQuery']>); + export type Kuery = (NonNullable<(NonNullable<(NonNullable)['filterQuery']>)['kuery']>); + export type Notes = (NonNullable<(NonNullable)[0]>); + export type PinnedEventsSaveObject = (NonNullable<(NonNullable)[0]>); + export type Sort = (NonNullable); + export const Document = GetOneTimelineDocument; + export const Component = GetOneTimelineComponent; + export const use = useGetOneTimelineQuery; +} + +export namespace PersistTimelineMutation { + export type Variables = PersistTimelineMutationMutationVariables; + export type Mutation = PersistTimelineMutationMutation; + export type PersistTimeline = PersistTimelineMutationMutation['persistTimeline']; + export type Timeline = PersistTimelineMutationMutation['persistTimeline']['timeline']; + export type Columns = (NonNullable<(NonNullable)[0]>); + export type DataProviders = (NonNullable<(NonNullable)[0]>); + export type QueryMatch = (NonNullable<(NonNullable<(NonNullable)[0]>)['queryMatch']>); + export type And = (NonNullable<(NonNullable<(NonNullable<(NonNullable)[0]>)['and']>)[0]>); + export type _QueryMatch = (NonNullable<(NonNullable<(NonNullable<(NonNullable<(NonNullable)[0]>)['and']>)[0]>)['queryMatch']>); + export type Favorite = (NonNullable<(NonNullable)[0]>); + export type Filters = (NonNullable<(NonNullable)[0]>); + export type Meta = (NonNullable<(NonNullable<(NonNullable)[0]>)['meta']>); + export type KqlQuery = (NonNullable); + export type FilterQuery = (NonNullable<(NonNullable)['filterQuery']>); + export type Kuery = (NonNullable<(NonNullable<(NonNullable)['filterQuery']>)['kuery']>); + export type DateRange = (NonNullable); + export type Sort = (NonNullable); + export const Document = PersistTimelineMutationDocument; + export const Component = PersistTimelineMutationComponent; + export const use = usePersistTimelineMutationMutation; +} + +export namespace PersistTimelinePinnedEventMutation { + export type Variables = PersistTimelinePinnedEventMutationMutationVariables; + export type Mutation = PersistTimelinePinnedEventMutationMutation; + export type PersistPinnedEventOnTimeline = (NonNullable); + export const Document = PersistTimelinePinnedEventMutationDocument; + export const Component = PersistTimelinePinnedEventMutationComponent; + export const use = usePersistTimelinePinnedEventMutationMutation; +} + +export namespace GetTlsQuery { + export type Variables = GetTlsQueryQueryVariables; + export type Query = GetTlsQueryQuery; + export type Source = GetTlsQueryQuery['source']; + export type Tls = GetTlsQueryQuery['source']['Tls']; + export type Edges = (NonNullable); + export type Node = (NonNullable)['node']; + export type Cursor = (NonNullable)['cursor']; + export type PageInfo = GetTlsQueryQuery['source']['Tls']['pageInfo']; + export type Inspect = (NonNullable); + export const Document = GetTlsQueryDocument; + export const Component = GetTlsQueryComponent; + export const use = useGetTlsQueryQuery; +} + +export namespace GetUncommonProcessesQuery { + export type Variables = GetUncommonProcessesQueryQueryVariables; + export type Query = GetUncommonProcessesQueryQuery; + export type Source = GetUncommonProcessesQueryQuery['source']; + export type UncommonProcesses = GetUncommonProcessesQueryQuery['source']['UncommonProcesses']; + export type Edges = (NonNullable); + export type Node = (NonNullable)['node']; + export type Process = (NonNullable)['node']['process']; + export type User = (NonNullable<(NonNullable)['node']['user']>); + export type Hosts = (NonNullable<(NonNullable)['node']['hosts'][0]>); + export type Cursor = (NonNullable)['cursor']; + export type PageInfo = GetUncommonProcessesQueryQuery['source']['UncommonProcesses']['pageInfo']; + export type Inspect = (NonNullable); + export const Document = GetUncommonProcessesQueryDocument; + export const Component = GetUncommonProcessesQueryComponent; + export const use = useGetUncommonProcessesQueryQuery; +} + +export namespace GetUsersQuery { + export type Variables = GetUsersQueryQueryVariables; + export type Query = GetUsersQueryQuery; + export type Source = GetUsersQueryQuery['source']; + export type Users = GetUsersQueryQuery['source']['Users']; + export type Edges = (NonNullable); + export type Node = (NonNullable)['node']; + export type User = (NonNullable<(NonNullable)['node']['user']>); + export type Cursor = (NonNullable)['cursor']; + export type PageInfo = GetUsersQueryQuery['source']['Users']['pageInfo']; + export type Inspect = (NonNullable); + export const Document = GetUsersQueryDocument; + export const Component = GetUsersQueryComponent; + export const use = useGetUsersQueryQuery; +} diff --git a/x-pack/legacy/plugins/siem/public/lib/compose/helpers.test.ts b/x-pack/legacy/plugins/siem/public/lib/compose/helpers.test.ts index af4521b4f6e2c..ae7d09d35bc3c 100644 --- a/x-pack/legacy/plugins/siem/public/lib/compose/helpers.test.ts +++ b/x-pack/legacy/plugins/siem/public/lib/compose/helpers.test.ts @@ -4,37 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ -import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; import { errorLink, reTryOneTimeOnErrorLink } from '../../containers/errors'; import { getLinks } from './helpers'; -import { withClientState } from 'apollo-link-state'; -import * as apolloLinkHttp from 'apollo-link-http'; -import introspectionQueryResultData from '../../graphql/introspection.json'; +import { HttpLink } from '@apollo/client'; -jest.mock('apollo-cache-inmemory'); -jest.mock('apollo-link-http'); -jest.mock('apollo-link-state'); +jest.mock('@apollo/client'); jest.mock('../../containers/errors'); -const mockWithClientState = 'mockWithClientState'; const mockHttpLink = { mockHttpLink: 'mockHttpLink' }; // @ts-ignore -withClientState.mockReturnValue(mockWithClientState); -// @ts-ignore -apolloLinkHttp.createHttpLink.mockImplementation(() => mockHttpLink); +HttpLink.mockImplementation(() => mockHttpLink); describe('getLinks helper', () => { test('It should return links in correct order', () => { - const mockCache = new InMemoryCache({ - dataIdFromObject: () => null, - fragmentMatcher: new IntrospectionFragmentMatcher({ - introspectionQueryResultData, - }), - }); - const links = getLinks(mockCache, 'basePath'); + const links = getLinks(''); expect(links[0]).toEqual(errorLink); expect(links[1]).toEqual(reTryOneTimeOnErrorLink); - expect(links[2]).toEqual(mockWithClientState); - expect(links[3]).toEqual(mockHttpLink); + expect(links[2]).toEqual(mockHttpLink); }); }); diff --git a/x-pack/legacy/plugins/siem/public/lib/compose/helpers.ts b/x-pack/legacy/plugins/siem/public/lib/compose/helpers.ts index b698fc55cc5e5..42ecdd211b927 100644 --- a/x-pack/legacy/plugins/siem/public/lib/compose/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/lib/compose/helpers.ts @@ -4,20 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createHttpLink } from 'apollo-link-http'; -import { withClientState } from 'apollo-link-state'; -import { InMemoryCache } from 'apollo-cache-inmemory'; +import { HttpLink } from '@apollo/client'; import { errorLink, reTryOneTimeOnErrorLink } from '../../containers/errors'; -export const getLinks = (cache: InMemoryCache, basePath: string) => [ +export const getLinks = (basePath: string) => [ errorLink, reTryOneTimeOnErrorLink, - withClientState({ - cache, - resolvers: {}, - }), - createHttpLink({ + new HttpLink({ credentials: 'same-origin', headers: { 'kbn-xsrf': 'true' }, uri: `${basePath}/api/siem/graphql`, diff --git a/x-pack/legacy/plugins/siem/public/lib/compose/kibana_compose.tsx b/x-pack/legacy/plugins/siem/public/lib/compose/kibana_compose.tsx index c742ced4c504c..3b670fb14e4b8 100644 --- a/x-pack/legacy/plugins/siem/public/lib/compose/kibana_compose.tsx +++ b/x-pack/legacy/plugins/siem/public/lib/compose/kibana_compose.tsx @@ -4,28 +4,25 @@ * you may not use this file except in compliance with the Elastic License. */ -import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; -import ApolloClient from 'apollo-client'; -import { ApolloLink } from 'apollo-link'; +import { ApolloClient, ApolloLink, InMemoryCache } from '@apollo/client'; -import introspectionQueryResultData from '../../graphql/introspection.json'; import { CoreStart } from '../../plugin'; import { AppFrontendLibs } from '../lib'; import { getLinks } from './helpers'; export function compose(core: CoreStart): AppFrontendLibs { - const cache = new InMemoryCache({ - dataIdFromObject: () => null, - fragmentMatcher: new IntrospectionFragmentMatcher({ - introspectionQueryResultData, - }), - }); const basePath = core.http.basePath.get(); const apolloClient = new ApolloClient({ connectToDevTools: process.env.NODE_ENV !== 'production', - cache, - link: ApolloLink.from(getLinks(cache, basePath)), + cache: new InMemoryCache({ + typePolicies: { + TimelineItem: { + keyFields: ['_id', '_index', 'data'], + }, + }, + }), + link: ApolloLink.from(getLinks(basePath)), }); const libs: AppFrontendLibs = { diff --git a/x-pack/legacy/plugins/siem/public/lib/lib.ts b/x-pack/legacy/plugins/siem/public/lib/lib.ts index e7b39d2ea50f9..084c62acef443 100644 --- a/x-pack/legacy/plugins/siem/public/lib/lib.ts +++ b/x-pack/legacy/plugins/siem/public/lib/lib.ts @@ -5,8 +5,7 @@ */ import { IScope } from 'angular'; -import { NormalizedCacheObject } from 'apollo-cache-inmemory'; -import ApolloClient from 'apollo-client'; +import { ApolloClient, NormalizedCacheObject } from '@apollo/client'; export interface AppFrontendLibs { apolloClient: AppApolloClient; diff --git a/x-pack/legacy/plugins/siem/public/mock/test_providers.tsx b/x-pack/legacy/plugins/siem/public/mock/test_providers.tsx index c7692755c1330..28e7b0deafa30 100644 --- a/x-pack/legacy/plugins/siem/public/mock/test_providers.tsx +++ b/x-pack/legacy/plugins/siem/public/mock/test_providers.tsx @@ -6,11 +6,8 @@ import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; import { I18nProvider } from '@kbn/i18n/react'; -import { InMemoryCache as Cache } from 'apollo-cache-inmemory'; -import ApolloClient from 'apollo-client'; -import { ApolloLink } from 'apollo-link'; import React from 'react'; -import { ApolloProvider } from 'react-apollo'; +import { ApolloProvider, ApolloClient, ApolloLink, InMemoryCache } from '@apollo/client'; import { DragDropContext, DropResult, ResponderProvided } from 'react-beautiful-dnd'; import { Provider as ReduxStoreProvider } from 'react-redux'; import { Store } from 'redux'; @@ -32,7 +29,7 @@ interface Props { } export const apolloClient = new ApolloClient({ - cache: new Cache(), + cache: new InMemoryCache(), link: new ApolloLink((o, f) => (f ? f(o) : null)), }); diff --git a/x-pack/legacy/plugins/siem/public/mock/timeline_results.ts b/x-pack/legacy/plugins/siem/public/mock/timeline_results.ts index d6dc0ae131391..26b8eb6bc5f15 100644 --- a/x-pack/legacy/plugins/siem/public/mock/timeline_results.ts +++ b/x-pack/legacy/plugins/siem/public/mock/timeline_results.ts @@ -4,15 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ +import { MockedResponse } from '@apollo/client/testing'; import { OpenTimelineResult } from '../components/open_timeline/types'; -import { GetAllTimeline, SortFieldTimeline, TimelineResult, Direction } from '../graphql/types'; +import { SortFieldTimeline, TimelineResult, Direction } from '../graphql/types'; import { allTimelinesQuery } from '../containers/timeline/all/index.gql_query'; -export interface MockedProvidedQuery { - request: { - query: GetAllTimeline.Query; - variables: GetAllTimeline.Variables; - }; +export interface MockedProvidedQuery extends MockedResponse { result: { data: { getAllTimeline: { @@ -22,6 +19,7 @@ export interface MockedProvidedQuery { }; }; } + /** Mocks results of a query run by the `OpenTimeline` component */ export const mockOpenTimelineQueryResults: MockedProvidedQuery[] = [ { diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx index 44c48b1879e89..94015d6090468 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx @@ -7,7 +7,7 @@ /* eslint-disable react/display-name */ import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; -import ApolloClient from 'apollo-client'; +import { ApolloClient } from '@apollo/client'; import React from 'react'; import { Filter } from '../../../../../../../../../src/plugins/data/common/es_query'; @@ -191,7 +191,7 @@ export const getSignalsActions = ({ status, updateTimelineIsLoading, }: { - apolloClient?: ApolloClient<{}>; + apolloClient?: ApolloClient; canUserCRUD: boolean; hasIndexWrite: boolean; setEventsLoading: ({ eventIds, isLoading }: SetEventsLoadingProps) => void; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx index 75f19218d9b38..1e1ed8766de25 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx @@ -9,6 +9,7 @@ import { isEmpty } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; +import { useApolloClient } from '@apollo/client'; import { Filter, esQuery } from '../../../../../../../../../src/plugins/data/public'; import { useFetchIndexPatterns } from '../../../../containers/detection_engine/rules/fetch_index_patterns'; @@ -20,7 +21,6 @@ import { inputsSelectors, State, inputsModel } from '../../../../store'; import { timelineActions, timelineSelectors } from '../../../../store/timeline'; import { TimelineModel } from '../../../../store/timeline/model'; import { timelineDefaults } from '../../../../store/timeline/defaults'; -import { useApolloClient } from '../../../../utils/apollo_context'; import { updateSignalStatusAction } from './actions'; import { diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts index b3e7ed75cfb99..cfcd1fe2d23fe 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import ApolloClient from 'apollo-client'; +import { ApolloClient } from '@apollo/client'; import { Ecs } from '../../../../graphql/types'; import { TimelineModel } from '../../../../store/timeline/model'; @@ -42,7 +42,7 @@ export interface UpdateSignalStatusActionProps { export type SendSignalsToTimeline = () => void; export interface SendSignalToTimelineActionProps { - apolloClient?: ApolloClient<{}>; + apolloClient?: ApolloClient; createTimeline: CreateTimeline; ecsData: Ecs; updateTimelineIsLoading: ({ id, isLoading }: { id: string; isLoading: boolean }) => void; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx index c3fb907ae83e1..575b85322dcb6 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx @@ -10,8 +10,8 @@ import { useParams } from 'react-router-dom'; import { StickyContainer } from 'react-sticky'; import { connect, ConnectedProps } from 'react-redux'; -import { GlobalTime } from '../../containers/global_time'; -import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; +import { useGlobalTime } from '../../containers/global_time'; +import { useWithSource } from '../../containers/source'; import { AlertsTable } from '../../components/alerts_viewer/alerts_table'; import { FiltersGlobal } from '../../components/filters_global'; import { @@ -88,6 +88,10 @@ const DetectionEnginePageComponent: React.FC = ({ signalIndexName, ]); + const { indexPattern, contentAvailable } = useWithSource(indexToAdd); + + const { to, from, deleteQuery, setQuery } = useGlobalTime(); + if (isUserAuthenticated != null && !isUserAuthenticated && !loading) { return ( @@ -109,89 +113,81 @@ const DetectionEnginePageComponent: React.FC = ({ <> {hasEncryptionKey != null && !hasEncryptionKey && } {hasIndexWrite != null && !hasIndexWrite && } - - {({ indicesExist, indexPattern }) => { - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - - - - {i18n.LAST_SIGNAL} - {': '} - {lastSignals} - - ) - } - title={i18n.PAGE_TITLE} - > - - {i18n.BUTTON_MANAGE_RULES} - - - - - {({ to, from, deleteQuery, setQuery }) => ( - <> - - - {tabName === DetectionEngineTab.signals && ( - <> - - - - - )} - {tabName === DetectionEngineTab.alerts && ( - <> - - - - )} - - )} - - - - ) : ( - - - - - ); - }} - + {contentAvailable ? ( + + + + + + + {i18n.LAST_SIGNAL} + {': '} + {lastSignals} + + ) + } + title={i18n.PAGE_TITLE} + > + + {i18n.BUTTON_MANAGE_RULES} + + + + <> + + + {tabName === DetectionEngineTab.signals && ( + <> + + + + + )} + {tabName === DetectionEngineTab.alerts && ( + <> + + + + )} + + + + ) : ( + + + + + )} ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx index 83dd18f0f14b7..5ccb4cf5d8372 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -/* eslint-disable react-hooks/rules-of-hooks */ +/* eslint-disable react-hooks/rules-of-hooks, complexity */ import { EuiButton, @@ -32,10 +32,7 @@ import { SiemSearchBar } from '../../../../components/search_bar'; import { WrapperPage } from '../../../../components/wrapper_page'; import { useRule } from '../../../../containers/detection_engine/rules'; -import { - indicesExistOrDataTemporarilyUnavailable, - WithSource, -} from '../../../../containers/source'; +import { useWithSource } from '../../../../containers/source'; import { SpyRoute } from '../../../../utils/route/spy_routes'; import { DetectionEngineHeaderPage } from '../../components/detection_engine_header_page'; @@ -56,7 +53,7 @@ import { StepPanel } from '../components/step_panel'; import { getStepsData, redirectToDetections } from '../helpers'; import * as ruleI18n from '../translations'; import * as i18n from './translations'; -import { GlobalTime } from '../../../../containers/global_time'; +import { useGlobalTime } from '../../../../containers/global_time'; import { signalsHistogramOptions } from '../../components/signals_histogram_panel/config'; import { inputsSelectors } from '../../../../store/inputs'; import { State } from '../../../../store'; @@ -218,6 +215,10 @@ const RuleDetailsPageComponent: FC = ({ [ruleEnabled, setRuleEnabled] ); + const { contentAvailable, indexPattern } = useWithSource(indexToAdd); + + const { to, from, deleteQuery, setQuery } = useGlobalTime(); + if (redirectToDetections(isSignalIndexExists, isAuthenticated, hasEncryptionKey)) { return ; } @@ -226,155 +227,147 @@ const RuleDetailsPageComponent: FC = ({ <> {hasIndexWrite != null && !hasIndexWrite && } {userHasNoPermissions && } - - {({ indicesExist, indexPattern }) => { - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - {({ to, from, deleteQuery, setQuery }) => ( - - - - - - - - {detectionI18n.LAST_SIGNAL} - {': '} - {lastSignals} - , - ] - : []), - , - ]} - title={title} - > - - - - + {contentAvailable ? ( + + + + - - - - - {ruleI18n.EDIT_RULE_SETTINGS} - - - - - - - - - - {ruleError} - {tabs} - - {ruleDetailTab === RuleDetailTabs.signals && ( + + - - - - {defineRuleData != null && ( - - )} - - + {detectionI18n.LAST_SIGNAL} + {': '} + {lastSignals} + , + ] + : []), + , + ]} + title={title} + > + + + + - - - {aboutRuleData != null && ( - - )} - - + + + + + {ruleI18n.EDIT_RULE_SETTINGS} + + + + + + + + + + {ruleError} + {tabs} + + {ruleDetailTab === RuleDetailTabs.signals && ( + <> + + + + {defineRuleData != null && ( + + )} + + - - - {scheduleRuleData != null && ( - - )} - - - - - + + {aboutRuleData != null && ( + - - {ruleId != null && ( - - )} - - )} - {ruleDetailTab === RuleDetailTabs.failures && } - - - )} - - ) : ( - - + )} + + + + + + {scheduleRuleData != null && ( + + )} + + + + + + + {ruleId != null && ( + + )} + + )} + {ruleDetailTab === RuleDetailTabs.failures && } + + + ) : ( + + - - - ); - }} - + + + )} diff --git a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx index 7c5fd56bf1e91..806f6c7937077 100644 --- a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { Redirect, Route, Switch } from 'react-router-dom'; import styled from 'styled-components'; import useResizeObserver from 'use-resize-observer/polyfilled'; @@ -19,7 +19,7 @@ import { MlNetworkConditionalContainer } from '../../components/ml/conditional_l import { StatefulTimeline } from '../../components/timeline'; import { AutoSaveWarningMsg } from '../../components/timeline/auto_save_warning'; import { UseUrlState } from '../../components/url_state'; -import { WithSource, indicesExistOrDataTemporarilyUnavailable } from '../../containers/source'; +import { useWithSource } from '../../containers/source'; import { SpyRoute } from '../../utils/route/spy_routes'; import { NotFoundPage } from '../404'; import { DetectionEngineContainer } from '../detection_engine'; @@ -61,84 +61,89 @@ const calculateFlyoutHeight = ({ windowHeight: number; }): number => Math.max(0, windowHeight - globalHeaderSize); -export const HomePage: React.FC = () => { +export const HomePageComponent = () => { const { ref: measureRef, height: windowHeight = 0 } = useResizeObserver({}); - const flyoutHeight = calculateFlyoutHeight({ - globalHeaderSize: globalHeaderHeightPx, - windowHeight, - }); + const flyoutHeight = useMemo( + () => + calculateFlyoutHeight({ + globalHeaderSize: globalHeaderHeightPx, + windowHeight, + }), + [windowHeight] + ); + + const { browserFields, indexPattern, contentAvailable } = useWithSource(); return ( - +
- - {({ browserFields, indexPattern, indicesExist }) => ( - - - {indicesExistOrDataTemporarilyUnavailable(indicesExist) && ( - <> - - - - - - )} - - - - } /> - } - /> - ( - - )} - /> - ( - - )} - /> - } - /> - } /> - ( - - )} + + + {contentAvailable && ( + <> + + + - ( - - )} - /> - - - - } /> - - + + )} - + + + + + + + } + /> + ( + + )} + /> + ( + + )} + /> + + + + } /> + ( + + )} + /> + ( + + )} + /> + + + + + + + +
@@ -148,4 +153,6 @@ export const HomePage: React.FC = () => { ); }; +export const HomePage = React.memo(HomePageComponent); + HomePage.displayName = 'HomePage'; 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 index 81c1b317d4596..1ef1edb4c4dce 100644 --- 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 @@ -5,7 +5,6 @@ */ import React from 'react'; -import { IIndexPattern } from 'src/plugins/data/public'; import { MemoryRouter } from 'react-router-dom'; import useResizeObserver from 'use-resize-observer/polyfilled'; @@ -18,15 +17,6 @@ import { type } from './utils'; import { useMountAppended } from '../../../utils/use_mount_appended'; import { getHostDetailsPageFilters } from './helpers'; -jest.mock('../../../containers/source', () => ({ - indicesExistOrDataTemporarilyUnavailable: () => true, - WithSource: ({ - children, - }: { - children: (args: { indicesExist: boolean; indexPattern: IIndexPattern }) => 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 and QueryBar jest.mock('../../../components/search_bar', () => ({ @@ -46,7 +36,7 @@ describe('body', () => { allHosts: 'HostsQueryTabBody', uncommonProcesses: 'UncommonProcessQueryTabBody', anomalies: 'AnomaliesQueryTabBody', - events: 'EventsQueryTabBody', + events: 'Memo(EventsQueryTabBodyComponent)', alerts: 'HostAlertsQueryTabBody', }; 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 index f5efd9248029d..76b43cbcdbb4b 100644 --- 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 @@ -85,7 +85,6 @@ export const HostDetailsTabs = React.memo( - 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 8af4731e4dda4..d2d6b6cb5298e 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 @@ -25,7 +25,7 @@ import { SiemSearchBar } from '../../../components/search_bar'; import { WrapperPage } from '../../../components/wrapper_page'; import { HostOverviewByNameQuery } from '../../../containers/hosts/overview'; import { KpiHostDetailsQuery } from '../../../containers/kpi_host_details'; -import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../../containers/source'; +import { useWithSource } from '../../../containers/source'; import { LastEventIndexKey } from '../../../graphql/types'; import { useKibana } from '../../../lib/kibana'; import { convertToBuildEsQuery } from '../../../lib/keury'; @@ -74,132 +74,126 @@ const HostDetailsComponent = React.memo( }, [setAbsoluteRangeDatePicker] ); + const { contentAvailable, indexPattern } = useWithSource(); + const filterQuery = convertToBuildEsQuery({ + config: esQuery.getEsQueryConfig(kibana.services.uiSettings), + indexPattern, + queries: [query], + filters: getFilters(), + }); return ( <> - - {({ indicesExist, indexPattern }) => { - const filterQuery = convertToBuildEsQuery({ - config: esQuery.getEsQueryConfig(kibana.services.uiSettings), - indexPattern, - queries: [query], - filters: getFilters(), - }); - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - - - - - } - title={detailName} - /> - - + + + + + + + } + title={detailName} + /> + + + {({ hostOverview, loading, id, inspect, refetch }) => ( + - {({ 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 }) => ( - ( + { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }} /> )} - - - - - - - - - + )} + + + + + + {({ kpiHostDetails, id, inspect, loading, refetch }) => ( + - - - ) : ( - - - - - - ); - }} - + )} + + + + + + + + + + + + ) : ( + + + + + + )} 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 99cf767c65e08..bbecef4e44a44 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 @@ -8,7 +8,8 @@ import { mount } from 'enzyme'; import { cloneDeep } from 'lodash/fp'; import React from 'react'; import { Router } from 'react-router-dom'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { GraphQLRequest } from '@apollo/client'; +import { MockedProvider } from '@apollo/client/testing'; import { Filter } from '../../../../../../../src/plugins/data/common/es_query'; import '../../mock/match_media'; @@ -32,7 +33,7 @@ jest.mock('../../components/query_bar', () => ({ })); let localSource: Array<{ - request: {}; + request: GraphQLRequest; result: { data: { source: { 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 a7aa9920b7d08..78d41f01c5d28 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx @@ -21,7 +21,7 @@ import { manageQuery } from '../../components/page/manage_query'; import { SiemSearchBar } from '../../components/search_bar'; import { WrapperPage } from '../../components/wrapper_page'; import { KpiHostsQuery } from '../../containers/kpi_hosts'; -import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; +import { useWithSource } from '../../containers/source'; import { LastEventIndexKey } from '../../graphql/types'; import { useKibana } from '../../lib/kibana'; import { convertToBuildEsQuery } from '../../lib/keury'; @@ -68,87 +68,83 @@ export const HostsComponent = React.memo( [setAbsoluteRangeDatePicker] ); + const { contentAvailable, indexPattern } = useWithSource(); + const filterQuery = convertToBuildEsQuery({ + config: esQuery.getEsQueryConfig(kibana.services.uiSettings), + indexPattern, + queries: [query], + filters, + }); + const tabsFilterQuery = convertToBuildEsQuery({ + config: esQuery.getEsQueryConfig(kibana.services.uiSettings), + indexPattern, + queries: [query], + filters: tabsFilters, + }); + return ( <> - - {({ indicesExist, indexPattern }) => { - const filterQuery = convertToBuildEsQuery({ - config: esQuery.getEsQueryConfig(kibana.services.uiSettings), - indexPattern, - queries: [query], - filters, - }); - const tabsFilterQuery = convertToBuildEsQuery({ - config: esQuery.getEsQueryConfig(kibana.services.uiSettings), - indexPattern, - queries: [query], - filters: tabsFilters, - }); - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - - - - } - title={i18n.PAGE_TITLE} - /> - - - {({ kpiHosts, loading, id, inspect, refetch }) => ( - - )} - - - - - - - - - + + + + + + } + title={i18n.PAGE_TITLE} + /> + + + {({ kpiHosts, loading, id, inspect, refetch }) => ( + - - - ) : ( - - - - - - ); - }} - - + )} + + + + + + + + + + + + ) : ( + + + + + + )} ); 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 index 80c35e5563c1d..e788eff9f8801 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx @@ -32,9 +32,26 @@ export const HostsTabs = memo( setQuery, isInitializing, type, - indexPattern, hostsPagePath, }) => { + const narrowDateRange = useCallback( + (score: Anomaly, interval: string) => { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }, + [setAbsoluteRangeDatePicker] + ); + const updateDateRange = useCallback( + (min: number, max: number) => { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }, + [setAbsoluteRangeDatePicker] + ); + const tabProps = { deleteQuery, endDate: to, @@ -43,24 +60,8 @@ export const HostsTabs = memo( setQuery, startDate: from, type, - indexPattern, - narrowDateRange: useCallback( - (score: Anomaly, interval: string) => { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }, - [setAbsoluteRangeDatePicker] - ), - updateDateRange: useCallback( - (min: number, max: number) => { - setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); - }, - [setAbsoluteRangeDatePicker] - ), + narrowDateRange, + updateDateRange, }; return ( 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 699b1441905c3..fd50f7c24d06e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx @@ -10,7 +10,7 @@ import { Redirect, Route, Switch, RouteComponentProps } from 'react-router-dom'; import { HostDetails } from './details'; import { HostsTableType } from '../../store/hosts/model'; -import { GlobalTime } from '../../containers/global_time'; +import { useGlobalTime } from '../../containers/global_time'; import { SiemPageName } from '../home/types'; import { Hosts } from './hosts'; import { hostsPagePath, hostDetailsPagePath } from './types'; @@ -34,62 +34,62 @@ const getHostDetailsTabPath = (pagePath: string) => type Props = Partial> & { url: string }; -export const HostsContainer = React.memo(({ url }) => ( - - {({ to, from, setQuery, deleteQuery, isInitializing }) => ( - - ( - - )} - /> - ( - - )} - /> - } - /> - ( - - )} - /> - - )} - -)); +export const HostsContainer = React.memo(({ url }) => { + const { to, from, setQuery, deleteQuery, isInitializing } = useGlobalTime(); + + return ( + + ( + + )} + /> + ( + + )} + /> + } + /> + ( + + )} + /> + + ); +}); 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 cb2c19c642bc4..d871c6f97e752 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 @@ -47,7 +47,7 @@ export const histogramConfigs: MatrixHisrogramConfigs = { title: i18n.NAVIGATION_EVENTS_TITLE, }; -export const EventsQueryTabBody = ({ +export const EventsQueryTabBodyComponent = ({ deleteQuery, endDate, filterQuery, @@ -86,4 +86,4 @@ export const EventsQueryTabBody = ({ ); }; -EventsQueryTabBody.displayName = 'EventsQueryTabBody'; +export const EventsQueryTabBody = React.memo(EventsQueryTabBodyComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/hosts_query_tab_body.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/hosts_query_tab_body.tsx index 6c301d692d0e1..d099bcd81da65 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/hosts_query_tab_body.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/hosts_query_tab_body.tsx @@ -17,7 +17,6 @@ export const HostsQueryTabBody = ({ deleteQuery, endDate, filterQuery, - indexPattern, skip, setQuery, startDate, @@ -37,7 +36,6 @@ export const HostsQueryTabBody = ({ data={hosts} fakeTotalCount={getOr(50, 'fakeTotalCount', pageInfo)} id={id} - indexPattern={indexPattern} inspect={inspect} isInspect={isInspected} loading={loading} 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 cb5fc62b96582..be21ed91c3291 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Filter, IIndexPattern } from '../../../../../../../../src/plugins/data/public'; +import { Filter } from '../../../../../../../../src/plugins/data/public'; import { NarrowDateRange } from '../../../components/ml/types'; import { ESTermQuery } from '../../../../common/typed_json'; import { InspectQuery, Refetch } from '../../../store/inputs/model'; @@ -45,7 +45,6 @@ export interface QueryTabBodyProps { export type HostsComponentsQueryProps = QueryTabBodyProps & { deleteQuery?: ({ id }: { id: string }) => void; - indexPattern: IIndexPattern; pageFilters?: Filter[]; skip: boolean; setQuery: SetQuery; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts b/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts index 408450aebebbd..cb276c0b44c00 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IIndexPattern } from 'src/plugins/data/public'; import { ActionCreator } from 'typescript-fsa'; import { SiemPageName } from '../home/types'; @@ -18,7 +17,6 @@ export const hostDetailsPagePath = `${hostsPagePath}/:detailName`; export type HostsTabsProps = HostsComponentProps & { filterQuery: string; type: hostsModel.HostsType; - indexPattern: IIndexPattern; setAbsoluteRangeDatePicker: ActionCreator<{ id: InputsModelId; from: number; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/index.tsx b/x-pack/legacy/plugins/siem/public/pages/network/index.tsx index 48fc1421d90bb..9e941b2c9a88c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/index.tsx @@ -13,7 +13,7 @@ import { FlowTarget } from '../../graphql/types'; import { IPDetails } from './ip_details'; import { Network } from './network'; -import { GlobalTime } from '../../containers/global_time'; +import { useGlobalTime } from '../../containers/global_time'; import { SiemPageName } from '../home/types'; import { getNetworkRoutePath } from './navigation'; import { NetworkRouteType } from './navigation/types'; @@ -33,67 +33,64 @@ const NetworkContainerComponent: React.FC = () => { () => getNetworkRoutePath(networkPagePath, capabilitiesFetched, userHasMlUserPermissions), [capabilitiesFetched, userHasMlUserPermissions] ); + const { to, from, setQuery, deleteQuery, isInitializing } = useGlobalTime(); return ( - - {({ to, from, setQuery, deleteQuery, isInitializing }) => ( - - ( - - )} + + ( + - ( - - )} + )} + /> + ( + - ( - - )} + )} + /> + ( + - ( - - )} - /> - - )} - + )} + /> + ( + + )} + /> + ); }; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/__snapshots__/index.test.tsx.snap index e7598ef03d786..1f74f026542a1 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/__snapshots__/index.test.tsx.snap @@ -1,13 +1,60 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Ip Details it matches the snapshot 1`] = ` - - - - - - + `; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx index 02132d790796c..908d5bf26212d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx @@ -8,7 +8,8 @@ import { shallow } from 'enzyme'; import { cloneDeep } from 'lodash/fp'; import React from 'react'; import { Router } from 'react-router-dom'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { GraphQLRequest } from '@apollo/client'; +import { MockedProvider } from '@apollo/client/testing'; import { ActionCreator } from 'typescript-fsa'; import '../../../mock/match_media'; @@ -19,6 +20,7 @@ import { apolloClientObservable, mockGlobalState, TestProviders } from '../../.. import { useMountAppended } from '../../../utils/use_mount_appended'; import { createStore, State } from '../../../store'; import { InputsModelId } from '../../../store/inputs/constants'; +// import { useUiSetting$ } from '../../lib/kibana'; import { IPDetailsComponent, IPDetails } from './index'; @@ -35,9 +37,47 @@ jest.mock('../../../components/search_bar', () => ({ jest.mock('../../../components/query_bar', () => ({ QueryBar: () => null, })); +jest.mock('../../../containers/source', () => ({ + useWithSource: () => ({ + contentAvailable: true, + }), +})); + +jest.mock('../../../../../../../../src/plugins/kibana_react/public/context/context', () => ({ + ...jest.requireActual('../../../../../../../../src/plugins/kibana_react/public/context/context'), + useKibana: () => ({ + services: { + http: { + basePath: { + get: () => '', + }, + }, + docLinks: { + links: { + siem: { + gettingStarted: '', + }, + }, + }, + uiSettings: { + get: () => '', + }, + }, + }), +})); + +jest.mock( + '../../../../../../../../src/plugins/kibana_react/public/ui_settings/use_ui_setting', + () => ({ + ...jest.requireActual( + '../../../../../../../../src/plugins/kibana_react/public/ui_settings/use_ui_setting' + ), + useUiSetting$: () => [], + }) +); let localSource: Array<{ - request: {}; + request: GraphQLRequest; result: { data: { source: { @@ -122,16 +162,31 @@ describe('Ip Details', () => { }); test('it renders', () => { - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="ip-details-page"]').exists()).toBe(true); + const wrapper = shallow( + + + + ); + + expect( + wrapper + .find('IPDetailsComponent') + .dive() + .find('[data-test-subj="ip-details-page"]') + .exists() + ).toBe(true); }); test('it matches the snapshot', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const wrapper = shallow( + + + + ); + expect(wrapper.find('IPDetailsComponent')).toMatchSnapshot(); }); - test('it renders ipv6 headline', async () => { + test('it renders ipv6 headline', () => { localSource[0].result.data.source.status.indicesExist = true; const ip = 'fe80--24ce-f7ff-fede-a571'; const wrapper = mount( @@ -143,9 +198,6 @@ describe('Ip Details', () => { ); - // Why => https://github.com/apollographql/react-apollo/issues/1711 - await new Promise(resolve => setTimeout(resolve)); - wrapper.update(); expect( wrapper .find('[data-test-subj="ip-details-headline"] [data-test-subj="header-page-title"]') diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx index e796eaca0cd28..160f9343caf75 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx @@ -22,7 +22,7 @@ import { IpOverview } from '../../../components/page/network/ip_overview'; import { SiemSearchBar } from '../../../components/search_bar'; import { WrapperPage } from '../../../components/wrapper_page'; import { IpOverviewQuery } from '../../../containers/ip_overview'; -import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../../containers/source'; +import { useWithSource } from '../../../containers/source'; import { FlowTargetSourceDest, LastEventIndexKey } from '../../../graphql/types'; import { useKibana } from '../../../lib/kibana'; import { decodeIpv6 } from '../../../lib/helpers'; @@ -76,202 +76,199 @@ export const IPDetailsComponent: React.FC - - {({ indicesExist, indexPattern }) => { - const ip = decodeIpv6(detailName); - const filterQuery = convertToBuildEsQuery({ - config: esQuery.getEsQueryConfig(kibana.services.uiSettings), - indexPattern, - queries: [query], - filters, - }); - - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - - - - } - title={ip} - > - - + const { indexPattern, contentAvailable } = useWithSource(); + const ip = decodeIpv6(detailName); + const filterQuery = convertToBuildEsQuery({ + config: esQuery.getEsQueryConfig(kibana.services.uiSettings), + indexPattern, + queries: [query], + filters, + }); - + {contentAvailable ? ( + + + + + + + } + title={ip} + > + + + + + {({ id, inspect, ipOverviewData, loading, refetch }) => ( + - {({ id, inspect, ipOverviewData, loading, refetch }) => ( - - {({ isLoadingAnomaliesData, anomaliesData }) => ( - - )} - - )} - - - - - - - ( + - - - - - - - - - - - - - - - - - - + )} + + )} + - + - + + + - - - + + + - + - + + + - - - + - - - ) : ( - - - - - - ); - }} - + + + + + + + + + + + + + + + + + + + + + ) : ( + + + + + + )} - + ); }; IPDetailsComponent.displayName = 'IPDetailsComponent'; @@ -291,7 +288,7 @@ const mapDispatchToProps = { setIpDetailsTablesActivePageToZero: dispatchIpDetailsTablesActivePageToZero, }; -export const connector = connect(makeMapStateToProps, mapDispatchToProps); +const connector = connect(makeMapStateToProps, mapDispatchToProps); type PropsFromRedux = ConnectedProps; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/network.test.tsx b/x-pack/legacy/plugins/siem/public/pages/network/network.test.tsx index 797fef1586518..41c967ffe9874 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/network.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/network.test.tsx @@ -8,7 +8,8 @@ import { mount } from 'enzyme'; import { cloneDeep } from 'lodash/fp'; import React from 'react'; import { Router } from 'react-router-dom'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { GraphQLRequest } from '@apollo/client'; +import { MockedProvider } from '@apollo/client/testing'; import '../../mock/match_media'; import { Filter } from '../../../../../../../src/plugins/data/common/es_query'; @@ -29,7 +30,7 @@ jest.mock('../../components/query_bar', () => ({ })); let localSource: Array<{ - request: {}; + request: GraphQLRequest; result: { data: { source: { 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 9b1ee76e1d376..c71f361e5c9f3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/network.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/network.tsx @@ -21,7 +21,7 @@ import { KpiNetworkComponent } from '../../components/page/network'; import { SiemSearchBar } from '../../components/search_bar'; import { WrapperPage } from '../../components/wrapper_page'; import { KpiNetworkQuery } from '../../containers/kpi_network'; -import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; +import { useWithSource } from '../../containers/source'; import { LastEventIndexKey } from '../../graphql/types'; import { useKibana } from '../../lib/kibana'; import { convertToBuildEsQuery } from '../../lib/keury'; @@ -68,103 +68,101 @@ const NetworkComponent = React.memo( [setAbsoluteRangeDatePicker] ); + const { contentAvailable, indexPattern } = useWithSource(); + + const filterQuery = convertToBuildEsQuery({ + config: esQuery.getEsQueryConfig(kibana.services.uiSettings), + indexPattern, + queries: [query], + filters, + }); + const tabsFilterQuery = convertToBuildEsQuery({ + config: esQuery.getEsQueryConfig(kibana.services.uiSettings), + indexPattern, + queries: [query], + filters: tabsFilters, + }); + return ( <> - - {({ indicesExist, indexPattern }) => { - const filterQuery = convertToBuildEsQuery({ - config: esQuery.getEsQueryConfig(kibana.services.uiSettings), - indexPattern, - queries: [query], - filters, - }); - const tabsFilterQuery = convertToBuildEsQuery({ - config: esQuery.getEsQueryConfig(kibana.services.uiSettings), - indexPattern, - queries: [query], - filters: tabsFilters, - }); - - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - - - - } - title={i18n.PAGE_TITLE} - /> - - + + + + + + } + title={i18n.PAGE_TITLE} + /> + + + + + + + {({ kpiNetwork, loading, id, inspect, refetch }) => ( + + )} + + {capabilitiesFetched && !isInitializing ? ( + <> - - {({ kpiNetwork, loading, id, inspect, refetch }) => ( - - )} - - - {capabilitiesFetched && !isInitializing ? ( - <> - - - - - - - - - ) : ( - - )} + - - - ) : ( - - - - - ); - }} - + + + + ) : ( + + )} + + + + + ) : ( + + + + + )} diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/event_counts/index.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/event_counts/index.tsx index 0fc37935b6062..a6725231ccf62 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/event_counts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/event_counts/index.tsx @@ -53,17 +53,26 @@ const EventCountsComponent: React.FC = ({ }) => { const kibana = useKibana(); + const hostFilterQuery = convertToBuildEsQuery({ + config: esQuery.getEsQueryConfig(kibana.services.uiSettings), + indexPattern, + queries: [query], + filters: [...filters, ...filterHostData], + }); + + const networkFilterQuery = convertToBuildEsQuery({ + config: esQuery.getEsQueryConfig(kibana.services.uiSettings), + indexPattern, + queries: [query], + filters: [...filters, ...filterNetworkData], + }); + return ( @@ -74,12 +83,7 @@ const EventCountsComponent: React.FC = ({ diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/index.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/index.tsx index 65b401f00a86e..2b8e61dec301c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/index.tsx @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { memo } from 'react'; +import { memo } from 'react'; import { StatefulOverview } from './overview'; -export const Overview = memo(() => ); +export const Overview = memo(StatefulOverview); Overview.displayName = 'Overview'; diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/overview.test.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/overview.test.tsx index b20cd84295566..aa523db32bde2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/overview.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/overview.test.tsx @@ -7,7 +7,8 @@ import { mount } from 'enzyme'; import { cloneDeep } from 'lodash/fp'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; +import { GraphQLRequest } from '@apollo/client'; +import { MockedProvider } from '@apollo/client/testing'; import { MemoryRouter } from 'react-router-dom'; import '../../mock/match_media'; @@ -34,7 +35,7 @@ jest.mock('../../components/query_bar', () => ({ })); let localSource: Array<{ - request: {}; + request: GraphQLRequest; result: { data: { source: { diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx index 2db49e60193fc..83d36e043b6e0 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx @@ -15,8 +15,8 @@ import { AlertsByCategory } from './alerts_by_category'; import { FiltersGlobal } from '../../components/filters_global'; import { SiemSearchBar } from '../../components/search_bar'; import { WrapperPage } from '../../components/wrapper_page'; -import { GlobalTime } from '../../containers/global_time'; -import { WithSource, indicesExistOrDataTemporarilyUnavailable } from '../../containers/source'; +import { useGlobalTime } from '../../containers/global_time'; +import { useWithSource } from '../../containers/source'; import { EventsByDataset } from './events_by_dataset'; import { EventCounts } from './event_counts'; import { OverviewEmpty } from './overview_empty'; @@ -37,89 +37,86 @@ const OverviewComponent: React.FC = ({ filters = NO_FILTERS, query = DEFAULT_QUERY, setAbsoluteRangeDatePicker, -}) => ( - <> - - {({ indicesExist, indexPattern }) => - indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - - - - - - - - - - - {({ from, deleteQuery, setQuery, to }) => ( - - - - - - - - - - - - - - - - - - - )} - - - - - - ) : ( - - ) - } - - - - -); +}) => { + const { indexPattern, contentAvailable } = useWithSource(); + const { from, deleteQuery, setQuery, to } = useGlobalTime(); + + return ( + <> + {contentAvailable ? ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) : ( + + )} + + + + ); +}; const makeMapStateToProps = () => { const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/sidebar/sidebar.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/sidebar/sidebar.tsx index d3b85afe62a2a..ac09a3a72dc64 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/sidebar/sidebar.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/sidebar/sidebar.tsx @@ -14,7 +14,6 @@ import { StatefulRecentTimelines } from '../../../components/recent_timelines'; import { StatefulNewsFeed } from '../../../components/news_feed'; import { FilterMode } from '../../../components/recent_timelines/types'; import { SidebarHeader } from '../../../components/sidebar_header'; -import { useApolloClient } from '../../../utils/apollo_context'; import * as i18n from '../translations'; @@ -26,7 +25,6 @@ export const Sidebar = React.memo<{ filterBy: FilterMode; setFilterBy: (filterBy: FilterMode) => void; }>(({ filterBy, setFilterBy }) => { - const apolloClient = useApolloClient(); const RecentTimelinesFilters = useMemo( () => , [filterBy, setFilterBy] @@ -36,7 +34,7 @@ export const Sidebar = React.memo<{ {RecentTimelinesFilters} - + diff --git a/x-pack/legacy/plugins/siem/public/pages/timelines/index.tsx b/x-pack/legacy/plugins/siem/public/pages/timelines/index.tsx index aa5c891de3628..7102b64535617 100644 --- a/x-pack/legacy/plugins/siem/public/pages/timelines/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/timelines/index.tsx @@ -5,12 +5,39 @@ */ import React from 'react'; -import { ApolloConsumer } from 'react-apollo'; +import styled from 'styled-components'; -import { TimelinesPage } from './timelines_page'; +import { HeaderPage } from '../../components/header_page'; +import { StatefulOpenTimeline } from '../../components/open_timeline'; +import { WrapperPage } from '../../components/wrapper_page'; +import { SpyRoute } from '../../utils/route/spy_routes'; +import * as i18n from './translations'; -export const Timelines = React.memo(() => ( - {client => } -)); +const TimelinesContainer = styled.div` + width: 100%; +`; +TimelinesContainer.displayName = 'TimelinesContainer'; -Timelines.displayName = 'Timelines'; +export const DEFAULT_SEARCH_RESULTS_PER_PAGE = 10; + +export const TimelinesPage = () => ( + <> + + + + + + + + + + +); + +TimelinesPage.displayName = 'TimelinesPage'; + +export const Timelines = React.memo(TimelinesPage); diff --git a/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.tsx b/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.tsx deleted file mode 100644 index 86f702a8ad8a4..0000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.tsx +++ /dev/null @@ -1,48 +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 ApolloClient from 'apollo-client'; -import React from 'react'; -import styled from 'styled-components'; - -import { HeaderPage } from '../../components/header_page'; -import { StatefulOpenTimeline } from '../../components/open_timeline'; -import { WrapperPage } from '../../components/wrapper_page'; -import { SpyRoute } from '../../utils/route/spy_routes'; -import * as i18n from './translations'; - -const TimelinesContainer = styled.div` - width: 100%; -`; - -interface TimelinesProps { - apolloClient: ApolloClient; -} - -type OwnProps = TimelinesProps; - -export const DEFAULT_SEARCH_RESULTS_PER_PAGE = 10; - -const TimelinesPageComponent: React.FC = ({ apolloClient }) => ( - <> - - - - - - - - - - -); - -export const TimelinesPage = React.memo(TimelinesPageComponent); diff --git a/x-pack/legacy/plugins/siem/public/store/timeline/epic_favorite.ts b/x-pack/legacy/plugins/siem/public/store/timeline/epic_favorite.ts index 4d1b73aa70a6e..52b2b8ec0c185 100644 --- a/x-pack/legacy/plugins/siem/public/store/timeline/epic_favorite.ts +++ b/x-pack/legacy/plugins/siem/public/store/timeline/epic_favorite.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { NormalizedCacheObject } from 'apollo-cache-inmemory'; -import { ApolloClient } from 'apollo-client'; +import { ApolloClient, NormalizedCacheObject } from '@apollo/client'; import { get } from 'lodash/fp'; import { Action } from 'redux'; import { Epic } from 'redux-observable'; diff --git a/x-pack/legacy/plugins/siem/public/store/timeline/epic_note.ts b/x-pack/legacy/plugins/siem/public/store/timeline/epic_note.ts index e5a712fe2c666..4dcdcbd33016b 100644 --- a/x-pack/legacy/plugins/siem/public/store/timeline/epic_note.ts +++ b/x-pack/legacy/plugins/siem/public/store/timeline/epic_note.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ApolloClient } from 'apollo-client'; -import { NormalizedCacheObject } from 'apollo-cache-inmemory'; +import { ApolloClient, NormalizedCacheObject } from '@apollo/client'; import { get } from 'lodash/fp'; import { Action } from 'redux'; import { Epic } from 'redux-observable'; diff --git a/x-pack/legacy/plugins/siem/public/store/timeline/epic_pinned_event.ts b/x-pack/legacy/plugins/siem/public/store/timeline/epic_pinned_event.ts index 2260999a91e7b..b73d1e3ad7fef 100644 --- a/x-pack/legacy/plugins/siem/public/store/timeline/epic_pinned_event.ts +++ b/x-pack/legacy/plugins/siem/public/store/timeline/epic_pinned_event.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { NormalizedCacheObject } from 'apollo-cache-inmemory'; -import { ApolloClient } from 'apollo-client'; +import { ApolloClient, NormalizedCacheObject } from '@apollo/client'; import { get, omit } from 'lodash/fp'; import { Action } from 'redux'; import { Epic } from 'redux-observable'; diff --git a/x-pack/legacy/plugins/siem/public/utils/apollo_context.ts b/x-pack/legacy/plugins/siem/public/utils/apollo_context.ts deleted file mode 100644 index f0c5e7e917e13..0000000000000 --- a/x-pack/legacy/plugins/siem/public/utils/apollo_context.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ApolloClient } from 'apollo-client'; -import { createContext, useContext } from 'react'; - -/** - * This is a temporary provider and hook for use with hooks until react-apollo - * has upgraded to the new-style `createContext` api. - */ - -export const ApolloClientContext = createContext | undefined>(undefined); - -export const useApolloClient = () => { - return useContext(ApolloClientContext); -}; diff --git a/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx b/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx index ddee2359b28ba..0d980c0bf7d66 100644 --- a/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx +++ b/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx @@ -81,7 +81,8 @@ export const SpyRouteComponent = memo( } }, [pathname, search, pageName, detailName, tabName, flowTarget, state]); return null; - } + }, + deepEqual ); export const SpyRoute = withRouter(SpyRouteComponent); diff --git a/x-pack/legacy/plugins/siem/scripts/combined_schema.ts b/x-pack/legacy/plugins/siem/scripts/combined_schema.ts index 625eb3a4a4755..71eaf8490f7e2 100644 --- a/x-pack/legacy/plugins/siem/scripts/combined_schema.ts +++ b/x-pack/legacy/plugins/siem/scripts/combined_schema.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { buildSchemaFromTypeDefinitions } from 'graphql-tools'; +import { buildSchemaFromTypeDefinitions } from '@kamilkisiela/graphql-tools'; import { schemas as serverSchemas } from '../server/graphql'; diff --git a/x-pack/legacy/plugins/siem/scripts/generate_types_from_graphql.js b/x-pack/legacy/plugins/siem/scripts/generate_types_from_graphql.js index 36674fec73e09..e6f5f2388a281 100644 --- a/x-pack/legacy/plugins/siem/scripts/generate_types_from_graphql.js +++ b/x-pack/legacy/plugins/siem/scripts/generate_types_from_graphql.js @@ -4,138 +4,171 @@ * you may not use this file except in compliance with the Elastic License. */ +/* eslint-disable import/no-extraneous-dependencies */ + require('../../../../../src/setup_node_env'); -const { join, resolve } = require('path'); -// eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved -const { generate } = require('graphql-code-generator'); +const path = require('path'); +const { codegen } = require('@graphql-codegen/core'); +const { loadDocuments } = require('@graphql-toolkit/core'); +const { GraphQLFileLoader } = require('@graphql-toolkit/graphql-file-loader'); +const { CodeFileLoader } = require('@graphql-toolkit/code-file-loader'); const GRAPHQL_GLOBS = [ - join('public', 'containers', '**', '*.gql_query.ts{,x}'), - join('common', 'graphql', '**', '*.gql_query.ts{,x}'), + path.join('public', 'containers', '**', '*.gql_query.ts'), + path.join('common', 'graphql', '**', '*.gql_query.ts'), ]; -const OUTPUT_INTROSPECTION_PATH = resolve('public', 'graphql', 'introspection.json'); -const OUTPUT_CLIENT_TYPES_PATH = resolve('public', 'graphql', 'types.ts'); -const OUTPUT_SERVER_TYPES_PATH = resolve('server', 'graphql', 'types.ts'); -const SCHEMA_PATH = resolve(__dirname, 'combined_schema.ts'); +const OUTPUT_CLIENT_TYPES_PATH = path.resolve('public', 'graphql', 'types.tsx'); +const OUTPUT_SERVER_TYPES_PATH = path.resolve('server', 'graphql', 'types.ts'); +const combinedSchema = require('./combined_schema'); + +const { printSchema, parse } = require('graphql'); +const fs = require('fs'); +const addPlugin = require('@graphql-codegen/add'); +const typescriptPlugin = require('@graphql-codegen/typescript'); +const typescriptOperationsPlugin = require('@graphql-codegen/typescript-operations'); +const typescriptResolversPlugin = require('@graphql-codegen/typescript-resolvers'); +const typescriptCompatibilityPlugin = require('@graphql-codegen/typescript-compatibility'); +const typescriptReactApolloPlugin = require('@graphql-codegen/typescript-react-apollo'); async function main() { - await generate( - { - schema: SCHEMA_PATH, - overwrite: true, - generates: { - [OUTPUT_INTROSPECTION_PATH]: { - documents: GRAPHQL_GLOBS, - primitives: { - String: 'string', - Int: 'number', - Float: 'number', - Boolean: 'boolean', - ID: 'string', - }, - config: { - namingConvention: { - typeNames: 'change-case#pascalCase', - enumValues: 'keep', - }, - contextType: 'SiemContext', - scalars: { - ToStringArray: 'string[] | string', - ToNumberArray: 'number[] | number', - ToDateArray: 'string[] | string', - ToBooleanArray: 'boolean[] | boolean', - Date: 'string', - }, - }, - plugins: ['introspection'], - }, - [OUTPUT_CLIENT_TYPES_PATH]: { - documents: GRAPHQL_GLOBS, - primitives: { - String: 'string', - Int: 'number', - Float: 'number', - Boolean: 'boolean', - ID: 'string', - }, - config: { - avoidOptionals: false, - namingConvention: { - typeNames: 'change-case#pascalCase', - enumValues: 'keep', - }, - contextType: 'SiemContext', - scalars: { - ToStringArray: 'string[]', - ToNumberArray: 'number[]', - ToDateArray: 'string[]', - ToBooleanArray: 'boolean[]', - Date: 'string', - }, - }, - plugins: [ - { - add: `/* tslint:disable */ - /* eslint-disable */ - /* - * 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. - */ - `, - }, - 'typescript-common', - 'typescript-server', - 'typescript-client', - ], - }, - [OUTPUT_SERVER_TYPES_PATH]: { - primitives: { - String: 'string', - Int: 'number', - Float: 'number', - Boolean: 'boolean', - ID: 'string', - }, - config: { - avoidOptionals: false, - namingConvention: { - typeNames: 'change-case#pascalCase', - enumValues: 'keep', - }, - contextType: 'SiemContext', - scalars: { - ToStringArray: 'string[] | string', - ToNumberArray: 'number[] | number', - ToDateArray: 'string[] | string', - ToBooleanArray: 'boolean[] | boolean', - Date: 'string', - }, - }, - plugins: [ - { - add: ` - /* tslint:disable */ - /* eslint-disable */ - /* - * 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. - */ + const documents = await loadDocuments(GRAPHQL_GLOBS, { + loaders: [new GraphQLFileLoader(), new CodeFileLoader()], + }); - import { SiemContext } from '../lib/types'; - `, - }, - 'typescript-common', - 'typescript-server', - 'typescript-resolvers', - ], + const client = await codegen({ + schema: parse(printSchema(combinedSchema.default)), + documents, + overwrite: true, + filename: OUTPUT_CLIENT_TYPES_PATH, + primitives: { + String: 'string', + Int: 'number', + Float: 'number', + Boolean: 'boolean', + ID: 'string', + }, + config: { + dedupeOperationSuffix: false, + preResolveTypes: true, + avoidOptionals: false, + namingConvention: { + typeNames: 'change-case#pascalCase', + enumValues: 'keep', + }, + contextType: 'SiemContext', + scalars: { + ToStringArray: 'string[]', + ToNumberArray: 'number[]', + ToDateArray: 'string[]', + ToBooleanArray: 'boolean[]', + Date: 'string', + }, + }, + plugins: [ + { + add: [ + '/*', + ' * 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.', + ' */', + '', + '/* tslint:disable */', + '/* eslint-disable */', + '', + ].join('\n'), + }, + { + typescript: {}, + }, + { + 'typescript-operations': {}, + }, + { + 'typescript-react-apollo': { + apolloReactComponentsImportFrom: '@apollo/react-components', + reactApolloVersion: 3, + withHooks: true, + withHOC: false, }, }, + { + 'typescript-compatibility': {}, + }, + ], + pluginMap: { + add: addPlugin, + typescript: typescriptPlugin, + 'typescript-operations': typescriptOperationsPlugin, + 'typescript-react-apollo': typescriptReactApolloPlugin, + 'typescript-compatibility': typescriptCompatibilityPlugin, + }, + }); + + const server = await codegen({ + schema: parse(printSchema(combinedSchema.default)), + documents, + overwrite: true, + filename: OUTPUT_SERVER_TYPES_PATH, + primitives: { + String: 'string', + Int: 'number', + Float: 'number', + Boolean: 'boolean', + ID: 'string', + }, + config: { + declarationKind: 'interface', + useIndexSignature: true, + skipTypename: true, + avoidOptionals: false, + preResolveTypes: true, + namingConvention: { + typeNames: 'change-case#pascalCase', + enumValues: 'keep', + }, + contextType: 'SiemContext', + scalars: { + ToStringArray: 'string[] | string', + ToNumberArray: 'number[] | number', + ToDateArray: 'string[] | string', + ToBooleanArray: 'boolean[] | boolean', + Date: 'string', + }, }, - true - ); + plugins: [ + { + add: [ + '/*', + ' * 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.', + '*/', + '', + '/* tslint:disable */', + '/* eslint-disable */', + '', + `import { SiemContext } from '../lib/types';`, + '', + ].join('\n'), + }, + { + typescript: {}, + }, + { + 'typescript-resolvers': {}, + }, + ], + pluginMap: { + add: addPlugin, + typescript: typescriptPlugin, + 'typescript-resolvers': typescriptResolversPlugin, + }, + }); + + fs.writeFileSync(OUTPUT_CLIENT_TYPES_PATH, client); + fs.writeFileSync(OUTPUT_SERVER_TYPES_PATH, server); } if (require.main === module) { diff --git a/x-pack/legacy/plugins/siem/server/graphql/authentications/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/authentications/resolvers.ts index b66ccd9a111b7..4bb626285e3ce 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/authentications/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/authentications/resolvers.ts @@ -6,14 +6,7 @@ import { SourceResolvers } from '../../graphql/types'; import { Authentications } from '../../lib/authentications'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { createOptionsPaginated } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -type QueryAuthenticationsResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export interface AuthenticationsResolversDeps { authentications: Authentications; @@ -23,7 +16,7 @@ export const createAuthenticationsResolvers = ( libs: AuthenticationsResolversDeps ): { Source: { - Authentications: QueryAuthenticationsResolver; + Authentications: SourceResolvers['Authentications']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/authentications/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/authentications/schema.gql.ts index 20935ce9ed03f..f297244762b1e 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/authentications/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/authentications/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const authenticationsSchema = gql` type LastSourceHost { diff --git a/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts index f897236b3470e..da7b1eda7935a 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const ecsSchema = gql` scalar ToStringArray diff --git a/x-pack/legacy/plugins/siem/server/graphql/events/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/events/resolvers.ts index a9ef6bc682c84..7a57c6f3e3776 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/events/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/events/resolvers.ts @@ -7,37 +7,21 @@ import { GraphQLScalarType, Kind } from 'graphql'; import { Events } from '../../lib/events'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { createOptions } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; import { SourceResolvers } from '../types'; import { LastEventTimeRequestOptions } from '../../lib/events/types'; -type QueryTimelineResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -type QueryTimelineDetailsResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -type QueryLastEventTimeResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - export interface EventsResolversDeps { events: Events; } + export const createEventsResolvers = ( libs: EventsResolversDeps ): { Source: { - Timeline: QueryTimelineResolver; - TimelineDetails: QueryTimelineDetailsResolver; - LastEventTime: QueryLastEventTimeResolver; + Timeline: SourceResolvers['Timeline']; + TimelineDetails: SourceResolvers['TimelineDetails']; + LastEventTime: SourceResolvers['LastEventTime']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/events/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/events/schema.gql.ts index 3b71977bc0d47..ffef0d218eb21 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/events/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/events/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const eventsSchema = gql` scalar EsValue diff --git a/x-pack/legacy/plugins/siem/server/graphql/hosts/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/hosts/resolvers.ts index 65403c4b31261..9d86cb3ffae48 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/hosts/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/hosts/resolvers.ts @@ -7,7 +7,6 @@ import { getOr } from 'lodash/fp'; import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { Hosts, HostOverviewRequestOptions, @@ -16,22 +15,6 @@ import { } from '../../lib/hosts'; import { getFields } from '../../utils/build_query'; import { createOptionsPaginated } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -type QueryHostsResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -type QueryHostOverviewResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -type QueryHostFirstLastSeenResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export interface HostsResolversDeps { hosts: Hosts; @@ -41,9 +24,9 @@ export const createHostsResolvers = ( libs: HostsResolversDeps ): { Source: { - Hosts: QueryHostsResolver; - HostOverview: QueryHostOverviewResolver; - HostFirstLastSeen: QueryHostFirstLastSeenResolver; + Hosts: SourceResolvers['Hosts']; + HostOverview: SourceResolvers['HostOverview']; + HostFirstLastSeen: SourceResolvers['HostFirstLastSeen']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/hosts/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/hosts/schema.gql.ts index d813a08cad6db..763a83f82a1d8 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/hosts/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/hosts/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const hostsSchema = gql` type OsFields { diff --git a/x-pack/legacy/plugins/siem/server/graphql/ip_details/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/ip_details/resolvers.ts index d0e84026de473..ab3f0f67dcef2 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/ip_details/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/ip_details/resolvers.ts @@ -5,20 +5,8 @@ */ import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { IpDetails, UsersRequestOptions } from '../../lib/ip_details'; import { createOptions, createOptionsPaginated } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -export type QueryIpOverviewResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -export type QueryUsersResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export interface IDetailsResolversDeps { ipDetails: IpDetails; @@ -28,8 +16,8 @@ export const createIpDetailsResolvers = ( libs: IDetailsResolversDeps ): { Source: { - IpOverview: QueryIpOverviewResolver; - Users: QueryUsersResolver; + IpOverview: SourceResolvers['IpOverview']; + Users: SourceResolvers['Users']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/ip_details/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/ip_details/schema.gql.ts index 4684449c1b80f..adfe0601b3584 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/ip_details/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/ip_details/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; const ipOverviewSchema = gql` type AutonomousSystemOrganization { diff --git a/x-pack/legacy/plugins/siem/server/graphql/kpi_hosts/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/kpi_hosts/resolvers.ts index 6708bdcd55d62..5579a877bd3a7 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/kpi_hosts/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/kpi_hosts/resolvers.ts @@ -5,20 +5,8 @@ */ import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { KpiHosts } from '../../lib/kpi_hosts'; import { createOptions } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -export type QueryKpiHostsResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -export type QueryKpiHostDetailsResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export interface KpiHostsResolversDeps { kpiHosts: KpiHosts; @@ -28,8 +16,8 @@ export const createKpiHostsResolvers = ( libs: KpiHostsResolversDeps ): { Source: { - KpiHosts: QueryKpiHostsResolver; - KpiHostDetails: QueryKpiHostDetailsResolver; + KpiHosts: SourceResolvers['KpiHosts']; + KpiHostDetails: SourceResolvers['KpiHostDetails']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/kpi_hosts/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/kpi_hosts/schema.gql.ts index 49c988436e977..f73346432b89f 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/kpi_hosts/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/kpi_hosts/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const kpiHostsSchema = gql` type KpiHostHistogramData { diff --git a/x-pack/legacy/plugins/siem/server/graphql/kpi_network/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/kpi_network/resolvers.ts index b587d8c4ac726..0cb14933fd887 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/kpi_network/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/kpi_network/resolvers.ts @@ -5,15 +5,8 @@ */ import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { KpiNetwork } from '../../lib/kpi_network'; import { createOptions } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -export type QueryKipNetworkResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export interface KpiNetworkResolversDeps { kpiNetwork: KpiNetwork; @@ -23,7 +16,7 @@ export const createKpiNetworkResolvers = ( libs: KpiNetworkResolversDeps ): { Source: { - KpiNetwork: QueryKipNetworkResolver; + KpiNetwork: SourceResolvers['KpiNetwork']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/kpi_network/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/kpi_network/schema.gql.ts index 830240a83bd91..9be8cc806a4c6 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/kpi_network/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/kpi_network/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const kpiNetworkSchema = gql` type KpiNetworkHistogramData { diff --git a/x-pack/legacy/plugins/siem/server/graphql/matrix_histogram/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/matrix_histogram/resolvers.ts index 35cebe4777dcf..c8375e53c5d61 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/matrix_histogram/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/matrix_histogram/resolvers.ts @@ -5,25 +5,18 @@ */ import { MatrixHistogram } from '../../lib/matrix_histogram'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { createOptions } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; import { SourceResolvers } from '../types'; export interface MatrixHistogramResolversDeps { matrixHistogram: MatrixHistogram; } -type QueryMatrixHistogramResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - export const createMatrixHistogramResolvers = ( libs: MatrixHistogramResolversDeps ): { Source: { - MatrixHistogram: QueryMatrixHistogramResolver; + MatrixHistogram: SourceResolvers['MatrixHistogram']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/matrix_histogram/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/matrix_histogram/schema.gql.ts index deda6dc6e5c1a..7dd0cbe5ba13f 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/matrix_histogram/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/matrix_histogram/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const matrixHistogramSchema = gql` type MatrixOverTimeHistogramData { diff --git a/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts index db15babc42a72..b99d026b33963 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts @@ -5,30 +5,8 @@ */ import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { Network } from '../../lib/network'; import { createOptionsPaginated } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -type QueryNetworkTopCountriesResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -type QueryNetworkTopNFlowResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -type QueryNetworkHttpResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -type QueryDnsResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export interface NetworkResolversDeps { network: Network; @@ -38,10 +16,10 @@ export const createNetworkResolvers = ( libs: NetworkResolversDeps ): { Source: { - NetworkHttp: QueryNetworkHttpResolver; - NetworkTopCountries: QueryNetworkTopCountriesResolver; - NetworkTopNFlow: QueryNetworkTopNFlowResolver; - NetworkDns: QueryDnsResolver; + NetworkHttp: SourceResolvers['NetworkHttp']; + NetworkTopCountries: SourceResolvers['NetworkTopCountries']; + NetworkTopNFlow: SourceResolvers['NetworkTopNFlow']; + NetworkDns: SourceResolvers['NetworkDns']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts index 15e2d832a73c9..c4d999cebb6f0 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const networkSchema = gql` enum NetworkDirectionEcs { diff --git a/x-pack/legacy/plugins/siem/server/graphql/note/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/note/resolvers.ts index 5f816b9ada54e..2f6c0f775d97d 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/note/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/note/resolvers.ts @@ -4,33 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AppResolverWithFields, AppResolverOf } from '../../lib/framework'; import { MutationResolvers, QueryResolvers } from '../types'; import { Note } from '../../lib/note/saved_object'; -export type QueryNoteResolver = AppResolverOf; - -export type QueryAllNoteResolver = AppResolverWithFields< - QueryResolvers.GetAllNotesResolver, - 'totalCount' | 'Note' ->; - -export type QueryNotesByTimelineIdResolver = AppResolverOf< - QueryResolvers.GetNotesByTimelineIdResolver ->; - -export type QueryNotesByEventIdResolver = AppResolverOf; - -export type MutationNoteResolver = AppResolverOf< - MutationResolvers.PersistNoteResolver ->; - -export type MutationDeleteNoteResolver = AppResolverOf; - -export type MutationDeleteNoteByTimelineIdResolver = AppResolverOf< - MutationResolvers.DeleteNoteByTimelineIdResolver ->; - interface NoteResolversDeps { note: Note; } @@ -39,15 +15,15 @@ export const createNoteResolvers = ( libs: NoteResolversDeps ): { Query: { - getNote: QueryNoteResolver; - getAllNotes: QueryAllNoteResolver; - getNotesByEventId: QueryNotesByEventIdResolver; - getNotesByTimelineId: QueryNotesByTimelineIdResolver; + getNote: QueryResolvers['getNote']; + getAllNotes: QueryResolvers['getAllNotes']; + getNotesByEventId: QueryResolvers['getNotesByEventId']; + getNotesByTimelineId: QueryResolvers['getNotesByTimelineId']; }; Mutation: { - deleteNote: MutationDeleteNoteResolver; - deleteNoteByTimelineId: MutationDeleteNoteByTimelineIdResolver; - persistNote: MutationNoteResolver; + deleteNote: MutationResolvers['deleteNote']; + deleteNoteByTimelineId: MutationResolvers['deleteNoteByTimelineId']; + persistNote: MutationResolvers['persistNote']; }; } => ({ Query: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/note/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/note/schema.gql.ts index fa26660d088c1..610d303d42b33 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/note/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/note/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; const note = ` eventId: String diff --git a/x-pack/legacy/plugins/siem/server/graphql/overview/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/overview/resolvers.ts index a7bafabb64092..beb9c8fc1a0e1 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/overview/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/overview/resolvers.ts @@ -5,20 +5,8 @@ */ import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { Overview } from '../../lib/overview'; import { createOptions } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -export type QueryOverviewNetworkResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -export type QueryOverviewHostResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export interface OverviewResolversDeps { overview: Overview; @@ -28,8 +16,8 @@ export const createOverviewResolvers = ( libs: OverviewResolversDeps ): { Source: { - OverviewHost: QueryOverviewHostResolver; - OverviewNetwork: QueryOverviewNetworkResolver; + OverviewHost: SourceResolvers['OverviewHost']; + OverviewNetwork: SourceResolvers['OverviewNetwork']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/overview/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/overview/schema.gql.ts index 7ab4f9fdb18d6..ffb44dad1e3cf 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/overview/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/overview/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const overviewSchema = gql` type OverviewNetworkData { diff --git a/x-pack/legacy/plugins/siem/server/graphql/pinned_event/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/pinned_event/resolvers.ts index 49072f0279de8..77322120e265b 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/pinned_event/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/pinned_event/resolvers.ts @@ -4,26 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AppResolverOf } from '../../lib/framework'; import { MutationResolvers, QueryResolvers } from '../types'; import { PinnedEvent } from '../../lib/pinned_event/saved_object'; -export type QueryAllPinnedEventsByTimelineIdResolver = AppResolverOf< - QueryResolvers.GetAllPinnedEventsByTimelineIdResolver ->; - -export type MutationPinnedEventResolver = AppResolverOf< - MutationResolvers.PersistPinnedEventOnTimelineResolver ->; - -export type MutationDeletePinnedEventOnTimelineResolver = AppResolverOf< - MutationResolvers.DeletePinnedEventOnTimelineResolver ->; - -export type MutationDeleteAllPinnedEventsOnTimelineResolver = AppResolverOf< - MutationResolvers.DeleteAllPinnedEventsOnTimelineResolver ->; - interface TimelineResolversDeps { pinnedEvent: PinnedEvent; } @@ -32,12 +15,12 @@ export const createPinnedEventResolvers = ( libs: TimelineResolversDeps ): { Query: { - getAllPinnedEventsByTimelineId: QueryAllPinnedEventsByTimelineIdResolver; + getAllPinnedEventsByTimelineId: QueryResolvers['getAllPinnedEventsByTimelineId']; }; Mutation: { - persistPinnedEventOnTimeline: MutationPinnedEventResolver; - deletePinnedEventOnTimeline: MutationDeletePinnedEventOnTimelineResolver; - deleteAllPinnedEventsOnTimeline: MutationDeleteAllPinnedEventsOnTimelineResolver; + persistPinnedEventOnTimeline: MutationResolvers['persistPinnedEventOnTimeline']; + deletePinnedEventOnTimeline: MutationResolvers['deletePinnedEventOnTimeline']; + deleteAllPinnedEventsOnTimeline: MutationResolvers['deleteAllPinnedEventsOnTimeline']; }; } => ({ Query: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/pinned_event/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/pinned_event/schema.gql.ts index a797cd6720af2..1c139f12af8c1 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/pinned_event/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/pinned_event/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const pinnedEventSchema = gql` ######################### diff --git a/x-pack/legacy/plugins/siem/server/graphql/scalar_date/resolvers.test.ts b/x-pack/legacy/plugins/siem/server/graphql/scalar_date/resolvers.test.ts index 4779d77ed446e..a974c814cf0e4 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/scalar_date/resolvers.test.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/scalar_date/resolvers.test.ts @@ -38,7 +38,7 @@ describe('Test ScalarDate Resolver', () => { kind: 'IntValue', value: '1514782800000', }; - const date = dateScalar.parseLiteral(valueNode); + const date = dateScalar.parseLiteral(valueNode, {}); expect(date).toEqual(1514782800000); }); @@ -47,7 +47,7 @@ describe('Test ScalarDate Resolver', () => { kind: 'StringValue', value: '2018-01-01T05:00:00.000Z', }; - const date = dateScalar.parseLiteral(valueNode); + const date = dateScalar.parseLiteral(valueNode, {}); expect(date).toEqual('2018-01-01T05:00:00.000Z'); }); }); diff --git a/x-pack/legacy/plugins/siem/server/graphql/scalar_date/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/scalar_date/schema.gql.ts index c18f6ba98014b..e9b6864427930 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/scalar_date/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/scalar_date/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const dateSchema = gql` scalar Date diff --git a/x-pack/legacy/plugins/siem/server/graphql/scalar_to_any/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/scalar_to_any/schema.gql.ts index f0adde0945b5f..ead1865ec2d7b 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/scalar_to_any/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/scalar_to_any/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const toAnySchema = gql` scalar ToAny diff --git a/x-pack/legacy/plugins/siem/server/graphql/scalar_to_boolean_array/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/scalar_to_boolean_array/schema.gql.ts index a741adf3cd89f..48c7e2a02b967 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/scalar_to_boolean_array/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/scalar_to_boolean_array/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const toBooleanSchema = gql` scalar ToBooleanArray diff --git a/x-pack/legacy/plugins/siem/server/graphql/scalar_to_date_array/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/scalar_to_date_array/schema.gql.ts index e7ec88c0c12cb..afe16dc1f4987 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/scalar_to_date_array/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/scalar_to_date_array/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const toDateSchema = gql` scalar ToDateArray diff --git a/x-pack/legacy/plugins/siem/server/graphql/scalar_to_number_array/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/scalar_to_number_array/schema.gql.ts index 1fe85cacd0ea0..cecbb8b3a008b 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/scalar_to_number_array/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/scalar_to_number_array/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const toNumberSchema = gql` scalar ToNumberArray diff --git a/x-pack/legacy/plugins/siem/server/graphql/source_status/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/source_status/resolvers.ts index 24589822f0250..db18f4e7bcaa2 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/source_status/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/source_status/resolvers.ts @@ -5,28 +5,16 @@ */ import { SourceStatusResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { IndexFields } from '../../lib/index_fields'; import { SourceStatus } from '../../lib/source_status'; -import { QuerySourceResolver } from '../sources/resolvers'; - -export type SourceStatusIndicesExistResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -export type SourceStatusIndexFieldsResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export const createSourceStatusResolvers = (libs: { sourceStatus: SourceStatus; fields: IndexFields; }): { SourceStatus: { - indicesExist: SourceStatusIndicesExistResolver; - indexFields: SourceStatusIndexFieldsResolver; + indicesExist: SourceStatusResolvers['indicesExist']; + indexFields: SourceStatusResolvers['indexFields']; }; } => ({ SourceStatus: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/source_status/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/source_status/schema.gql.ts index e484b60f8f364..bce13eb1f8f88 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/source_status/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/source_status/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const sourceStatusSchema = gql` "A descriptor of a field in an index" diff --git a/x-pack/legacy/plugins/siem/server/graphql/sources/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/sources/resolvers.ts index f3cccfa15b566..c59888bf37938 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/sources/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/sources/resolvers.ts @@ -4,45 +4,41 @@ * you may not use this file except in compliance with the Elastic License. */ -import { QueryResolvers, SourceResolvers } from '../../graphql/types'; import { - AppResolverOf, - AppResolverWithFields, - ChildResolverOf, - ResultOf, -} from '../../lib/framework'; + ResolversParentTypes, + Resolver, + ResolversTypes, + Maybe, + QuerySourceArgs, + RequireFields, +} from '../../graphql/types'; import { SourceStatus } from '../../lib/source_status'; import { Sources } from '../../lib/sources'; +import { SiemContext } from '../../lib/types'; -export type QuerySourceResolver = AppResolverWithFields< - QueryResolvers.SourceResolver, - 'id' | 'configuration' ->; - -export type QueryAllSourcesResolver = AppResolverWithFields< - QueryResolvers.AllSourcesResolver, - 'id' | 'configuration' ->; - -export type SourceStatusResolver = ChildResolverOf< - AppResolverOf>>, - QuerySourceResolver ->; - -export interface SourcesResolversDeps { +export const createSourcesResolvers = (libs: { sources: Sources; sourceStatus: SourceStatus; -} - -export const createSourcesResolvers = ( - libs: SourcesResolversDeps -): { +}): { Query: { - source: QuerySourceResolver; - allSources: QueryAllSourcesResolver; + source: Resolver< + Pick, + ResolversParentTypes['Source'], + SiemContext, + RequireFields + >; + allSources: Resolver< + Array>, + ResolversParentTypes['Source'], + SiemContext + >; }; Source: { - status: SourceStatusResolver; + status: Resolver< + Maybe, + ResolversParentTypes['SourceStatus'], + SiemContext + >; }; } => ({ Query: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/sources/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/sources/schema.gql.ts index f213b9db17c69..b60da4d2e95cb 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/sources/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/sources/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const sourcesSchema = gql` extend type Query { diff --git a/x-pack/legacy/plugins/siem/server/graphql/timeline/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/timeline/resolvers.ts index a33751179e93a..04edf0b7b62f9 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/timeline/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/timeline/resolvers.ts @@ -4,27 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AppResolverWithFields, AppResolverOf } from '../../lib/framework'; import { MutationResolvers, QueryResolvers } from '../types'; import { Timeline } from '../../lib/timeline/saved_object'; -export type QueryTimelineResolver = AppResolverOf; - -export type QueryAllTimelineResolver = AppResolverWithFields< - QueryResolvers.GetAllTimelineResolver, - 'totalCount' | 'timeline' ->; - -export type MutationTimelineResolver = AppResolverOf< - MutationResolvers.PersistTimelineResolver ->; - -export type MutationDeleteTimelineResolver = AppResolverOf< - MutationResolvers.DeleteTimelineResolver ->; - -export type MutationFavoriteResolver = AppResolverOf; - interface TimelineResolversDeps { timeline: Timeline; } @@ -33,13 +15,13 @@ export const createTimelineResolvers = ( libs: TimelineResolversDeps ): { Query: { - getOneTimeline: QueryTimelineResolver; - getAllTimeline: QueryAllTimelineResolver; + getOneTimeline: QueryResolvers['getOneTimeline']; + getAllTimeline: QueryResolvers['getAllTimeline']; }; Mutation: { - deleteTimeline: MutationDeleteTimelineResolver; - persistTimeline: MutationTimelineResolver; - persistFavorite: MutationFavoriteResolver; + deleteTimeline: MutationResolvers['deleteTimeline']; + persistTimeline: MutationResolvers['persistTimeline']; + persistFavorite: MutationResolvers['persistFavorite']; }; } => ({ Query: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/timeline/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/timeline/schema.gql.ts index 8b24cea0d6af9..aae73489e8170 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/timeline/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/timeline/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; const columnHeader = ` aggregatable: Boolean diff --git a/x-pack/legacy/plugins/siem/server/graphql/tls/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/tls/resolvers.ts index bfa3fddc3c8a5..72cf76c0603b7 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/tls/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/tls/resolvers.ts @@ -5,15 +5,8 @@ */ import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { TLS, TlsRequestOptions } from '../../lib/tls'; import { createOptionsPaginated } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -export type QueryTlsResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export interface TlsResolversDeps { tls: TLS; @@ -23,7 +16,7 @@ export const createTlsResolvers = ( libs: TlsResolversDeps ): { Source: { - Tls: QueryTlsResolver; + Tls: SourceResolvers['Tls']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/tls/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/tls/schema.gql.ts index 301960cea33ef..fda139109f275 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/tls/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/tls/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const tlsSchema = gql` enum TlsFields { diff --git a/x-pack/legacy/plugins/siem/server/graphql/types.ts b/x-pack/legacy/plugins/siem/server/graphql/types.ts index f42da48f2c1da..19b57c3519201 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/types.ts @@ -1,9189 +1,3876 @@ -/* tslint:disable */ -/* eslint-disable */ /* * 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. - */ +*/ + +/* tslint:disable */ +/* eslint-disable */ import { SiemContext } from '../lib/types'; +import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql'; export type Maybe = T | null; - -export interface PageInfoNote { - pageIndex: number; - - pageSize: number; -} - -export interface SortNote { - sortField: SortFieldNote; - - sortOrder: Direction; -} - -export interface TimerangeInput { - /** The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan. */ - interval: string; - /** The end of the timerange */ - to: number; - /** The beginning of the timerange */ - from: number; -} - -export interface PaginationInputPaginated { - /** The activePage parameter defines the page of results you want to fetch */ - activePage: number; - /** The cursorStart parameter defines the start of the results to be displayed */ - cursorStart: number; - /** The fakePossibleCount parameter determines the total count in order to show 5 additional pages */ - fakePossibleCount: number; - /** The querySize parameter is the number of items to be returned */ - querySize: number; -} - -export interface PaginationInput { - /** The limit parameter allows you to configure the maximum amount of items to be returned */ - limit: number; - /** The cursor parameter defines the next result you want to fetch */ - cursor?: Maybe; - /** The tiebreaker parameter allow to be more precise to fetch the next item */ - tiebreaker?: Maybe; -} - -export interface SortField { - sortFieldId: string; - - direction: Direction; -} - -export interface LastTimeDetails { - hostName?: Maybe; - - ip?: Maybe; -} - -export interface HostsSortField { - field: HostsFields; - - direction: Direction; -} - -export interface UsersSortField { - field: UsersFields; - - direction: Direction; -} - -export interface NetworkTopTablesSortField { - field: NetworkTopTablesFields; - - direction: Direction; -} - -export interface NetworkDnsSortField { - field: NetworkDnsFields; - - direction: Direction; -} - -export interface NetworkHttpSortField { - direction: Direction; -} - -export interface TlsSortField { - field: TlsFields; - - direction: Direction; -} - -export interface PageInfoTimeline { - pageIndex: number; - - pageSize: number; -} - -export interface SortTimeline { - sortField: SortFieldTimeline; - - sortOrder: Direction; -} - -export interface NoteInput { - eventId?: Maybe; - - note?: Maybe; - - timelineId?: Maybe; -} - -export interface TimelineInput { - columns?: Maybe; - - dataProviders?: Maybe; - - description?: Maybe; - - eventType?: Maybe; - - filters?: Maybe; - - kqlMode?: Maybe; - - kqlQuery?: Maybe; - - title?: Maybe; - - dateRange?: Maybe; - - savedQueryId?: Maybe; - - sort?: Maybe; -} - -export interface ColumnHeaderInput { - aggregatable?: Maybe; - - category?: Maybe; - - columnHeaderType?: Maybe; - - description?: Maybe; - - example?: Maybe; - - indexes?: Maybe; - - id?: Maybe; - - name?: Maybe; - - placeholder?: Maybe; - - searchable?: Maybe; - - type?: Maybe; -} - -export interface DataProviderInput { - id?: Maybe; - - name?: Maybe; - - enabled?: Maybe; - - excluded?: Maybe; - - kqlQuery?: Maybe; - - queryMatch?: Maybe; - - and?: Maybe; -} - -export interface QueryMatchInput { - field?: Maybe; - - displayField?: Maybe; - - value?: Maybe; - - displayValue?: Maybe; - - operator?: Maybe; -} - -export interface FilterTimelineInput { - exists?: Maybe; - - meta?: Maybe; - - match_all?: Maybe; - - missing?: Maybe; - - query?: Maybe; - - range?: Maybe; - - script?: Maybe; -} - -export interface FilterMetaTimelineInput { - alias?: Maybe; - - controlledBy?: Maybe; - - disabled?: Maybe; - - field?: Maybe; - - formattedValue?: Maybe; - - index?: Maybe; - - key?: Maybe; - - negate?: Maybe; - - params?: Maybe; - - type?: Maybe; - - value?: Maybe; -} - -export interface SerializedFilterQueryInput { - filterQuery?: Maybe; -} - -export interface SerializedKueryQueryInput { - kuery?: Maybe; - - serializedQuery?: Maybe; -} - -export interface KueryFilterQueryInput { - kind?: Maybe; - - expression?: Maybe; -} - -export interface DateRangePickerInput { - start?: Maybe; - - end?: Maybe; -} - -export interface SortTimelineInput { - columnId?: Maybe; - - sortDirection?: Maybe; -} - -export interface FavoriteTimelineInput { - fullName?: Maybe; - - userName?: Maybe; - - favoriteDate?: Maybe; -} - -export enum SortFieldNote { - updatedBy = 'updatedBy', - updated = 'updated', -} - -export enum Direction { - asc = 'asc', - desc = 'desc', -} - -export enum LastEventIndexKey { - hostDetails = 'hostDetails', - hosts = 'hosts', - ipDetails = 'ipDetails', - network = 'network', -} - -export enum HostsFields { - hostName = 'hostName', - lastSeen = 'lastSeen', -} - -export enum UsersFields { - name = 'name', - count = 'count', -} - -export enum FlowTarget { - client = 'client', - destination = 'destination', - server = 'server', - source = 'source', +export type RequireFields = { [X in Exclude]?: T[X] } & { [P in K]-?: NonNullable }; + +/** All built-in and custom scalars, mapped to their actual values */ +export interface Scalars { + ID: string, + String: string, + Boolean: boolean, + Int: number, + Float: number, + ToStringArray: string[] | string, + Date: string, + ToNumberArray: number[] | number, + ToDateArray: string[] | string, + ToBooleanArray: boolean[] | boolean, + ToAny: any, + EsValue: any, } -export enum HistogramType { - authentications = 'authentications', - anomalies = 'anomalies', - events = 'events', - alerts = 'alerts', - dns = 'dns', +export interface AuditdData { + acct?: Maybe, + terminal?: Maybe, + op?: Maybe, } -export enum FlowTargetSourceDest { - destination = 'destination', - source = 'source', +export interface AuditdEcsFields { + result?: Maybe, + session?: Maybe, + data?: Maybe, + summary?: Maybe, + sequence?: Maybe, } -export enum NetworkTopTablesFields { - bytes_in = 'bytes_in', - bytes_out = 'bytes_out', - flows = 'flows', - destination_ips = 'destination_ips', - source_ips = 'source_ips', +export interface AuditEcsFields { + package?: Maybe, } -export enum NetworkDnsFields { - dnsName = 'dnsName', - queryCount = 'queryCount', - uniqueDomains = 'uniqueDomains', - dnsBytesIn = 'dnsBytesIn', - dnsBytesOut = 'dnsBytesOut', +export interface AuthEcsFields { + ssh?: Maybe, } -export enum TlsFields { - _id = '_id', +export interface AuthenticationItem { + _id: Scalars['String'], + failures: Scalars['Float'], + successes: Scalars['Float'], + user: UserEcsFields, + lastSuccess?: Maybe, + lastFailure?: Maybe, } -export enum SortFieldTimeline { - title = 'title', - description = 'description', - updated = 'updated', - created = 'created', +export interface AuthenticationsData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, } -export enum NetworkDirectionEcs { - inbound = 'inbound', - outbound = 'outbound', - internal = 'internal', - external = 'external', - incoming = 'incoming', - outgoing = 'outgoing', - listening = 'listening', - unknown = 'unknown', +export interface AuthenticationsEdges { + node: AuthenticationItem, + cursor: CursorType, } -export enum NetworkHttpFields { - domains = 'domains', - lastHost = 'lastHost', - lastSourceIp = 'lastSourceIp', - methods = 'methods', - path = 'path', - requestCount = 'requestCount', - statuses = 'statuses', +export interface AutonomousSystem { + number?: Maybe, + organization?: Maybe, } -export enum FlowDirection { - uniDirectional = 'uniDirectional', - biDirectional = 'biDirectional', +export interface AutonomousSystemItem { + name?: Maybe, + number?: Maybe, } -export type ToStringArray = string[] | string; - -export type Date = string; - -export type ToNumberArray = number[] | number; - -export type ToDateArray = string[] | string; - -export type ToBooleanArray = boolean[] | boolean; - -export type ToAny = any; - -export type EsValue = any; - -// ==================================================== -// Scalars -// ==================================================== - -// ==================================================== -// Types -// ==================================================== - -export interface Query { - getNote: NoteResult; - - getNotesByTimelineId: NoteResult[]; - - getNotesByEventId: NoteResult[]; - - getAllNotes: ResponseNotes; - - getAllPinnedEventsByTimelineId: PinnedEvent[]; - /** Get a security data source by id */ - source: Source; - /** Get a list of all security data sources */ - allSources: Source[]; - - getOneTimeline: TimelineResult; - - getAllTimeline: ResponseTimelines; -} - -export interface NoteResult { - eventId?: Maybe; - - note?: Maybe; - - timelineId?: Maybe; - - noteId: string; - - created?: Maybe; - - createdBy?: Maybe; - - timelineVersion?: Maybe; - - updated?: Maybe; - - updatedBy?: Maybe; - - version?: Maybe; -} - -export interface ResponseNotes { - notes: NoteResult[]; - - totalCount?: Maybe; -} - -export interface PinnedEvent { - code?: Maybe; - - message?: Maybe; - - pinnedEventId: string; - - eventId?: Maybe; - - timelineId?: Maybe; - - timelineVersion?: Maybe; - - created?: Maybe; - - createdBy?: Maybe; - - updated?: Maybe; - - updatedBy?: Maybe; - - version?: Maybe; -} - -export interface Source { - /** The id of the source */ - id: string; - /** The raw configuration of the source */ - configuration: SourceConfiguration; - /** The status of the source */ - status: SourceStatus; - /** Gets Authentication success and failures based on a timerange */ - Authentications: AuthenticationsData; - - Timeline: TimelineData; - - TimelineDetails: TimelineDetailsData; - - LastEventTime: LastEventTimeData; - /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ - Hosts: HostsData; - - HostOverview: HostItem; - - HostFirstLastSeen: FirstLastSeenHost; - - IpOverview?: Maybe; - - Users: UsersData; - - KpiNetwork?: Maybe; - - KpiHosts: KpiHostsData; - - KpiHostDetails: KpiHostDetailsData; - - MatrixHistogram: MatrixHistogramOverTimeData; - - NetworkTopCountries: NetworkTopCountriesData; - - NetworkTopNFlow: NetworkTopNFlowData; - - NetworkDns: NetworkDnsData; - - NetworkDnsHistogram: NetworkDsOverTimeData; - - NetworkHttp: NetworkHttpData; - - OverviewNetwork?: Maybe; - - OverviewHost?: Maybe; - - Tls: TlsData; - /** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */ - UncommonProcesses: UncommonProcessesData; - /** Just a simple example to get the app name */ - whoAmI?: Maybe; -} - -/** A set of configuration options for a security data source */ -export interface SourceConfiguration { - /** The field mapping to use for this source */ - fields: SourceFields; -} - -/** A mapping of semantic fields to their document counterparts */ -export interface SourceFields { - /** The field to identify a container by */ - container: string; - /** The fields to identify a host by */ - host: string; - /** The fields that may contain the log event message. The first field found win. */ - message: string[]; - /** The field to identify a pod by */ - pod: string; - /** The field to use as a tiebreaker for log events that have identical timestamps */ - tiebreaker: string; - /** The field to use as a timestamp for metrics and logs */ - timestamp: string; -} - -/** The status of an infrastructure data source */ -export interface SourceStatus { - /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ - indicesExist: boolean; - /** The list of fields defined in the index mappings */ - indexFields: IndexField[]; -} - -/** A descriptor of a field in an index */ -export interface IndexField { - /** Where the field belong */ - category: string; - /** Example of field's value */ - example?: Maybe; - /** whether the field's belong to an alias index */ - indexes: (Maybe)[]; - /** The name of the field */ - name: string; - /** The type of the field's values as recognized by Kibana */ - type: string; - /** Whether the field's values can be efficiently searched for */ - searchable: boolean; - /** Whether the field's values can be aggregated */ - aggregatable: boolean; - /** Description of the field */ - description?: Maybe; - - format?: Maybe; -} - -export interface AuthenticationsData { - edges: AuthenticationsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface AuthenticationsEdges { - node: AuthenticationItem; - - cursor: CursorType; -} - -export interface AuthenticationItem { - _id: string; - - failures: number; - - successes: number; - - user: UserEcsFields; - - lastSuccess?: Maybe; - - lastFailure?: Maybe; -} - -export interface UserEcsFields { - domain?: Maybe; - - id?: Maybe; - - name?: Maybe; - - full_name?: Maybe; - - email?: Maybe; - - hash?: Maybe; - - group?: Maybe; -} - -export interface LastSourceHost { - timestamp?: Maybe; - - source?: Maybe; - - host?: Maybe; -} - -export interface SourceEcsFields { - bytes?: Maybe; - - ip?: Maybe; - - port?: Maybe; - - domain?: Maybe; - - geo?: Maybe; - - packets?: Maybe; -} - -export interface GeoEcsFields { - city_name?: Maybe; - - continent_name?: Maybe; - - country_iso_code?: Maybe; - - country_name?: Maybe; - - location?: Maybe; - - region_iso_code?: Maybe; - - region_name?: Maybe; -} - -export interface Location { - lon?: Maybe; - - lat?: Maybe; -} - -export interface HostEcsFields { - architecture?: Maybe; - - id?: Maybe; - - ip?: Maybe; - - mac?: Maybe; - - name?: Maybe; - - os?: Maybe; - - type?: Maybe; -} - -export interface OsEcsFields { - platform?: Maybe; - - name?: Maybe; - - full?: Maybe; - - family?: Maybe; - - version?: Maybe; - - kernel?: Maybe; -} - -export interface CursorType { - value?: Maybe; - - tiebreaker?: Maybe; -} - -export interface PageInfoPaginated { - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; -} - -export interface Inspect { - dsl: string[]; - - response: string[]; -} - -export interface TimelineData { - edges: TimelineEdges[]; - - totalCount: number; - - pageInfo: PageInfo; - - inspect?: Maybe; -} - -export interface TimelineEdges { - node: TimelineItem; - - cursor: CursorType; -} - -export interface TimelineItem { - _id: string; - - _index?: Maybe; - - data: TimelineNonEcsData[]; - - ecs: Ecs; -} - -export interface TimelineNonEcsData { - field: string; - - value?: Maybe; -} - -export interface Ecs { - _id: string; - - _index?: Maybe; - - auditd?: Maybe; - - destination?: Maybe; - - dns?: Maybe; - - endgame?: Maybe; - - event?: Maybe; - - geo?: Maybe; - - host?: Maybe; - - network?: Maybe; - - rule?: Maybe; - - signal?: Maybe; - - source?: Maybe; - - suricata?: Maybe; - - tls?: Maybe; - - zeek?: Maybe; - - http?: Maybe; - - url?: Maybe; - - timestamp?: Maybe; - - message?: Maybe; - - user?: Maybe; - - winlog?: Maybe; - - process?: Maybe; - - file?: Maybe; - - system?: Maybe; -} - -export interface AuditdEcsFields { - result?: Maybe; - - session?: Maybe; - - data?: Maybe; - - summary?: Maybe; - - sequence?: Maybe; -} - -export interface AuditdData { - acct?: Maybe; - - terminal?: Maybe; - - op?: Maybe; -} - -export interface Summary { - actor?: Maybe; - - object?: Maybe; - - how?: Maybe; - - message_type?: Maybe; - - sequence?: Maybe; -} - -export interface PrimarySecondary { - primary?: Maybe; - - secondary?: Maybe; - - type?: Maybe; -} - -export interface DestinationEcsFields { - bytes?: Maybe; - - ip?: Maybe; - - port?: Maybe; - - domain?: Maybe; - - geo?: Maybe; - - packets?: Maybe; -} - -export interface DnsEcsFields { - question?: Maybe; - - resolved_ip?: Maybe; - - response_code?: Maybe; -} - -export interface DnsQuestionData { - name?: Maybe; - - type?: Maybe; -} - -export interface EndgameEcsFields { - exit_code?: Maybe; - - file_name?: Maybe; - - file_path?: Maybe; - - logon_type?: Maybe; - - parent_process_name?: Maybe; - - pid?: Maybe; - - process_name?: Maybe; - - subject_domain_name?: Maybe; - - subject_logon_id?: Maybe; - - subject_user_name?: Maybe; - - target_domain_name?: Maybe; - - target_logon_id?: Maybe; - - target_user_name?: Maybe; -} - -export interface EventEcsFields { - action?: Maybe; - - category?: Maybe; - - code?: Maybe; - - created?: Maybe; - - dataset?: Maybe; - - duration?: Maybe; - - end?: Maybe; - - hash?: Maybe; - - id?: Maybe; - - kind?: Maybe; - - module?: Maybe; - - original?: Maybe; - - outcome?: Maybe; - - risk_score?: Maybe; - - risk_score_norm?: Maybe; - - severity?: Maybe; - - start?: Maybe; - - timezone?: Maybe; - - type?: Maybe; -} - -export interface NetworkEcsField { - bytes?: Maybe; - - community_id?: Maybe; - - direction?: Maybe; - - packets?: Maybe; - - protocol?: Maybe; - - transport?: Maybe; -} - -export interface RuleEcsField { - reference?: Maybe; -} - -export interface SignalField { - rule?: Maybe; - - original_time?: Maybe; -} - -export interface RuleField { - id?: Maybe; - - rule_id?: Maybe; - - false_positives: string[]; - - saved_id?: Maybe; - - timeline_id?: Maybe; - - timeline_title?: Maybe; - - max_signals?: Maybe; - - risk_score?: Maybe; - - output_index?: Maybe; - - description?: Maybe; - - from?: Maybe; - - immutable?: Maybe; - - index?: Maybe; - - interval?: Maybe; - - language?: Maybe; - - query?: Maybe; - - references?: Maybe; - - severity?: Maybe; - - tags?: Maybe; - - threat?: Maybe; - - type?: Maybe; - - size?: Maybe; - - to?: Maybe; - - enabled?: Maybe; - - filters?: Maybe; - - created_at?: Maybe; - - updated_at?: Maybe; - - created_by?: Maybe; - - updated_by?: Maybe; - - version?: Maybe; -} - -export interface SuricataEcsFields { - eve?: Maybe; -} - -export interface SuricataEveData { - alert?: Maybe; - - flow_id?: Maybe; - - proto?: Maybe; -} - -export interface SuricataAlertData { - signature?: Maybe; - - signature_id?: Maybe; -} - -export interface TlsEcsFields { - client_certificate?: Maybe; - - fingerprints?: Maybe; - - server_certificate?: Maybe; -} - -export interface TlsClientCertificateData { - fingerprint?: Maybe; -} - -export interface FingerprintData { - sha1?: Maybe; -} - -export interface TlsFingerprintsData { - ja3?: Maybe; -} - -export interface TlsJa3Data { - hash?: Maybe; -} - -export interface TlsServerCertificateData { - fingerprint?: Maybe; -} - -export interface ZeekEcsFields { - session_id?: Maybe; - - connection?: Maybe; - - notice?: Maybe; - - dns?: Maybe; - - http?: Maybe; - - files?: Maybe; - - ssl?: Maybe; -} - -export interface ZeekConnectionData { - local_resp?: Maybe; - - local_orig?: Maybe; - - missed_bytes?: Maybe; - - state?: Maybe; - - history?: Maybe; -} - -export interface ZeekNoticeData { - suppress_for?: Maybe; - - msg?: Maybe; - - note?: Maybe; - - sub?: Maybe; - - dst?: Maybe; - - dropped?: Maybe; - - peer_descr?: Maybe; -} - -export interface ZeekDnsData { - AA?: Maybe; - - qclass_name?: Maybe; - - RD?: Maybe; - - qtype_name?: Maybe; - - rejected?: Maybe; - - qtype?: Maybe; - - query?: Maybe; - - trans_id?: Maybe; - - qclass?: Maybe; - - RA?: Maybe; - - TC?: Maybe; -} - -export interface ZeekHttpData { - resp_mime_types?: Maybe; - - trans_depth?: Maybe; - - status_msg?: Maybe; - - resp_fuids?: Maybe; - - tags?: Maybe; -} - -export interface ZeekFileData { - session_ids?: Maybe; - - timedout?: Maybe; - - local_orig?: Maybe; - - tx_host?: Maybe; - - source?: Maybe; - - is_orig?: Maybe; - - overflow_bytes?: Maybe; - - sha1?: Maybe; - - duration?: Maybe; - - depth?: Maybe; - - analyzers?: Maybe; - - mime_type?: Maybe; - - rx_host?: Maybe; - - total_bytes?: Maybe; - - fuid?: Maybe; - - seen_bytes?: Maybe; - - missing_bytes?: Maybe; - - md5?: Maybe; -} - -export interface ZeekSslData { - cipher?: Maybe; - - established?: Maybe; - - resumed?: Maybe; - - version?: Maybe; -} - -export interface HttpEcsFields { - version?: Maybe; - - request?: Maybe; - - response?: Maybe; -} - -export interface HttpRequestData { - method?: Maybe; - - body?: Maybe; - - referrer?: Maybe; - - bytes?: Maybe; -} - -export interface HttpBodyData { - content?: Maybe; - - bytes?: Maybe; -} - -export interface HttpResponseData { - status_code?: Maybe; - - body?: Maybe; - - bytes?: Maybe; -} - -export interface UrlEcsFields { - domain?: Maybe; - - original?: Maybe; - - username?: Maybe; - - password?: Maybe; -} - -export interface WinlogEcsFields { - event_id?: Maybe; -} - -export interface ProcessEcsFields { - hash?: Maybe; - - pid?: Maybe; - - name?: Maybe; - - ppid?: Maybe; - - args?: Maybe; - - executable?: Maybe; - - title?: Maybe; - - thread?: Maybe; - - working_directory?: Maybe; -} - -export interface ProcessHashData { - md5?: Maybe; - - sha1?: Maybe; - - sha256?: Maybe; -} - -export interface Thread { - id?: Maybe; - - start?: Maybe; -} - -export interface FileFields { - name?: Maybe; - - path?: Maybe; - - target_path?: Maybe; - - extension?: Maybe; - - type?: Maybe; - - device?: Maybe; - - inode?: Maybe; - - uid?: Maybe; - - owner?: Maybe; - - gid?: Maybe; - - group?: Maybe; - - mode?: Maybe; - - size?: Maybe; - - mtime?: Maybe; - - ctime?: Maybe; -} - -export interface SystemEcsField { - audit?: Maybe; - - auth?: Maybe; -} - -export interface AuditEcsFields { - package?: Maybe; -} - -export interface PackageEcsFields { - arch?: Maybe; - - entity_id?: Maybe; - - name?: Maybe; - - size?: Maybe; - - summary?: Maybe; - - version?: Maybe; -} - -export interface AuthEcsFields { - ssh?: Maybe; -} - -export interface SshEcsFields { - method?: Maybe; - - signature?: Maybe; -} - -export interface PageInfo { - endCursor?: Maybe; - - hasNextPage?: Maybe; -} - -export interface TimelineDetailsData { - data?: Maybe; - - inspect?: Maybe; -} - -export interface DetailItem { - field: string; - - values?: Maybe; - - originalValue?: Maybe; -} - -export interface LastEventTimeData { - lastSeen?: Maybe; - - inspect?: Maybe; -} - -export interface HostsData { - edges: HostsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface HostsEdges { - node: HostItem; - - cursor: CursorType; -} - -export interface HostItem { - _id?: Maybe; - - lastSeen?: Maybe; - - host?: Maybe; - - cloud?: Maybe; - - inspect?: Maybe; -} - -export interface CloudFields { - instance?: Maybe; - - machine?: Maybe; - - provider?: Maybe<(Maybe)[]>; - - region?: Maybe<(Maybe)[]>; -} - -export interface CloudInstance { - id?: Maybe<(Maybe)[]>; -} - -export interface CloudMachine { - type?: Maybe<(Maybe)[]>; -} - -export interface FirstLastSeenHost { - inspect?: Maybe; - - firstSeen?: Maybe; - - lastSeen?: Maybe; -} - -export interface IpOverviewData { - client?: Maybe; - - destination?: Maybe; - - host: HostEcsFields; - - server?: Maybe; - - source?: Maybe; - - inspect?: Maybe; -} - -export interface Overview { - firstSeen?: Maybe; - - lastSeen?: Maybe; - - autonomousSystem: AutonomousSystem; - - geo: GeoEcsFields; -} - -export interface AutonomousSystem { - number?: Maybe; - - organization?: Maybe; -} - -export interface AutonomousSystemOrganization { - name?: Maybe; -} - -export interface UsersData { - edges: UsersEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface UsersEdges { - node: UsersNode; - - cursor: CursorType; -} - -export interface UsersNode { - _id?: Maybe; - - timestamp?: Maybe; - - user?: Maybe; -} - -export interface UsersItem { - name?: Maybe; - - id?: Maybe; - - groupId?: Maybe; - - groupName?: Maybe; - - count?: Maybe; -} - -export interface KpiNetworkData { - networkEvents?: Maybe; - - uniqueFlowId?: Maybe; - - uniqueSourcePrivateIps?: Maybe; - - uniqueSourcePrivateIpsHistogram?: Maybe; - - uniqueDestinationPrivateIps?: Maybe; - - uniqueDestinationPrivateIpsHistogram?: Maybe; - - dnsQueries?: Maybe; - - tlsHandshakes?: Maybe; - - inspect?: Maybe; -} - -export interface KpiNetworkHistogramData { - x?: Maybe; - - y?: Maybe; -} - -export interface KpiHostsData { - hosts?: Maybe; - - hostsHistogram?: Maybe; - - authSuccess?: Maybe; - - authSuccessHistogram?: Maybe; - - authFailure?: Maybe; - - authFailureHistogram?: Maybe; - - uniqueSourceIps?: Maybe; - - uniqueSourceIpsHistogram?: Maybe; - - uniqueDestinationIps?: Maybe; - - uniqueDestinationIpsHistogram?: Maybe; - - inspect?: Maybe; -} - -export interface KpiHostHistogramData { - x?: Maybe; - - y?: Maybe; -} - -export interface KpiHostDetailsData { - authSuccess?: Maybe; - - authSuccessHistogram?: Maybe; - - authFailure?: Maybe; - - authFailureHistogram?: Maybe; - - uniqueSourceIps?: Maybe; - - uniqueSourceIpsHistogram?: Maybe; - - uniqueDestinationIps?: Maybe; - - uniqueDestinationIpsHistogram?: Maybe; - - inspect?: Maybe; -} - -export interface MatrixHistogramOverTimeData { - inspect?: Maybe; - - matrixHistogramData: MatrixOverTimeHistogramData[]; - - totalCount: number; -} - -export interface MatrixOverTimeHistogramData { - x?: Maybe; - - y?: Maybe; - - g?: Maybe; -} - -export interface NetworkTopCountriesData { - edges: NetworkTopCountriesEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface NetworkTopCountriesEdges { - node: NetworkTopCountriesItem; - - cursor: CursorType; -} - -export interface NetworkTopCountriesItem { - _id?: Maybe; - - source?: Maybe; - - destination?: Maybe; - - network?: Maybe; -} - -export interface TopCountriesItemSource { - country?: Maybe; - - destination_ips?: Maybe; - - flows?: Maybe; - - location?: Maybe; - - source_ips?: Maybe; -} - -export interface GeoItem { - geo?: Maybe; - - flowTarget?: Maybe; -} - -export interface TopCountriesItemDestination { - country?: Maybe; - - destination_ips?: Maybe; - - flows?: Maybe; - - location?: Maybe; - - source_ips?: Maybe; -} - -export interface TopNetworkTablesEcsField { - bytes_in?: Maybe; - - bytes_out?: Maybe; -} - -export interface NetworkTopNFlowData { - edges: NetworkTopNFlowEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface NetworkTopNFlowEdges { - node: NetworkTopNFlowItem; - - cursor: CursorType; -} - -export interface NetworkTopNFlowItem { - _id?: Maybe; - - source?: Maybe; - - destination?: Maybe; - - network?: Maybe; -} - -export interface TopNFlowItemSource { - autonomous_system?: Maybe; - - domain?: Maybe; - - ip?: Maybe; - - location?: Maybe; - - flows?: Maybe; - - destination_ips?: Maybe; -} - -export interface AutonomousSystemItem { - name?: Maybe; - - number?: Maybe; -} - -export interface TopNFlowItemDestination { - autonomous_system?: Maybe; - - domain?: Maybe; - - ip?: Maybe; - - location?: Maybe; - - flows?: Maybe; - - source_ips?: Maybe; -} - -export interface NetworkDnsData { - edges: NetworkDnsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; - - histogram?: Maybe; -} - -export interface NetworkDnsEdges { - node: NetworkDnsItem; - - cursor: CursorType; -} - -export interface NetworkDnsItem { - _id?: Maybe; - - dnsBytesIn?: Maybe; - - dnsBytesOut?: Maybe; - - dnsName?: Maybe; - - queryCount?: Maybe; - - uniqueDomains?: Maybe; -} - -export interface MatrixOverOrdinalHistogramData { - x: string; - - y: number; - - g: string; -} - -export interface NetworkDsOverTimeData { - inspect?: Maybe; - - matrixHistogramData: MatrixOverTimeHistogramData[]; - - totalCount: number; -} - -export interface NetworkHttpData { - edges: NetworkHttpEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface NetworkHttpEdges { - node: NetworkHttpItem; - - cursor: CursorType; -} - -export interface NetworkHttpItem { - _id?: Maybe; - - domains: string[]; - - lastHost?: Maybe; - - lastSourceIp?: Maybe; - - methods: string[]; - - path?: Maybe; - - requestCount?: Maybe; - - statuses: string[]; -} - -export interface OverviewNetworkData { - auditbeatSocket?: Maybe; - - filebeatCisco?: Maybe; - - filebeatNetflow?: Maybe; - - filebeatPanw?: Maybe; - - filebeatSuricata?: Maybe; - - filebeatZeek?: Maybe; - - packetbeatDNS?: Maybe; - - packetbeatFlow?: Maybe; - - packetbeatTLS?: Maybe; - - inspect?: Maybe; -} - -export interface OverviewHostData { - auditbeatAuditd?: Maybe; - - auditbeatFIM?: Maybe; - - auditbeatLogin?: Maybe; - - auditbeatPackage?: Maybe; - - auditbeatProcess?: Maybe; - - auditbeatUser?: Maybe; - - endgameDns?: Maybe; - - endgameFile?: Maybe; - - endgameImageLoad?: Maybe; - - endgameNetwork?: Maybe; - - endgameProcess?: Maybe; - - endgameRegistry?: Maybe; - - endgameSecurity?: Maybe; - - filebeatSystemModule?: Maybe; - - winlogbeatSecurity?: Maybe; - - winlogbeatMWSysmonOperational?: Maybe; - - inspect?: Maybe; -} - -export interface TlsData { - edges: TlsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface TlsEdges { - node: TlsNode; - - cursor: CursorType; -} - -export interface TlsNode { - _id?: Maybe; - - timestamp?: Maybe; - - alternativeNames?: Maybe; - - notAfter?: Maybe; - - commonNames?: Maybe; - - ja3?: Maybe; - - issuerNames?: Maybe; -} - -export interface UncommonProcessesData { - edges: UncommonProcessesEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface UncommonProcessesEdges { - node: UncommonProcessItem; - - cursor: CursorType; -} - -export interface UncommonProcessItem { - _id: string; - - instances: number; - - process: ProcessEcsFields; - - hosts: HostEcsFields[]; - - user?: Maybe; -} - -export interface SayMyName { - /** The id of the source */ - appName: string; -} - -export interface TimelineResult { - columns?: Maybe; - - created?: Maybe; - - createdBy?: Maybe; - - dataProviders?: Maybe; - - dateRange?: Maybe; - - description?: Maybe; - - eventIdToNoteIds?: Maybe; - - eventType?: Maybe; - - favorite?: Maybe; - - filters?: Maybe; - - kqlMode?: Maybe; - - kqlQuery?: Maybe; - - notes?: Maybe; - - noteIds?: Maybe; - - pinnedEventIds?: Maybe; - - pinnedEventsSaveObject?: Maybe; - - savedQueryId?: Maybe; - - savedObjectId: string; - - sort?: Maybe; - - title?: Maybe; - - updated?: Maybe; - - updatedBy?: Maybe; - - version: string; -} - -export interface ColumnHeaderResult { - aggregatable?: Maybe; - - category?: Maybe; - - columnHeaderType?: Maybe; - - description?: Maybe; - - example?: Maybe; - - indexes?: Maybe; - - id?: Maybe; - - name?: Maybe; - - placeholder?: Maybe; - - searchable?: Maybe; - - type?: Maybe; -} - -export interface DataProviderResult { - id?: Maybe; - - name?: Maybe; - - enabled?: Maybe; - - excluded?: Maybe; - - kqlQuery?: Maybe; - - queryMatch?: Maybe; - - and?: Maybe; -} - -export interface QueryMatchResult { - field?: Maybe; - - displayField?: Maybe; - - value?: Maybe; - - displayValue?: Maybe; - - operator?: Maybe; -} - -export interface DateRangePickerResult { - start?: Maybe; - - end?: Maybe; -} - -export interface FavoriteTimelineResult { - fullName?: Maybe; - - userName?: Maybe; - - favoriteDate?: Maybe; -} - -export interface FilterTimelineResult { - exists?: Maybe; - - meta?: Maybe; - - match_all?: Maybe; - - missing?: Maybe; - - query?: Maybe; - - range?: Maybe; - - script?: Maybe; -} - -export interface FilterMetaTimelineResult { - alias?: Maybe; - - controlledBy?: Maybe; - - disabled?: Maybe; - - field?: Maybe; - - formattedValue?: Maybe; - - index?: Maybe; - - key?: Maybe; - - negate?: Maybe; - - params?: Maybe; - - type?: Maybe; +export interface AutonomousSystemOrganization { + name?: Maybe, +} - value?: Maybe; +export interface CloudFields { + instance?: Maybe, + machine?: Maybe, + provider?: Maybe>>, + region?: Maybe>>, } -export interface SerializedFilterQueryResult { - filterQuery?: Maybe; +export interface CloudInstance { + id?: Maybe>>, } -export interface SerializedKueryQueryResult { - kuery?: Maybe; +export interface CloudMachine { + type?: Maybe>>, +} - serializedQuery?: Maybe; +export interface ColumnHeaderInput { + aggregatable?: Maybe, + category?: Maybe, + columnHeaderType?: Maybe, + description?: Maybe, + example?: Maybe, + indexes?: Maybe>, + id?: Maybe, + name?: Maybe, + placeholder?: Maybe, + searchable?: Maybe, + type?: Maybe, } -export interface KueryFilterQueryResult { - kind?: Maybe; +export interface ColumnHeaderResult { + aggregatable?: Maybe, + category?: Maybe, + columnHeaderType?: Maybe, + description?: Maybe, + example?: Maybe, + indexes?: Maybe>, + id?: Maybe, + name?: Maybe, + placeholder?: Maybe, + searchable?: Maybe, + type?: Maybe, +} - expression?: Maybe; +export interface CursorType { + value?: Maybe, + tiebreaker?: Maybe, } -export interface SortTimelineResult { - columnId?: Maybe; +export interface DataProviderInput { + id?: Maybe, + name?: Maybe, + enabled?: Maybe, + excluded?: Maybe, + kqlQuery?: Maybe, + queryMatch?: Maybe, + and?: Maybe>, +} - sortDirection?: Maybe; +export interface DataProviderResult { + id?: Maybe, + name?: Maybe, + enabled?: Maybe, + excluded?: Maybe, + kqlQuery?: Maybe, + queryMatch?: Maybe, + and?: Maybe>, } -export interface ResponseTimelines { - timeline: (Maybe)[]; - totalCount?: Maybe; +export interface DateRangePickerInput { + start?: Maybe, + end?: Maybe, } -export interface Mutation { - /** Persists a note */ - persistNote: ResponseNote; +export interface DateRangePickerResult { + start?: Maybe, + end?: Maybe, +} - deleteNote?: Maybe; +export interface DestinationEcsFields { + bytes?: Maybe, + ip?: Maybe, + port?: Maybe, + domain?: Maybe, + geo?: Maybe, + packets?: Maybe, +} - deleteNoteByTimelineId?: Maybe; - /** Persists a pinned event in a timeline */ - persistPinnedEventOnTimeline?: Maybe; - /** Remove a pinned events in a timeline */ - deletePinnedEventOnTimeline: boolean; - /** Remove all pinned events in a timeline */ - deleteAllPinnedEventsOnTimeline: boolean; - /** Persists a timeline */ - persistTimeline: ResponseTimeline; +export interface DetailItem { + field: Scalars['String'], + values?: Maybe, + originalValue?: Maybe, +} - persistFavorite: ResponseFavoriteTimeline; +export enum Direction { + asc = 'asc', + desc = 'desc' +} - deleteTimeline: boolean; +export interface DnsEcsFields { + question?: Maybe, + resolved_ip?: Maybe, + response_code?: Maybe, } -export interface ResponseNote { - code?: Maybe; +export interface DnsQuestionData { + name?: Maybe, + type?: Maybe, +} - message?: Maybe; +export interface Ecs { + _id: Scalars['String'], + _index?: Maybe, + auditd?: Maybe, + destination?: Maybe, + dns?: Maybe, + endgame?: Maybe, + event?: Maybe, + geo?: Maybe, + host?: Maybe, + network?: Maybe, + rule?: Maybe, + signal?: Maybe, + source?: Maybe, + suricata?: Maybe, + tls?: Maybe, + zeek?: Maybe, + http?: Maybe, + url?: Maybe, + timestamp?: Maybe, + message?: Maybe, + user?: Maybe, + winlog?: Maybe, + process?: Maybe, + file?: Maybe, + system?: Maybe, +} - note: NoteResult; +export interface EcsEdges { + node: Ecs, + cursor: CursorType, } -export interface ResponseTimeline { - code?: Maybe; +export interface EndgameEcsFields { + exit_code?: Maybe, + file_name?: Maybe, + file_path?: Maybe, + logon_type?: Maybe, + parent_process_name?: Maybe, + pid?: Maybe, + process_name?: Maybe, + subject_domain_name?: Maybe, + subject_logon_id?: Maybe, + subject_user_name?: Maybe, + target_domain_name?: Maybe, + target_logon_id?: Maybe, + target_user_name?: Maybe, +} - message?: Maybe; - timeline: TimelineResult; +export interface EventEcsFields { + action?: Maybe, + category?: Maybe, + code?: Maybe, + created?: Maybe, + dataset?: Maybe, + duration?: Maybe, + end?: Maybe, + hash?: Maybe, + id?: Maybe, + kind?: Maybe, + module?: Maybe, + original?: Maybe, + outcome?: Maybe, + risk_score?: Maybe, + risk_score_norm?: Maybe, + severity?: Maybe, + start?: Maybe, + timezone?: Maybe, + type?: Maybe, } -export interface ResponseFavoriteTimeline { - code?: Maybe; +export interface EventsTimelineData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfo, + inspect?: Maybe, +} - message?: Maybe; +export interface FavoriteTimelineInput { + fullName?: Maybe, + userName?: Maybe, + favoriteDate?: Maybe, +} - savedObjectId: string; +export interface FavoriteTimelineResult { + fullName?: Maybe, + userName?: Maybe, + favoriteDate?: Maybe, +} - version: string; +export interface FileFields { + name?: Maybe, + path?: Maybe, + target_path?: Maybe, + extension?: Maybe, + type?: Maybe, + device?: Maybe, + inode?: Maybe, + uid?: Maybe, + owner?: Maybe, + gid?: Maybe, + group?: Maybe, + mode?: Maybe, + size?: Maybe, + mtime?: Maybe, + ctime?: Maybe, +} - favorite?: Maybe; +export interface FilterMetaTimelineInput { + alias?: Maybe, + controlledBy?: Maybe, + disabled?: Maybe, + field?: Maybe, + formattedValue?: Maybe, + index?: Maybe, + key?: Maybe, + negate?: Maybe, + params?: Maybe, + type?: Maybe, + value?: Maybe, } -export interface EcsEdges { - node: Ecs; +export interface FilterMetaTimelineResult { + alias?: Maybe, + controlledBy?: Maybe, + disabled?: Maybe, + field?: Maybe, + formattedValue?: Maybe, + index?: Maybe, + key?: Maybe, + negate?: Maybe, + params?: Maybe, + type?: Maybe, + value?: Maybe, +} - cursor: CursorType; +export interface FilterTimelineInput { + exists?: Maybe, + meta?: Maybe, + match_all?: Maybe, + missing?: Maybe, + query?: Maybe, + range?: Maybe, + script?: Maybe, } -export interface EventsTimelineData { - edges: EcsEdges[]; +export interface FilterTimelineResult { + exists?: Maybe, + meta?: Maybe, + match_all?: Maybe, + missing?: Maybe, + query?: Maybe, + range?: Maybe, + script?: Maybe, +} - totalCount: number; +export interface FingerprintData { + sha1?: Maybe, +} - pageInfo: PageInfo; +export interface FirstLastSeenHost { + inspect?: Maybe, + firstSeen?: Maybe, + lastSeen?: Maybe, +} - inspect?: Maybe; +export enum FlowDirection { + uniDirectional = 'uniDirectional', + biDirectional = 'biDirectional' } -export interface OsFields { - platform?: Maybe; +export enum FlowTarget { + client = 'client', + destination = 'destination', + server = 'server', + source = 'source' +} - name?: Maybe; +export enum FlowTargetSourceDest { + destination = 'destination', + source = 'source' +} - full?: Maybe; +export interface GeoEcsFields { + city_name?: Maybe, + continent_name?: Maybe, + country_iso_code?: Maybe, + country_name?: Maybe, + location?: Maybe, + region_iso_code?: Maybe, + region_name?: Maybe, +} - family?: Maybe; +export interface GeoItem { + geo?: Maybe, + flowTarget?: Maybe, +} - version?: Maybe; +export enum HistogramType { + authentications = 'authentications', + anomalies = 'anomalies', + events = 'events', + alerts = 'alerts', + dns = 'dns' +} - kernel?: Maybe; +export interface HostEcsFields { + architecture?: Maybe, + id?: Maybe, + ip?: Maybe, + mac?: Maybe, + name?: Maybe, + os?: Maybe, + type?: Maybe, } export interface HostFields { - architecture?: Maybe; - - id?: Maybe; + architecture?: Maybe, + id?: Maybe, + ip?: Maybe>>, + mac?: Maybe>>, + name?: Maybe, + os?: Maybe, + type?: Maybe, +} - ip?: Maybe<(Maybe)[]>; +export interface HostItem { + _id?: Maybe, + lastSeen?: Maybe, + host?: Maybe, + cloud?: Maybe, + inspect?: Maybe, +} - mac?: Maybe<(Maybe)[]>; +export interface HostsData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +} - name?: Maybe; +export interface HostsEdges { + node: HostItem, + cursor: CursorType, +} - os?: Maybe; +export enum HostsFields { + hostName = 'hostName', + lastSeen = 'lastSeen' +} - type?: Maybe; +export interface HostsSortField { + field: HostsFields, + direction: Direction, } -// ==================================================== -// Arguments -// ==================================================== +export interface HttpBodyData { + content?: Maybe, + bytes?: Maybe, +} -export interface GetNoteQueryArgs { - id: string; +export interface HttpEcsFields { + version?: Maybe, + request?: Maybe, + response?: Maybe, } -export interface GetNotesByTimelineIdQueryArgs { - timelineId: string; + +export interface HttpRequestData { + method?: Maybe, + body?: Maybe, + referrer?: Maybe, + bytes?: Maybe, } -export interface GetNotesByEventIdQueryArgs { - eventId: string; + +export interface HttpResponseData { + status_code?: Maybe, + body?: Maybe, + bytes?: Maybe, } -export interface GetAllNotesQueryArgs { - pageInfo?: Maybe; - search?: Maybe; +/** A descriptor of a field in an index */ +export interface IndexField { + /** Where the field belong */ + category: Scalars['String'], + /** Example of field's value */ + example?: Maybe, + /** whether the field's belong to an alias index */ + indexes: Array>, + /** The name of the field */ + name: Scalars['String'], + /** The type of the field's values as recognized by Kibana */ + type: Scalars['String'], + /** Whether the field's values can be efficiently searched for */ + searchable: Scalars['Boolean'], + /** Whether the field's values can be aggregated */ + aggregatable: Scalars['Boolean'], + /** Description of the field */ + description?: Maybe, + format?: Maybe, +} - sort?: Maybe; +export interface Inspect { + dsl: Array, + response: Array, } -export interface GetAllPinnedEventsByTimelineIdQueryArgs { - timelineId: string; + +export interface IpOverviewData { + client?: Maybe, + destination?: Maybe, + host: HostEcsFields, + server?: Maybe, + source?: Maybe, + inspect?: Maybe, } -export interface SourceQueryArgs { - /** The id of the source */ - id: string; + +export interface KpiHostDetailsData { + authSuccess?: Maybe, + authSuccessHistogram?: Maybe>, + authFailure?: Maybe, + authFailureHistogram?: Maybe>, + uniqueSourceIps?: Maybe, + uniqueSourceIpsHistogram?: Maybe>, + uniqueDestinationIps?: Maybe, + uniqueDestinationIpsHistogram?: Maybe>, + inspect?: Maybe, } -export interface GetOneTimelineQueryArgs { - id: string; + +export interface KpiHostHistogramData { + x?: Maybe, + y?: Maybe, } -export interface GetAllTimelineQueryArgs { - pageInfo?: Maybe; - search?: Maybe; +export interface KpiHostsData { + hosts?: Maybe, + hostsHistogram?: Maybe>, + authSuccess?: Maybe, + authSuccessHistogram?: Maybe>, + authFailure?: Maybe, + authFailureHistogram?: Maybe>, + uniqueSourceIps?: Maybe, + uniqueSourceIpsHistogram?: Maybe>, + uniqueDestinationIps?: Maybe, + uniqueDestinationIpsHistogram?: Maybe>, + inspect?: Maybe, +} - sort?: Maybe; +export interface KpiNetworkData { + networkEvents?: Maybe, + uniqueFlowId?: Maybe, + uniqueSourcePrivateIps?: Maybe, + uniqueSourcePrivateIpsHistogram?: Maybe>, + uniqueDestinationPrivateIps?: Maybe, + uniqueDestinationPrivateIpsHistogram?: Maybe>, + dnsQueries?: Maybe, + tlsHandshakes?: Maybe, + inspect?: Maybe, +} - onlyUserFavorite?: Maybe; +export interface KpiNetworkHistogramData { + x?: Maybe, + y?: Maybe, } -export interface AuthenticationsSourceArgs { - timerange: TimerangeInput; - pagination: PaginationInputPaginated; +export interface KueryFilterQueryInput { + kind?: Maybe, + expression?: Maybe, +} - filterQuery?: Maybe; +export interface KueryFilterQueryResult { + kind?: Maybe, + expression?: Maybe, +} - defaultIndex: string[]; +export enum LastEventIndexKey { + hostDetails = 'hostDetails', + hosts = 'hosts', + ipDetails = 'ipDetails', + network = 'network' } -export interface TimelineSourceArgs { - pagination: PaginationInput; - sortField: SortField; +export interface LastEventTimeData { + lastSeen?: Maybe, + inspect?: Maybe, +} - fieldRequested: string[]; +export interface LastSourceHost { + timestamp?: Maybe, + source?: Maybe, + host?: Maybe, +} - timerange?: Maybe; +export interface LastTimeDetails { + hostName?: Maybe, + ip?: Maybe, +} - filterQuery?: Maybe; +export interface Location { + lon?: Maybe, + lat?: Maybe, +} - defaultIndex: string[]; +export interface MatrixHistogramOverTimeData { + inspect?: Maybe, + matrixHistogramData: Array, + totalCount: Scalars['Float'], } -export interface TimelineDetailsSourceArgs { - eventId: string; - indexName: string; +export interface MatrixOverOrdinalHistogramData { + x: Scalars['String'], + y: Scalars['Float'], + g: Scalars['String'], +} - defaultIndex: string[]; +export interface MatrixOverTimeHistogramData { + x?: Maybe, + y?: Maybe, + g?: Maybe, } -export interface LastEventTimeSourceArgs { - id?: Maybe; - indexKey: LastEventIndexKey; +export interface Mutation { + /** Persists a note */ + persistNote: ResponseNote, + deleteNote?: Maybe, + deleteNoteByTimelineId?: Maybe, + /** Persists a pinned event in a timeline */ + persistPinnedEventOnTimeline?: Maybe, + /** Remove a pinned events in a timeline */ + deletePinnedEventOnTimeline: Scalars['Boolean'], + /** Remove all pinned events in a timeline */ + deleteAllPinnedEventsOnTimeline: Scalars['Boolean'], + /** Persists a timeline */ + persistTimeline: ResponseTimeline, + persistFavorite: ResponseFavoriteTimeline, + deleteTimeline: Scalars['Boolean'], +} - details: LastTimeDetails; - defaultIndex: string[]; +export interface MutationPersistNoteArgs { + noteId?: Maybe, + version?: Maybe, + note: NoteInput } -export interface HostsSourceArgs { - id?: Maybe; - timerange: TimerangeInput; - pagination: PaginationInputPaginated; - - sort: HostsSortField; +export interface MutationDeleteNoteArgs { + id: Array +} - filterQuery?: Maybe; - defaultIndex: string[]; +export interface MutationDeleteNoteByTimelineIdArgs { + timelineId: Scalars['ID'], + version?: Maybe } -export interface HostOverviewSourceArgs { - id?: Maybe; - hostName: string; - timerange: TimerangeInput; +export interface MutationPersistPinnedEventOnTimelineArgs { + pinnedEventId?: Maybe, + eventId: Scalars['ID'], + timelineId?: Maybe +} + - defaultIndex: string[]; +export interface MutationDeletePinnedEventOnTimelineArgs { + id: Array } -export interface HostFirstLastSeenSourceArgs { - id?: Maybe; - hostName: string; - defaultIndex: string[]; +export interface MutationDeleteAllPinnedEventsOnTimelineArgs { + timelineId: Scalars['ID'] } -export interface IpOverviewSourceArgs { - id?: Maybe; - filterQuery?: Maybe; - ip: string; +export interface MutationPersistTimelineArgs { + id?: Maybe, + version?: Maybe, + timeline: TimelineInput +} + - defaultIndex: string[]; +export interface MutationPersistFavoriteArgs { + timelineId?: Maybe } -export interface UsersSourceArgs { - filterQuery?: Maybe; - id?: Maybe; - ip: string; +export interface MutationDeleteTimelineArgs { + id: Array +} - pagination: PaginationInputPaginated; +export enum NetworkDirectionEcs { + inbound = 'inbound', + outbound = 'outbound', + internal = 'internal', + external = 'external', + incoming = 'incoming', + outgoing = 'outgoing', + listening = 'listening', + unknown = 'unknown' +} - sort: UsersSortField; +export interface NetworkDnsData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, + histogram?: Maybe>, +} - flowTarget: FlowTarget; +export interface NetworkDnsEdges { + node: NetworkDnsItem, + cursor: CursorType, +} - timerange: TimerangeInput; +export enum NetworkDnsFields { + dnsName = 'dnsName', + queryCount = 'queryCount', + uniqueDomains = 'uniqueDomains', + dnsBytesIn = 'dnsBytesIn', + dnsBytesOut = 'dnsBytesOut' +} - defaultIndex: string[]; +export interface NetworkDnsItem { + _id?: Maybe, + dnsBytesIn?: Maybe, + dnsBytesOut?: Maybe, + dnsName?: Maybe, + queryCount?: Maybe, + uniqueDomains?: Maybe, } -export interface KpiNetworkSourceArgs { - id?: Maybe; - timerange: TimerangeInput; +export interface NetworkDnsSortField { + field: NetworkDnsFields, + direction: Direction, +} - filterQuery?: Maybe; +export interface NetworkDsOverTimeData { + inspect?: Maybe, + matrixHistogramData: Array, + totalCount: Scalars['Float'], +} - defaultIndex: string[]; +export interface NetworkEcsField { + bytes?: Maybe, + community_id?: Maybe, + direction?: Maybe, + packets?: Maybe, + protocol?: Maybe, + transport?: Maybe, } -export interface KpiHostsSourceArgs { - id?: Maybe; - timerange: TimerangeInput; +export interface NetworkHttpData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +} - filterQuery?: Maybe; +export interface NetworkHttpEdges { + node: NetworkHttpItem, + cursor: CursorType, +} - defaultIndex: string[]; +export enum NetworkHttpFields { + domains = 'domains', + lastHost = 'lastHost', + lastSourceIp = 'lastSourceIp', + methods = 'methods', + path = 'path', + requestCount = 'requestCount', + statuses = 'statuses' } -export interface KpiHostDetailsSourceArgs { - id?: Maybe; - timerange: TimerangeInput; +export interface NetworkHttpItem { + _id?: Maybe, + domains: Array, + lastHost?: Maybe, + lastSourceIp?: Maybe, + methods: Array, + path?: Maybe, + requestCount?: Maybe, + statuses: Array, +} - filterQuery?: Maybe; +export interface NetworkHttpSortField { + direction: Direction, +} - defaultIndex: string[]; +export interface NetworkTopCountriesData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, } -export interface MatrixHistogramSourceArgs { - filterQuery?: Maybe; - defaultIndex: string[]; +export interface NetworkTopCountriesEdges { + node: NetworkTopCountriesItem, + cursor: CursorType, +} - timerange: TimerangeInput; +export interface NetworkTopCountriesItem { + _id?: Maybe, + source?: Maybe, + destination?: Maybe, + network?: Maybe, +} - stackByField: string; +export interface NetworkTopNFlowData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +} - histogramType: HistogramType; +export interface NetworkTopNFlowEdges { + node: NetworkTopNFlowItem, + cursor: CursorType, } -export interface NetworkTopCountriesSourceArgs { - id?: Maybe; - filterQuery?: Maybe; +export interface NetworkTopNFlowItem { + _id?: Maybe, + source?: Maybe, + destination?: Maybe, + network?: Maybe, +} - ip?: Maybe; +export enum NetworkTopTablesFields { + bytes_in = 'bytes_in', + bytes_out = 'bytes_out', + flows = 'flows', + destination_ips = 'destination_ips', + source_ips = 'source_ips' +} - flowTarget: FlowTargetSourceDest; +export interface NetworkTopTablesSortField { + field: NetworkTopTablesFields, + direction: Direction, +} - pagination: PaginationInputPaginated; +export interface NoteInput { + eventId?: Maybe, + note?: Maybe, + timelineId?: Maybe, +} - sort: NetworkTopTablesSortField; +export interface NoteResult { + eventId?: Maybe, + note?: Maybe, + timelineId?: Maybe, + noteId: Scalars['String'], + created?: Maybe, + createdBy?: Maybe, + timelineVersion?: Maybe, + updated?: Maybe, + updatedBy?: Maybe, + version?: Maybe, +} - timerange: TimerangeInput; +export interface OsEcsFields { + platform?: Maybe, + name?: Maybe, + full?: Maybe, + family?: Maybe, + version?: Maybe, + kernel?: Maybe, +} - defaultIndex: string[]; +export interface OsFields { + platform?: Maybe, + name?: Maybe, + full?: Maybe, + family?: Maybe, + version?: Maybe, + kernel?: Maybe, } -export interface NetworkTopNFlowSourceArgs { - id?: Maybe; - filterQuery?: Maybe; +export interface Overview { + firstSeen?: Maybe, + lastSeen?: Maybe, + autonomousSystem: AutonomousSystem, + geo: GeoEcsFields, +} - ip?: Maybe; +export interface OverviewHostData { + auditbeatAuditd?: Maybe, + auditbeatFIM?: Maybe, + auditbeatLogin?: Maybe, + auditbeatPackage?: Maybe, + auditbeatProcess?: Maybe, + auditbeatUser?: Maybe, + endgameDns?: Maybe, + endgameFile?: Maybe, + endgameImageLoad?: Maybe, + endgameNetwork?: Maybe, + endgameProcess?: Maybe, + endgameRegistry?: Maybe, + endgameSecurity?: Maybe, + filebeatSystemModule?: Maybe, + winlogbeatSecurity?: Maybe, + winlogbeatMWSysmonOperational?: Maybe, + inspect?: Maybe, +} - flowTarget: FlowTargetSourceDest; +export interface OverviewNetworkData { + auditbeatSocket?: Maybe, + filebeatCisco?: Maybe, + filebeatNetflow?: Maybe, + filebeatPanw?: Maybe, + filebeatSuricata?: Maybe, + filebeatZeek?: Maybe, + packetbeatDNS?: Maybe, + packetbeatFlow?: Maybe, + packetbeatTLS?: Maybe, + inspect?: Maybe, +} - pagination: PaginationInputPaginated; +export interface PackageEcsFields { + arch?: Maybe, + entity_id?: Maybe, + name?: Maybe, + size?: Maybe, + summary?: Maybe, + version?: Maybe, +} - sort: NetworkTopTablesSortField; +export interface PageInfo { + endCursor?: Maybe, + hasNextPage?: Maybe, +} - timerange: TimerangeInput; +export interface PageInfoNote { + pageIndex: Scalars['Float'], + pageSize: Scalars['Float'], +} - defaultIndex: string[]; +export interface PageInfoPaginated { + activePage: Scalars['Float'], + fakeTotalCount: Scalars['Float'], + showMorePagesIndicator: Scalars['Boolean'], } -export interface NetworkDnsSourceArgs { - filterQuery?: Maybe; - id?: Maybe; +export interface PageInfoTimeline { + pageIndex: Scalars['Float'], + pageSize: Scalars['Float'], +} - isPtrIncluded: boolean; +export interface PaginationInput { + /** The limit parameter allows you to configure the maximum amount of items to be returned */ + limit: Scalars['Float'], + /** The cursor parameter defines the next result you want to fetch */ + cursor?: Maybe, + /** The tiebreaker parameter allow to be more precise to fetch the next item */ + tiebreaker?: Maybe, +} - pagination: PaginationInputPaginated; +export interface PaginationInputPaginated { + /** The activePage parameter defines the page of results you want to fetch */ + activePage: Scalars['Float'], + /** The cursorStart parameter defines the start of the results to be displayed */ + cursorStart: Scalars['Float'], + /** The fakePossibleCount parameter determines the total count in order to show 5 additional pages */ + fakePossibleCount: Scalars['Float'], + /** The querySize parameter is the number of items to be returned */ + querySize: Scalars['Float'], +} - sort: NetworkDnsSortField; +export interface PinnedEvent { + code?: Maybe, + message?: Maybe, + pinnedEventId: Scalars['ID'], + eventId?: Maybe, + timelineId?: Maybe, + timelineVersion?: Maybe, + created?: Maybe, + createdBy?: Maybe, + updated?: Maybe, + updatedBy?: Maybe, + version?: Maybe, +} - stackByField?: Maybe; +export interface PrimarySecondary { + primary?: Maybe, + secondary?: Maybe, + type?: Maybe, +} - timerange: TimerangeInput; +export interface ProcessEcsFields { + hash?: Maybe, + pid?: Maybe, + name?: Maybe, + ppid?: Maybe, + args?: Maybe, + executable?: Maybe, + title?: Maybe, + thread?: Maybe, + working_directory?: Maybe, +} - defaultIndex: string[]; +export interface ProcessHashData { + md5?: Maybe, + sha1?: Maybe, + sha256?: Maybe, } -export interface NetworkDnsHistogramSourceArgs { - filterQuery?: Maybe; - defaultIndex: string[]; +export interface Query { + getNote: NoteResult, + getNotesByTimelineId: Array, + getNotesByEventId: Array, + getAllNotes: ResponseNotes, + getAllPinnedEventsByTimelineId: Array, + /** Get a security data source by id */ + source: Source, + /** Get a list of all security data sources */ + allSources: Array, + getOneTimeline: TimelineResult, + getAllTimeline: ResponseTimelines, +} - timerange: TimerangeInput; - stackByField?: Maybe; +export interface QueryGetNoteArgs { + id: Scalars['ID'] } -export interface NetworkHttpSourceArgs { - id?: Maybe; - filterQuery?: Maybe; - ip?: Maybe; +export interface QueryGetNotesByTimelineIdArgs { + timelineId: Scalars['ID'] +} - pagination: PaginationInputPaginated; - sort: NetworkHttpSortField; +export interface QueryGetNotesByEventIdArgs { + eventId: Scalars['ID'] +} - timerange: TimerangeInput; - defaultIndex: string[]; +export interface QueryGetAllNotesArgs { + pageInfo?: Maybe, + search?: Maybe, + sort?: Maybe } -export interface OverviewNetworkSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - filterQuery?: Maybe; - defaultIndex: string[]; +export interface QueryGetAllPinnedEventsByTimelineIdArgs { + timelineId: Scalars['ID'] } -export interface OverviewHostSourceArgs { - id?: Maybe; - timerange: TimerangeInput; - filterQuery?: Maybe; - - defaultIndex: string[]; +export interface QuerySourceArgs { + id: Scalars['ID'] } -export interface TlsSourceArgs { - filterQuery?: Maybe; - - id?: Maybe; - ip: string; - pagination: PaginationInputPaginated; +export interface QueryGetOneTimelineArgs { + id: Scalars['ID'] +} - sort: TlsSortField; - flowTarget: FlowTargetSourceDest; +export interface QueryGetAllTimelineArgs { + pageInfo?: Maybe, + search?: Maybe, + sort?: Maybe, + onlyUserFavorite?: Maybe +} - timerange: TimerangeInput; +export interface QueryMatchInput { + field?: Maybe, + displayField?: Maybe, + value?: Maybe, + displayValue?: Maybe, + operator?: Maybe, +} - defaultIndex: string[]; +export interface QueryMatchResult { + field?: Maybe, + displayField?: Maybe, + value?: Maybe, + displayValue?: Maybe, + operator?: Maybe, } -export interface UncommonProcessesSourceArgs { - timerange: TimerangeInput; - pagination: PaginationInputPaginated; +export interface ResponseFavoriteTimeline { + code?: Maybe, + message?: Maybe, + savedObjectId: Scalars['String'], + version: Scalars['String'], + favorite?: Maybe>, +} - filterQuery?: Maybe; +export interface ResponseNote { + code?: Maybe, + message?: Maybe, + note: NoteResult, +} - defaultIndex: string[]; +export interface ResponseNotes { + notes: Array, + totalCount?: Maybe, } -export interface IndicesExistSourceStatusArgs { - defaultIndex: string[]; + +export interface ResponseTimeline { + code?: Maybe, + message?: Maybe, + timeline: TimelineResult, } -export interface IndexFieldsSourceStatusArgs { - defaultIndex: string[]; + +export interface ResponseTimelines { + timeline: Array>, + totalCount?: Maybe, } -export interface PersistNoteMutationArgs { - noteId?: Maybe; - version?: Maybe; +export interface RuleEcsField { + reference?: Maybe, +} - note: NoteInput; +export interface RuleField { + id?: Maybe, + rule_id?: Maybe, + false_positives: Array, + saved_id?: Maybe, + timeline_id?: Maybe, + timeline_title?: Maybe, + max_signals?: Maybe, + risk_score?: Maybe, + output_index?: Maybe, + description?: Maybe, + from?: Maybe, + immutable?: Maybe, + index?: Maybe, + interval?: Maybe, + language?: Maybe, + query?: Maybe, + references?: Maybe, + severity?: Maybe, + tags?: Maybe, + threat?: Maybe, + type?: Maybe, + size?: Maybe, + to?: Maybe, + enabled?: Maybe, + filters?: Maybe, + created_at?: Maybe, + updated_at?: Maybe, + created_by?: Maybe, + updated_by?: Maybe, + version?: Maybe, } -export interface DeleteNoteMutationArgs { - id: string[]; + +export interface SayMyName { + /** The id of the source */ + appName: Scalars['String'], } -export interface DeleteNoteByTimelineIdMutationArgs { - timelineId: string; - version?: Maybe; +export interface SerializedFilterQueryInput { + filterQuery?: Maybe, } -export interface PersistPinnedEventOnTimelineMutationArgs { - pinnedEventId?: Maybe; - eventId: string; +export interface SerializedFilterQueryResult { + filterQuery?: Maybe, +} - timelineId?: Maybe; +export interface SerializedKueryQueryInput { + kuery?: Maybe, + serializedQuery?: Maybe, } -export interface DeletePinnedEventOnTimelineMutationArgs { - id: string[]; + +export interface SerializedKueryQueryResult { + kuery?: Maybe, + serializedQuery?: Maybe, } -export interface DeleteAllPinnedEventsOnTimelineMutationArgs { - timelineId: string; + +export interface SignalField { + rule?: Maybe, + original_time?: Maybe, } -export interface PersistTimelineMutationArgs { - id?: Maybe; - version?: Maybe; +export interface SortField { + sortFieldId: Scalars['String'], + direction: Direction, +} - timeline: TimelineInput; +export enum SortFieldNote { + updatedBy = 'updatedBy', + updated = 'updated' } -export interface PersistFavoriteMutationArgs { - timelineId?: Maybe; + +export enum SortFieldTimeline { + title = 'title', + description = 'description', + updated = 'updated', + created = 'created' } -export interface DeleteTimelineMutationArgs { - id: string[]; + +export interface SortNote { + sortField: SortFieldNote, + sortOrder: Direction, } -import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql'; +export interface SortTimeline { + sortField: SortFieldTimeline, + sortOrder: Direction, +} -export type Resolver = ( - parent: Parent, - args: Args, - context: TContext, - info: GraphQLResolveInfo -) => Promise | Result; - -export interface ISubscriptionResolverObject { - subscribe( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): AsyncIterator | Promise>; - resolve?( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): R | Result | Promise; -} - -export type SubscriptionResolver = - | ((...args: any[]) => ISubscriptionResolverObject) - | ISubscriptionResolverObject; - -export type TypeResolveFn = ( - parent: Parent, - context: TContext, - info: GraphQLResolveInfo -) => Maybe; +export interface SortTimelineInput { + columnId?: Maybe, + sortDirection?: Maybe, +} -export type NextResolverFn = () => Promise; +export interface SortTimelineResult { + columnId?: Maybe, + sortDirection?: Maybe, +} -export type DirectiveResolverFn = ( - next: NextResolverFn, - source: any, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo -) => TResult | Promise; +export interface Source { + /** The id of the source */ + id: Scalars['ID'], + /** The raw configuration of the source */ + configuration: SourceConfiguration, + /** The status of the source */ + status: SourceStatus, + /** Gets Authentication success and failures based on a timerange */ + Authentications: AuthenticationsData, + Timeline: TimelineData, + TimelineDetails: TimelineDetailsData, + LastEventTime: LastEventTimeData, + /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ + Hosts: HostsData, + HostOverview: HostItem, + HostFirstLastSeen: FirstLastSeenHost, + IpOverview?: Maybe, + Users: UsersData, + KpiNetwork?: Maybe, + KpiHosts: KpiHostsData, + KpiHostDetails: KpiHostDetailsData, + MatrixHistogram: MatrixHistogramOverTimeData, + NetworkTopCountries: NetworkTopCountriesData, + NetworkTopNFlow: NetworkTopNFlowData, + NetworkDns: NetworkDnsData, + NetworkDnsHistogram: NetworkDsOverTimeData, + NetworkHttp: NetworkHttpData, + OverviewNetwork?: Maybe, + OverviewHost?: Maybe, + Tls: TlsData, + /** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */ + UncommonProcesses: UncommonProcessesData, + /** Just a simple example to get the app name */ + whoAmI?: Maybe, +} -export namespace QueryResolvers { - export interface Resolvers { - getNote?: GetNoteResolver; - - getNotesByTimelineId?: GetNotesByTimelineIdResolver; - - getNotesByEventId?: GetNotesByEventIdResolver; - - getAllNotes?: GetAllNotesResolver; - - getAllPinnedEventsByTimelineId?: GetAllPinnedEventsByTimelineIdResolver< - PinnedEvent[], - TypeParent, - TContext - >; - /** Get a security data source by id */ - source?: SourceResolver; - /** Get a list of all security data sources */ - allSources?: AllSourcesResolver; - - getOneTimeline?: GetOneTimelineResolver; - - getAllTimeline?: GetAllTimelineResolver; - } - - export type GetNoteResolver = Resolver< - R, - Parent, - TContext, - GetNoteArgs - >; - export interface GetNoteArgs { - id: string; - } - - export type GetNotesByTimelineIdResolver< - R = NoteResult[], - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface GetNotesByTimelineIdArgs { - timelineId: string; - } - - export type GetNotesByEventIdResolver< - R = NoteResult[], - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface GetNotesByEventIdArgs { - eventId: string; - } - - export type GetAllNotesResolver< - R = ResponseNotes, - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface GetAllNotesArgs { - pageInfo?: Maybe; - - search?: Maybe; - - sort?: Maybe; - } - - export type GetAllPinnedEventsByTimelineIdResolver< - R = PinnedEvent[], - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface GetAllPinnedEventsByTimelineIdArgs { - timelineId: string; - } - - export type SourceResolver = Resolver< - R, - Parent, - TContext, - SourceArgs - >; - export interface SourceArgs { - /** The id of the source */ - id: string; - } - - export type AllSourcesResolver = Resolver< - R, - Parent, - TContext - >; - export type GetOneTimelineResolver< - R = TimelineResult, - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface GetOneTimelineArgs { - id: string; - } - - export type GetAllTimelineResolver< - R = ResponseTimelines, - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface GetAllTimelineArgs { - pageInfo?: Maybe; - - search?: Maybe; - - sort?: Maybe; - - onlyUserFavorite?: Maybe; - } -} - -export namespace NoteResultResolvers { - export interface Resolvers { - eventId?: EventIdResolver, TypeParent, TContext>; - - note?: NoteResolver, TypeParent, TContext>; - - timelineId?: TimelineIdResolver, TypeParent, TContext>; - - noteId?: NoteIdResolver; - - created?: CreatedResolver, TypeParent, TContext>; - - createdBy?: CreatedByResolver, TypeParent, TContext>; - - timelineVersion?: TimelineVersionResolver, TypeParent, TContext>; - - updated?: UpdatedResolver, TypeParent, TContext>; - - updatedBy?: UpdatedByResolver, TypeParent, TContext>; - - version?: VersionResolver, TypeParent, TContext>; - } - - export type EventIdResolver< - R = Maybe, - Parent = NoteResult, - TContext = SiemContext - > = Resolver; - export type NoteResolver< - R = Maybe, - Parent = NoteResult, - TContext = SiemContext - > = Resolver; - export type TimelineIdResolver< - R = Maybe, - Parent = NoteResult, - TContext = SiemContext - > = Resolver; - export type NoteIdResolver = Resolver< - R, - Parent, - TContext - >; - export type CreatedResolver< - R = Maybe, - Parent = NoteResult, - TContext = SiemContext - > = Resolver; - export type CreatedByResolver< - R = Maybe, - Parent = NoteResult, - TContext = SiemContext - > = Resolver; - export type TimelineVersionResolver< - R = Maybe, - Parent = NoteResult, - TContext = SiemContext - > = Resolver; - export type UpdatedResolver< - R = Maybe, - Parent = NoteResult, - TContext = SiemContext - > = Resolver; - export type UpdatedByResolver< - R = Maybe, - Parent = NoteResult, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = Maybe, - Parent = NoteResult, - TContext = SiemContext - > = Resolver; -} - -export namespace ResponseNotesResolvers { - export interface Resolvers { - notes?: NotesResolver; - - totalCount?: TotalCountResolver, TypeParent, TContext>; - } - - export type NotesResolver< - R = NoteResult[], - Parent = ResponseNotes, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = Maybe, - Parent = ResponseNotes, - TContext = SiemContext - > = Resolver; -} - -export namespace PinnedEventResolvers { - export interface Resolvers { - code?: CodeResolver, TypeParent, TContext>; - - message?: MessageResolver, TypeParent, TContext>; - - pinnedEventId?: PinnedEventIdResolver; - - eventId?: EventIdResolver, TypeParent, TContext>; - - timelineId?: TimelineIdResolver, TypeParent, TContext>; - - timelineVersion?: TimelineVersionResolver, TypeParent, TContext>; - - created?: CreatedResolver, TypeParent, TContext>; - - createdBy?: CreatedByResolver, TypeParent, TContext>; - - updated?: UpdatedResolver, TypeParent, TContext>; - - updatedBy?: UpdatedByResolver, TypeParent, TContext>; - - version?: VersionResolver, TypeParent, TContext>; - } - - export type CodeResolver< - R = Maybe, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; - export type MessageResolver< - R = Maybe, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; - export type PinnedEventIdResolver< - R = string, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; - export type EventIdResolver< - R = Maybe, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; - export type TimelineIdResolver< - R = Maybe, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; - export type TimelineVersionResolver< - R = Maybe, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; - export type CreatedResolver< - R = Maybe, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; - export type CreatedByResolver< - R = Maybe, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; - export type UpdatedResolver< - R = Maybe, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; - export type UpdatedByResolver< - R = Maybe, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = Maybe, - Parent = PinnedEvent, - TContext = SiemContext - > = Resolver; -} - -export namespace SourceResolvers { - export interface Resolvers { - /** The id of the source */ - id?: IdResolver; - /** The raw configuration of the source */ - configuration?: ConfigurationResolver; - /** The status of the source */ - status?: StatusResolver; - /** Gets Authentication success and failures based on a timerange */ - Authentications?: AuthenticationsResolver; - - Timeline?: TimelineResolver; - - TimelineDetails?: TimelineDetailsResolver; - - LastEventTime?: LastEventTimeResolver; - /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ - Hosts?: HostsResolver; - - HostOverview?: HostOverviewResolver; - - HostFirstLastSeen?: HostFirstLastSeenResolver; - - IpOverview?: IpOverviewResolver, TypeParent, TContext>; - - Users?: UsersResolver; - - KpiNetwork?: KpiNetworkResolver, TypeParent, TContext>; - - KpiHosts?: KpiHostsResolver; - - KpiHostDetails?: KpiHostDetailsResolver; - - MatrixHistogram?: MatrixHistogramResolver; - - NetworkTopCountries?: NetworkTopCountriesResolver< - NetworkTopCountriesData, - TypeParent, - TContext - >; - - NetworkTopNFlow?: NetworkTopNFlowResolver; - - NetworkDns?: NetworkDnsResolver; - - NetworkDnsHistogram?: NetworkDnsHistogramResolver; - - NetworkHttp?: NetworkHttpResolver; - - OverviewNetwork?: OverviewNetworkResolver, TypeParent, TContext>; - - OverviewHost?: OverviewHostResolver, TypeParent, TContext>; - - Tls?: TlsResolver; - /** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */ - UncommonProcesses?: UncommonProcessesResolver; - /** Just a simple example to get the app name */ - whoAmI?: WhoAmIResolver, TypeParent, TContext>; - } - - export type IdResolver = Resolver< - R, - Parent, - TContext - >; - export type ConfigurationResolver< - R = SourceConfiguration, - Parent = Source, - TContext = SiemContext - > = Resolver; - export type StatusResolver = Resolver< - R, - Parent, - TContext - >; - export type AuthenticationsResolver< - R = AuthenticationsData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface AuthenticationsArgs { - timerange: TimerangeInput; - pagination: PaginationInputPaginated; +export interface SourceAuthenticationsArgs { + timerange: TimerangeInput, + pagination: PaginationInputPaginated, + filterQuery?: Maybe, + defaultIndex: Array +} - filterQuery?: Maybe; - defaultIndex: string[]; - } +export interface SourceTimelineArgs { + pagination: PaginationInput, + sortField: SortField, + fieldRequested: Array, + timerange?: Maybe, + filterQuery?: Maybe, + defaultIndex: Array +} - export type TimelineResolver< - R = TimelineData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface TimelineArgs { - pagination: PaginationInput; - sortField: SortField; +export interface SourceTimelineDetailsArgs { + eventId: Scalars['String'], + indexName: Scalars['String'], + defaultIndex: Array +} - fieldRequested: string[]; - timerange?: Maybe; +export interface SourceLastEventTimeArgs { + id?: Maybe, + indexKey: LastEventIndexKey, + details: LastTimeDetails, + defaultIndex: Array +} - filterQuery?: Maybe; - defaultIndex: string[]; - } +export interface SourceHostsArgs { + id?: Maybe, + timerange: TimerangeInput, + pagination: PaginationInputPaginated, + sort: HostsSortField, + filterQuery?: Maybe, + defaultIndex: Array +} - export type TimelineDetailsResolver< - R = TimelineDetailsData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface TimelineDetailsArgs { - eventId: string; - indexName: string; +export interface SourceHostOverviewArgs { + id?: Maybe, + hostName: Scalars['String'], + timerange: TimerangeInput, + defaultIndex: Array +} - defaultIndex: string[]; - } - export type LastEventTimeResolver< - R = LastEventTimeData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface LastEventTimeArgs { - id?: Maybe; +export interface SourceHostFirstLastSeenArgs { + id?: Maybe, + hostName: Scalars['String'], + defaultIndex: Array +} - indexKey: LastEventIndexKey; - details: LastTimeDetails; +export interface SourceIpOverviewArgs { + id?: Maybe, + filterQuery?: Maybe, + ip: Scalars['String'], + defaultIndex: Array +} - defaultIndex: string[]; - } - export type HostsResolver = Resolver< - R, - Parent, - TContext, - HostsArgs - >; - export interface HostsArgs { - id?: Maybe; +export interface SourceUsersArgs { + filterQuery?: Maybe, + id?: Maybe, + ip: Scalars['String'], + pagination: PaginationInputPaginated, + sort: UsersSortField, + flowTarget: FlowTarget, + timerange: TimerangeInput, + defaultIndex: Array +} - timerange: TimerangeInput; - pagination: PaginationInputPaginated; +export interface SourceKpiNetworkArgs { + id?: Maybe, + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array +} - sort: HostsSortField; - filterQuery?: Maybe; +export interface SourceKpiHostsArgs { + id?: Maybe, + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array +} - defaultIndex: string[]; - } - export type HostOverviewResolver< - R = HostItem, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface HostOverviewArgs { - id?: Maybe; +export interface SourceKpiHostDetailsArgs { + id?: Maybe, + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array +} - hostName: string; - timerange: TimerangeInput; +export interface SourceMatrixHistogramArgs { + filterQuery?: Maybe, + defaultIndex: Array, + timerange: TimerangeInput, + stackByField: Scalars['String'], + histogramType: HistogramType +} - defaultIndex: string[]; - } - export type HostFirstLastSeenResolver< - R = FirstLastSeenHost, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface HostFirstLastSeenArgs { - id?: Maybe; +export interface SourceNetworkTopCountriesArgs { + id?: Maybe, + filterQuery?: Maybe, + ip?: Maybe, + flowTarget: FlowTargetSourceDest, + pagination: PaginationInputPaginated, + sort: NetworkTopTablesSortField, + timerange: TimerangeInput, + defaultIndex: Array +} - hostName: string; - defaultIndex: string[]; - } +export interface SourceNetworkTopNFlowArgs { + id?: Maybe, + filterQuery?: Maybe, + ip?: Maybe, + flowTarget: FlowTargetSourceDest, + pagination: PaginationInputPaginated, + sort: NetworkTopTablesSortField, + timerange: TimerangeInput, + defaultIndex: Array +} - export type IpOverviewResolver< - R = Maybe, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface IpOverviewArgs { - id?: Maybe; - filterQuery?: Maybe; +export interface SourceNetworkDnsArgs { + filterQuery?: Maybe, + id?: Maybe, + isPtrIncluded: Scalars['Boolean'], + pagination: PaginationInputPaginated, + sort: NetworkDnsSortField, + stackByField?: Maybe, + timerange: TimerangeInput, + defaultIndex: Array +} - ip: string; - defaultIndex: string[]; - } +export interface SourceNetworkDnsHistogramArgs { + filterQuery?: Maybe, + defaultIndex: Array, + timerange: TimerangeInput, + stackByField?: Maybe +} - export type UsersResolver = Resolver< - R, - Parent, - TContext, - UsersArgs - >; - export interface UsersArgs { - filterQuery?: Maybe; - id?: Maybe; +export interface SourceNetworkHttpArgs { + id?: Maybe, + filterQuery?: Maybe, + ip?: Maybe, + pagination: PaginationInputPaginated, + sort: NetworkHttpSortField, + timerange: TimerangeInput, + defaultIndex: Array +} - ip: string; - pagination: PaginationInputPaginated; +export interface SourceOverviewNetworkArgs { + id?: Maybe, + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array +} - sort: UsersSortField; - flowTarget: FlowTarget; +export interface SourceOverviewHostArgs { + id?: Maybe, + timerange: TimerangeInput, + filterQuery?: Maybe, + defaultIndex: Array +} - timerange: TimerangeInput; - defaultIndex: string[]; - } +export interface SourceTlsArgs { + filterQuery?: Maybe, + id?: Maybe, + ip: Scalars['String'], + pagination: PaginationInputPaginated, + sort: TlsSortField, + flowTarget: FlowTargetSourceDest, + timerange: TimerangeInput, + defaultIndex: Array +} - export type KpiNetworkResolver< - R = Maybe, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface KpiNetworkArgs { - id?: Maybe; - timerange: TimerangeInput; +export interface SourceUncommonProcessesArgs { + timerange: TimerangeInput, + pagination: PaginationInputPaginated, + filterQuery?: Maybe, + defaultIndex: Array +} - filterQuery?: Maybe; +/** A set of configuration options for a security data source */ +export interface SourceConfiguration { + /** The field mapping to use for this source */ + fields: SourceFields, +} - defaultIndex: string[]; - } +export interface SourceEcsFields { + bytes?: Maybe, + ip?: Maybe, + port?: Maybe, + domain?: Maybe, + geo?: Maybe, + packets?: Maybe, +} - export type KpiHostsResolver< - R = KpiHostsData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface KpiHostsArgs { - id?: Maybe; +/** A mapping of semantic fields to their document counterparts */ +export interface SourceFields { + /** The field to identify a container by */ + container: Scalars['String'], + /** The fields to identify a host by */ + host: Scalars['String'], + /** The fields that may contain the log event message. The first field found win. */ + message: Array, + /** The field to identify a pod by */ + pod: Scalars['String'], + /** The field to use as a tiebreaker for log events that have identical timestamps */ + tiebreaker: Scalars['String'], + /** The field to use as a timestamp for metrics and logs */ + timestamp: Scalars['String'], +} - timerange: TimerangeInput; +/** The status of an infrastructure data source */ +export interface SourceStatus { + /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ + indicesExist: Scalars['Boolean'], + /** The list of fields defined in the index mappings */ + indexFields: Array, +} - filterQuery?: Maybe; - defaultIndex: string[]; - } +/** The status of an infrastructure data source */ +export interface SourceStatusIndicesExistArgs { + defaultIndex: Array +} - export type KpiHostDetailsResolver< - R = KpiHostDetailsData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface KpiHostDetailsArgs { - id?: Maybe; - timerange: TimerangeInput; +/** The status of an infrastructure data source */ +export interface SourceStatusIndexFieldsArgs { + defaultIndex: Array +} - filterQuery?: Maybe; +export interface SshEcsFields { + method?: Maybe, + signature?: Maybe, +} - defaultIndex: string[]; - } +export interface Summary { + actor?: Maybe, + object?: Maybe, + how?: Maybe, + message_type?: Maybe, + sequence?: Maybe, +} - export type MatrixHistogramResolver< - R = MatrixHistogramOverTimeData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface MatrixHistogramArgs { - filterQuery?: Maybe; +export interface SuricataAlertData { + signature?: Maybe, + signature_id?: Maybe, +} - defaultIndex: string[]; +export interface SuricataEcsFields { + eve?: Maybe, +} - timerange: TimerangeInput; +export interface SuricataEveData { + alert?: Maybe, + flow_id?: Maybe, + proto?: Maybe, +} - stackByField: string; +export interface SystemEcsField { + audit?: Maybe, + auth?: Maybe, +} - histogramType: HistogramType; - } +export interface Thread { + id?: Maybe, + start?: Maybe, +} - export type NetworkTopCountriesResolver< - R = NetworkTopCountriesData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface NetworkTopCountriesArgs { - id?: Maybe; +export interface TimelineData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfo, + inspect?: Maybe, +} - filterQuery?: Maybe; +export interface TimelineDetailsData { + data?: Maybe>, + inspect?: Maybe, +} - ip?: Maybe; +export interface TimelineEdges { + node: TimelineItem, + cursor: CursorType, +} - flowTarget: FlowTargetSourceDest; +export interface TimelineInput { + columns?: Maybe>, + dataProviders?: Maybe>, + description?: Maybe, + eventType?: Maybe, + filters?: Maybe>, + kqlMode?: Maybe, + kqlQuery?: Maybe, + title?: Maybe, + dateRange?: Maybe, + savedQueryId?: Maybe, + sort?: Maybe, +} - pagination: PaginationInputPaginated; +export interface TimelineItem { + _id: Scalars['String'], + _index?: Maybe, + data: Array, + ecs: Ecs, +} - sort: NetworkTopTablesSortField; +export interface TimelineNonEcsData { + field: Scalars['String'], + value?: Maybe, +} - timerange: TimerangeInput; +export interface TimelineResult { + columns?: Maybe>, + created?: Maybe, + createdBy?: Maybe, + dataProviders?: Maybe>, + dateRange?: Maybe, + description?: Maybe, + eventIdToNoteIds?: Maybe>, + eventType?: Maybe, + favorite?: Maybe>, + filters?: Maybe>, + kqlMode?: Maybe, + kqlQuery?: Maybe, + notes?: Maybe>, + noteIds?: Maybe>, + pinnedEventIds?: Maybe>, + pinnedEventsSaveObject?: Maybe>, + savedQueryId?: Maybe, + savedObjectId: Scalars['String'], + sort?: Maybe, + title?: Maybe, + updated?: Maybe, + updatedBy?: Maybe, + version: Scalars['String'], +} - defaultIndex: string[]; - } +export interface TimerangeInput { + /** + * The interval string to use for last bucket. The format is '{value}{unit}'. For + * example '5m' would return the metrics for the last 5 minutes of the timespan. + */ + interval: Scalars['String'], + /** The end of the timerange */ + to: Scalars['Float'], + /** The beginning of the timerange */ + from: Scalars['Float'], +} - export type NetworkTopNFlowResolver< - R = NetworkTopNFlowData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface NetworkTopNFlowArgs { - id?: Maybe; +export interface TlsClientCertificateData { + fingerprint?: Maybe, +} - filterQuery?: Maybe; +export interface TlsData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +} - ip?: Maybe; +export interface TlsEcsFields { + client_certificate?: Maybe, + fingerprints?: Maybe, + server_certificate?: Maybe, +} - flowTarget: FlowTargetSourceDest; +export interface TlsEdges { + node: TlsNode, + cursor: CursorType, +} - pagination: PaginationInputPaginated; +export enum TlsFields { + _id = '_id' +} - sort: NetworkTopTablesSortField; +export interface TlsFingerprintsData { + ja3?: Maybe, +} - timerange: TimerangeInput; +export interface TlsJa3Data { + hash?: Maybe, +} - defaultIndex: string[]; - } +export interface TlsNode { + _id?: Maybe, + timestamp?: Maybe, + alternativeNames?: Maybe>, + notAfter?: Maybe>, + commonNames?: Maybe>, + ja3?: Maybe>, + issuerNames?: Maybe>, +} - export type NetworkDnsResolver< - R = NetworkDnsData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface NetworkDnsArgs { - filterQuery?: Maybe; +export interface TlsServerCertificateData { + fingerprint?: Maybe, +} - id?: Maybe; +export interface TlsSortField { + field: TlsFields, + direction: Direction, +} - isPtrIncluded: boolean; - pagination: PaginationInputPaginated; - sort: NetworkDnsSortField; - stackByField?: Maybe; - timerange: TimerangeInput; +export interface TopCountriesItemDestination { + country?: Maybe, + destination_ips?: Maybe, + flows?: Maybe, + location?: Maybe, + source_ips?: Maybe, +} - defaultIndex: string[]; - } +export interface TopCountriesItemSource { + country?: Maybe, + destination_ips?: Maybe, + flows?: Maybe, + location?: Maybe, + source_ips?: Maybe, +} - export type NetworkDnsHistogramResolver< - R = NetworkDsOverTimeData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface NetworkDnsHistogramArgs { - filterQuery?: Maybe; +export interface TopNetworkTablesEcsField { + bytes_in?: Maybe, + bytes_out?: Maybe, +} - defaultIndex: string[]; +export interface TopNFlowItemDestination { + autonomous_system?: Maybe, + domain?: Maybe>, + ip?: Maybe, + location?: Maybe, + flows?: Maybe, + source_ips?: Maybe, +} - timerange: TimerangeInput; +export interface TopNFlowItemSource { + autonomous_system?: Maybe, + domain?: Maybe>, + ip?: Maybe, + location?: Maybe, + flows?: Maybe, + destination_ips?: Maybe, +} - stackByField?: Maybe; - } - export type NetworkHttpResolver< - R = NetworkHttpData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface NetworkHttpArgs { - id?: Maybe; +export interface UncommonProcessesData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +} - filterQuery?: Maybe; +export interface UncommonProcessesEdges { + node: UncommonProcessItem, + cursor: CursorType, +} - ip?: Maybe; +export interface UncommonProcessItem { + _id: Scalars['String'], + instances: Scalars['Float'], + process: ProcessEcsFields, + hosts: Array, + user?: Maybe, +} - pagination: PaginationInputPaginated; +export interface UrlEcsFields { + domain?: Maybe, + original?: Maybe, + username?: Maybe, + password?: Maybe, +} - sort: NetworkHttpSortField; +export interface UserEcsFields { + domain?: Maybe, + id?: Maybe, + name?: Maybe, + full_name?: Maybe, + email?: Maybe, + hash?: Maybe, + group?: Maybe, +} - timerange: TimerangeInput; +export interface UsersData { + edges: Array, + totalCount: Scalars['Float'], + pageInfo: PageInfoPaginated, + inspect?: Maybe, +} - defaultIndex: string[]; - } +export interface UsersEdges { + node: UsersNode, + cursor: CursorType, +} - export type OverviewNetworkResolver< - R = Maybe, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface OverviewNetworkArgs { - id?: Maybe; +export enum UsersFields { + name = 'name', + count = 'count' +} - timerange: TimerangeInput; +export interface UsersItem { + name?: Maybe, + id?: Maybe, + groupId?: Maybe, + groupName?: Maybe, + count?: Maybe, +} - filterQuery?: Maybe; +export interface UsersNode { + _id?: Maybe, + timestamp?: Maybe, + user?: Maybe, +} - defaultIndex: string[]; - } +export interface UsersSortField { + field: UsersFields, + direction: Direction, +} - export type OverviewHostResolver< - R = Maybe, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface OverviewHostArgs { - id?: Maybe; +export interface WinlogEcsFields { + event_id?: Maybe, +} - timerange: TimerangeInput; +export interface ZeekConnectionData { + local_resp?: Maybe, + local_orig?: Maybe, + missed_bytes?: Maybe, + state?: Maybe, + history?: Maybe, +} - filterQuery?: Maybe; +export interface ZeekDnsData { + AA?: Maybe, + qclass_name?: Maybe, + RD?: Maybe, + qtype_name?: Maybe, + rejected?: Maybe, + qtype?: Maybe, + query?: Maybe, + trans_id?: Maybe, + qclass?: Maybe, + RA?: Maybe, + TC?: Maybe, +} - defaultIndex: string[]; - } +export interface ZeekEcsFields { + session_id?: Maybe, + connection?: Maybe, + notice?: Maybe, + dns?: Maybe, + http?: Maybe, + files?: Maybe, + ssl?: Maybe, +} - export type TlsResolver = Resolver< - R, - Parent, - TContext, - TlsArgs - >; - export interface TlsArgs { - filterQuery?: Maybe; +export interface ZeekFileData { + session_ids?: Maybe, + timedout?: Maybe, + local_orig?: Maybe, + tx_host?: Maybe, + source?: Maybe, + is_orig?: Maybe, + overflow_bytes?: Maybe, + sha1?: Maybe, + duration?: Maybe, + depth?: Maybe, + analyzers?: Maybe, + mime_type?: Maybe, + rx_host?: Maybe, + total_bytes?: Maybe, + fuid?: Maybe, + seen_bytes?: Maybe, + missing_bytes?: Maybe, + md5?: Maybe, +} - id?: Maybe; +export interface ZeekHttpData { + resp_mime_types?: Maybe, + trans_depth?: Maybe, + status_msg?: Maybe, + resp_fuids?: Maybe, + tags?: Maybe, +} - ip: string; +export interface ZeekNoticeData { + suppress_for?: Maybe, + msg?: Maybe, + note?: Maybe, + sub?: Maybe, + dst?: Maybe, + dropped?: Maybe, + peer_descr?: Maybe, +} - pagination: PaginationInputPaginated; +export interface ZeekSslData { + cipher?: Maybe, + established?: Maybe, + resumed?: Maybe, + version?: Maybe, +} - sort: TlsSortField; +export type WithIndex = TObject & Record; +export type ResolversObject = WithIndex; - flowTarget: FlowTargetSourceDest; +export type ResolverTypeWrapper = Promise | T; - timerange: TimerangeInput; +export type ResolverFn = ( + parent: TParent, + args: TArgs, + context: TContext, + info: GraphQLResolveInfo +) => Promise | TResult; - defaultIndex: string[]; - } - export type UncommonProcessesResolver< - R = UncommonProcessesData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface UncommonProcessesArgs { - timerange: TimerangeInput; +export type StitchingResolver = { + fragment: string; + resolve: ResolverFn; +}; - pagination: PaginationInputPaginated; +export type Resolver = + | ResolverFn + | StitchingResolver; - filterQuery?: Maybe; +export type SubscriptionSubscribeFn = ( + parent: TParent, + args: TArgs, + context: TContext, + info: GraphQLResolveInfo +) => AsyncIterator | Promise>; - defaultIndex: string[]; - } +export type SubscriptionResolveFn = ( + parent: TParent, + args: TArgs, + context: TContext, + info: GraphQLResolveInfo +) => TResult | Promise; - export type WhoAmIResolver< - R = Maybe, - Parent = Source, - TContext = SiemContext - > = Resolver; -} -/** A set of configuration options for a security data source */ -export namespace SourceConfigurationResolvers { - export interface Resolvers { - /** The field mapping to use for this source */ - fields?: FieldsResolver; - } - - export type FieldsResolver< - R = SourceFields, - Parent = SourceConfiguration, - TContext = SiemContext - > = Resolver; -} -/** A mapping of semantic fields to their document counterparts */ -export namespace SourceFieldsResolvers { - export interface Resolvers { - /** The field to identify a container by */ - container?: ContainerResolver; - /** The fields to identify a host by */ - host?: HostResolver; - /** The fields that may contain the log event message. The first field found win. */ - message?: MessageResolver; - /** The field to identify a pod by */ - pod?: PodResolver; - /** The field to use as a tiebreaker for log events that have identical timestamps */ - tiebreaker?: TiebreakerResolver; - /** The field to use as a timestamp for metrics and logs */ - timestamp?: TimestampResolver; - } - - export type ContainerResolver< - R = string, - Parent = SourceFields, - TContext = SiemContext - > = Resolver; - export type HostResolver = Resolver< - R, - Parent, - TContext - >; - export type MessageResolver< - R = string[], - Parent = SourceFields, - TContext = SiemContext - > = Resolver; - export type PodResolver = Resolver< - R, - Parent, - TContext - >; - export type TiebreakerResolver< - R = string, - Parent = SourceFields, - TContext = SiemContext - > = Resolver; - export type TimestampResolver< - R = string, - Parent = SourceFields, - TContext = SiemContext - > = Resolver; -} -/** The status of an infrastructure data source */ -export namespace SourceStatusResolvers { - export interface Resolvers { - /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ - indicesExist?: IndicesExistResolver; - /** The list of fields defined in the index mappings */ - indexFields?: IndexFieldsResolver; - } - - export type IndicesExistResolver< - R = boolean, - Parent = SourceStatus, - TContext = SiemContext - > = Resolver; - export interface IndicesExistArgs { - defaultIndex: string[]; - } - - export type IndexFieldsResolver< - R = IndexField[], - Parent = SourceStatus, - TContext = SiemContext - > = Resolver; - export interface IndexFieldsArgs { - defaultIndex: string[]; - } +export interface SubscriptionSubscriberObject { + subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>; + resolve?: SubscriptionResolveFn; } -/** A descriptor of a field in an index */ -export namespace IndexFieldResolvers { - export interface Resolvers { - /** Where the field belong */ - category?: CategoryResolver; - /** Example of field's value */ - example?: ExampleResolver, TypeParent, TContext>; - /** whether the field's belong to an alias index */ - indexes?: IndexesResolver<(Maybe)[], TypeParent, TContext>; - /** The name of the field */ - name?: NameResolver; - /** The type of the field's values as recognized by Kibana */ - type?: TypeResolver; - /** Whether the field's values can be efficiently searched for */ - searchable?: SearchableResolver; - /** Whether the field's values can be aggregated */ - aggregatable?: AggregatableResolver; - /** Description of the field */ - description?: DescriptionResolver, TypeParent, TContext>; - - format?: FormatResolver, TypeParent, TContext>; - } - - export type CategoryResolver = Resolver< - R, - Parent, - TContext - >; - export type ExampleResolver< - R = Maybe, - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type IndexesResolver< - R = (Maybe)[], - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type NameResolver = Resolver< - R, - Parent, - TContext - >; - export type TypeResolver = Resolver< - R, - Parent, - TContext - >; - export type SearchableResolver< - R = boolean, - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type AggregatableResolver< - R = boolean, - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type DescriptionResolver< - R = Maybe, - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type FormatResolver< - R = Maybe, - Parent = IndexField, - TContext = SiemContext - > = Resolver; -} - -export namespace AuthenticationsDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = AuthenticationsEdges[], - Parent = AuthenticationsData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = AuthenticationsData, - TContext = SiemContext - > = Resolver; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = AuthenticationsData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = AuthenticationsData, - TContext = SiemContext - > = Resolver; -} - -export namespace AuthenticationsEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver< - R = AuthenticationItem, - Parent = AuthenticationsEdges, - TContext = SiemContext - > = Resolver; - export type CursorResolver< - R = CursorType, - Parent = AuthenticationsEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace AuthenticationItemResolvers { - export interface Resolvers { - _id?: _IdResolver; - - failures?: FailuresResolver; - - successes?: SuccessesResolver; - - user?: UserResolver; - - lastSuccess?: LastSuccessResolver, TypeParent, TContext>; - - lastFailure?: LastFailureResolver, TypeParent, TContext>; - } - - export type _IdResolver< - R = string, - Parent = AuthenticationItem, - TContext = SiemContext - > = Resolver; - export type FailuresResolver< - R = number, - Parent = AuthenticationItem, - TContext = SiemContext - > = Resolver; - export type SuccessesResolver< - R = number, - Parent = AuthenticationItem, - TContext = SiemContext - > = Resolver; - export type UserResolver< - R = UserEcsFields, - Parent = AuthenticationItem, - TContext = SiemContext - > = Resolver; - export type LastSuccessResolver< - R = Maybe, - Parent = AuthenticationItem, - TContext = SiemContext - > = Resolver; - export type LastFailureResolver< - R = Maybe, - Parent = AuthenticationItem, - TContext = SiemContext - > = Resolver; -} - -export namespace UserEcsFieldsResolvers { - export interface Resolvers { - domain?: DomainResolver, TypeParent, TContext>; - - id?: IdResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - full_name?: FullNameResolver, TypeParent, TContext>; - - email?: EmailResolver, TypeParent, TContext>; - - hash?: HashResolver, TypeParent, TContext>; - - group?: GroupResolver, TypeParent, TContext>; - } - - export type DomainResolver< - R = Maybe, - Parent = UserEcsFields, - TContext = SiemContext - > = Resolver; - export type IdResolver< - R = Maybe, - Parent = UserEcsFields, - TContext = SiemContext - > = Resolver; - export type NameResolver< - R = Maybe, - Parent = UserEcsFields, - TContext = SiemContext - > = Resolver; - export type FullNameResolver< - R = Maybe, - Parent = UserEcsFields, - TContext = SiemContext - > = Resolver; - export type EmailResolver< - R = Maybe, - Parent = UserEcsFields, - TContext = SiemContext - > = Resolver; - export type HashResolver< - R = Maybe, - Parent = UserEcsFields, - TContext = SiemContext - > = Resolver; - export type GroupResolver< - R = Maybe, - Parent = UserEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace LastSourceHostResolvers { - export interface Resolvers { - timestamp?: TimestampResolver, TypeParent, TContext>; - - source?: SourceResolver, TypeParent, TContext>; - - host?: HostResolver, TypeParent, TContext>; - } - - export type TimestampResolver< - R = Maybe, - Parent = LastSourceHost, - TContext = SiemContext - > = Resolver; - export type SourceResolver< - R = Maybe, - Parent = LastSourceHost, - TContext = SiemContext - > = Resolver; - export type HostResolver< - R = Maybe, - Parent = LastSourceHost, - TContext = SiemContext - > = Resolver; -} - -export namespace SourceEcsFieldsResolvers { - export interface Resolvers { - bytes?: BytesResolver, TypeParent, TContext>; - - ip?: IpResolver, TypeParent, TContext>; - - port?: PortResolver, TypeParent, TContext>; - - domain?: DomainResolver, TypeParent, TContext>; - - geo?: GeoResolver, TypeParent, TContext>; - - packets?: PacketsResolver, TypeParent, TContext>; - } - - export type BytesResolver< - R = Maybe, - Parent = SourceEcsFields, - TContext = SiemContext - > = Resolver; - export type IpResolver< - R = Maybe, - Parent = SourceEcsFields, - TContext = SiemContext - > = Resolver; - export type PortResolver< - R = Maybe, - Parent = SourceEcsFields, - TContext = SiemContext - > = Resolver; - export type DomainResolver< - R = Maybe, - Parent = SourceEcsFields, - TContext = SiemContext - > = Resolver; - export type GeoResolver< - R = Maybe, - Parent = SourceEcsFields, - TContext = SiemContext - > = Resolver; - export type PacketsResolver< - R = Maybe, - Parent = SourceEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace GeoEcsFieldsResolvers { - export interface Resolvers { - city_name?: CityNameResolver, TypeParent, TContext>; - - continent_name?: ContinentNameResolver, TypeParent, TContext>; - - country_iso_code?: CountryIsoCodeResolver, TypeParent, TContext>; - - country_name?: CountryNameResolver, TypeParent, TContext>; - - location?: LocationResolver, TypeParent, TContext>; - - region_iso_code?: RegionIsoCodeResolver, TypeParent, TContext>; - - region_name?: RegionNameResolver, TypeParent, TContext>; - } - - export type CityNameResolver< - R = Maybe, - Parent = GeoEcsFields, - TContext = SiemContext - > = Resolver; - export type ContinentNameResolver< - R = Maybe, - Parent = GeoEcsFields, - TContext = SiemContext - > = Resolver; - export type CountryIsoCodeResolver< - R = Maybe, - Parent = GeoEcsFields, - TContext = SiemContext - > = Resolver; - export type CountryNameResolver< - R = Maybe, - Parent = GeoEcsFields, - TContext = SiemContext - > = Resolver; - export type LocationResolver< - R = Maybe, - Parent = GeoEcsFields, - TContext = SiemContext - > = Resolver; - export type RegionIsoCodeResolver< - R = Maybe, - Parent = GeoEcsFields, - TContext = SiemContext - > = Resolver; - export type RegionNameResolver< - R = Maybe, - Parent = GeoEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace LocationResolvers { - export interface Resolvers { - lon?: LonResolver, TypeParent, TContext>; - - lat?: LatResolver, TypeParent, TContext>; - } - - export type LonResolver< - R = Maybe, - Parent = Location, - TContext = SiemContext - > = Resolver; - export type LatResolver< - R = Maybe, - Parent = Location, - TContext = SiemContext - > = Resolver; -} - -export namespace HostEcsFieldsResolvers { - export interface Resolvers { - architecture?: ArchitectureResolver, TypeParent, TContext>; - - id?: IdResolver, TypeParent, TContext>; - - ip?: IpResolver, TypeParent, TContext>; - - mac?: MacResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - os?: OsResolver, TypeParent, TContext>; - - type?: TypeResolver, TypeParent, TContext>; - } - - export type ArchitectureResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type IdResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type IpResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type MacResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type NameResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type OsResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type TypeResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace OsEcsFieldsResolvers { - export interface Resolvers { - platform?: PlatformResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - full?: FullResolver, TypeParent, TContext>; - - family?: FamilyResolver, TypeParent, TContext>; - - version?: VersionResolver, TypeParent, TContext>; - - kernel?: KernelResolver, TypeParent, TContext>; - } - - export type PlatformResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; - export type NameResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; - export type FullResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; - export type FamilyResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; - export type KernelResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace CursorTypeResolvers { - export interface Resolvers { - value?: ValueResolver, TypeParent, TContext>; - - tiebreaker?: TiebreakerResolver, TypeParent, TContext>; - } - - export type ValueResolver< - R = Maybe, - Parent = CursorType, - TContext = SiemContext - > = Resolver; - export type TiebreakerResolver< - R = Maybe, - Parent = CursorType, - TContext = SiemContext - > = Resolver; -} - -export namespace PageInfoPaginatedResolvers { - export interface Resolvers { - activePage?: ActivePageResolver; - - fakeTotalCount?: FakeTotalCountResolver; - - showMorePagesIndicator?: ShowMorePagesIndicatorResolver; - } - - export type ActivePageResolver< - R = number, - Parent = PageInfoPaginated, - TContext = SiemContext - > = Resolver; - export type FakeTotalCountResolver< - R = number, - Parent = PageInfoPaginated, - TContext = SiemContext - > = Resolver; - export type ShowMorePagesIndicatorResolver< - R = boolean, - Parent = PageInfoPaginated, - TContext = SiemContext - > = Resolver; -} - -export namespace InspectResolvers { - export interface Resolvers { - dsl?: DslResolver; - - response?: ResponseResolver; - } - - export type DslResolver = Resolver< - R, - Parent, - TContext - >; - export type ResponseResolver = Resolver< - R, - Parent, - TContext - >; -} - -export namespace TimelineDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = TimelineEdges[], - Parent = TimelineData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = TimelineData, - TContext = SiemContext - > = Resolver; - export type PageInfoResolver< - R = PageInfo, - Parent = TimelineData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = TimelineData, - TContext = SiemContext - > = Resolver; -} - -export namespace TimelineEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - export type NodeResolver< - R = TimelineItem, - Parent = TimelineEdges, - TContext = SiemContext - > = Resolver; - export type CursorResolver< - R = CursorType, - Parent = TimelineEdges, - TContext = SiemContext - > = Resolver; +export interface SubscriptionResolverObject { + subscribe: SubscriptionSubscribeFn; + resolve: SubscriptionResolveFn; } -export namespace TimelineItemResolvers { - export interface Resolvers { - _id?: _IdResolver; +export type SubscriptionObject = + | SubscriptionSubscriberObject + | SubscriptionResolverObject; + +export type SubscriptionResolver = + | ((...args: any[]) => SubscriptionObject) + | SubscriptionObject; + +export type TypeResolveFn = ( + parent: TParent, + context: TContext, + info: GraphQLResolveInfo +) => Maybe; - _index?: _IndexResolver, TypeParent, TContext>; +export type isTypeOfResolverFn = (obj: T, info: GraphQLResolveInfo) => boolean; - data?: DataResolver; +export type NextResolverFn = () => Promise; - ecs?: EcsResolver; - } +export type DirectiveResolverFn = ( + next: NextResolverFn, + parent: TParent, + args: TArgs, + context: TContext, + info: GraphQLResolveInfo +) => TResult | Promise; - export type _IdResolver = Resolver< - R, - Parent, - TContext - >; - export type _IndexResolver< - R = Maybe, - Parent = TimelineItem, - TContext = SiemContext - > = Resolver; - export type DataResolver< - R = TimelineNonEcsData[], - Parent = TimelineItem, - TContext = SiemContext - > = Resolver; - export type EcsResolver = Resolver< - R, - Parent, - TContext - >; -} - -export namespace TimelineNonEcsDataResolvers { - export interface Resolvers { - field?: FieldResolver; - - value?: ValueResolver, TypeParent, TContext>; - } - - export type FieldResolver< - R = string, - Parent = TimelineNonEcsData, - TContext = SiemContext - > = Resolver; - export type ValueResolver< - R = Maybe, - Parent = TimelineNonEcsData, - TContext = SiemContext - > = Resolver; -} - -export namespace EcsResolvers { - export interface Resolvers { - _id?: _IdResolver; - - _index?: _IndexResolver, TypeParent, TContext>; - - auditd?: AuditdResolver, TypeParent, TContext>; - - destination?: DestinationResolver, TypeParent, TContext>; - - dns?: DnsResolver, TypeParent, TContext>; - - endgame?: EndgameResolver, TypeParent, TContext>; - - event?: EventResolver, TypeParent, TContext>; - - geo?: GeoResolver, TypeParent, TContext>; - - host?: HostResolver, TypeParent, TContext>; - - network?: NetworkResolver, TypeParent, TContext>; - - rule?: RuleResolver, TypeParent, TContext>; - - signal?: SignalResolver, TypeParent, TContext>; - - source?: SourceResolver, TypeParent, TContext>; - - suricata?: SuricataResolver, TypeParent, TContext>; - - tls?: TlsResolver, TypeParent, TContext>; - - zeek?: ZeekResolver, TypeParent, TContext>; - - http?: HttpResolver, TypeParent, TContext>; - - url?: UrlResolver, TypeParent, TContext>; - - timestamp?: TimestampResolver, TypeParent, TContext>; - - message?: MessageResolver, TypeParent, TContext>; - - user?: UserResolver, TypeParent, TContext>; - - winlog?: WinlogResolver, TypeParent, TContext>; - - process?: ProcessResolver, TypeParent, TContext>; - - file?: FileResolver, TypeParent, TContext>; - - system?: SystemResolver, TypeParent, TContext>; - } - - export type _IdResolver = Resolver< - R, - Parent, - TContext - >; - export type _IndexResolver, Parent = Ecs, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type AuditdResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type DestinationResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type DnsResolver, Parent = Ecs, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type EndgameResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type EventResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type GeoResolver, Parent = Ecs, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type HostResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type NetworkResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type RuleResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type SignalResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type SourceResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type SuricataResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type TlsResolver, Parent = Ecs, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type ZeekResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type HttpResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type UrlResolver, Parent = Ecs, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type TimestampResolver, Parent = Ecs, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type MessageResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type UserResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type WinlogResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type ProcessResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; - export type FileResolver, Parent = Ecs, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type SystemResolver< - R = Maybe, - Parent = Ecs, - TContext = SiemContext - > = Resolver; -} - -export namespace AuditdEcsFieldsResolvers { - export interface Resolvers { - result?: ResultResolver, TypeParent, TContext>; - - session?: SessionResolver, TypeParent, TContext>; - - data?: DataResolver, TypeParent, TContext>; - - summary?: SummaryResolver, TypeParent, TContext>; - - sequence?: SequenceResolver, TypeParent, TContext>; - } - - export type ResultResolver< - R = Maybe, - Parent = AuditdEcsFields, - TContext = SiemContext - > = Resolver; - export type SessionResolver< - R = Maybe, - Parent = AuditdEcsFields, - TContext = SiemContext - > = Resolver; - export type DataResolver< - R = Maybe, - Parent = AuditdEcsFields, - TContext = SiemContext - > = Resolver; - export type SummaryResolver< - R = Maybe, - Parent = AuditdEcsFields, - TContext = SiemContext - > = Resolver; - export type SequenceResolver< - R = Maybe, - Parent = AuditdEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace AuditdDataResolvers { - export interface Resolvers { - acct?: AcctResolver, TypeParent, TContext>; - - terminal?: TerminalResolver, TypeParent, TContext>; - - op?: OpResolver, TypeParent, TContext>; - } - - export type AcctResolver< - R = Maybe, - Parent = AuditdData, - TContext = SiemContext - > = Resolver; - export type TerminalResolver< - R = Maybe, - Parent = AuditdData, - TContext = SiemContext - > = Resolver; - export type OpResolver< - R = Maybe, - Parent = AuditdData, - TContext = SiemContext - > = Resolver; -} - -export namespace SummaryResolvers { - export interface Resolvers { - actor?: ActorResolver, TypeParent, TContext>; - - object?: ObjectResolver, TypeParent, TContext>; - - how?: HowResolver, TypeParent, TContext>; - - message_type?: MessageTypeResolver, TypeParent, TContext>; - - sequence?: SequenceResolver, TypeParent, TContext>; - } - - export type ActorResolver< - R = Maybe, - Parent = Summary, - TContext = SiemContext - > = Resolver; - export type ObjectResolver< - R = Maybe, - Parent = Summary, - TContext = SiemContext - > = Resolver; - export type HowResolver< - R = Maybe, - Parent = Summary, - TContext = SiemContext - > = Resolver; - export type MessageTypeResolver< - R = Maybe, - Parent = Summary, - TContext = SiemContext - > = Resolver; - export type SequenceResolver< - R = Maybe, - Parent = Summary, - TContext = SiemContext - > = Resolver; -} - -export namespace PrimarySecondaryResolvers { - export interface Resolvers { - primary?: PrimaryResolver, TypeParent, TContext>; - - secondary?: SecondaryResolver, TypeParent, TContext>; - - type?: TypeResolver, TypeParent, TContext>; - } - - export type PrimaryResolver< - R = Maybe, - Parent = PrimarySecondary, - TContext = SiemContext - > = Resolver; - export type SecondaryResolver< - R = Maybe, - Parent = PrimarySecondary, - TContext = SiemContext - > = Resolver; - export type TypeResolver< - R = Maybe, - Parent = PrimarySecondary, - TContext = SiemContext - > = Resolver; -} - -export namespace DestinationEcsFieldsResolvers { - export interface Resolvers { - bytes?: BytesResolver, TypeParent, TContext>; - - ip?: IpResolver, TypeParent, TContext>; - - port?: PortResolver, TypeParent, TContext>; - - domain?: DomainResolver, TypeParent, TContext>; - - geo?: GeoResolver, TypeParent, TContext>; - - packets?: PacketsResolver, TypeParent, TContext>; - } - - export type BytesResolver< - R = Maybe, - Parent = DestinationEcsFields, - TContext = SiemContext - > = Resolver; - export type IpResolver< - R = Maybe, - Parent = DestinationEcsFields, - TContext = SiemContext - > = Resolver; - export type PortResolver< - R = Maybe, - Parent = DestinationEcsFields, - TContext = SiemContext - > = Resolver; - export type DomainResolver< - R = Maybe, - Parent = DestinationEcsFields, - TContext = SiemContext - > = Resolver; - export type GeoResolver< - R = Maybe, - Parent = DestinationEcsFields, - TContext = SiemContext - > = Resolver; - export type PacketsResolver< - R = Maybe, - Parent = DestinationEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace DnsEcsFieldsResolvers { - export interface Resolvers { - question?: QuestionResolver, TypeParent, TContext>; - - resolved_ip?: ResolvedIpResolver, TypeParent, TContext>; - - response_code?: ResponseCodeResolver, TypeParent, TContext>; - } - - export type QuestionResolver< - R = Maybe, - Parent = DnsEcsFields, - TContext = SiemContext - > = Resolver; - export type ResolvedIpResolver< - R = Maybe, - Parent = DnsEcsFields, - TContext = SiemContext - > = Resolver; - export type ResponseCodeResolver< - R = Maybe, - Parent = DnsEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace DnsQuestionDataResolvers { - export interface Resolvers { - name?: NameResolver, TypeParent, TContext>; - - type?: TypeResolver, TypeParent, TContext>; - } - - export type NameResolver< - R = Maybe, - Parent = DnsQuestionData, - TContext = SiemContext - > = Resolver; - export type TypeResolver< - R = Maybe, - Parent = DnsQuestionData, - TContext = SiemContext - > = Resolver; -} - -export namespace EndgameEcsFieldsResolvers { - export interface Resolvers { - exit_code?: ExitCodeResolver, TypeParent, TContext>; - - file_name?: FileNameResolver, TypeParent, TContext>; - - file_path?: FilePathResolver, TypeParent, TContext>; - - logon_type?: LogonTypeResolver, TypeParent, TContext>; - - parent_process_name?: ParentProcessNameResolver, TypeParent, TContext>; - - pid?: PidResolver, TypeParent, TContext>; - - process_name?: ProcessNameResolver, TypeParent, TContext>; - - subject_domain_name?: SubjectDomainNameResolver, TypeParent, TContext>; - - subject_logon_id?: SubjectLogonIdResolver, TypeParent, TContext>; - - subject_user_name?: SubjectUserNameResolver, TypeParent, TContext>; - - target_domain_name?: TargetDomainNameResolver, TypeParent, TContext>; - - target_logon_id?: TargetLogonIdResolver, TypeParent, TContext>; - - target_user_name?: TargetUserNameResolver, TypeParent, TContext>; - } - - export type ExitCodeResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type FileNameResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type FilePathResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type LogonTypeResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type ParentProcessNameResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type PidResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type ProcessNameResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type SubjectDomainNameResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type SubjectLogonIdResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type SubjectUserNameResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type TargetDomainNameResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type TargetLogonIdResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; - export type TargetUserNameResolver< - R = Maybe, - Parent = EndgameEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace EventEcsFieldsResolvers { - export interface Resolvers { - action?: ActionResolver, TypeParent, TContext>; - - category?: CategoryResolver, TypeParent, TContext>; - - code?: CodeResolver, TypeParent, TContext>; - - created?: CreatedResolver, TypeParent, TContext>; - - dataset?: DatasetResolver, TypeParent, TContext>; - - duration?: DurationResolver, TypeParent, TContext>; - - end?: EndResolver, TypeParent, TContext>; - - hash?: HashResolver, TypeParent, TContext>; - - id?: IdResolver, TypeParent, TContext>; - - kind?: KindResolver, TypeParent, TContext>; - - module?: ModuleResolver, TypeParent, TContext>; - - original?: OriginalResolver, TypeParent, TContext>; - - outcome?: OutcomeResolver, TypeParent, TContext>; - - risk_score?: RiskScoreResolver, TypeParent, TContext>; - - risk_score_norm?: RiskScoreNormResolver, TypeParent, TContext>; - - severity?: SeverityResolver, TypeParent, TContext>; - - start?: StartResolver, TypeParent, TContext>; - - timezone?: TimezoneResolver, TypeParent, TContext>; - - type?: TypeResolver, TypeParent, TContext>; - } - - export type ActionResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type CategoryResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type CodeResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type CreatedResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type DatasetResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type DurationResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type EndResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type HashResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type IdResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type KindResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type ModuleResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type OriginalResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type OutcomeResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type RiskScoreResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type RiskScoreNormResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type SeverityResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type StartResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type TimezoneResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; - export type TypeResolver< - R = Maybe, - Parent = EventEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkEcsFieldResolvers { - export interface Resolvers { - bytes?: BytesResolver, TypeParent, TContext>; - - community_id?: CommunityIdResolver, TypeParent, TContext>; - - direction?: DirectionResolver, TypeParent, TContext>; - - packets?: PacketsResolver, TypeParent, TContext>; - - protocol?: ProtocolResolver, TypeParent, TContext>; - - transport?: TransportResolver, TypeParent, TContext>; - } - - export type BytesResolver< - R = Maybe, - Parent = NetworkEcsField, - TContext = SiemContext - > = Resolver; - export type CommunityIdResolver< - R = Maybe, - Parent = NetworkEcsField, - TContext = SiemContext - > = Resolver; - export type DirectionResolver< - R = Maybe, - Parent = NetworkEcsField, - TContext = SiemContext - > = Resolver; - export type PacketsResolver< - R = Maybe, - Parent = NetworkEcsField, - TContext = SiemContext - > = Resolver; - export type ProtocolResolver< - R = Maybe, - Parent = NetworkEcsField, - TContext = SiemContext - > = Resolver; - export type TransportResolver< - R = Maybe, - Parent = NetworkEcsField, - TContext = SiemContext - > = Resolver; -} - -export namespace RuleEcsFieldResolvers { - export interface Resolvers { - reference?: ReferenceResolver, TypeParent, TContext>; - } - - export type ReferenceResolver< - R = Maybe, - Parent = RuleEcsField, - TContext = SiemContext - > = Resolver; -} - -export namespace SignalFieldResolvers { - export interface Resolvers { - rule?: RuleResolver, TypeParent, TContext>; - - original_time?: OriginalTimeResolver, TypeParent, TContext>; - } - - export type RuleResolver< - R = Maybe, - Parent = SignalField, - TContext = SiemContext - > = Resolver; - export type OriginalTimeResolver< - R = Maybe, - Parent = SignalField, - TContext = SiemContext - > = Resolver; -} - -export namespace RuleFieldResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - - rule_id?: RuleIdResolver, TypeParent, TContext>; - - false_positives?: FalsePositivesResolver; - - saved_id?: SavedIdResolver, TypeParent, TContext>; - - timeline_id?: TimelineIdResolver, TypeParent, TContext>; - - timeline_title?: TimelineTitleResolver, TypeParent, TContext>; - - max_signals?: MaxSignalsResolver, TypeParent, TContext>; - - risk_score?: RiskScoreResolver, TypeParent, TContext>; - - output_index?: OutputIndexResolver, TypeParent, TContext>; - - description?: DescriptionResolver, TypeParent, TContext>; - - from?: FromResolver, TypeParent, TContext>; - - immutable?: ImmutableResolver, TypeParent, TContext>; - - index?: IndexResolver, TypeParent, TContext>; - - interval?: IntervalResolver, TypeParent, TContext>; - - language?: LanguageResolver, TypeParent, TContext>; - - query?: QueryResolver, TypeParent, TContext>; - - references?: ReferencesResolver, TypeParent, TContext>; - - severity?: SeverityResolver, TypeParent, TContext>; - - tags?: TagsResolver, TypeParent, TContext>; - - threat?: ThreatResolver, TypeParent, TContext>; - - type?: TypeResolver, TypeParent, TContext>; - - size?: SizeResolver, TypeParent, TContext>; - - to?: ToResolver, TypeParent, TContext>; - - enabled?: EnabledResolver, TypeParent, TContext>; - - filters?: FiltersResolver, TypeParent, TContext>; - - created_at?: CreatedAtResolver, TypeParent, TContext>; - - updated_at?: UpdatedAtResolver, TypeParent, TContext>; - - created_by?: CreatedByResolver, TypeParent, TContext>; - - updated_by?: UpdatedByResolver, TypeParent, TContext>; - - version?: VersionResolver, TypeParent, TContext>; - } - - export type IdResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type RuleIdResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type FalsePositivesResolver< - R = string[], - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type SavedIdResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type TimelineIdResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type TimelineTitleResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type MaxSignalsResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type RiskScoreResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type OutputIndexResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type DescriptionResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type FromResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type ImmutableResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type IndexResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type IntervalResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type LanguageResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type QueryResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type ReferencesResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type SeverityResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type TagsResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type ThreatResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type TypeResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type SizeResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type ToResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type EnabledResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type FiltersResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type CreatedAtResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type UpdatedAtResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type CreatedByResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type UpdatedByResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = Maybe, - Parent = RuleField, - TContext = SiemContext - > = Resolver; -} - -export namespace SuricataEcsFieldsResolvers { - export interface Resolvers { - eve?: EveResolver, TypeParent, TContext>; - } - - export type EveResolver< - R = Maybe, - Parent = SuricataEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace SuricataEveDataResolvers { - export interface Resolvers { - alert?: AlertResolver, TypeParent, TContext>; - - flow_id?: FlowIdResolver, TypeParent, TContext>; - - proto?: ProtoResolver, TypeParent, TContext>; - } - - export type AlertResolver< - R = Maybe, - Parent = SuricataEveData, - TContext = SiemContext - > = Resolver; - export type FlowIdResolver< - R = Maybe, - Parent = SuricataEveData, - TContext = SiemContext - > = Resolver; - export type ProtoResolver< - R = Maybe, - Parent = SuricataEveData, - TContext = SiemContext - > = Resolver; -} - -export namespace SuricataAlertDataResolvers { - export interface Resolvers { - signature?: SignatureResolver, TypeParent, TContext>; - - signature_id?: SignatureIdResolver, TypeParent, TContext>; - } - - export type SignatureResolver< - R = Maybe, - Parent = SuricataAlertData, - TContext = SiemContext - > = Resolver; - export type SignatureIdResolver< - R = Maybe, - Parent = SuricataAlertData, - TContext = SiemContext - > = Resolver; -} - -export namespace TlsEcsFieldsResolvers { - export interface Resolvers { - client_certificate?: ClientCertificateResolver< - Maybe, - TypeParent, - TContext - >; - - fingerprints?: FingerprintsResolver, TypeParent, TContext>; - - server_certificate?: ServerCertificateResolver< - Maybe, - TypeParent, - TContext - >; - } - - export type ClientCertificateResolver< - R = Maybe, - Parent = TlsEcsFields, - TContext = SiemContext - > = Resolver; - export type FingerprintsResolver< - R = Maybe, - Parent = TlsEcsFields, - TContext = SiemContext - > = Resolver; - export type ServerCertificateResolver< - R = Maybe, - Parent = TlsEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace TlsClientCertificateDataResolvers { - export interface Resolvers { - fingerprint?: FingerprintResolver, TypeParent, TContext>; - } - - export type FingerprintResolver< - R = Maybe, - Parent = TlsClientCertificateData, - TContext = SiemContext - > = Resolver; -} - -export namespace FingerprintDataResolvers { - export interface Resolvers { - sha1?: Sha1Resolver, TypeParent, TContext>; - } - - export type Sha1Resolver< - R = Maybe, - Parent = FingerprintData, - TContext = SiemContext - > = Resolver; -} - -export namespace TlsFingerprintsDataResolvers { - export interface Resolvers { - ja3?: Ja3Resolver, TypeParent, TContext>; - } - - export type Ja3Resolver< - R = Maybe, - Parent = TlsFingerprintsData, - TContext = SiemContext - > = Resolver; -} - -export namespace TlsJa3DataResolvers { - export interface Resolvers { - hash?: HashResolver, TypeParent, TContext>; - } - - export type HashResolver< - R = Maybe, - Parent = TlsJa3Data, - TContext = SiemContext - > = Resolver; -} - -export namespace TlsServerCertificateDataResolvers { - export interface Resolvers { - fingerprint?: FingerprintResolver, TypeParent, TContext>; - } - - export type FingerprintResolver< - R = Maybe, - Parent = TlsServerCertificateData, - TContext = SiemContext - > = Resolver; -} - -export namespace ZeekEcsFieldsResolvers { - export interface Resolvers { - session_id?: SessionIdResolver, TypeParent, TContext>; - - connection?: ConnectionResolver, TypeParent, TContext>; - - notice?: NoticeResolver, TypeParent, TContext>; - - dns?: DnsResolver, TypeParent, TContext>; - - http?: HttpResolver, TypeParent, TContext>; - - files?: FilesResolver, TypeParent, TContext>; - - ssl?: SslResolver, TypeParent, TContext>; - } - - export type SessionIdResolver< - R = Maybe, - Parent = ZeekEcsFields, - TContext = SiemContext - > = Resolver; - export type ConnectionResolver< - R = Maybe, - Parent = ZeekEcsFields, - TContext = SiemContext - > = Resolver; - export type NoticeResolver< - R = Maybe, - Parent = ZeekEcsFields, - TContext = SiemContext - > = Resolver; - export type DnsResolver< - R = Maybe, - Parent = ZeekEcsFields, - TContext = SiemContext - > = Resolver; - export type HttpResolver< - R = Maybe, - Parent = ZeekEcsFields, - TContext = SiemContext - > = Resolver; - export type FilesResolver< - R = Maybe, - Parent = ZeekEcsFields, - TContext = SiemContext - > = Resolver; - export type SslResolver< - R = Maybe, - Parent = ZeekEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace ZeekConnectionDataResolvers { - export interface Resolvers { - local_resp?: LocalRespResolver, TypeParent, TContext>; - - local_orig?: LocalOrigResolver, TypeParent, TContext>; - - missed_bytes?: MissedBytesResolver, TypeParent, TContext>; - - state?: StateResolver, TypeParent, TContext>; - - history?: HistoryResolver, TypeParent, TContext>; - } - - export type LocalRespResolver< - R = Maybe, - Parent = ZeekConnectionData, - TContext = SiemContext - > = Resolver; - export type LocalOrigResolver< - R = Maybe, - Parent = ZeekConnectionData, - TContext = SiemContext - > = Resolver; - export type MissedBytesResolver< - R = Maybe, - Parent = ZeekConnectionData, - TContext = SiemContext - > = Resolver; - export type StateResolver< - R = Maybe, - Parent = ZeekConnectionData, - TContext = SiemContext - > = Resolver; - export type HistoryResolver< - R = Maybe, - Parent = ZeekConnectionData, - TContext = SiemContext - > = Resolver; -} - -export namespace ZeekNoticeDataResolvers { - export interface Resolvers { - suppress_for?: SuppressForResolver, TypeParent, TContext>; - - msg?: MsgResolver, TypeParent, TContext>; - - note?: NoteResolver, TypeParent, TContext>; - - sub?: SubResolver, TypeParent, TContext>; - - dst?: DstResolver, TypeParent, TContext>; - - dropped?: DroppedResolver, TypeParent, TContext>; - - peer_descr?: PeerDescrResolver, TypeParent, TContext>; - } - - export type SuppressForResolver< - R = Maybe, - Parent = ZeekNoticeData, - TContext = SiemContext - > = Resolver; - export type MsgResolver< - R = Maybe, - Parent = ZeekNoticeData, - TContext = SiemContext - > = Resolver; - export type NoteResolver< - R = Maybe, - Parent = ZeekNoticeData, - TContext = SiemContext - > = Resolver; - export type SubResolver< - R = Maybe, - Parent = ZeekNoticeData, - TContext = SiemContext - > = Resolver; - export type DstResolver< - R = Maybe, - Parent = ZeekNoticeData, - TContext = SiemContext - > = Resolver; - export type DroppedResolver< - R = Maybe, - Parent = ZeekNoticeData, - TContext = SiemContext - > = Resolver; - export type PeerDescrResolver< - R = Maybe, - Parent = ZeekNoticeData, - TContext = SiemContext - > = Resolver; -} - -export namespace ZeekDnsDataResolvers { - export interface Resolvers { - AA?: AaResolver, TypeParent, TContext>; - - qclass_name?: QclassNameResolver, TypeParent, TContext>; - - RD?: RdResolver, TypeParent, TContext>; - - qtype_name?: QtypeNameResolver, TypeParent, TContext>; - - rejected?: RejectedResolver, TypeParent, TContext>; - - qtype?: QtypeResolver, TypeParent, TContext>; - - query?: QueryResolver, TypeParent, TContext>; - - trans_id?: TransIdResolver, TypeParent, TContext>; - - qclass?: QclassResolver, TypeParent, TContext>; - - RA?: RaResolver, TypeParent, TContext>; - - TC?: TcResolver, TypeParent, TContext>; - } - - export type AaResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; - export type QclassNameResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; - export type RdResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; - export type QtypeNameResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; - export type RejectedResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; - export type QtypeResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; - export type QueryResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; - export type TransIdResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; - export type QclassResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; - export type RaResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; - export type TcResolver< - R = Maybe, - Parent = ZeekDnsData, - TContext = SiemContext - > = Resolver; -} - -export namespace ZeekHttpDataResolvers { - export interface Resolvers { - resp_mime_types?: RespMimeTypesResolver, TypeParent, TContext>; - - trans_depth?: TransDepthResolver, TypeParent, TContext>; - - status_msg?: StatusMsgResolver, TypeParent, TContext>; - - resp_fuids?: RespFuidsResolver, TypeParent, TContext>; - - tags?: TagsResolver, TypeParent, TContext>; - } - - export type RespMimeTypesResolver< - R = Maybe, - Parent = ZeekHttpData, - TContext = SiemContext - > = Resolver; - export type TransDepthResolver< - R = Maybe, - Parent = ZeekHttpData, - TContext = SiemContext - > = Resolver; - export type StatusMsgResolver< - R = Maybe, - Parent = ZeekHttpData, - TContext = SiemContext - > = Resolver; - export type RespFuidsResolver< - R = Maybe, - Parent = ZeekHttpData, - TContext = SiemContext - > = Resolver; - export type TagsResolver< - R = Maybe, - Parent = ZeekHttpData, - TContext = SiemContext - > = Resolver; -} - -export namespace ZeekFileDataResolvers { - export interface Resolvers { - session_ids?: SessionIdsResolver, TypeParent, TContext>; - - timedout?: TimedoutResolver, TypeParent, TContext>; - - local_orig?: LocalOrigResolver, TypeParent, TContext>; - - tx_host?: TxHostResolver, TypeParent, TContext>; - - source?: SourceResolver, TypeParent, TContext>; - - is_orig?: IsOrigResolver, TypeParent, TContext>; - - overflow_bytes?: OverflowBytesResolver, TypeParent, TContext>; - - sha1?: Sha1Resolver, TypeParent, TContext>; - - duration?: DurationResolver, TypeParent, TContext>; - - depth?: DepthResolver, TypeParent, TContext>; - - analyzers?: AnalyzersResolver, TypeParent, TContext>; - - mime_type?: MimeTypeResolver, TypeParent, TContext>; - - rx_host?: RxHostResolver, TypeParent, TContext>; - - total_bytes?: TotalBytesResolver, TypeParent, TContext>; - - fuid?: FuidResolver, TypeParent, TContext>; - - seen_bytes?: SeenBytesResolver, TypeParent, TContext>; - - missing_bytes?: MissingBytesResolver, TypeParent, TContext>; - - md5?: Md5Resolver, TypeParent, TContext>; - } - - export type SessionIdsResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type TimedoutResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type LocalOrigResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type TxHostResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type SourceResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type IsOrigResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type OverflowBytesResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type Sha1Resolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type DurationResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type DepthResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type AnalyzersResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type MimeTypeResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type RxHostResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type TotalBytesResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type FuidResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type SeenBytesResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type MissingBytesResolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; - export type Md5Resolver< - R = Maybe, - Parent = ZeekFileData, - TContext = SiemContext - > = Resolver; -} - -export namespace ZeekSslDataResolvers { - export interface Resolvers { - cipher?: CipherResolver, TypeParent, TContext>; - - established?: EstablishedResolver, TypeParent, TContext>; - - resumed?: ResumedResolver, TypeParent, TContext>; - - version?: VersionResolver, TypeParent, TContext>; - } - - export type CipherResolver< - R = Maybe, - Parent = ZeekSslData, - TContext = SiemContext - > = Resolver; - export type EstablishedResolver< - R = Maybe, - Parent = ZeekSslData, - TContext = SiemContext - > = Resolver; - export type ResumedResolver< - R = Maybe, - Parent = ZeekSslData, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = Maybe, - Parent = ZeekSslData, - TContext = SiemContext - > = Resolver; -} - -export namespace HttpEcsFieldsResolvers { - export interface Resolvers { - version?: VersionResolver, TypeParent, TContext>; - - request?: RequestResolver, TypeParent, TContext>; - - response?: ResponseResolver, TypeParent, TContext>; - } - - export type VersionResolver< - R = Maybe, - Parent = HttpEcsFields, - TContext = SiemContext - > = Resolver; - export type RequestResolver< - R = Maybe, - Parent = HttpEcsFields, - TContext = SiemContext - > = Resolver; - export type ResponseResolver< - R = Maybe, - Parent = HttpEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace HttpRequestDataResolvers { - export interface Resolvers { - method?: MethodResolver, TypeParent, TContext>; - - body?: BodyResolver, TypeParent, TContext>; - - referrer?: ReferrerResolver, TypeParent, TContext>; - - bytes?: BytesResolver, TypeParent, TContext>; - } - - export type MethodResolver< - R = Maybe, - Parent = HttpRequestData, - TContext = SiemContext - > = Resolver; - export type BodyResolver< - R = Maybe, - Parent = HttpRequestData, - TContext = SiemContext - > = Resolver; - export type ReferrerResolver< - R = Maybe, - Parent = HttpRequestData, - TContext = SiemContext - > = Resolver; - export type BytesResolver< - R = Maybe, - Parent = HttpRequestData, - TContext = SiemContext - > = Resolver; -} - -export namespace HttpBodyDataResolvers { - export interface Resolvers { - content?: ContentResolver, TypeParent, TContext>; - - bytes?: BytesResolver, TypeParent, TContext>; - } - - export type ContentResolver< - R = Maybe, - Parent = HttpBodyData, - TContext = SiemContext - > = Resolver; - export type BytesResolver< - R = Maybe, - Parent = HttpBodyData, - TContext = SiemContext - > = Resolver; -} - -export namespace HttpResponseDataResolvers { - export interface Resolvers { - status_code?: StatusCodeResolver, TypeParent, TContext>; - - body?: BodyResolver, TypeParent, TContext>; - - bytes?: BytesResolver, TypeParent, TContext>; - } - - export type StatusCodeResolver< - R = Maybe, - Parent = HttpResponseData, - TContext = SiemContext - > = Resolver; - export type BodyResolver< - R = Maybe, - Parent = HttpResponseData, - TContext = SiemContext - > = Resolver; - export type BytesResolver< - R = Maybe, - Parent = HttpResponseData, - TContext = SiemContext - > = Resolver; -} - -export namespace UrlEcsFieldsResolvers { - export interface Resolvers { - domain?: DomainResolver, TypeParent, TContext>; - - original?: OriginalResolver, TypeParent, TContext>; - - username?: UsernameResolver, TypeParent, TContext>; - - password?: PasswordResolver, TypeParent, TContext>; - } - - export type DomainResolver< - R = Maybe, - Parent = UrlEcsFields, - TContext = SiemContext - > = Resolver; - export type OriginalResolver< - R = Maybe, - Parent = UrlEcsFields, - TContext = SiemContext - > = Resolver; - export type UsernameResolver< - R = Maybe, - Parent = UrlEcsFields, - TContext = SiemContext - > = Resolver; - export type PasswordResolver< - R = Maybe, - Parent = UrlEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace WinlogEcsFieldsResolvers { - export interface Resolvers { - event_id?: EventIdResolver, TypeParent, TContext>; - } - - export type EventIdResolver< - R = Maybe, - Parent = WinlogEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace ProcessEcsFieldsResolvers { - export interface Resolvers { - hash?: HashResolver, TypeParent, TContext>; - - pid?: PidResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - ppid?: PpidResolver, TypeParent, TContext>; - - args?: ArgsResolver, TypeParent, TContext>; - - executable?: ExecutableResolver, TypeParent, TContext>; - - title?: TitleResolver, TypeParent, TContext>; - - thread?: ThreadResolver, TypeParent, TContext>; - - working_directory?: WorkingDirectoryResolver, TypeParent, TContext>; - } - - export type HashResolver< - R = Maybe, - Parent = ProcessEcsFields, - TContext = SiemContext - > = Resolver; - export type PidResolver< - R = Maybe, - Parent = ProcessEcsFields, - TContext = SiemContext - > = Resolver; - export type NameResolver< - R = Maybe, - Parent = ProcessEcsFields, - TContext = SiemContext - > = Resolver; - export type PpidResolver< - R = Maybe, - Parent = ProcessEcsFields, - TContext = SiemContext - > = Resolver; - export type ArgsResolver< - R = Maybe, - Parent = ProcessEcsFields, - TContext = SiemContext - > = Resolver; - export type ExecutableResolver< - R = Maybe, - Parent = ProcessEcsFields, - TContext = SiemContext - > = Resolver; - export type TitleResolver< - R = Maybe, - Parent = ProcessEcsFields, - TContext = SiemContext - > = Resolver; - export type ThreadResolver< - R = Maybe, - Parent = ProcessEcsFields, - TContext = SiemContext - > = Resolver; - export type WorkingDirectoryResolver< - R = Maybe, - Parent = ProcessEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace ProcessHashDataResolvers { - export interface Resolvers { - md5?: Md5Resolver, TypeParent, TContext>; - - sha1?: Sha1Resolver, TypeParent, TContext>; - - sha256?: Sha256Resolver, TypeParent, TContext>; - } - - export type Md5Resolver< - R = Maybe, - Parent = ProcessHashData, - TContext = SiemContext - > = Resolver; - export type Sha1Resolver< - R = Maybe, - Parent = ProcessHashData, - TContext = SiemContext - > = Resolver; - export type Sha256Resolver< - R = Maybe, - Parent = ProcessHashData, - TContext = SiemContext - > = Resolver; -} - -export namespace ThreadResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - - start?: StartResolver, TypeParent, TContext>; - } - - export type IdResolver< - R = Maybe, - Parent = Thread, - TContext = SiemContext - > = Resolver; - export type StartResolver< - R = Maybe, - Parent = Thread, - TContext = SiemContext - > = Resolver; -} - -export namespace FileFieldsResolvers { - export interface Resolvers { - name?: NameResolver, TypeParent, TContext>; - - path?: PathResolver, TypeParent, TContext>; - - target_path?: TargetPathResolver, TypeParent, TContext>; - - extension?: ExtensionResolver, TypeParent, TContext>; - - type?: TypeResolver, TypeParent, TContext>; - - device?: DeviceResolver, TypeParent, TContext>; - - inode?: InodeResolver, TypeParent, TContext>; - - uid?: UidResolver, TypeParent, TContext>; - - owner?: OwnerResolver, TypeParent, TContext>; - - gid?: GidResolver, TypeParent, TContext>; - - group?: GroupResolver, TypeParent, TContext>; - - mode?: ModeResolver, TypeParent, TContext>; - - size?: SizeResolver, TypeParent, TContext>; - - mtime?: MtimeResolver, TypeParent, TContext>; - - ctime?: CtimeResolver, TypeParent, TContext>; - } - - export type NameResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type PathResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type TargetPathResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type ExtensionResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type TypeResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type DeviceResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type InodeResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type UidResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type OwnerResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type GidResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type GroupResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type ModeResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type SizeResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type MtimeResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; - export type CtimeResolver< - R = Maybe, - Parent = FileFields, - TContext = SiemContext - > = Resolver; -} - -export namespace SystemEcsFieldResolvers { - export interface Resolvers { - audit?: AuditResolver, TypeParent, TContext>; - - auth?: AuthResolver, TypeParent, TContext>; - } - - export type AuditResolver< - R = Maybe, - Parent = SystemEcsField, - TContext = SiemContext - > = Resolver; - export type AuthResolver< - R = Maybe, - Parent = SystemEcsField, - TContext = SiemContext - > = Resolver; -} - -export namespace AuditEcsFieldsResolvers { - export interface Resolvers { - package?: PackageResolver, TypeParent, TContext>; - } - - export type PackageResolver< - R = Maybe, - Parent = AuditEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace PackageEcsFieldsResolvers { - export interface Resolvers { - arch?: ArchResolver, TypeParent, TContext>; - - entity_id?: EntityIdResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - size?: SizeResolver, TypeParent, TContext>; - - summary?: SummaryResolver, TypeParent, TContext>; - - version?: VersionResolver, TypeParent, TContext>; - } - - export type ArchResolver< - R = Maybe, - Parent = PackageEcsFields, - TContext = SiemContext - > = Resolver; - export type EntityIdResolver< - R = Maybe, - Parent = PackageEcsFields, - TContext = SiemContext - > = Resolver; - export type NameResolver< - R = Maybe, - Parent = PackageEcsFields, - TContext = SiemContext - > = Resolver; - export type SizeResolver< - R = Maybe, - Parent = PackageEcsFields, - TContext = SiemContext - > = Resolver; - export type SummaryResolver< - R = Maybe, - Parent = PackageEcsFields, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = Maybe, - Parent = PackageEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace AuthEcsFieldsResolvers { - export interface Resolvers { - ssh?: SshResolver, TypeParent, TContext>; - } - - export type SshResolver< - R = Maybe, - Parent = AuthEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace SshEcsFieldsResolvers { - export interface Resolvers { - method?: MethodResolver, TypeParent, TContext>; - - signature?: SignatureResolver, TypeParent, TContext>; - } - - export type MethodResolver< - R = Maybe, - Parent = SshEcsFields, - TContext = SiemContext - > = Resolver; - export type SignatureResolver< - R = Maybe, - Parent = SshEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace PageInfoResolvers { - export interface Resolvers { - endCursor?: EndCursorResolver, TypeParent, TContext>; - - hasNextPage?: HasNextPageResolver, TypeParent, TContext>; - } - - export type EndCursorResolver< - R = Maybe, - Parent = PageInfo, - TContext = SiemContext - > = Resolver; - export type HasNextPageResolver< - R = Maybe, - Parent = PageInfo, - TContext = SiemContext - > = Resolver; -} - -export namespace TimelineDetailsDataResolvers { - export interface Resolvers { - data?: DataResolver, TypeParent, TContext>; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type DataResolver< - R = Maybe, - Parent = TimelineDetailsData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = TimelineDetailsData, - TContext = SiemContext - > = Resolver; -} - -export namespace DetailItemResolvers { - export interface Resolvers { - field?: FieldResolver; - - values?: ValuesResolver, TypeParent, TContext>; - - originalValue?: OriginalValueResolver, TypeParent, TContext>; - } - - export type FieldResolver = Resolver< - R, - Parent, - TContext - >; - export type ValuesResolver< - R = Maybe, - Parent = DetailItem, - TContext = SiemContext - > = Resolver; - export type OriginalValueResolver< - R = Maybe, - Parent = DetailItem, - TContext = SiemContext - > = Resolver; -} - -export namespace LastEventTimeDataResolvers { - export interface Resolvers { - lastSeen?: LastSeenResolver, TypeParent, TContext>; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type LastSeenResolver< - R = Maybe, - Parent = LastEventTimeData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = LastEventTimeData, - TContext = SiemContext - > = Resolver; -} - -export namespace HostsDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = HostsEdges[], - Parent = HostsData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver = Resolver< - R, - Parent, - TContext - >; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = HostsData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = HostsData, - TContext = SiemContext - > = Resolver; -} - -export namespace HostsEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver = Resolver< - R, - Parent, - TContext - >; - export type CursorResolver< - R = CursorType, - Parent = HostsEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace HostItemResolvers { - export interface Resolvers { - _id?: _IdResolver, TypeParent, TContext>; - - lastSeen?: LastSeenResolver, TypeParent, TContext>; - - host?: HostResolver, TypeParent, TContext>; - - cloud?: CloudResolver, TypeParent, TContext>; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type _IdResolver, Parent = HostItem, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type LastSeenResolver< - R = Maybe, - Parent = HostItem, - TContext = SiemContext - > = Resolver; - export type HostResolver< - R = Maybe, - Parent = HostItem, - TContext = SiemContext - > = Resolver; - export type CloudResolver< - R = Maybe, - Parent = HostItem, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = HostItem, - TContext = SiemContext - > = Resolver; -} - -export namespace CloudFieldsResolvers { - export interface Resolvers { - instance?: InstanceResolver, TypeParent, TContext>; - - machine?: MachineResolver, TypeParent, TContext>; - - provider?: ProviderResolver)[]>, TypeParent, TContext>; - - region?: RegionResolver)[]>, TypeParent, TContext>; - } - - export type InstanceResolver< - R = Maybe, - Parent = CloudFields, - TContext = SiemContext - > = Resolver; - export type MachineResolver< - R = Maybe, - Parent = CloudFields, - TContext = SiemContext - > = Resolver; - export type ProviderResolver< - R = Maybe<(Maybe)[]>, - Parent = CloudFields, - TContext = SiemContext - > = Resolver; - export type RegionResolver< - R = Maybe<(Maybe)[]>, - Parent = CloudFields, - TContext = SiemContext - > = Resolver; -} - -export namespace CloudInstanceResolvers { - export interface Resolvers { - id?: IdResolver)[]>, TypeParent, TContext>; - } - - export type IdResolver< - R = Maybe<(Maybe)[]>, - Parent = CloudInstance, - TContext = SiemContext - > = Resolver; -} - -export namespace CloudMachineResolvers { - export interface Resolvers { - type?: TypeResolver)[]>, TypeParent, TContext>; - } - - export type TypeResolver< - R = Maybe<(Maybe)[]>, - Parent = CloudMachine, - TContext = SiemContext - > = Resolver; -} - -export namespace FirstLastSeenHostResolvers { - export interface Resolvers { - inspect?: InspectResolver, TypeParent, TContext>; - - firstSeen?: FirstSeenResolver, TypeParent, TContext>; - - lastSeen?: LastSeenResolver, TypeParent, TContext>; - } - - export type InspectResolver< - R = Maybe, - Parent = FirstLastSeenHost, - TContext = SiemContext - > = Resolver; - export type FirstSeenResolver< - R = Maybe, - Parent = FirstLastSeenHost, - TContext = SiemContext - > = Resolver; - export type LastSeenResolver< - R = Maybe, - Parent = FirstLastSeenHost, - TContext = SiemContext - > = Resolver; -} - -export namespace IpOverviewDataResolvers { - export interface Resolvers { - client?: ClientResolver, TypeParent, TContext>; - - destination?: DestinationResolver, TypeParent, TContext>; - - host?: HostResolver; - - server?: ServerResolver, TypeParent, TContext>; - - source?: SourceResolver, TypeParent, TContext>; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type ClientResolver< - R = Maybe, - Parent = IpOverviewData, - TContext = SiemContext - > = Resolver; - export type DestinationResolver< - R = Maybe, - Parent = IpOverviewData, - TContext = SiemContext - > = Resolver; - export type HostResolver< - R = HostEcsFields, - Parent = IpOverviewData, - TContext = SiemContext - > = Resolver; - export type ServerResolver< - R = Maybe, - Parent = IpOverviewData, - TContext = SiemContext - > = Resolver; - export type SourceResolver< - R = Maybe, - Parent = IpOverviewData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = IpOverviewData, - TContext = SiemContext - > = Resolver; -} - -export namespace OverviewResolvers { - export interface Resolvers { - firstSeen?: FirstSeenResolver, TypeParent, TContext>; - - lastSeen?: LastSeenResolver, TypeParent, TContext>; - - autonomousSystem?: AutonomousSystemResolver; - - geo?: GeoResolver; - } - - export type FirstSeenResolver< - R = Maybe, - Parent = Overview, - TContext = SiemContext - > = Resolver; - export type LastSeenResolver< - R = Maybe, - Parent = Overview, - TContext = SiemContext - > = Resolver; - export type AutonomousSystemResolver< - R = AutonomousSystem, - Parent = Overview, - TContext = SiemContext - > = Resolver; - export type GeoResolver = Resolver< - R, - Parent, - TContext - >; -} - -export namespace AutonomousSystemResolvers { - export interface Resolvers { - number?: NumberResolver, TypeParent, TContext>; - - organization?: OrganizationResolver, TypeParent, TContext>; - } - - export type NumberResolver< - R = Maybe, - Parent = AutonomousSystem, - TContext = SiemContext - > = Resolver; - export type OrganizationResolver< - R = Maybe, - Parent = AutonomousSystem, - TContext = SiemContext - > = Resolver; -} - -export namespace AutonomousSystemOrganizationResolvers { - export interface Resolvers { - name?: NameResolver, TypeParent, TContext>; - } - - export type NameResolver< - R = Maybe, - Parent = AutonomousSystemOrganization, - TContext = SiemContext - > = Resolver; -} - -export namespace UsersDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = UsersEdges[], - Parent = UsersData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver = Resolver< - R, - Parent, - TContext - >; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = UsersData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = UsersData, - TContext = SiemContext - > = Resolver; -} - -export namespace UsersEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver = Resolver< - R, - Parent, - TContext - >; - export type CursorResolver< - R = CursorType, - Parent = UsersEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace UsersNodeResolvers { - export interface Resolvers { - _id?: _IdResolver, TypeParent, TContext>; - - timestamp?: TimestampResolver, TypeParent, TContext>; - - user?: UserResolver, TypeParent, TContext>; - } - - export type _IdResolver, Parent = UsersNode, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type TimestampResolver< - R = Maybe, - Parent = UsersNode, - TContext = SiemContext - > = Resolver; - export type UserResolver< - R = Maybe, - Parent = UsersNode, - TContext = SiemContext - > = Resolver; -} - -export namespace UsersItemResolvers { - export interface Resolvers { - name?: NameResolver, TypeParent, TContext>; - - id?: IdResolver, TypeParent, TContext>; - - groupId?: GroupIdResolver, TypeParent, TContext>; - - groupName?: GroupNameResolver, TypeParent, TContext>; - - count?: CountResolver, TypeParent, TContext>; - } - - export type NameResolver< - R = Maybe, - Parent = UsersItem, - TContext = SiemContext - > = Resolver; - export type IdResolver< - R = Maybe, - Parent = UsersItem, - TContext = SiemContext - > = Resolver; - export type GroupIdResolver< - R = Maybe, - Parent = UsersItem, - TContext = SiemContext - > = Resolver; - export type GroupNameResolver< - R = Maybe, - Parent = UsersItem, - TContext = SiemContext - > = Resolver; - export type CountResolver< - R = Maybe, - Parent = UsersItem, - TContext = SiemContext - > = Resolver; -} - -export namespace KpiNetworkDataResolvers { - export interface Resolvers { - networkEvents?: NetworkEventsResolver, TypeParent, TContext>; - - uniqueFlowId?: UniqueFlowIdResolver, TypeParent, TContext>; - - uniqueSourcePrivateIps?: UniqueSourcePrivateIpsResolver, TypeParent, TContext>; - - uniqueSourcePrivateIpsHistogram?: UniqueSourcePrivateIpsHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - uniqueDestinationPrivateIps?: UniqueDestinationPrivateIpsResolver< - Maybe, - TypeParent, - TContext - >; - - uniqueDestinationPrivateIpsHistogram?: UniqueDestinationPrivateIpsHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - dnsQueries?: DnsQueriesResolver, TypeParent, TContext>; - - tlsHandshakes?: TlsHandshakesResolver, TypeParent, TContext>; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type NetworkEventsResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type UniqueFlowIdResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type UniqueSourcePrivateIpsResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type UniqueSourcePrivateIpsHistogramResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type UniqueDestinationPrivateIpsResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type UniqueDestinationPrivateIpsHistogramResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type DnsQueriesResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type TlsHandshakesResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; -} - -export namespace KpiNetworkHistogramDataResolvers { - export interface Resolvers { - x?: XResolver, TypeParent, TContext>; - - y?: YResolver, TypeParent, TContext>; - } - - export type XResolver< - R = Maybe, - Parent = KpiNetworkHistogramData, - TContext = SiemContext - > = Resolver; - export type YResolver< - R = Maybe, - Parent = KpiNetworkHistogramData, - TContext = SiemContext - > = Resolver; -} - -export namespace KpiHostsDataResolvers { - export interface Resolvers { - hosts?: HostsResolver, TypeParent, TContext>; - - hostsHistogram?: HostsHistogramResolver, TypeParent, TContext>; - - authSuccess?: AuthSuccessResolver, TypeParent, TContext>; - - authSuccessHistogram?: AuthSuccessHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - authFailure?: AuthFailureResolver, TypeParent, TContext>; - - authFailureHistogram?: AuthFailureHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - uniqueSourceIps?: UniqueSourceIpsResolver, TypeParent, TContext>; - - uniqueSourceIpsHistogram?: UniqueSourceIpsHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - uniqueDestinationIps?: UniqueDestinationIpsResolver, TypeParent, TContext>; - - uniqueDestinationIpsHistogram?: UniqueDestinationIpsHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type HostsResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; - export type HostsHistogramResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; - export type AuthSuccessResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; - export type AuthSuccessHistogramResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; - export type AuthFailureResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; - export type AuthFailureHistogramResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; - export type UniqueSourceIpsResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; - export type UniqueSourceIpsHistogramResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; - export type UniqueDestinationIpsResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; - export type UniqueDestinationIpsHistogramResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = KpiHostsData, - TContext = SiemContext - > = Resolver; -} - -export namespace KpiHostHistogramDataResolvers { - export interface Resolvers { - x?: XResolver, TypeParent, TContext>; - - y?: YResolver, TypeParent, TContext>; - } - - export type XResolver< - R = Maybe, - Parent = KpiHostHistogramData, - TContext = SiemContext - > = Resolver; - export type YResolver< - R = Maybe, - Parent = KpiHostHistogramData, - TContext = SiemContext - > = Resolver; -} - -export namespace KpiHostDetailsDataResolvers { - export interface Resolvers { - authSuccess?: AuthSuccessResolver, TypeParent, TContext>; - - authSuccessHistogram?: AuthSuccessHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - authFailure?: AuthFailureResolver, TypeParent, TContext>; - - authFailureHistogram?: AuthFailureHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - uniqueSourceIps?: UniqueSourceIpsResolver, TypeParent, TContext>; - - uniqueSourceIpsHistogram?: UniqueSourceIpsHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - uniqueDestinationIps?: UniqueDestinationIpsResolver, TypeParent, TContext>; - - uniqueDestinationIpsHistogram?: UniqueDestinationIpsHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type AuthSuccessResolver< - R = Maybe, - Parent = KpiHostDetailsData, - TContext = SiemContext - > = Resolver; - export type AuthSuccessHistogramResolver< - R = Maybe, - Parent = KpiHostDetailsData, - TContext = SiemContext - > = Resolver; - export type AuthFailureResolver< - R = Maybe, - Parent = KpiHostDetailsData, - TContext = SiemContext - > = Resolver; - export type AuthFailureHistogramResolver< - R = Maybe, - Parent = KpiHostDetailsData, - TContext = SiemContext - > = Resolver; - export type UniqueSourceIpsResolver< - R = Maybe, - Parent = KpiHostDetailsData, - TContext = SiemContext - > = Resolver; - export type UniqueSourceIpsHistogramResolver< - R = Maybe, - Parent = KpiHostDetailsData, - TContext = SiemContext - > = Resolver; - export type UniqueDestinationIpsResolver< - R = Maybe, - Parent = KpiHostDetailsData, - TContext = SiemContext - > = Resolver; - export type UniqueDestinationIpsHistogramResolver< - R = Maybe, - Parent = KpiHostDetailsData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = KpiHostDetailsData, - TContext = SiemContext - > = Resolver; -} - -export namespace MatrixHistogramOverTimeDataResolvers { - export interface Resolvers { - inspect?: InspectResolver, TypeParent, TContext>; - - matrixHistogramData?: MatrixHistogramDataResolver< - MatrixOverTimeHistogramData[], - TypeParent, - TContext - >; - - totalCount?: TotalCountResolver; - } - - export type InspectResolver< - R = Maybe, - Parent = MatrixHistogramOverTimeData, - TContext = SiemContext - > = Resolver; - export type MatrixHistogramDataResolver< - R = MatrixOverTimeHistogramData[], - Parent = MatrixHistogramOverTimeData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = MatrixHistogramOverTimeData, - TContext = SiemContext - > = Resolver; -} - -export namespace MatrixOverTimeHistogramDataResolvers { - export interface Resolvers { - x?: XResolver, TypeParent, TContext>; - - y?: YResolver, TypeParent, TContext>; - - g?: GResolver, TypeParent, TContext>; - } - - export type XResolver< - R = Maybe, - Parent = MatrixOverTimeHistogramData, - TContext = SiemContext - > = Resolver; - export type YResolver< - R = Maybe, - Parent = MatrixOverTimeHistogramData, - TContext = SiemContext - > = Resolver; - export type GResolver< - R = Maybe, - Parent = MatrixOverTimeHistogramData, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkTopCountriesDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = NetworkTopCountriesEdges[], - Parent = NetworkTopCountriesData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = NetworkTopCountriesData, - TContext = SiemContext - > = Resolver; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = NetworkTopCountriesData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = NetworkTopCountriesData, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkTopCountriesEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver< - R = NetworkTopCountriesItem, - Parent = NetworkTopCountriesEdges, - TContext = SiemContext - > = Resolver; - export type CursorResolver< - R = CursorType, - Parent = NetworkTopCountriesEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkTopCountriesItemResolvers { - export interface Resolvers { - _id?: _IdResolver, TypeParent, TContext>; - - source?: SourceResolver, TypeParent, TContext>; - - destination?: DestinationResolver, TypeParent, TContext>; - - network?: NetworkResolver, TypeParent, TContext>; - } - - export type _IdResolver< - R = Maybe, - Parent = NetworkTopCountriesItem, - TContext = SiemContext - > = Resolver; - export type SourceResolver< - R = Maybe, - Parent = NetworkTopCountriesItem, - TContext = SiemContext - > = Resolver; - export type DestinationResolver< - R = Maybe, - Parent = NetworkTopCountriesItem, - TContext = SiemContext - > = Resolver; - export type NetworkResolver< - R = Maybe, - Parent = NetworkTopCountriesItem, - TContext = SiemContext - > = Resolver; -} - -export namespace TopCountriesItemSourceResolvers { - export interface Resolvers { - country?: CountryResolver, TypeParent, TContext>; - - destination_ips?: DestinationIpsResolver, TypeParent, TContext>; - - flows?: FlowsResolver, TypeParent, TContext>; - - location?: LocationResolver, TypeParent, TContext>; - - source_ips?: SourceIpsResolver, TypeParent, TContext>; - } - - export type CountryResolver< - R = Maybe, - Parent = TopCountriesItemSource, - TContext = SiemContext - > = Resolver; - export type DestinationIpsResolver< - R = Maybe, - Parent = TopCountriesItemSource, - TContext = SiemContext - > = Resolver; - export type FlowsResolver< - R = Maybe, - Parent = TopCountriesItemSource, - TContext = SiemContext - > = Resolver; - export type LocationResolver< - R = Maybe, - Parent = TopCountriesItemSource, - TContext = SiemContext - > = Resolver; - export type SourceIpsResolver< - R = Maybe, - Parent = TopCountriesItemSource, - TContext = SiemContext - > = Resolver; -} - -export namespace GeoItemResolvers { - export interface Resolvers { - geo?: GeoResolver, TypeParent, TContext>; - - flowTarget?: FlowTargetResolver, TypeParent, TContext>; - } - - export type GeoResolver< - R = Maybe, - Parent = GeoItem, - TContext = SiemContext - > = Resolver; - export type FlowTargetResolver< - R = Maybe, - Parent = GeoItem, - TContext = SiemContext - > = Resolver; -} - -export namespace TopCountriesItemDestinationResolvers { - export interface Resolvers { - country?: CountryResolver, TypeParent, TContext>; - - destination_ips?: DestinationIpsResolver, TypeParent, TContext>; - - flows?: FlowsResolver, TypeParent, TContext>; - - location?: LocationResolver, TypeParent, TContext>; - - source_ips?: SourceIpsResolver, TypeParent, TContext>; - } - - export type CountryResolver< - R = Maybe, - Parent = TopCountriesItemDestination, - TContext = SiemContext - > = Resolver; - export type DestinationIpsResolver< - R = Maybe, - Parent = TopCountriesItemDestination, - TContext = SiemContext - > = Resolver; - export type FlowsResolver< - R = Maybe, - Parent = TopCountriesItemDestination, - TContext = SiemContext - > = Resolver; - export type LocationResolver< - R = Maybe, - Parent = TopCountriesItemDestination, - TContext = SiemContext - > = Resolver; - export type SourceIpsResolver< - R = Maybe, - Parent = TopCountriesItemDestination, - TContext = SiemContext - > = Resolver; -} - -export namespace TopNetworkTablesEcsFieldResolvers { - export interface Resolvers { - bytes_in?: BytesInResolver, TypeParent, TContext>; - - bytes_out?: BytesOutResolver, TypeParent, TContext>; - } - - export type BytesInResolver< - R = Maybe, - Parent = TopNetworkTablesEcsField, - TContext = SiemContext - > = Resolver; - export type BytesOutResolver< - R = Maybe, - Parent = TopNetworkTablesEcsField, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkTopNFlowDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = NetworkTopNFlowEdges[], - Parent = NetworkTopNFlowData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = NetworkTopNFlowData, - TContext = SiemContext - > = Resolver; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = NetworkTopNFlowData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = NetworkTopNFlowData, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkTopNFlowEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver< - R = NetworkTopNFlowItem, - Parent = NetworkTopNFlowEdges, - TContext = SiemContext - > = Resolver; - export type CursorResolver< - R = CursorType, - Parent = NetworkTopNFlowEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkTopNFlowItemResolvers { - export interface Resolvers { - _id?: _IdResolver, TypeParent, TContext>; - - source?: SourceResolver, TypeParent, TContext>; - - destination?: DestinationResolver, TypeParent, TContext>; - - network?: NetworkResolver, TypeParent, TContext>; - } - - export type _IdResolver< - R = Maybe, - Parent = NetworkTopNFlowItem, - TContext = SiemContext - > = Resolver; - export type SourceResolver< - R = Maybe, - Parent = NetworkTopNFlowItem, - TContext = SiemContext - > = Resolver; - export type DestinationResolver< - R = Maybe, - Parent = NetworkTopNFlowItem, - TContext = SiemContext - > = Resolver; - export type NetworkResolver< - R = Maybe, - Parent = NetworkTopNFlowItem, - TContext = SiemContext - > = Resolver; -} - -export namespace TopNFlowItemSourceResolvers { - export interface Resolvers { - autonomous_system?: AutonomousSystemResolver, TypeParent, TContext>; - - domain?: DomainResolver, TypeParent, TContext>; - - ip?: IpResolver, TypeParent, TContext>; - - location?: LocationResolver, TypeParent, TContext>; - - flows?: FlowsResolver, TypeParent, TContext>; - - destination_ips?: DestinationIpsResolver, TypeParent, TContext>; - } - - export type AutonomousSystemResolver< - R = Maybe, - Parent = TopNFlowItemSource, - TContext = SiemContext - > = Resolver; - export type DomainResolver< - R = Maybe, - Parent = TopNFlowItemSource, - TContext = SiemContext - > = Resolver; - export type IpResolver< - R = Maybe, - Parent = TopNFlowItemSource, - TContext = SiemContext - > = Resolver; - export type LocationResolver< - R = Maybe, - Parent = TopNFlowItemSource, - TContext = SiemContext - > = Resolver; - export type FlowsResolver< - R = Maybe, - Parent = TopNFlowItemSource, - TContext = SiemContext - > = Resolver; - export type DestinationIpsResolver< - R = Maybe, - Parent = TopNFlowItemSource, - TContext = SiemContext - > = Resolver; -} - -export namespace AutonomousSystemItemResolvers { - export interface Resolvers { - name?: NameResolver, TypeParent, TContext>; - - number?: NumberResolver, TypeParent, TContext>; - } - - export type NameResolver< - R = Maybe, - Parent = AutonomousSystemItem, - TContext = SiemContext - > = Resolver; - export type NumberResolver< - R = Maybe, - Parent = AutonomousSystemItem, - TContext = SiemContext - > = Resolver; -} - -export namespace TopNFlowItemDestinationResolvers { - export interface Resolvers { - autonomous_system?: AutonomousSystemResolver, TypeParent, TContext>; - - domain?: DomainResolver, TypeParent, TContext>; - - ip?: IpResolver, TypeParent, TContext>; - - location?: LocationResolver, TypeParent, TContext>; - - flows?: FlowsResolver, TypeParent, TContext>; - - source_ips?: SourceIpsResolver, TypeParent, TContext>; - } - - export type AutonomousSystemResolver< - R = Maybe, - Parent = TopNFlowItemDestination, - TContext = SiemContext - > = Resolver; - export type DomainResolver< - R = Maybe, - Parent = TopNFlowItemDestination, - TContext = SiemContext - > = Resolver; - export type IpResolver< - R = Maybe, - Parent = TopNFlowItemDestination, - TContext = SiemContext - > = Resolver; - export type LocationResolver< - R = Maybe, - Parent = TopNFlowItemDestination, - TContext = SiemContext - > = Resolver; - export type FlowsResolver< - R = Maybe, - Parent = TopNFlowItemDestination, - TContext = SiemContext - > = Resolver; - export type SourceIpsResolver< - R = Maybe, - Parent = TopNFlowItemDestination, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkDnsDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - - histogram?: HistogramResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = NetworkDnsEdges[], - Parent = NetworkDnsData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = NetworkDnsData, - TContext = SiemContext - > = Resolver; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = NetworkDnsData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = NetworkDnsData, - TContext = SiemContext - > = Resolver; - export type HistogramResolver< - R = Maybe, - Parent = NetworkDnsData, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkDnsEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver< - R = NetworkDnsItem, - Parent = NetworkDnsEdges, - TContext = SiemContext - > = Resolver; - export type CursorResolver< - R = CursorType, - Parent = NetworkDnsEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkDnsItemResolvers { - export interface Resolvers { - _id?: _IdResolver, TypeParent, TContext>; - - dnsBytesIn?: DnsBytesInResolver, TypeParent, TContext>; - - dnsBytesOut?: DnsBytesOutResolver, TypeParent, TContext>; - - dnsName?: DnsNameResolver, TypeParent, TContext>; - - queryCount?: QueryCountResolver, TypeParent, TContext>; - - uniqueDomains?: UniqueDomainsResolver, TypeParent, TContext>; - } - - export type _IdResolver< - R = Maybe, - Parent = NetworkDnsItem, - TContext = SiemContext - > = Resolver; - export type DnsBytesInResolver< - R = Maybe, - Parent = NetworkDnsItem, - TContext = SiemContext - > = Resolver; - export type DnsBytesOutResolver< - R = Maybe, - Parent = NetworkDnsItem, - TContext = SiemContext - > = Resolver; - export type DnsNameResolver< - R = Maybe, - Parent = NetworkDnsItem, - TContext = SiemContext - > = Resolver; - export type QueryCountResolver< - R = Maybe, - Parent = NetworkDnsItem, - TContext = SiemContext - > = Resolver; - export type UniqueDomainsResolver< - R = Maybe, - Parent = NetworkDnsItem, - TContext = SiemContext - > = Resolver; -} - -export namespace MatrixOverOrdinalHistogramDataResolvers { - export interface Resolvers { - x?: XResolver; - - y?: YResolver; - - g?: GResolver; - } - - export type XResolver< - R = string, - Parent = MatrixOverOrdinalHistogramData, - TContext = SiemContext - > = Resolver; - export type YResolver< - R = number, - Parent = MatrixOverOrdinalHistogramData, - TContext = SiemContext - > = Resolver; - export type GResolver< - R = string, - Parent = MatrixOverOrdinalHistogramData, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkDsOverTimeDataResolvers { - export interface Resolvers { - inspect?: InspectResolver, TypeParent, TContext>; - - matrixHistogramData?: MatrixHistogramDataResolver< - MatrixOverTimeHistogramData[], - TypeParent, - TContext - >; - - totalCount?: TotalCountResolver; - } - - export type InspectResolver< - R = Maybe, - Parent = NetworkDsOverTimeData, - TContext = SiemContext - > = Resolver; - export type MatrixHistogramDataResolver< - R = MatrixOverTimeHistogramData[], - Parent = NetworkDsOverTimeData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = NetworkDsOverTimeData, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkHttpDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = NetworkHttpEdges[], - Parent = NetworkHttpData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = NetworkHttpData, - TContext = SiemContext - > = Resolver; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = NetworkHttpData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = NetworkHttpData, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkHttpEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver< - R = NetworkHttpItem, - Parent = NetworkHttpEdges, - TContext = SiemContext - > = Resolver; - export type CursorResolver< - R = CursorType, - Parent = NetworkHttpEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace NetworkHttpItemResolvers { - export interface Resolvers { - _id?: _IdResolver, TypeParent, TContext>; - - domains?: DomainsResolver; - - lastHost?: LastHostResolver, TypeParent, TContext>; - - lastSourceIp?: LastSourceIpResolver, TypeParent, TContext>; - - methods?: MethodsResolver; - - path?: PathResolver, TypeParent, TContext>; - - requestCount?: RequestCountResolver, TypeParent, TContext>; - - statuses?: StatusesResolver; - } - - export type _IdResolver< - R = Maybe, - Parent = NetworkHttpItem, - TContext = SiemContext - > = Resolver; - export type DomainsResolver< - R = string[], - Parent = NetworkHttpItem, - TContext = SiemContext - > = Resolver; - export type LastHostResolver< - R = Maybe, - Parent = NetworkHttpItem, - TContext = SiemContext - > = Resolver; - export type LastSourceIpResolver< - R = Maybe, - Parent = NetworkHttpItem, - TContext = SiemContext - > = Resolver; - export type MethodsResolver< - R = string[], - Parent = NetworkHttpItem, - TContext = SiemContext - > = Resolver; - export type PathResolver< - R = Maybe, - Parent = NetworkHttpItem, - TContext = SiemContext - > = Resolver; - export type RequestCountResolver< - R = Maybe, - Parent = NetworkHttpItem, - TContext = SiemContext - > = Resolver; - export type StatusesResolver< - R = string[], - Parent = NetworkHttpItem, - TContext = SiemContext - > = Resolver; -} - -export namespace OverviewNetworkDataResolvers { - export interface Resolvers { - auditbeatSocket?: AuditbeatSocketResolver, TypeParent, TContext>; - - filebeatCisco?: FilebeatCiscoResolver, TypeParent, TContext>; - - filebeatNetflow?: FilebeatNetflowResolver, TypeParent, TContext>; - - filebeatPanw?: FilebeatPanwResolver, TypeParent, TContext>; - - filebeatSuricata?: FilebeatSuricataResolver, TypeParent, TContext>; - - filebeatZeek?: FilebeatZeekResolver, TypeParent, TContext>; - - packetbeatDNS?: PacketbeatDnsResolver, TypeParent, TContext>; - - packetbeatFlow?: PacketbeatFlowResolver, TypeParent, TContext>; - - packetbeatTLS?: PacketbeatTlsResolver, TypeParent, TContext>; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type AuditbeatSocketResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type FilebeatCiscoResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type FilebeatNetflowResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type FilebeatPanwResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type FilebeatSuricataResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type FilebeatZeekResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type PacketbeatDnsResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type PacketbeatFlowResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type PacketbeatTlsResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; -} - -export namespace OverviewHostDataResolvers { - export interface Resolvers { - auditbeatAuditd?: AuditbeatAuditdResolver, TypeParent, TContext>; - - auditbeatFIM?: AuditbeatFimResolver, TypeParent, TContext>; - - auditbeatLogin?: AuditbeatLoginResolver, TypeParent, TContext>; - - auditbeatPackage?: AuditbeatPackageResolver, TypeParent, TContext>; - - auditbeatProcess?: AuditbeatProcessResolver, TypeParent, TContext>; - - auditbeatUser?: AuditbeatUserResolver, TypeParent, TContext>; - - endgameDns?: EndgameDnsResolver, TypeParent, TContext>; - - endgameFile?: EndgameFileResolver, TypeParent, TContext>; - - endgameImageLoad?: EndgameImageLoadResolver, TypeParent, TContext>; - - endgameNetwork?: EndgameNetworkResolver, TypeParent, TContext>; - - endgameProcess?: EndgameProcessResolver, TypeParent, TContext>; - - endgameRegistry?: EndgameRegistryResolver, TypeParent, TContext>; - - endgameSecurity?: EndgameSecurityResolver, TypeParent, TContext>; - - filebeatSystemModule?: FilebeatSystemModuleResolver, TypeParent, TContext>; - - winlogbeatSecurity?: WinlogbeatSecurityResolver, TypeParent, TContext>; - - winlogbeatMWSysmonOperational?: WinlogbeatMwSysmonOperationalResolver< - Maybe, - TypeParent, - TContext - >; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type AuditbeatAuditdResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type AuditbeatFimResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type AuditbeatLoginResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type AuditbeatPackageResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type AuditbeatProcessResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type AuditbeatUserResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameDnsResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameFileResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameImageLoadResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameNetworkResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameProcessResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameRegistryResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameSecurityResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type FilebeatSystemModuleResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type WinlogbeatSecurityResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type WinlogbeatMwSysmonOperationalResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; -} - -export namespace TlsDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver = Resolver< - R, - Parent, - TContext - >; - export type TotalCountResolver = Resolver< - R, - Parent, - TContext - >; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = TlsData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = TlsData, - TContext = SiemContext - > = Resolver; -} - -export namespace TlsEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver = Resolver< - R, - Parent, - TContext - >; - export type CursorResolver = Resolver< - R, - Parent, - TContext - >; -} - -export namespace TlsNodeResolvers { - export interface Resolvers { - _id?: _IdResolver, TypeParent, TContext>; - - timestamp?: TimestampResolver, TypeParent, TContext>; - - alternativeNames?: AlternativeNamesResolver, TypeParent, TContext>; - - notAfter?: NotAfterResolver, TypeParent, TContext>; - - commonNames?: CommonNamesResolver, TypeParent, TContext>; - - ja3?: Ja3Resolver, TypeParent, TContext>; - - issuerNames?: IssuerNamesResolver, TypeParent, TContext>; - } - - export type _IdResolver, Parent = TlsNode, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type TimestampResolver< - R = Maybe, - Parent = TlsNode, - TContext = SiemContext - > = Resolver; - export type AlternativeNamesResolver< - R = Maybe, - Parent = TlsNode, - TContext = SiemContext - > = Resolver; - export type NotAfterResolver< - R = Maybe, - Parent = TlsNode, - TContext = SiemContext - > = Resolver; - export type CommonNamesResolver< - R = Maybe, - Parent = TlsNode, - TContext = SiemContext - > = Resolver; - export type Ja3Resolver, Parent = TlsNode, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type IssuerNamesResolver< - R = Maybe, - Parent = TlsNode, - TContext = SiemContext - > = Resolver; -} - -export namespace UncommonProcessesDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = UncommonProcessesEdges[], - Parent = UncommonProcessesData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = UncommonProcessesData, - TContext = SiemContext - > = Resolver; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = UncommonProcessesData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = UncommonProcessesData, - TContext = SiemContext - > = Resolver; -} - -export namespace UncommonProcessesEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver< - R = UncommonProcessItem, - Parent = UncommonProcessesEdges, - TContext = SiemContext - > = Resolver; - export type CursorResolver< - R = CursorType, - Parent = UncommonProcessesEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace UncommonProcessItemResolvers { - export interface Resolvers { - _id?: _IdResolver; - - instances?: InstancesResolver; - - process?: ProcessResolver; - - hosts?: HostsResolver; - - user?: UserResolver, TypeParent, TContext>; - } - - export type _IdResolver< - R = string, - Parent = UncommonProcessItem, - TContext = SiemContext - > = Resolver; - export type InstancesResolver< - R = number, - Parent = UncommonProcessItem, - TContext = SiemContext - > = Resolver; - export type ProcessResolver< - R = ProcessEcsFields, - Parent = UncommonProcessItem, - TContext = SiemContext - > = Resolver; - export type HostsResolver< - R = HostEcsFields[], - Parent = UncommonProcessItem, - TContext = SiemContext - > = Resolver; - export type UserResolver< - R = Maybe, - Parent = UncommonProcessItem, - TContext = SiemContext - > = Resolver; -} - -export namespace SayMyNameResolvers { - export interface Resolvers { - /** The id of the source */ - appName?: AppNameResolver; - } - - export type AppNameResolver = Resolver< - R, - Parent, - TContext - >; -} - -export namespace TimelineResultResolvers { - export interface Resolvers { - columns?: ColumnsResolver, TypeParent, TContext>; - - created?: CreatedResolver, TypeParent, TContext>; - - createdBy?: CreatedByResolver, TypeParent, TContext>; - - dataProviders?: DataProvidersResolver, TypeParent, TContext>; - - dateRange?: DateRangeResolver, TypeParent, TContext>; - - description?: DescriptionResolver, TypeParent, TContext>; - - eventIdToNoteIds?: EventIdToNoteIdsResolver, TypeParent, TContext>; - - eventType?: EventTypeResolver, TypeParent, TContext>; - - favorite?: FavoriteResolver, TypeParent, TContext>; - - filters?: FiltersResolver, TypeParent, TContext>; - - kqlMode?: KqlModeResolver, TypeParent, TContext>; - - kqlQuery?: KqlQueryResolver, TypeParent, TContext>; - - notes?: NotesResolver, TypeParent, TContext>; - - noteIds?: NoteIdsResolver, TypeParent, TContext>; - - pinnedEventIds?: PinnedEventIdsResolver, TypeParent, TContext>; - - pinnedEventsSaveObject?: PinnedEventsSaveObjectResolver< - Maybe, - TypeParent, - TContext - >; - - savedQueryId?: SavedQueryIdResolver, TypeParent, TContext>; - - savedObjectId?: SavedObjectIdResolver; - - sort?: SortResolver, TypeParent, TContext>; - - title?: TitleResolver, TypeParent, TContext>; - - updated?: UpdatedResolver, TypeParent, TContext>; - - updatedBy?: UpdatedByResolver, TypeParent, TContext>; - - version?: VersionResolver; - } - - export type ColumnsResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type CreatedResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type CreatedByResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type DataProvidersResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type DateRangeResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type DescriptionResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type EventIdToNoteIdsResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type EventTypeResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type FavoriteResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type FiltersResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type KqlModeResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type KqlQueryResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type NotesResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type NoteIdsResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type PinnedEventIdsResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type PinnedEventsSaveObjectResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type SavedQueryIdResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type SavedObjectIdResolver< - R = string, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type SortResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type TitleResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type UpdatedResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type UpdatedByResolver< - R = Maybe, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = string, - Parent = TimelineResult, - TContext = SiemContext - > = Resolver; -} - -export namespace ColumnHeaderResultResolvers { - export interface Resolvers { - aggregatable?: AggregatableResolver, TypeParent, TContext>; - - category?: CategoryResolver, TypeParent, TContext>; - - columnHeaderType?: ColumnHeaderTypeResolver, TypeParent, TContext>; - - description?: DescriptionResolver, TypeParent, TContext>; - - example?: ExampleResolver, TypeParent, TContext>; - - indexes?: IndexesResolver, TypeParent, TContext>; - - id?: IdResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - placeholder?: PlaceholderResolver, TypeParent, TContext>; - - searchable?: SearchableResolver, TypeParent, TContext>; - - type?: TypeResolver, TypeParent, TContext>; - } - - export type AggregatableResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; - export type CategoryResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; - export type ColumnHeaderTypeResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; - export type DescriptionResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; - export type ExampleResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; - export type IndexesResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; - export type IdResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; - export type NameResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; - export type PlaceholderResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; - export type SearchableResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; - export type TypeResolver< - R = Maybe, - Parent = ColumnHeaderResult, - TContext = SiemContext - > = Resolver; -} - -export namespace DataProviderResultResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - enabled?: EnabledResolver, TypeParent, TContext>; - - excluded?: ExcludedResolver, TypeParent, TContext>; - - kqlQuery?: KqlQueryResolver, TypeParent, TContext>; - - queryMatch?: QueryMatchResolver, TypeParent, TContext>; - - and?: AndResolver, TypeParent, TContext>; - } - - export type IdResolver< - R = Maybe, - Parent = DataProviderResult, - TContext = SiemContext - > = Resolver; - export type NameResolver< - R = Maybe, - Parent = DataProviderResult, - TContext = SiemContext - > = Resolver; - export type EnabledResolver< - R = Maybe, - Parent = DataProviderResult, - TContext = SiemContext - > = Resolver; - export type ExcludedResolver< - R = Maybe, - Parent = DataProviderResult, - TContext = SiemContext - > = Resolver; - export type KqlQueryResolver< - R = Maybe, - Parent = DataProviderResult, - TContext = SiemContext - > = Resolver; - export type QueryMatchResolver< - R = Maybe, - Parent = DataProviderResult, - TContext = SiemContext - > = Resolver; - export type AndResolver< - R = Maybe, - Parent = DataProviderResult, - TContext = SiemContext - > = Resolver; -} - -export namespace QueryMatchResultResolvers { - export interface Resolvers { - field?: FieldResolver, TypeParent, TContext>; - - displayField?: DisplayFieldResolver, TypeParent, TContext>; - - value?: ValueResolver, TypeParent, TContext>; - - displayValue?: DisplayValueResolver, TypeParent, TContext>; - - operator?: OperatorResolver, TypeParent, TContext>; - } - - export type FieldResolver< - R = Maybe, - Parent = QueryMatchResult, - TContext = SiemContext - > = Resolver; - export type DisplayFieldResolver< - R = Maybe, - Parent = QueryMatchResult, - TContext = SiemContext - > = Resolver; - export type ValueResolver< - R = Maybe, - Parent = QueryMatchResult, - TContext = SiemContext - > = Resolver; - export type DisplayValueResolver< - R = Maybe, - Parent = QueryMatchResult, - TContext = SiemContext - > = Resolver; - export type OperatorResolver< - R = Maybe, - Parent = QueryMatchResult, - TContext = SiemContext - > = Resolver; -} - -export namespace DateRangePickerResultResolvers { - export interface Resolvers { - start?: StartResolver, TypeParent, TContext>; - - end?: EndResolver, TypeParent, TContext>; - } - - export type StartResolver< - R = Maybe, - Parent = DateRangePickerResult, - TContext = SiemContext - > = Resolver; - export type EndResolver< - R = Maybe, - Parent = DateRangePickerResult, - TContext = SiemContext - > = Resolver; -} - -export namespace FavoriteTimelineResultResolvers { - export interface Resolvers { - fullName?: FullNameResolver, TypeParent, TContext>; - - userName?: UserNameResolver, TypeParent, TContext>; - - favoriteDate?: FavoriteDateResolver, TypeParent, TContext>; - } - - export type FullNameResolver< - R = Maybe, - Parent = FavoriteTimelineResult, - TContext = SiemContext - > = Resolver; - export type UserNameResolver< - R = Maybe, - Parent = FavoriteTimelineResult, - TContext = SiemContext - > = Resolver; - export type FavoriteDateResolver< - R = Maybe, - Parent = FavoriteTimelineResult, - TContext = SiemContext - > = Resolver; -} - -export namespace FilterTimelineResultResolvers { - export interface Resolvers { - exists?: ExistsResolver, TypeParent, TContext>; - - meta?: MetaResolver, TypeParent, TContext>; - - match_all?: MatchAllResolver, TypeParent, TContext>; - - missing?: MissingResolver, TypeParent, TContext>; - - query?: QueryResolver, TypeParent, TContext>; - - range?: RangeResolver, TypeParent, TContext>; - - script?: ScriptResolver, TypeParent, TContext>; - } - - export type ExistsResolver< - R = Maybe, - Parent = FilterTimelineResult, - TContext = SiemContext - > = Resolver; - export type MetaResolver< - R = Maybe, - Parent = FilterTimelineResult, - TContext = SiemContext - > = Resolver; - export type MatchAllResolver< - R = Maybe, - Parent = FilterTimelineResult, - TContext = SiemContext - > = Resolver; - export type MissingResolver< - R = Maybe, - Parent = FilterTimelineResult, - TContext = SiemContext - > = Resolver; - export type QueryResolver< - R = Maybe, - Parent = FilterTimelineResult, - TContext = SiemContext - > = Resolver; - export type RangeResolver< - R = Maybe, - Parent = FilterTimelineResult, - TContext = SiemContext - > = Resolver; - export type ScriptResolver< - R = Maybe, - Parent = FilterTimelineResult, - TContext = SiemContext - > = Resolver; -} - -export namespace FilterMetaTimelineResultResolvers { - export interface Resolvers { - alias?: AliasResolver, TypeParent, TContext>; - - controlledBy?: ControlledByResolver, TypeParent, TContext>; - - disabled?: DisabledResolver, TypeParent, TContext>; - - field?: FieldResolver, TypeParent, TContext>; - - formattedValue?: FormattedValueResolver, TypeParent, TContext>; - - index?: IndexResolver, TypeParent, TContext>; - - key?: KeyResolver, TypeParent, TContext>; - - negate?: NegateResolver, TypeParent, TContext>; - - params?: ParamsResolver, TypeParent, TContext>; - - type?: TypeResolver, TypeParent, TContext>; - - value?: ValueResolver, TypeParent, TContext>; - } - - export type AliasResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; - export type ControlledByResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; - export type DisabledResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; - export type FieldResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; - export type FormattedValueResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; - export type IndexResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; - export type KeyResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; - export type NegateResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; - export type ParamsResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; - export type TypeResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; - export type ValueResolver< - R = Maybe, - Parent = FilterMetaTimelineResult, - TContext = SiemContext - > = Resolver; -} - -export namespace SerializedFilterQueryResultResolvers { - export interface Resolvers { - filterQuery?: FilterQueryResolver, TypeParent, TContext>; - } - - export type FilterQueryResolver< - R = Maybe, - Parent = SerializedFilterQueryResult, - TContext = SiemContext - > = Resolver; -} - -export namespace SerializedKueryQueryResultResolvers { - export interface Resolvers { - kuery?: KueryResolver, TypeParent, TContext>; - - serializedQuery?: SerializedQueryResolver, TypeParent, TContext>; - } - - export type KueryResolver< - R = Maybe, - Parent = SerializedKueryQueryResult, - TContext = SiemContext - > = Resolver; - export type SerializedQueryResolver< - R = Maybe, - Parent = SerializedKueryQueryResult, - TContext = SiemContext - > = Resolver; -} - -export namespace KueryFilterQueryResultResolvers { - export interface Resolvers { - kind?: KindResolver, TypeParent, TContext>; - - expression?: ExpressionResolver, TypeParent, TContext>; - } - - export type KindResolver< - R = Maybe, - Parent = KueryFilterQueryResult, - TContext = SiemContext - > = Resolver; - export type ExpressionResolver< - R = Maybe, - Parent = KueryFilterQueryResult, - TContext = SiemContext - > = Resolver; -} - -export namespace SortTimelineResultResolvers { - export interface Resolvers { - columnId?: ColumnIdResolver, TypeParent, TContext>; - - sortDirection?: SortDirectionResolver, TypeParent, TContext>; - } - - export type ColumnIdResolver< - R = Maybe, - Parent = SortTimelineResult, - TContext = SiemContext - > = Resolver; - export type SortDirectionResolver< - R = Maybe, - Parent = SortTimelineResult, - TContext = SiemContext - > = Resolver; -} - -export namespace ResponseTimelinesResolvers { - export interface Resolvers { - timeline?: TimelineResolver<(Maybe)[], TypeParent, TContext>; - - totalCount?: TotalCountResolver, TypeParent, TContext>; - } - - export type TimelineResolver< - R = (Maybe)[], - Parent = ResponseTimelines, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = Maybe, - Parent = ResponseTimelines, - TContext = SiemContext - > = Resolver; -} - -export namespace MutationResolvers { - export interface Resolvers { - /** Persists a note */ - persistNote?: PersistNoteResolver; - - deleteNote?: DeleteNoteResolver, TypeParent, TContext>; - - deleteNoteByTimelineId?: DeleteNoteByTimelineIdResolver, TypeParent, TContext>; - /** Persists a pinned event in a timeline */ - persistPinnedEventOnTimeline?: PersistPinnedEventOnTimelineResolver< - Maybe, - TypeParent, - TContext - >; - /** Remove a pinned events in a timeline */ - deletePinnedEventOnTimeline?: DeletePinnedEventOnTimelineResolver< - boolean, - TypeParent, - TContext - >; - /** Remove all pinned events in a timeline */ - deleteAllPinnedEventsOnTimeline?: DeleteAllPinnedEventsOnTimelineResolver< - boolean, - TypeParent, - TContext - >; - /** Persists a timeline */ - persistTimeline?: PersistTimelineResolver; - - persistFavorite?: PersistFavoriteResolver; - - deleteTimeline?: DeleteTimelineResolver; - } - - export type PersistNoteResolver = Resolver< - R, - Parent, - TContext, - PersistNoteArgs - >; - export interface PersistNoteArgs { - noteId?: Maybe; - - version?: Maybe; - - note: NoteInput; - } - - export type DeleteNoteResolver< - R = Maybe, - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface DeleteNoteArgs { - id: string[]; - } - - export type DeleteNoteByTimelineIdResolver< - R = Maybe, - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface DeleteNoteByTimelineIdArgs { - timelineId: string; - - version?: Maybe; - } - - export type PersistPinnedEventOnTimelineResolver< - R = Maybe, - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface PersistPinnedEventOnTimelineArgs { - pinnedEventId?: Maybe; - - eventId: string; - - timelineId?: Maybe; - } - - export type DeletePinnedEventOnTimelineResolver< - R = boolean, - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface DeletePinnedEventOnTimelineArgs { - id: string[]; - } - - export type DeleteAllPinnedEventsOnTimelineResolver< - R = boolean, - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface DeleteAllPinnedEventsOnTimelineArgs { - timelineId: string; - } - - export type PersistTimelineResolver< - R = ResponseTimeline, - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface PersistTimelineArgs { - id?: Maybe; - - version?: Maybe; - - timeline: TimelineInput; - } - - export type PersistFavoriteResolver< - R = ResponseFavoriteTimeline, - Parent = {}, - TContext = SiemContext - > = Resolver; - export interface PersistFavoriteArgs { - timelineId?: Maybe; - } - - export type DeleteTimelineResolver = Resolver< - R, - Parent, - TContext, - DeleteTimelineArgs - >; - export interface DeleteTimelineArgs { - id: string[]; - } -} - -export namespace ResponseNoteResolvers { - export interface Resolvers { - code?: CodeResolver, TypeParent, TContext>; - - message?: MessageResolver, TypeParent, TContext>; - - note?: NoteResolver; - } - - export type CodeResolver< - R = Maybe, - Parent = ResponseNote, - TContext = SiemContext - > = Resolver; - export type MessageResolver< - R = Maybe, - Parent = ResponseNote, - TContext = SiemContext - > = Resolver; - export type NoteResolver< - R = NoteResult, - Parent = ResponseNote, - TContext = SiemContext - > = Resolver; -} - -export namespace ResponseTimelineResolvers { - export interface Resolvers { - code?: CodeResolver, TypeParent, TContext>; - - message?: MessageResolver, TypeParent, TContext>; - - timeline?: TimelineResolver; - } - - export type CodeResolver< - R = Maybe, - Parent = ResponseTimeline, - TContext = SiemContext - > = Resolver; - export type MessageResolver< - R = Maybe, - Parent = ResponseTimeline, - TContext = SiemContext - > = Resolver; - export type TimelineResolver< - R = TimelineResult, - Parent = ResponseTimeline, - TContext = SiemContext - > = Resolver; -} - -export namespace ResponseFavoriteTimelineResolvers { - export interface Resolvers { - code?: CodeResolver, TypeParent, TContext>; - - message?: MessageResolver, TypeParent, TContext>; - - savedObjectId?: SavedObjectIdResolver; - - version?: VersionResolver; - - favorite?: FavoriteResolver, TypeParent, TContext>; - } - - export type CodeResolver< - R = Maybe, - Parent = ResponseFavoriteTimeline, - TContext = SiemContext - > = Resolver; - export type MessageResolver< - R = Maybe, - Parent = ResponseFavoriteTimeline, - TContext = SiemContext - > = Resolver; - export type SavedObjectIdResolver< - R = string, - Parent = ResponseFavoriteTimeline, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = string, - Parent = ResponseFavoriteTimeline, - TContext = SiemContext - > = Resolver; - export type FavoriteResolver< - R = Maybe, - Parent = ResponseFavoriteTimeline, - TContext = SiemContext - > = Resolver; -} - -export namespace EcsEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver = Resolver< - R, - Parent, - TContext - >; - export type CursorResolver = Resolver< - R, - Parent, - TContext - >; -} - -export namespace EventsTimelineDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = EcsEdges[], - Parent = EventsTimelineData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = EventsTimelineData, - TContext = SiemContext - > = Resolver; - export type PageInfoResolver< - R = PageInfo, - Parent = EventsTimelineData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = EventsTimelineData, - TContext = SiemContext - > = Resolver; -} - -export namespace OsFieldsResolvers { - export interface Resolvers { - platform?: PlatformResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - full?: FullResolver, TypeParent, TContext>; - - family?: FamilyResolver, TypeParent, TContext>; - - version?: VersionResolver, TypeParent, TContext>; - - kernel?: KernelResolver, TypeParent, TContext>; - } - - export type PlatformResolver< - R = Maybe, - Parent = OsFields, - TContext = SiemContext - > = Resolver; - export type NameResolver, Parent = OsFields, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type FullResolver, Parent = OsFields, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type FamilyResolver< - R = Maybe, - Parent = OsFields, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = Maybe, - Parent = OsFields, - TContext = SiemContext - > = Resolver; - export type KernelResolver< - R = Maybe, - Parent = OsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace HostFieldsResolvers { - export interface Resolvers { - architecture?: ArchitectureResolver, TypeParent, TContext>; - - id?: IdResolver, TypeParent, TContext>; - - ip?: IpResolver)[]>, TypeParent, TContext>; - - mac?: MacResolver)[]>, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - os?: OsResolver, TypeParent, TContext>; - - type?: TypeResolver, TypeParent, TContext>; - } - - export type ArchitectureResolver< - R = Maybe, - Parent = HostFields, - TContext = SiemContext - > = Resolver; - export type IdResolver, Parent = HostFields, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type IpResolver< - R = Maybe<(Maybe)[]>, - Parent = HostFields, - TContext = SiemContext - > = Resolver; - export type MacResolver< - R = Maybe<(Maybe)[]>, - Parent = HostFields, - TContext = SiemContext - > = Resolver; - export type NameResolver< - R = Maybe, - Parent = HostFields, - TContext = SiemContext - > = Resolver; - export type OsResolver< - R = Maybe, - Parent = HostFields, - TContext = SiemContext - > = Resolver; - export type TypeResolver< - R = Maybe, - Parent = HostFields, - TContext = SiemContext - > = Resolver; -} - -/** Directs the executor to skip this field or fragment when the `if` argument is true. */ -export type SkipDirectiveResolver = DirectiveResolverFn< - Result, - SkipDirectiveArgs, - SiemContext ->; -export interface SkipDirectiveArgs { - /** Skipped when true. */ - if: boolean; -} - -/** Directs the executor to include this field or fragment only when the `if` argument is true. */ -export type IncludeDirectiveResolver = DirectiveResolverFn< - Result, - IncludeDirectiveArgs, - SiemContext ->; -export interface IncludeDirectiveArgs { - /** Included when true. */ - if: boolean; -} - -/** Marks an element of a GraphQL schema as no longer supported. */ -export type DeprecatedDirectiveResolver = DirectiveResolverFn< - Result, - DeprecatedDirectiveArgs, - SiemContext ->; -export interface DeprecatedDirectiveArgs { - /** Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/). */ - reason?: string; -} - -export interface ToStringArrayScalarConfig extends GraphQLScalarTypeConfig { - name: 'ToStringArray'; -} -export interface DateScalarConfig extends GraphQLScalarTypeConfig { - name: 'Date'; -} -export interface ToNumberArrayScalarConfig extends GraphQLScalarTypeConfig { - name: 'ToNumberArray'; -} -export interface ToDateArrayScalarConfig extends GraphQLScalarTypeConfig { - name: 'ToDateArray'; -} -export interface ToBooleanArrayScalarConfig extends GraphQLScalarTypeConfig { - name: 'ToBooleanArray'; -} -export interface ToAnyScalarConfig extends GraphQLScalarTypeConfig { - name: 'ToAny'; -} -export interface EsValueScalarConfig extends GraphQLScalarTypeConfig { - name: 'EsValue'; -} - -export type IResolvers = { - Query?: QueryResolvers.Resolvers; - NoteResult?: NoteResultResolvers.Resolvers; - ResponseNotes?: ResponseNotesResolvers.Resolvers; - PinnedEvent?: PinnedEventResolvers.Resolvers; - Source?: SourceResolvers.Resolvers; - SourceConfiguration?: SourceConfigurationResolvers.Resolvers; - SourceFields?: SourceFieldsResolvers.Resolvers; - SourceStatus?: SourceStatusResolvers.Resolvers; - IndexField?: IndexFieldResolvers.Resolvers; - AuthenticationsData?: AuthenticationsDataResolvers.Resolvers; - AuthenticationsEdges?: AuthenticationsEdgesResolvers.Resolvers; - AuthenticationItem?: AuthenticationItemResolvers.Resolvers; - UserEcsFields?: UserEcsFieldsResolvers.Resolvers; - LastSourceHost?: LastSourceHostResolvers.Resolvers; - SourceEcsFields?: SourceEcsFieldsResolvers.Resolvers; - GeoEcsFields?: GeoEcsFieldsResolvers.Resolvers; - Location?: LocationResolvers.Resolvers; - HostEcsFields?: HostEcsFieldsResolvers.Resolvers; - OsEcsFields?: OsEcsFieldsResolvers.Resolvers; - CursorType?: CursorTypeResolvers.Resolvers; - PageInfoPaginated?: PageInfoPaginatedResolvers.Resolvers; - Inspect?: InspectResolvers.Resolvers; - TimelineData?: TimelineDataResolvers.Resolvers; - TimelineEdges?: TimelineEdgesResolvers.Resolvers; - TimelineItem?: TimelineItemResolvers.Resolvers; - TimelineNonEcsData?: TimelineNonEcsDataResolvers.Resolvers; - Ecs?: EcsResolvers.Resolvers; - AuditdEcsFields?: AuditdEcsFieldsResolvers.Resolvers; - AuditdData?: AuditdDataResolvers.Resolvers; - Summary?: SummaryResolvers.Resolvers; - PrimarySecondary?: PrimarySecondaryResolvers.Resolvers; - DestinationEcsFields?: DestinationEcsFieldsResolvers.Resolvers; - DnsEcsFields?: DnsEcsFieldsResolvers.Resolvers; - DnsQuestionData?: DnsQuestionDataResolvers.Resolvers; - EndgameEcsFields?: EndgameEcsFieldsResolvers.Resolvers; - EventEcsFields?: EventEcsFieldsResolvers.Resolvers; - NetworkEcsField?: NetworkEcsFieldResolvers.Resolvers; - RuleEcsField?: RuleEcsFieldResolvers.Resolvers; - SignalField?: SignalFieldResolvers.Resolvers; - RuleField?: RuleFieldResolvers.Resolvers; - SuricataEcsFields?: SuricataEcsFieldsResolvers.Resolvers; - SuricataEveData?: SuricataEveDataResolvers.Resolvers; - SuricataAlertData?: SuricataAlertDataResolvers.Resolvers; - TlsEcsFields?: TlsEcsFieldsResolvers.Resolvers; - TlsClientCertificateData?: TlsClientCertificateDataResolvers.Resolvers; - FingerprintData?: FingerprintDataResolvers.Resolvers; - TlsFingerprintsData?: TlsFingerprintsDataResolvers.Resolvers; - TlsJa3Data?: TlsJa3DataResolvers.Resolvers; - TlsServerCertificateData?: TlsServerCertificateDataResolvers.Resolvers; - ZeekEcsFields?: ZeekEcsFieldsResolvers.Resolvers; - ZeekConnectionData?: ZeekConnectionDataResolvers.Resolvers; - ZeekNoticeData?: ZeekNoticeDataResolvers.Resolvers; - ZeekDnsData?: ZeekDnsDataResolvers.Resolvers; - ZeekHttpData?: ZeekHttpDataResolvers.Resolvers; - ZeekFileData?: ZeekFileDataResolvers.Resolvers; - ZeekSslData?: ZeekSslDataResolvers.Resolvers; - HttpEcsFields?: HttpEcsFieldsResolvers.Resolvers; - HttpRequestData?: HttpRequestDataResolvers.Resolvers; - HttpBodyData?: HttpBodyDataResolvers.Resolvers; - HttpResponseData?: HttpResponseDataResolvers.Resolvers; - UrlEcsFields?: UrlEcsFieldsResolvers.Resolvers; - WinlogEcsFields?: WinlogEcsFieldsResolvers.Resolvers; - ProcessEcsFields?: ProcessEcsFieldsResolvers.Resolvers; - ProcessHashData?: ProcessHashDataResolvers.Resolvers; - Thread?: ThreadResolvers.Resolvers; - FileFields?: FileFieldsResolvers.Resolvers; - SystemEcsField?: SystemEcsFieldResolvers.Resolvers; - AuditEcsFields?: AuditEcsFieldsResolvers.Resolvers; - PackageEcsFields?: PackageEcsFieldsResolvers.Resolvers; - AuthEcsFields?: AuthEcsFieldsResolvers.Resolvers; - SshEcsFields?: SshEcsFieldsResolvers.Resolvers; - PageInfo?: PageInfoResolvers.Resolvers; - TimelineDetailsData?: TimelineDetailsDataResolvers.Resolvers; - DetailItem?: DetailItemResolvers.Resolvers; - LastEventTimeData?: LastEventTimeDataResolvers.Resolvers; - HostsData?: HostsDataResolvers.Resolvers; - HostsEdges?: HostsEdgesResolvers.Resolvers; - HostItem?: HostItemResolvers.Resolvers; - CloudFields?: CloudFieldsResolvers.Resolvers; - CloudInstance?: CloudInstanceResolvers.Resolvers; - CloudMachine?: CloudMachineResolvers.Resolvers; - FirstLastSeenHost?: FirstLastSeenHostResolvers.Resolvers; - IpOverviewData?: IpOverviewDataResolvers.Resolvers; - Overview?: OverviewResolvers.Resolvers; - AutonomousSystem?: AutonomousSystemResolvers.Resolvers; - AutonomousSystemOrganization?: AutonomousSystemOrganizationResolvers.Resolvers; - UsersData?: UsersDataResolvers.Resolvers; - UsersEdges?: UsersEdgesResolvers.Resolvers; - UsersNode?: UsersNodeResolvers.Resolvers; - UsersItem?: UsersItemResolvers.Resolvers; - KpiNetworkData?: KpiNetworkDataResolvers.Resolvers; - KpiNetworkHistogramData?: KpiNetworkHistogramDataResolvers.Resolvers; - KpiHostsData?: KpiHostsDataResolvers.Resolvers; - KpiHostHistogramData?: KpiHostHistogramDataResolvers.Resolvers; - KpiHostDetailsData?: KpiHostDetailsDataResolvers.Resolvers; - MatrixHistogramOverTimeData?: MatrixHistogramOverTimeDataResolvers.Resolvers; - MatrixOverTimeHistogramData?: MatrixOverTimeHistogramDataResolvers.Resolvers; - NetworkTopCountriesData?: NetworkTopCountriesDataResolvers.Resolvers; - NetworkTopCountriesEdges?: NetworkTopCountriesEdgesResolvers.Resolvers; - NetworkTopCountriesItem?: NetworkTopCountriesItemResolvers.Resolvers; - TopCountriesItemSource?: TopCountriesItemSourceResolvers.Resolvers; - GeoItem?: GeoItemResolvers.Resolvers; - TopCountriesItemDestination?: TopCountriesItemDestinationResolvers.Resolvers; - TopNetworkTablesEcsField?: TopNetworkTablesEcsFieldResolvers.Resolvers; - NetworkTopNFlowData?: NetworkTopNFlowDataResolvers.Resolvers; - NetworkTopNFlowEdges?: NetworkTopNFlowEdgesResolvers.Resolvers; - NetworkTopNFlowItem?: NetworkTopNFlowItemResolvers.Resolvers; - TopNFlowItemSource?: TopNFlowItemSourceResolvers.Resolvers; - AutonomousSystemItem?: AutonomousSystemItemResolvers.Resolvers; - TopNFlowItemDestination?: TopNFlowItemDestinationResolvers.Resolvers; - NetworkDnsData?: NetworkDnsDataResolvers.Resolvers; - NetworkDnsEdges?: NetworkDnsEdgesResolvers.Resolvers; - NetworkDnsItem?: NetworkDnsItemResolvers.Resolvers; - MatrixOverOrdinalHistogramData?: MatrixOverOrdinalHistogramDataResolvers.Resolvers; - NetworkDsOverTimeData?: NetworkDsOverTimeDataResolvers.Resolvers; - NetworkHttpData?: NetworkHttpDataResolvers.Resolvers; - NetworkHttpEdges?: NetworkHttpEdgesResolvers.Resolvers; - NetworkHttpItem?: NetworkHttpItemResolvers.Resolvers; - OverviewNetworkData?: OverviewNetworkDataResolvers.Resolvers; - OverviewHostData?: OverviewHostDataResolvers.Resolvers; - TlsData?: TlsDataResolvers.Resolvers; - TlsEdges?: TlsEdgesResolvers.Resolvers; - TlsNode?: TlsNodeResolvers.Resolvers; - UncommonProcessesData?: UncommonProcessesDataResolvers.Resolvers; - UncommonProcessesEdges?: UncommonProcessesEdgesResolvers.Resolvers; - UncommonProcessItem?: UncommonProcessItemResolvers.Resolvers; - SayMyName?: SayMyNameResolvers.Resolvers; - TimelineResult?: TimelineResultResolvers.Resolvers; - ColumnHeaderResult?: ColumnHeaderResultResolvers.Resolvers; - DataProviderResult?: DataProviderResultResolvers.Resolvers; - QueryMatchResult?: QueryMatchResultResolvers.Resolvers; - DateRangePickerResult?: DateRangePickerResultResolvers.Resolvers; - FavoriteTimelineResult?: FavoriteTimelineResultResolvers.Resolvers; - FilterTimelineResult?: FilterTimelineResultResolvers.Resolvers; - FilterMetaTimelineResult?: FilterMetaTimelineResultResolvers.Resolvers; - SerializedFilterQueryResult?: SerializedFilterQueryResultResolvers.Resolvers; - SerializedKueryQueryResult?: SerializedKueryQueryResultResolvers.Resolvers; - KueryFilterQueryResult?: KueryFilterQueryResultResolvers.Resolvers; - SortTimelineResult?: SortTimelineResultResolvers.Resolvers; - ResponseTimelines?: ResponseTimelinesResolvers.Resolvers; - Mutation?: MutationResolvers.Resolvers; - ResponseNote?: ResponseNoteResolvers.Resolvers; - ResponseTimeline?: ResponseTimelineResolvers.Resolvers; - ResponseFavoriteTimeline?: ResponseFavoriteTimelineResolvers.Resolvers; - EcsEdges?: EcsEdgesResolvers.Resolvers; - EventsTimelineData?: EventsTimelineDataResolvers.Resolvers; - OsFields?: OsFieldsResolvers.Resolvers; - HostFields?: HostFieldsResolvers.Resolvers; - ToStringArray?: GraphQLScalarType; - Date?: GraphQLScalarType; - ToNumberArray?: GraphQLScalarType; - ToDateArray?: GraphQLScalarType; - ToBooleanArray?: GraphQLScalarType; - ToAny?: GraphQLScalarType; - EsValue?: GraphQLScalarType; -} & { [typeName: string]: never }; - -export type IDirectiveResolvers = { - skip?: SkipDirectiveResolver; - include?: IncludeDirectiveResolver; - deprecated?: DeprecatedDirectiveResolver; -} & { [directiveName: string]: never }; +/** Mapping between all available schema types and the resolvers types */ +export type ResolversTypes = ResolversObject<{ + Query: ResolverTypeWrapper<{}>, + ID: ResolverTypeWrapper, + NoteResult: ResolverTypeWrapper, + String: ResolverTypeWrapper, + Float: ResolverTypeWrapper, + PageInfoNote: PageInfoNote, + SortNote: SortNote, + SortFieldNote: SortFieldNote, + Direction: Direction, + ResponseNotes: ResolverTypeWrapper, + PinnedEvent: ResolverTypeWrapper, + Source: ResolverTypeWrapper, + SourceConfiguration: ResolverTypeWrapper, + SourceFields: ResolverTypeWrapper, + SourceStatus: ResolverTypeWrapper, + Boolean: ResolverTypeWrapper, + IndexField: ResolverTypeWrapper, + TimerangeInput: TimerangeInput, + PaginationInputPaginated: PaginationInputPaginated, + AuthenticationsData: ResolverTypeWrapper, + AuthenticationsEdges: ResolverTypeWrapper, + AuthenticationItem: ResolverTypeWrapper, + UserEcsFields: ResolverTypeWrapper, + ToStringArray: ResolverTypeWrapper, + LastSourceHost: ResolverTypeWrapper, + Date: ResolverTypeWrapper, + SourceEcsFields: ResolverTypeWrapper, + ToNumberArray: ResolverTypeWrapper, + GeoEcsFields: ResolverTypeWrapper, + Location: ResolverTypeWrapper, + HostEcsFields: ResolverTypeWrapper, + OsEcsFields: ResolverTypeWrapper, + CursorType: ResolverTypeWrapper, + PageInfoPaginated: ResolverTypeWrapper, + Inspect: ResolverTypeWrapper, + PaginationInput: PaginationInput, + SortField: SortField, + TimelineData: ResolverTypeWrapper, + TimelineEdges: ResolverTypeWrapper, + TimelineItem: ResolverTypeWrapper, + TimelineNonEcsData: ResolverTypeWrapper, + ECS: ResolverTypeWrapper, + AuditdEcsFields: ResolverTypeWrapper, + AuditdData: ResolverTypeWrapper, + Summary: ResolverTypeWrapper, + PrimarySecondary: ResolverTypeWrapper, + DestinationEcsFields: ResolverTypeWrapper, + DnsEcsFields: ResolverTypeWrapper, + DnsQuestionData: ResolverTypeWrapper, + EndgameEcsFields: ResolverTypeWrapper, + EventEcsFields: ResolverTypeWrapper, + ToDateArray: ResolverTypeWrapper, + NetworkEcsField: ResolverTypeWrapper, + RuleEcsField: ResolverTypeWrapper, + SignalField: ResolverTypeWrapper, + RuleField: ResolverTypeWrapper, + ToBooleanArray: ResolverTypeWrapper, + ToAny: ResolverTypeWrapper, + SuricataEcsFields: ResolverTypeWrapper, + SuricataEveData: ResolverTypeWrapper, + SuricataAlertData: ResolverTypeWrapper, + TlsEcsFields: ResolverTypeWrapper, + TlsClientCertificateData: ResolverTypeWrapper, + FingerprintData: ResolverTypeWrapper, + TlsFingerprintsData: ResolverTypeWrapper, + TlsJa3Data: ResolverTypeWrapper, + TlsServerCertificateData: ResolverTypeWrapper, + ZeekEcsFields: ResolverTypeWrapper, + ZeekConnectionData: ResolverTypeWrapper, + ZeekNoticeData: ResolverTypeWrapper, + ZeekDnsData: ResolverTypeWrapper, + ZeekHttpData: ResolverTypeWrapper, + ZeekFileData: ResolverTypeWrapper, + ZeekSslData: ResolverTypeWrapper, + HttpEcsFields: ResolverTypeWrapper, + HttpRequestData: ResolverTypeWrapper, + HttpBodyData: ResolverTypeWrapper, + HttpResponseData: ResolverTypeWrapper, + UrlEcsFields: ResolverTypeWrapper, + WinlogEcsFields: ResolverTypeWrapper, + ProcessEcsFields: ResolverTypeWrapper, + ProcessHashData: ResolverTypeWrapper, + Thread: ResolverTypeWrapper, + FileFields: ResolverTypeWrapper, + SystemEcsField: ResolverTypeWrapper, + AuditEcsFields: ResolverTypeWrapper, + PackageEcsFields: ResolverTypeWrapper, + AuthEcsFields: ResolverTypeWrapper, + SshEcsFields: ResolverTypeWrapper, + PageInfo: ResolverTypeWrapper, + TimelineDetailsData: ResolverTypeWrapper, + DetailItem: ResolverTypeWrapper, + EsValue: ResolverTypeWrapper, + LastEventIndexKey: LastEventIndexKey, + LastTimeDetails: LastTimeDetails, + LastEventTimeData: ResolverTypeWrapper, + HostsSortField: HostsSortField, + HostsFields: HostsFields, + HostsData: ResolverTypeWrapper, + HostsEdges: ResolverTypeWrapper, + HostItem: ResolverTypeWrapper, + CloudFields: ResolverTypeWrapper, + CloudInstance: ResolverTypeWrapper, + CloudMachine: ResolverTypeWrapper, + FirstLastSeenHost: ResolverTypeWrapper, + IpOverviewData: ResolverTypeWrapper, + Overview: ResolverTypeWrapper, + AutonomousSystem: ResolverTypeWrapper, + AutonomousSystemOrganization: ResolverTypeWrapper, + UsersSortField: UsersSortField, + UsersFields: UsersFields, + FlowTarget: FlowTarget, + UsersData: ResolverTypeWrapper, + UsersEdges: ResolverTypeWrapper, + UsersNode: ResolverTypeWrapper, + UsersItem: ResolverTypeWrapper, + KpiNetworkData: ResolverTypeWrapper, + KpiNetworkHistogramData: ResolverTypeWrapper, + KpiHostsData: ResolverTypeWrapper, + KpiHostHistogramData: ResolverTypeWrapper, + KpiHostDetailsData: ResolverTypeWrapper, + HistogramType: HistogramType, + MatrixHistogramOverTimeData: ResolverTypeWrapper, + MatrixOverTimeHistogramData: ResolverTypeWrapper, + FlowTargetSourceDest: FlowTargetSourceDest, + NetworkTopTablesSortField: NetworkTopTablesSortField, + NetworkTopTablesFields: NetworkTopTablesFields, + NetworkTopCountriesData: ResolverTypeWrapper, + NetworkTopCountriesEdges: ResolverTypeWrapper, + NetworkTopCountriesItem: ResolverTypeWrapper, + TopCountriesItemSource: ResolverTypeWrapper, + GeoItem: ResolverTypeWrapper, + TopCountriesItemDestination: ResolverTypeWrapper, + TopNetworkTablesEcsField: ResolverTypeWrapper, + NetworkTopNFlowData: ResolverTypeWrapper, + NetworkTopNFlowEdges: ResolverTypeWrapper, + NetworkTopNFlowItem: ResolverTypeWrapper, + TopNFlowItemSource: ResolverTypeWrapper, + AutonomousSystemItem: ResolverTypeWrapper, + TopNFlowItemDestination: ResolverTypeWrapper, + NetworkDnsSortField: NetworkDnsSortField, + NetworkDnsFields: NetworkDnsFields, + NetworkDnsData: ResolverTypeWrapper, + NetworkDnsEdges: ResolverTypeWrapper, + NetworkDnsItem: ResolverTypeWrapper, + MatrixOverOrdinalHistogramData: ResolverTypeWrapper, + NetworkDsOverTimeData: ResolverTypeWrapper, + NetworkHttpSortField: NetworkHttpSortField, + NetworkHttpData: ResolverTypeWrapper, + NetworkHttpEdges: ResolverTypeWrapper, + NetworkHttpItem: ResolverTypeWrapper, + OverviewNetworkData: ResolverTypeWrapper, + OverviewHostData: ResolverTypeWrapper, + TlsSortField: TlsSortField, + TlsFields: TlsFields, + TlsData: ResolverTypeWrapper, + TlsEdges: ResolverTypeWrapper, + TlsNode: ResolverTypeWrapper, + UncommonProcessesData: ResolverTypeWrapper, + UncommonProcessesEdges: ResolverTypeWrapper, + UncommonProcessItem: ResolverTypeWrapper, + SayMyName: ResolverTypeWrapper, + TimelineResult: ResolverTypeWrapper, + ColumnHeaderResult: ResolverTypeWrapper, + DataProviderResult: ResolverTypeWrapper, + QueryMatchResult: ResolverTypeWrapper, + DateRangePickerResult: ResolverTypeWrapper, + FavoriteTimelineResult: ResolverTypeWrapper, + FilterTimelineResult: ResolverTypeWrapper, + FilterMetaTimelineResult: ResolverTypeWrapper, + SerializedFilterQueryResult: ResolverTypeWrapper, + SerializedKueryQueryResult: ResolverTypeWrapper, + KueryFilterQueryResult: ResolverTypeWrapper, + SortTimelineResult: ResolverTypeWrapper, + PageInfoTimeline: PageInfoTimeline, + SortTimeline: SortTimeline, + SortFieldTimeline: SortFieldTimeline, + ResponseTimelines: ResolverTypeWrapper, + Mutation: ResolverTypeWrapper<{}>, + NoteInput: NoteInput, + ResponseNote: ResolverTypeWrapper, + TimelineInput: TimelineInput, + ColumnHeaderInput: ColumnHeaderInput, + DataProviderInput: DataProviderInput, + QueryMatchInput: QueryMatchInput, + FilterTimelineInput: FilterTimelineInput, + FilterMetaTimelineInput: FilterMetaTimelineInput, + SerializedFilterQueryInput: SerializedFilterQueryInput, + SerializedKueryQueryInput: SerializedKueryQueryInput, + KueryFilterQueryInput: KueryFilterQueryInput, + DateRangePickerInput: DateRangePickerInput, + SortTimelineInput: SortTimelineInput, + ResponseTimeline: ResolverTypeWrapper, + ResponseFavoriteTimeline: ResolverTypeWrapper, + EcsEdges: ResolverTypeWrapper, + EventsTimelineData: ResolverTypeWrapper, + FavoriteTimelineInput: FavoriteTimelineInput, + FlowDirection: FlowDirection, + HostFields: ResolverTypeWrapper, + OsFields: ResolverTypeWrapper, + NetworkDirectionEcs: NetworkDirectionEcs, + NetworkHttpFields: NetworkHttpFields, +}>; + +/** Mapping between all available schema types and the resolvers parents */ +export type ResolversParentTypes = ResolversObject<{ + Query: {}, + ID: Scalars['ID'], + NoteResult: NoteResult, + String: Scalars['String'], + Float: Scalars['Float'], + PageInfoNote: PageInfoNote, + SortNote: SortNote, + SortFieldNote: SortFieldNote, + Direction: Direction, + ResponseNotes: ResponseNotes, + PinnedEvent: PinnedEvent, + Source: Source, + SourceConfiguration: SourceConfiguration, + SourceFields: SourceFields, + SourceStatus: SourceStatus, + Boolean: Scalars['Boolean'], + IndexField: IndexField, + TimerangeInput: TimerangeInput, + PaginationInputPaginated: PaginationInputPaginated, + AuthenticationsData: AuthenticationsData, + AuthenticationsEdges: AuthenticationsEdges, + AuthenticationItem: AuthenticationItem, + UserEcsFields: UserEcsFields, + ToStringArray: Scalars['ToStringArray'], + LastSourceHost: LastSourceHost, + Date: Scalars['Date'], + SourceEcsFields: SourceEcsFields, + ToNumberArray: Scalars['ToNumberArray'], + GeoEcsFields: GeoEcsFields, + Location: Location, + HostEcsFields: HostEcsFields, + OsEcsFields: OsEcsFields, + CursorType: CursorType, + PageInfoPaginated: PageInfoPaginated, + Inspect: Inspect, + PaginationInput: PaginationInput, + SortField: SortField, + TimelineData: TimelineData, + TimelineEdges: TimelineEdges, + TimelineItem: TimelineItem, + TimelineNonEcsData: TimelineNonEcsData, + ECS: Ecs, + AuditdEcsFields: AuditdEcsFields, + AuditdData: AuditdData, + Summary: Summary, + PrimarySecondary: PrimarySecondary, + DestinationEcsFields: DestinationEcsFields, + DnsEcsFields: DnsEcsFields, + DnsQuestionData: DnsQuestionData, + EndgameEcsFields: EndgameEcsFields, + EventEcsFields: EventEcsFields, + ToDateArray: Scalars['ToDateArray'], + NetworkEcsField: NetworkEcsField, + RuleEcsField: RuleEcsField, + SignalField: SignalField, + RuleField: RuleField, + ToBooleanArray: Scalars['ToBooleanArray'], + ToAny: Scalars['ToAny'], + SuricataEcsFields: SuricataEcsFields, + SuricataEveData: SuricataEveData, + SuricataAlertData: SuricataAlertData, + TlsEcsFields: TlsEcsFields, + TlsClientCertificateData: TlsClientCertificateData, + FingerprintData: FingerprintData, + TlsFingerprintsData: TlsFingerprintsData, + TlsJa3Data: TlsJa3Data, + TlsServerCertificateData: TlsServerCertificateData, + ZeekEcsFields: ZeekEcsFields, + ZeekConnectionData: ZeekConnectionData, + ZeekNoticeData: ZeekNoticeData, + ZeekDnsData: ZeekDnsData, + ZeekHttpData: ZeekHttpData, + ZeekFileData: ZeekFileData, + ZeekSslData: ZeekSslData, + HttpEcsFields: HttpEcsFields, + HttpRequestData: HttpRequestData, + HttpBodyData: HttpBodyData, + HttpResponseData: HttpResponseData, + UrlEcsFields: UrlEcsFields, + WinlogEcsFields: WinlogEcsFields, + ProcessEcsFields: ProcessEcsFields, + ProcessHashData: ProcessHashData, + Thread: Thread, + FileFields: FileFields, + SystemEcsField: SystemEcsField, + AuditEcsFields: AuditEcsFields, + PackageEcsFields: PackageEcsFields, + AuthEcsFields: AuthEcsFields, + SshEcsFields: SshEcsFields, + PageInfo: PageInfo, + TimelineDetailsData: TimelineDetailsData, + DetailItem: DetailItem, + EsValue: Scalars['EsValue'], + LastEventIndexKey: LastEventIndexKey, + LastTimeDetails: LastTimeDetails, + LastEventTimeData: LastEventTimeData, + HostsSortField: HostsSortField, + HostsFields: HostsFields, + HostsData: HostsData, + HostsEdges: HostsEdges, + HostItem: HostItem, + CloudFields: CloudFields, + CloudInstance: CloudInstance, + CloudMachine: CloudMachine, + FirstLastSeenHost: FirstLastSeenHost, + IpOverviewData: IpOverviewData, + Overview: Overview, + AutonomousSystem: AutonomousSystem, + AutonomousSystemOrganization: AutonomousSystemOrganization, + UsersSortField: UsersSortField, + UsersFields: UsersFields, + FlowTarget: FlowTarget, + UsersData: UsersData, + UsersEdges: UsersEdges, + UsersNode: UsersNode, + UsersItem: UsersItem, + KpiNetworkData: KpiNetworkData, + KpiNetworkHistogramData: KpiNetworkHistogramData, + KpiHostsData: KpiHostsData, + KpiHostHistogramData: KpiHostHistogramData, + KpiHostDetailsData: KpiHostDetailsData, + HistogramType: HistogramType, + MatrixHistogramOverTimeData: MatrixHistogramOverTimeData, + MatrixOverTimeHistogramData: MatrixOverTimeHistogramData, + FlowTargetSourceDest: FlowTargetSourceDest, + NetworkTopTablesSortField: NetworkTopTablesSortField, + NetworkTopTablesFields: NetworkTopTablesFields, + NetworkTopCountriesData: NetworkTopCountriesData, + NetworkTopCountriesEdges: NetworkTopCountriesEdges, + NetworkTopCountriesItem: NetworkTopCountriesItem, + TopCountriesItemSource: TopCountriesItemSource, + GeoItem: GeoItem, + TopCountriesItemDestination: TopCountriesItemDestination, + TopNetworkTablesEcsField: TopNetworkTablesEcsField, + NetworkTopNFlowData: NetworkTopNFlowData, + NetworkTopNFlowEdges: NetworkTopNFlowEdges, + NetworkTopNFlowItem: NetworkTopNFlowItem, + TopNFlowItemSource: TopNFlowItemSource, + AutonomousSystemItem: AutonomousSystemItem, + TopNFlowItemDestination: TopNFlowItemDestination, + NetworkDnsSortField: NetworkDnsSortField, + NetworkDnsFields: NetworkDnsFields, + NetworkDnsData: NetworkDnsData, + NetworkDnsEdges: NetworkDnsEdges, + NetworkDnsItem: NetworkDnsItem, + MatrixOverOrdinalHistogramData: MatrixOverOrdinalHistogramData, + NetworkDsOverTimeData: NetworkDsOverTimeData, + NetworkHttpSortField: NetworkHttpSortField, + NetworkHttpData: NetworkHttpData, + NetworkHttpEdges: NetworkHttpEdges, + NetworkHttpItem: NetworkHttpItem, + OverviewNetworkData: OverviewNetworkData, + OverviewHostData: OverviewHostData, + TlsSortField: TlsSortField, + TlsFields: TlsFields, + TlsData: TlsData, + TlsEdges: TlsEdges, + TlsNode: TlsNode, + UncommonProcessesData: UncommonProcessesData, + UncommonProcessesEdges: UncommonProcessesEdges, + UncommonProcessItem: UncommonProcessItem, + SayMyName: SayMyName, + TimelineResult: TimelineResult, + ColumnHeaderResult: ColumnHeaderResult, + DataProviderResult: DataProviderResult, + QueryMatchResult: QueryMatchResult, + DateRangePickerResult: DateRangePickerResult, + FavoriteTimelineResult: FavoriteTimelineResult, + FilterTimelineResult: FilterTimelineResult, + FilterMetaTimelineResult: FilterMetaTimelineResult, + SerializedFilterQueryResult: SerializedFilterQueryResult, + SerializedKueryQueryResult: SerializedKueryQueryResult, + KueryFilterQueryResult: KueryFilterQueryResult, + SortTimelineResult: SortTimelineResult, + PageInfoTimeline: PageInfoTimeline, + SortTimeline: SortTimeline, + SortFieldTimeline: SortFieldTimeline, + ResponseTimelines: ResponseTimelines, + Mutation: {}, + NoteInput: NoteInput, + ResponseNote: ResponseNote, + TimelineInput: TimelineInput, + ColumnHeaderInput: ColumnHeaderInput, + DataProviderInput: DataProviderInput, + QueryMatchInput: QueryMatchInput, + FilterTimelineInput: FilterTimelineInput, + FilterMetaTimelineInput: FilterMetaTimelineInput, + SerializedFilterQueryInput: SerializedFilterQueryInput, + SerializedKueryQueryInput: SerializedKueryQueryInput, + KueryFilterQueryInput: KueryFilterQueryInput, + DateRangePickerInput: DateRangePickerInput, + SortTimelineInput: SortTimelineInput, + ResponseTimeline: ResponseTimeline, + ResponseFavoriteTimeline: ResponseFavoriteTimeline, + EcsEdges: EcsEdges, + EventsTimelineData: EventsTimelineData, + FavoriteTimelineInput: FavoriteTimelineInput, + FlowDirection: FlowDirection, + HostFields: HostFields, + OsFields: OsFields, + NetworkDirectionEcs: NetworkDirectionEcs, + NetworkHttpFields: NetworkHttpFields, +}>; + +export type AuditdDataResolvers = ResolversObject<{ + acct?: Resolver, ParentType, ContextType>, + terminal?: Resolver, ParentType, ContextType>, + op?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type AuditdEcsFieldsResolvers = ResolversObject<{ + result?: Resolver, ParentType, ContextType>, + session?: Resolver, ParentType, ContextType>, + data?: Resolver, ParentType, ContextType>, + summary?: Resolver, ParentType, ContextType>, + sequence?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type AuditEcsFieldsResolvers = ResolversObject<{ + package?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type AuthEcsFieldsResolvers = ResolversObject<{ + ssh?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type AuthenticationItemResolvers = ResolversObject<{ + _id?: Resolver, + failures?: Resolver, + successes?: Resolver, + user?: Resolver, + lastSuccess?: Resolver, ParentType, ContextType>, + lastFailure?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type AuthenticationsDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type AuthenticationsEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type AutonomousSystemResolvers = ResolversObject<{ + number?: Resolver, ParentType, ContextType>, + organization?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type AutonomousSystemItemResolvers = ResolversObject<{ + name?: Resolver, ParentType, ContextType>, + number?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type AutonomousSystemOrganizationResolvers = ResolversObject<{ + name?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type CloudFieldsResolvers = ResolversObject<{ + instance?: Resolver, ParentType, ContextType>, + machine?: Resolver, ParentType, ContextType>, + provider?: Resolver>>, ParentType, ContextType>, + region?: Resolver>>, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type CloudInstanceResolvers = ResolversObject<{ + id?: Resolver>>, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type CloudMachineResolvers = ResolversObject<{ + type?: Resolver>>, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ColumnHeaderResultResolvers = ResolversObject<{ + aggregatable?: Resolver, ParentType, ContextType>, + category?: Resolver, ParentType, ContextType>, + columnHeaderType?: Resolver, ParentType, ContextType>, + description?: Resolver, ParentType, ContextType>, + example?: Resolver, ParentType, ContextType>, + indexes?: Resolver>, ParentType, ContextType>, + id?: Resolver, ParentType, ContextType>, + name?: Resolver, ParentType, ContextType>, + placeholder?: Resolver, ParentType, ContextType>, + searchable?: Resolver, ParentType, ContextType>, + type?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type CursorTypeResolvers = ResolversObject<{ + value?: Resolver, ParentType, ContextType>, + tiebreaker?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type DataProviderResultResolvers = ResolversObject<{ + id?: Resolver, ParentType, ContextType>, + name?: Resolver, ParentType, ContextType>, + enabled?: Resolver, ParentType, ContextType>, + excluded?: Resolver, ParentType, ContextType>, + kqlQuery?: Resolver, ParentType, ContextType>, + queryMatch?: Resolver, ParentType, ContextType>, + and?: Resolver>, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export interface DateScalarConfig extends GraphQLScalarTypeConfig { + name: 'Date' +} + +export type DateRangePickerResultResolvers = ResolversObject<{ + start?: Resolver, ParentType, ContextType>, + end?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type DestinationEcsFieldsResolvers = ResolversObject<{ + bytes?: Resolver, ParentType, ContextType>, + ip?: Resolver, ParentType, ContextType>, + port?: Resolver, ParentType, ContextType>, + domain?: Resolver, ParentType, ContextType>, + geo?: Resolver, ParentType, ContextType>, + packets?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type DetailItemResolvers = ResolversObject<{ + field?: Resolver, + values?: Resolver, ParentType, ContextType>, + originalValue?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type DnsEcsFieldsResolvers = ResolversObject<{ + question?: Resolver, ParentType, ContextType>, + resolved_ip?: Resolver, ParentType, ContextType>, + response_code?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type DnsQuestionDataResolvers = ResolversObject<{ + name?: Resolver, ParentType, ContextType>, + type?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type EcsResolvers = ResolversObject<{ + _id?: Resolver, + _index?: Resolver, ParentType, ContextType>, + auditd?: Resolver, ParentType, ContextType>, + destination?: Resolver, ParentType, ContextType>, + dns?: Resolver, ParentType, ContextType>, + endgame?: Resolver, ParentType, ContextType>, + event?: Resolver, ParentType, ContextType>, + geo?: Resolver, ParentType, ContextType>, + host?: Resolver, ParentType, ContextType>, + network?: Resolver, ParentType, ContextType>, + rule?: Resolver, ParentType, ContextType>, + signal?: Resolver, ParentType, ContextType>, + source?: Resolver, ParentType, ContextType>, + suricata?: Resolver, ParentType, ContextType>, + tls?: Resolver, ParentType, ContextType>, + zeek?: Resolver, ParentType, ContextType>, + http?: Resolver, ParentType, ContextType>, + url?: Resolver, ParentType, ContextType>, + timestamp?: Resolver, ParentType, ContextType>, + message?: Resolver, ParentType, ContextType>, + user?: Resolver, ParentType, ContextType>, + winlog?: Resolver, ParentType, ContextType>, + process?: Resolver, ParentType, ContextType>, + file?: Resolver, ParentType, ContextType>, + system?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type EcsEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type EndgameEcsFieldsResolvers = ResolversObject<{ + exit_code?: Resolver, ParentType, ContextType>, + file_name?: Resolver, ParentType, ContextType>, + file_path?: Resolver, ParentType, ContextType>, + logon_type?: Resolver, ParentType, ContextType>, + parent_process_name?: Resolver, ParentType, ContextType>, + pid?: Resolver, ParentType, ContextType>, + process_name?: Resolver, ParentType, ContextType>, + subject_domain_name?: Resolver, ParentType, ContextType>, + subject_logon_id?: Resolver, ParentType, ContextType>, + subject_user_name?: Resolver, ParentType, ContextType>, + target_domain_name?: Resolver, ParentType, ContextType>, + target_logon_id?: Resolver, ParentType, ContextType>, + target_user_name?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export interface EsValueScalarConfig extends GraphQLScalarTypeConfig { + name: 'EsValue' +} + +export type EventEcsFieldsResolvers = ResolversObject<{ + action?: Resolver, ParentType, ContextType>, + category?: Resolver, ParentType, ContextType>, + code?: Resolver, ParentType, ContextType>, + created?: Resolver, ParentType, ContextType>, + dataset?: Resolver, ParentType, ContextType>, + duration?: Resolver, ParentType, ContextType>, + end?: Resolver, ParentType, ContextType>, + hash?: Resolver, ParentType, ContextType>, + id?: Resolver, ParentType, ContextType>, + kind?: Resolver, ParentType, ContextType>, + module?: Resolver, ParentType, ContextType>, + original?: Resolver, ParentType, ContextType>, + outcome?: Resolver, ParentType, ContextType>, + risk_score?: Resolver, ParentType, ContextType>, + risk_score_norm?: Resolver, ParentType, ContextType>, + severity?: Resolver, ParentType, ContextType>, + start?: Resolver, ParentType, ContextType>, + timezone?: Resolver, ParentType, ContextType>, + type?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type EventsTimelineDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type FavoriteTimelineResultResolvers = ResolversObject<{ + fullName?: Resolver, ParentType, ContextType>, + userName?: Resolver, ParentType, ContextType>, + favoriteDate?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type FileFieldsResolvers = ResolversObject<{ + name?: Resolver, ParentType, ContextType>, + path?: Resolver, ParentType, ContextType>, + target_path?: Resolver, ParentType, ContextType>, + extension?: Resolver, ParentType, ContextType>, + type?: Resolver, ParentType, ContextType>, + device?: Resolver, ParentType, ContextType>, + inode?: Resolver, ParentType, ContextType>, + uid?: Resolver, ParentType, ContextType>, + owner?: Resolver, ParentType, ContextType>, + gid?: Resolver, ParentType, ContextType>, + group?: Resolver, ParentType, ContextType>, + mode?: Resolver, ParentType, ContextType>, + size?: Resolver, ParentType, ContextType>, + mtime?: Resolver, ParentType, ContextType>, + ctime?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type FilterMetaTimelineResultResolvers = ResolversObject<{ + alias?: Resolver, ParentType, ContextType>, + controlledBy?: Resolver, ParentType, ContextType>, + disabled?: Resolver, ParentType, ContextType>, + field?: Resolver, ParentType, ContextType>, + formattedValue?: Resolver, ParentType, ContextType>, + index?: Resolver, ParentType, ContextType>, + key?: Resolver, ParentType, ContextType>, + negate?: Resolver, ParentType, ContextType>, + params?: Resolver, ParentType, ContextType>, + type?: Resolver, ParentType, ContextType>, + value?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type FilterTimelineResultResolvers = ResolversObject<{ + exists?: Resolver, ParentType, ContextType>, + meta?: Resolver, ParentType, ContextType>, + match_all?: Resolver, ParentType, ContextType>, + missing?: Resolver, ParentType, ContextType>, + query?: Resolver, ParentType, ContextType>, + range?: Resolver, ParentType, ContextType>, + script?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type FingerprintDataResolvers = ResolversObject<{ + sha1?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type FirstLastSeenHostResolvers = ResolversObject<{ + inspect?: Resolver, ParentType, ContextType>, + firstSeen?: Resolver, ParentType, ContextType>, + lastSeen?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type GeoEcsFieldsResolvers = ResolversObject<{ + city_name?: Resolver, ParentType, ContextType>, + continent_name?: Resolver, ParentType, ContextType>, + country_iso_code?: Resolver, ParentType, ContextType>, + country_name?: Resolver, ParentType, ContextType>, + location?: Resolver, ParentType, ContextType>, + region_iso_code?: Resolver, ParentType, ContextType>, + region_name?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type GeoItemResolvers = ResolversObject<{ + geo?: Resolver, ParentType, ContextType>, + flowTarget?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type HostEcsFieldsResolvers = ResolversObject<{ + architecture?: Resolver, ParentType, ContextType>, + id?: Resolver, ParentType, ContextType>, + ip?: Resolver, ParentType, ContextType>, + mac?: Resolver, ParentType, ContextType>, + name?: Resolver, ParentType, ContextType>, + os?: Resolver, ParentType, ContextType>, + type?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type HostFieldsResolvers = ResolversObject<{ + architecture?: Resolver, ParentType, ContextType>, + id?: Resolver, ParentType, ContextType>, + ip?: Resolver>>, ParentType, ContextType>, + mac?: Resolver>>, ParentType, ContextType>, + name?: Resolver, ParentType, ContextType>, + os?: Resolver, ParentType, ContextType>, + type?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type HostItemResolvers = ResolversObject<{ + _id?: Resolver, ParentType, ContextType>, + lastSeen?: Resolver, ParentType, ContextType>, + host?: Resolver, ParentType, ContextType>, + cloud?: Resolver, ParentType, ContextType>, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type HostsDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type HostsEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type HttpBodyDataResolvers = ResolversObject<{ + content?: Resolver, ParentType, ContextType>, + bytes?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type HttpEcsFieldsResolvers = ResolversObject<{ + version?: Resolver, ParentType, ContextType>, + request?: Resolver, ParentType, ContextType>, + response?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type HttpRequestDataResolvers = ResolversObject<{ + method?: Resolver, ParentType, ContextType>, + body?: Resolver, ParentType, ContextType>, + referrer?: Resolver, ParentType, ContextType>, + bytes?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type HttpResponseDataResolvers = ResolversObject<{ + status_code?: Resolver, ParentType, ContextType>, + body?: Resolver, ParentType, ContextType>, + bytes?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type IndexFieldResolvers = ResolversObject<{ + category?: Resolver, + example?: Resolver, ParentType, ContextType>, + indexes?: Resolver>, ParentType, ContextType>, + name?: Resolver, + type?: Resolver, + searchable?: Resolver, + aggregatable?: Resolver, + description?: Resolver, ParentType, ContextType>, + format?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type InspectResolvers = ResolversObject<{ + dsl?: Resolver, ParentType, ContextType>, + response?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type IpOverviewDataResolvers = ResolversObject<{ + client?: Resolver, ParentType, ContextType>, + destination?: Resolver, ParentType, ContextType>, + host?: Resolver, + server?: Resolver, ParentType, ContextType>, + source?: Resolver, ParentType, ContextType>, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type KpiHostDetailsDataResolvers = ResolversObject<{ + authSuccess?: Resolver, ParentType, ContextType>, + authSuccessHistogram?: Resolver>, ParentType, ContextType>, + authFailure?: Resolver, ParentType, ContextType>, + authFailureHistogram?: Resolver>, ParentType, ContextType>, + uniqueSourceIps?: Resolver, ParentType, ContextType>, + uniqueSourceIpsHistogram?: Resolver>, ParentType, ContextType>, + uniqueDestinationIps?: Resolver, ParentType, ContextType>, + uniqueDestinationIpsHistogram?: Resolver>, ParentType, ContextType>, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type KpiHostHistogramDataResolvers = ResolversObject<{ + x?: Resolver, ParentType, ContextType>, + y?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type KpiHostsDataResolvers = ResolversObject<{ + hosts?: Resolver, ParentType, ContextType>, + hostsHistogram?: Resolver>, ParentType, ContextType>, + authSuccess?: Resolver, ParentType, ContextType>, + authSuccessHistogram?: Resolver>, ParentType, ContextType>, + authFailure?: Resolver, ParentType, ContextType>, + authFailureHistogram?: Resolver>, ParentType, ContextType>, + uniqueSourceIps?: Resolver, ParentType, ContextType>, + uniqueSourceIpsHistogram?: Resolver>, ParentType, ContextType>, + uniqueDestinationIps?: Resolver, ParentType, ContextType>, + uniqueDestinationIpsHistogram?: Resolver>, ParentType, ContextType>, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type KpiNetworkDataResolvers = ResolversObject<{ + networkEvents?: Resolver, ParentType, ContextType>, + uniqueFlowId?: Resolver, ParentType, ContextType>, + uniqueSourcePrivateIps?: Resolver, ParentType, ContextType>, + uniqueSourcePrivateIpsHistogram?: Resolver>, ParentType, ContextType>, + uniqueDestinationPrivateIps?: Resolver, ParentType, ContextType>, + uniqueDestinationPrivateIpsHistogram?: Resolver>, ParentType, ContextType>, + dnsQueries?: Resolver, ParentType, ContextType>, + tlsHandshakes?: Resolver, ParentType, ContextType>, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type KpiNetworkHistogramDataResolvers = ResolversObject<{ + x?: Resolver, ParentType, ContextType>, + y?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type KueryFilterQueryResultResolvers = ResolversObject<{ + kind?: Resolver, ParentType, ContextType>, + expression?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type LastEventTimeDataResolvers = ResolversObject<{ + lastSeen?: Resolver, ParentType, ContextType>, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type LastSourceHostResolvers = ResolversObject<{ + timestamp?: Resolver, ParentType, ContextType>, + source?: Resolver, ParentType, ContextType>, + host?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type LocationResolvers = ResolversObject<{ + lon?: Resolver, ParentType, ContextType>, + lat?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type MatrixHistogramOverTimeDataResolvers = ResolversObject<{ + inspect?: Resolver, ParentType, ContextType>, + matrixHistogramData?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type MatrixOverOrdinalHistogramDataResolvers = ResolversObject<{ + x?: Resolver, + y?: Resolver, + g?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type MatrixOverTimeHistogramDataResolvers = ResolversObject<{ + x?: Resolver, ParentType, ContextType>, + y?: Resolver, ParentType, ContextType>, + g?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type MutationResolvers = ResolversObject<{ + persistNote?: Resolver>, + deleteNote?: Resolver, ParentType, ContextType, RequireFields>, + deleteNoteByTimelineId?: Resolver, ParentType, ContextType, RequireFields>, + persistPinnedEventOnTimeline?: Resolver, ParentType, ContextType, RequireFields>, + deletePinnedEventOnTimeline?: Resolver>, + deleteAllPinnedEventsOnTimeline?: Resolver>, + persistTimeline?: Resolver>, + persistFavorite?: Resolver, + deleteTimeline?: Resolver>, +}>; + +export type NetworkDnsDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + histogram?: Resolver>, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkDnsEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkDnsItemResolvers = ResolversObject<{ + _id?: Resolver, ParentType, ContextType>, + dnsBytesIn?: Resolver, ParentType, ContextType>, + dnsBytesOut?: Resolver, ParentType, ContextType>, + dnsName?: Resolver, ParentType, ContextType>, + queryCount?: Resolver, ParentType, ContextType>, + uniqueDomains?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkDsOverTimeDataResolvers = ResolversObject<{ + inspect?: Resolver, ParentType, ContextType>, + matrixHistogramData?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkEcsFieldResolvers = ResolversObject<{ + bytes?: Resolver, ParentType, ContextType>, + community_id?: Resolver, ParentType, ContextType>, + direction?: Resolver, ParentType, ContextType>, + packets?: Resolver, ParentType, ContextType>, + protocol?: Resolver, ParentType, ContextType>, + transport?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkHttpDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkHttpEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkHttpItemResolvers = ResolversObject<{ + _id?: Resolver, ParentType, ContextType>, + domains?: Resolver, ParentType, ContextType>, + lastHost?: Resolver, ParentType, ContextType>, + lastSourceIp?: Resolver, ParentType, ContextType>, + methods?: Resolver, ParentType, ContextType>, + path?: Resolver, ParentType, ContextType>, + requestCount?: Resolver, ParentType, ContextType>, + statuses?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkTopCountriesDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkTopCountriesEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkTopCountriesItemResolvers = ResolversObject<{ + _id?: Resolver, ParentType, ContextType>, + source?: Resolver, ParentType, ContextType>, + destination?: Resolver, ParentType, ContextType>, + network?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkTopNFlowDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkTopNFlowEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NetworkTopNFlowItemResolvers = ResolversObject<{ + _id?: Resolver, ParentType, ContextType>, + source?: Resolver, ParentType, ContextType>, + destination?: Resolver, ParentType, ContextType>, + network?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type NoteResultResolvers = ResolversObject<{ + eventId?: Resolver, ParentType, ContextType>, + note?: Resolver, ParentType, ContextType>, + timelineId?: Resolver, ParentType, ContextType>, + noteId?: Resolver, + created?: Resolver, ParentType, ContextType>, + createdBy?: Resolver, ParentType, ContextType>, + timelineVersion?: Resolver, ParentType, ContextType>, + updated?: Resolver, ParentType, ContextType>, + updatedBy?: Resolver, ParentType, ContextType>, + version?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type OsEcsFieldsResolvers = ResolversObject<{ + platform?: Resolver, ParentType, ContextType>, + name?: Resolver, ParentType, ContextType>, + full?: Resolver, ParentType, ContextType>, + family?: Resolver, ParentType, ContextType>, + version?: Resolver, ParentType, ContextType>, + kernel?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type OsFieldsResolvers = ResolversObject<{ + platform?: Resolver, ParentType, ContextType>, + name?: Resolver, ParentType, ContextType>, + full?: Resolver, ParentType, ContextType>, + family?: Resolver, ParentType, ContextType>, + version?: Resolver, ParentType, ContextType>, + kernel?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type OverviewResolvers = ResolversObject<{ + firstSeen?: Resolver, ParentType, ContextType>, + lastSeen?: Resolver, ParentType, ContextType>, + autonomousSystem?: Resolver, + geo?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type OverviewHostDataResolvers = ResolversObject<{ + auditbeatAuditd?: Resolver, ParentType, ContextType>, + auditbeatFIM?: Resolver, ParentType, ContextType>, + auditbeatLogin?: Resolver, ParentType, ContextType>, + auditbeatPackage?: Resolver, ParentType, ContextType>, + auditbeatProcess?: Resolver, ParentType, ContextType>, + auditbeatUser?: Resolver, ParentType, ContextType>, + endgameDns?: Resolver, ParentType, ContextType>, + endgameFile?: Resolver, ParentType, ContextType>, + endgameImageLoad?: Resolver, ParentType, ContextType>, + endgameNetwork?: Resolver, ParentType, ContextType>, + endgameProcess?: Resolver, ParentType, ContextType>, + endgameRegistry?: Resolver, ParentType, ContextType>, + endgameSecurity?: Resolver, ParentType, ContextType>, + filebeatSystemModule?: Resolver, ParentType, ContextType>, + winlogbeatSecurity?: Resolver, ParentType, ContextType>, + winlogbeatMWSysmonOperational?: Resolver, ParentType, ContextType>, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type OverviewNetworkDataResolvers = ResolversObject<{ + auditbeatSocket?: Resolver, ParentType, ContextType>, + filebeatCisco?: Resolver, ParentType, ContextType>, + filebeatNetflow?: Resolver, ParentType, ContextType>, + filebeatPanw?: Resolver, ParentType, ContextType>, + filebeatSuricata?: Resolver, ParentType, ContextType>, + filebeatZeek?: Resolver, ParentType, ContextType>, + packetbeatDNS?: Resolver, ParentType, ContextType>, + packetbeatFlow?: Resolver, ParentType, ContextType>, + packetbeatTLS?: Resolver, ParentType, ContextType>, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type PackageEcsFieldsResolvers = ResolversObject<{ + arch?: Resolver, ParentType, ContextType>, + entity_id?: Resolver, ParentType, ContextType>, + name?: Resolver, ParentType, ContextType>, + size?: Resolver, ParentType, ContextType>, + summary?: Resolver, ParentType, ContextType>, + version?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type PageInfoResolvers = ResolversObject<{ + endCursor?: Resolver, ParentType, ContextType>, + hasNextPage?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type PageInfoPaginatedResolvers = ResolversObject<{ + activePage?: Resolver, + fakeTotalCount?: Resolver, + showMorePagesIndicator?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type PinnedEventResolvers = ResolversObject<{ + code?: Resolver, ParentType, ContextType>, + message?: Resolver, ParentType, ContextType>, + pinnedEventId?: Resolver, + eventId?: Resolver, ParentType, ContextType>, + timelineId?: Resolver, ParentType, ContextType>, + timelineVersion?: Resolver, ParentType, ContextType>, + created?: Resolver, ParentType, ContextType>, + createdBy?: Resolver, ParentType, ContextType>, + updated?: Resolver, ParentType, ContextType>, + updatedBy?: Resolver, ParentType, ContextType>, + version?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type PrimarySecondaryResolvers = ResolversObject<{ + primary?: Resolver, ParentType, ContextType>, + secondary?: Resolver, ParentType, ContextType>, + type?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ProcessEcsFieldsResolvers = ResolversObject<{ + hash?: Resolver, ParentType, ContextType>, + pid?: Resolver, ParentType, ContextType>, + name?: Resolver, ParentType, ContextType>, + ppid?: Resolver, ParentType, ContextType>, + args?: Resolver, ParentType, ContextType>, + executable?: Resolver, ParentType, ContextType>, + title?: Resolver, ParentType, ContextType>, + thread?: Resolver, ParentType, ContextType>, + working_directory?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ProcessHashDataResolvers = ResolversObject<{ + md5?: Resolver, ParentType, ContextType>, + sha1?: Resolver, ParentType, ContextType>, + sha256?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type QueryResolvers = ResolversObject<{ + getNote?: Resolver>, + getNotesByTimelineId?: Resolver, ParentType, ContextType, RequireFields>, + getNotesByEventId?: Resolver, ParentType, ContextType, RequireFields>, + getAllNotes?: Resolver, + getAllPinnedEventsByTimelineId?: Resolver, ParentType, ContextType, RequireFields>, + source?: Resolver>, + allSources?: Resolver, ParentType, ContextType>, + getOneTimeline?: Resolver>, + getAllTimeline?: Resolver, +}>; + +export type QueryMatchResultResolvers = ResolversObject<{ + field?: Resolver, ParentType, ContextType>, + displayField?: Resolver, ParentType, ContextType>, + value?: Resolver, ParentType, ContextType>, + displayValue?: Resolver, ParentType, ContextType>, + operator?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ResponseFavoriteTimelineResolvers = ResolversObject<{ + code?: Resolver, ParentType, ContextType>, + message?: Resolver, ParentType, ContextType>, + savedObjectId?: Resolver, + version?: Resolver, + favorite?: Resolver>, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ResponseNoteResolvers = ResolversObject<{ + code?: Resolver, ParentType, ContextType>, + message?: Resolver, ParentType, ContextType>, + note?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ResponseNotesResolvers = ResolversObject<{ + notes?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ResponseTimelineResolvers = ResolversObject<{ + code?: Resolver, ParentType, ContextType>, + message?: Resolver, ParentType, ContextType>, + timeline?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ResponseTimelinesResolvers = ResolversObject<{ + timeline?: Resolver>, ParentType, ContextType>, + totalCount?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type RuleEcsFieldResolvers = ResolversObject<{ + reference?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type RuleFieldResolvers = ResolversObject<{ + id?: Resolver, ParentType, ContextType>, + rule_id?: Resolver, ParentType, ContextType>, + false_positives?: Resolver, ParentType, ContextType>, + saved_id?: Resolver, ParentType, ContextType>, + timeline_id?: Resolver, ParentType, ContextType>, + timeline_title?: Resolver, ParentType, ContextType>, + max_signals?: Resolver, ParentType, ContextType>, + risk_score?: Resolver, ParentType, ContextType>, + output_index?: Resolver, ParentType, ContextType>, + description?: Resolver, ParentType, ContextType>, + from?: Resolver, ParentType, ContextType>, + immutable?: Resolver, ParentType, ContextType>, + index?: Resolver, ParentType, ContextType>, + interval?: Resolver, ParentType, ContextType>, + language?: Resolver, ParentType, ContextType>, + query?: Resolver, ParentType, ContextType>, + references?: Resolver, ParentType, ContextType>, + severity?: Resolver, ParentType, ContextType>, + tags?: Resolver, ParentType, ContextType>, + threat?: Resolver, ParentType, ContextType>, + type?: Resolver, ParentType, ContextType>, + size?: Resolver, ParentType, ContextType>, + to?: Resolver, ParentType, ContextType>, + enabled?: Resolver, ParentType, ContextType>, + filters?: Resolver, ParentType, ContextType>, + created_at?: Resolver, ParentType, ContextType>, + updated_at?: Resolver, ParentType, ContextType>, + created_by?: Resolver, ParentType, ContextType>, + updated_by?: Resolver, ParentType, ContextType>, + version?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SayMyNameResolvers = ResolversObject<{ + appName?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SerializedFilterQueryResultResolvers = ResolversObject<{ + filterQuery?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SerializedKueryQueryResultResolvers = ResolversObject<{ + kuery?: Resolver, ParentType, ContextType>, + serializedQuery?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SignalFieldResolvers = ResolversObject<{ + rule?: Resolver, ParentType, ContextType>, + original_time?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SortTimelineResultResolvers = ResolversObject<{ + columnId?: Resolver, ParentType, ContextType>, + sortDirection?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SourceResolvers = ResolversObject<{ + id?: Resolver, + configuration?: Resolver, + status?: Resolver, + Authentications?: Resolver>, + Timeline?: Resolver>, + TimelineDetails?: Resolver>, + LastEventTime?: Resolver>, + Hosts?: Resolver>, + HostOverview?: Resolver>, + HostFirstLastSeen?: Resolver>, + IpOverview?: Resolver, ParentType, ContextType, RequireFields>, + Users?: Resolver>, + KpiNetwork?: Resolver, ParentType, ContextType, RequireFields>, + KpiHosts?: Resolver>, + KpiHostDetails?: Resolver>, + MatrixHistogram?: Resolver>, + NetworkTopCountries?: Resolver>, + NetworkTopNFlow?: Resolver>, + NetworkDns?: Resolver>, + NetworkDnsHistogram?: Resolver>, + NetworkHttp?: Resolver>, + OverviewNetwork?: Resolver, ParentType, ContextType, RequireFields>, + OverviewHost?: Resolver, ParentType, ContextType, RequireFields>, + Tls?: Resolver>, + UncommonProcesses?: Resolver>, + whoAmI?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SourceConfigurationResolvers = ResolversObject<{ + fields?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SourceEcsFieldsResolvers = ResolversObject<{ + bytes?: Resolver, ParentType, ContextType>, + ip?: Resolver, ParentType, ContextType>, + port?: Resolver, ParentType, ContextType>, + domain?: Resolver, ParentType, ContextType>, + geo?: Resolver, ParentType, ContextType>, + packets?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SourceFieldsResolvers = ResolversObject<{ + container?: Resolver, + host?: Resolver, + message?: Resolver, ParentType, ContextType>, + pod?: Resolver, + tiebreaker?: Resolver, + timestamp?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SourceStatusResolvers = ResolversObject<{ + indicesExist?: Resolver>, + indexFields?: Resolver, ParentType, ContextType, RequireFields>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SshEcsFieldsResolvers = ResolversObject<{ + method?: Resolver, ParentType, ContextType>, + signature?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SummaryResolvers = ResolversObject<{ + actor?: Resolver, ParentType, ContextType>, + object?: Resolver, ParentType, ContextType>, + how?: Resolver, ParentType, ContextType>, + message_type?: Resolver, ParentType, ContextType>, + sequence?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SuricataAlertDataResolvers = ResolversObject<{ + signature?: Resolver, ParentType, ContextType>, + signature_id?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SuricataEcsFieldsResolvers = ResolversObject<{ + eve?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SuricataEveDataResolvers = ResolversObject<{ + alert?: Resolver, ParentType, ContextType>, + flow_id?: Resolver, ParentType, ContextType>, + proto?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type SystemEcsFieldResolvers = ResolversObject<{ + audit?: Resolver, ParentType, ContextType>, + auth?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ThreadResolvers = ResolversObject<{ + id?: Resolver, ParentType, ContextType>, + start?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TimelineDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TimelineDetailsDataResolvers = ResolversObject<{ + data?: Resolver>, ParentType, ContextType>, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TimelineEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TimelineItemResolvers = ResolversObject<{ + _id?: Resolver, + _index?: Resolver, ParentType, ContextType>, + data?: Resolver, ParentType, ContextType>, + ecs?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TimelineNonEcsDataResolvers = ResolversObject<{ + field?: Resolver, + value?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TimelineResultResolvers = ResolversObject<{ + columns?: Resolver>, ParentType, ContextType>, + created?: Resolver, ParentType, ContextType>, + createdBy?: Resolver, ParentType, ContextType>, + dataProviders?: Resolver>, ParentType, ContextType>, + dateRange?: Resolver, ParentType, ContextType>, + description?: Resolver, ParentType, ContextType>, + eventIdToNoteIds?: Resolver>, ParentType, ContextType>, + eventType?: Resolver, ParentType, ContextType>, + favorite?: Resolver>, ParentType, ContextType>, + filters?: Resolver>, ParentType, ContextType>, + kqlMode?: Resolver, ParentType, ContextType>, + kqlQuery?: Resolver, ParentType, ContextType>, + notes?: Resolver>, ParentType, ContextType>, + noteIds?: Resolver>, ParentType, ContextType>, + pinnedEventIds?: Resolver>, ParentType, ContextType>, + pinnedEventsSaveObject?: Resolver>, ParentType, ContextType>, + savedQueryId?: Resolver, ParentType, ContextType>, + savedObjectId?: Resolver, + sort?: Resolver, ParentType, ContextType>, + title?: Resolver, ParentType, ContextType>, + updated?: Resolver, ParentType, ContextType>, + updatedBy?: Resolver, ParentType, ContextType>, + version?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TlsClientCertificateDataResolvers = ResolversObject<{ + fingerprint?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TlsDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TlsEcsFieldsResolvers = ResolversObject<{ + client_certificate?: Resolver, ParentType, ContextType>, + fingerprints?: Resolver, ParentType, ContextType>, + server_certificate?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TlsEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TlsFingerprintsDataResolvers = ResolversObject<{ + ja3?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TlsJa3DataResolvers = ResolversObject<{ + hash?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TlsNodeResolvers = ResolversObject<{ + _id?: Resolver, ParentType, ContextType>, + timestamp?: Resolver, ParentType, ContextType>, + alternativeNames?: Resolver>, ParentType, ContextType>, + notAfter?: Resolver>, ParentType, ContextType>, + commonNames?: Resolver>, ParentType, ContextType>, + ja3?: Resolver>, ParentType, ContextType>, + issuerNames?: Resolver>, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TlsServerCertificateDataResolvers = ResolversObject<{ + fingerprint?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export interface ToAnyScalarConfig extends GraphQLScalarTypeConfig { + name: 'ToAny' +} + +export interface ToBooleanArrayScalarConfig extends GraphQLScalarTypeConfig { + name: 'ToBooleanArray' +} + +export interface ToDateArrayScalarConfig extends GraphQLScalarTypeConfig { + name: 'ToDateArray' +} + +export interface ToNumberArrayScalarConfig extends GraphQLScalarTypeConfig { + name: 'ToNumberArray' +} + +export type TopCountriesItemDestinationResolvers = ResolversObject<{ + country?: Resolver, ParentType, ContextType>, + destination_ips?: Resolver, ParentType, ContextType>, + flows?: Resolver, ParentType, ContextType>, + location?: Resolver, ParentType, ContextType>, + source_ips?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TopCountriesItemSourceResolvers = ResolversObject<{ + country?: Resolver, ParentType, ContextType>, + destination_ips?: Resolver, ParentType, ContextType>, + flows?: Resolver, ParentType, ContextType>, + location?: Resolver, ParentType, ContextType>, + source_ips?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TopNetworkTablesEcsFieldResolvers = ResolversObject<{ + bytes_in?: Resolver, ParentType, ContextType>, + bytes_out?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TopNFlowItemDestinationResolvers = ResolversObject<{ + autonomous_system?: Resolver, ParentType, ContextType>, + domain?: Resolver>, ParentType, ContextType>, + ip?: Resolver, ParentType, ContextType>, + location?: Resolver, ParentType, ContextType>, + flows?: Resolver, ParentType, ContextType>, + source_ips?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type TopNFlowItemSourceResolvers = ResolversObject<{ + autonomous_system?: Resolver, ParentType, ContextType>, + domain?: Resolver>, ParentType, ContextType>, + ip?: Resolver, ParentType, ContextType>, + location?: Resolver, ParentType, ContextType>, + flows?: Resolver, ParentType, ContextType>, + destination_ips?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export interface ToStringArrayScalarConfig extends GraphQLScalarTypeConfig { + name: 'ToStringArray' +} + +export type UncommonProcessesDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type UncommonProcessesEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type UncommonProcessItemResolvers = ResolversObject<{ + _id?: Resolver, + instances?: Resolver, + process?: Resolver, + hosts?: Resolver, ParentType, ContextType>, + user?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type UrlEcsFieldsResolvers = ResolversObject<{ + domain?: Resolver, ParentType, ContextType>, + original?: Resolver, ParentType, ContextType>, + username?: Resolver, ParentType, ContextType>, + password?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type UserEcsFieldsResolvers = ResolversObject<{ + domain?: Resolver, ParentType, ContextType>, + id?: Resolver, ParentType, ContextType>, + name?: Resolver, ParentType, ContextType>, + full_name?: Resolver, ParentType, ContextType>, + email?: Resolver, ParentType, ContextType>, + hash?: Resolver, ParentType, ContextType>, + group?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type UsersDataResolvers = ResolversObject<{ + edges?: Resolver, ParentType, ContextType>, + totalCount?: Resolver, + pageInfo?: Resolver, + inspect?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type UsersEdgesResolvers = ResolversObject<{ + node?: Resolver, + cursor?: Resolver, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type UsersItemResolvers = ResolversObject<{ + name?: Resolver, ParentType, ContextType>, + id?: Resolver, ParentType, ContextType>, + groupId?: Resolver, ParentType, ContextType>, + groupName?: Resolver, ParentType, ContextType>, + count?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type UsersNodeResolvers = ResolversObject<{ + _id?: Resolver, ParentType, ContextType>, + timestamp?: Resolver, ParentType, ContextType>, + user?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type WinlogEcsFieldsResolvers = ResolversObject<{ + event_id?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ZeekConnectionDataResolvers = ResolversObject<{ + local_resp?: Resolver, ParentType, ContextType>, + local_orig?: Resolver, ParentType, ContextType>, + missed_bytes?: Resolver, ParentType, ContextType>, + state?: Resolver, ParentType, ContextType>, + history?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ZeekDnsDataResolvers = ResolversObject<{ + AA?: Resolver, ParentType, ContextType>, + qclass_name?: Resolver, ParentType, ContextType>, + RD?: Resolver, ParentType, ContextType>, + qtype_name?: Resolver, ParentType, ContextType>, + rejected?: Resolver, ParentType, ContextType>, + qtype?: Resolver, ParentType, ContextType>, + query?: Resolver, ParentType, ContextType>, + trans_id?: Resolver, ParentType, ContextType>, + qclass?: Resolver, ParentType, ContextType>, + RA?: Resolver, ParentType, ContextType>, + TC?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ZeekEcsFieldsResolvers = ResolversObject<{ + session_id?: Resolver, ParentType, ContextType>, + connection?: Resolver, ParentType, ContextType>, + notice?: Resolver, ParentType, ContextType>, + dns?: Resolver, ParentType, ContextType>, + http?: Resolver, ParentType, ContextType>, + files?: Resolver, ParentType, ContextType>, + ssl?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ZeekFileDataResolvers = ResolversObject<{ + session_ids?: Resolver, ParentType, ContextType>, + timedout?: Resolver, ParentType, ContextType>, + local_orig?: Resolver, ParentType, ContextType>, + tx_host?: Resolver, ParentType, ContextType>, + source?: Resolver, ParentType, ContextType>, + is_orig?: Resolver, ParentType, ContextType>, + overflow_bytes?: Resolver, ParentType, ContextType>, + sha1?: Resolver, ParentType, ContextType>, + duration?: Resolver, ParentType, ContextType>, + depth?: Resolver, ParentType, ContextType>, + analyzers?: Resolver, ParentType, ContextType>, + mime_type?: Resolver, ParentType, ContextType>, + rx_host?: Resolver, ParentType, ContextType>, + total_bytes?: Resolver, ParentType, ContextType>, + fuid?: Resolver, ParentType, ContextType>, + seen_bytes?: Resolver, ParentType, ContextType>, + missing_bytes?: Resolver, ParentType, ContextType>, + md5?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ZeekHttpDataResolvers = ResolversObject<{ + resp_mime_types?: Resolver, ParentType, ContextType>, + trans_depth?: Resolver, ParentType, ContextType>, + status_msg?: Resolver, ParentType, ContextType>, + resp_fuids?: Resolver, ParentType, ContextType>, + tags?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ZeekNoticeDataResolvers = ResolversObject<{ + suppress_for?: Resolver, ParentType, ContextType>, + msg?: Resolver, ParentType, ContextType>, + note?: Resolver, ParentType, ContextType>, + sub?: Resolver, ParentType, ContextType>, + dst?: Resolver, ParentType, ContextType>, + dropped?: Resolver, ParentType, ContextType>, + peer_descr?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type ZeekSslDataResolvers = ResolversObject<{ + cipher?: Resolver, ParentType, ContextType>, + established?: Resolver, ParentType, ContextType>, + resumed?: Resolver, ParentType, ContextType>, + version?: Resolver, ParentType, ContextType>, + __isTypeOf?: isTypeOfResolverFn, +}>; + +export type Resolvers = ResolversObject<{ + AuditdData?: AuditdDataResolvers, + AuditdEcsFields?: AuditdEcsFieldsResolvers, + AuditEcsFields?: AuditEcsFieldsResolvers, + AuthEcsFields?: AuthEcsFieldsResolvers, + AuthenticationItem?: AuthenticationItemResolvers, + AuthenticationsData?: AuthenticationsDataResolvers, + AuthenticationsEdges?: AuthenticationsEdgesResolvers, + AutonomousSystem?: AutonomousSystemResolvers, + AutonomousSystemItem?: AutonomousSystemItemResolvers, + AutonomousSystemOrganization?: AutonomousSystemOrganizationResolvers, + CloudFields?: CloudFieldsResolvers, + CloudInstance?: CloudInstanceResolvers, + CloudMachine?: CloudMachineResolvers, + ColumnHeaderResult?: ColumnHeaderResultResolvers, + CursorType?: CursorTypeResolvers, + DataProviderResult?: DataProviderResultResolvers, + Date?: GraphQLScalarType, + DateRangePickerResult?: DateRangePickerResultResolvers, + DestinationEcsFields?: DestinationEcsFieldsResolvers, + DetailItem?: DetailItemResolvers, + DnsEcsFields?: DnsEcsFieldsResolvers, + DnsQuestionData?: DnsQuestionDataResolvers, + ECS?: EcsResolvers, + EcsEdges?: EcsEdgesResolvers, + EndgameEcsFields?: EndgameEcsFieldsResolvers, + EsValue?: GraphQLScalarType, + EventEcsFields?: EventEcsFieldsResolvers, + EventsTimelineData?: EventsTimelineDataResolvers, + FavoriteTimelineResult?: FavoriteTimelineResultResolvers, + FileFields?: FileFieldsResolvers, + FilterMetaTimelineResult?: FilterMetaTimelineResultResolvers, + FilterTimelineResult?: FilterTimelineResultResolvers, + FingerprintData?: FingerprintDataResolvers, + FirstLastSeenHost?: FirstLastSeenHostResolvers, + GeoEcsFields?: GeoEcsFieldsResolvers, + GeoItem?: GeoItemResolvers, + HostEcsFields?: HostEcsFieldsResolvers, + HostFields?: HostFieldsResolvers, + HostItem?: HostItemResolvers, + HostsData?: HostsDataResolvers, + HostsEdges?: HostsEdgesResolvers, + HttpBodyData?: HttpBodyDataResolvers, + HttpEcsFields?: HttpEcsFieldsResolvers, + HttpRequestData?: HttpRequestDataResolvers, + HttpResponseData?: HttpResponseDataResolvers, + IndexField?: IndexFieldResolvers, + Inspect?: InspectResolvers, + IpOverviewData?: IpOverviewDataResolvers, + KpiHostDetailsData?: KpiHostDetailsDataResolvers, + KpiHostHistogramData?: KpiHostHistogramDataResolvers, + KpiHostsData?: KpiHostsDataResolvers, + KpiNetworkData?: KpiNetworkDataResolvers, + KpiNetworkHistogramData?: KpiNetworkHistogramDataResolvers, + KueryFilterQueryResult?: KueryFilterQueryResultResolvers, + LastEventTimeData?: LastEventTimeDataResolvers, + LastSourceHost?: LastSourceHostResolvers, + Location?: LocationResolvers, + MatrixHistogramOverTimeData?: MatrixHistogramOverTimeDataResolvers, + MatrixOverOrdinalHistogramData?: MatrixOverOrdinalHistogramDataResolvers, + MatrixOverTimeHistogramData?: MatrixOverTimeHistogramDataResolvers, + Mutation?: MutationResolvers, + NetworkDnsData?: NetworkDnsDataResolvers, + NetworkDnsEdges?: NetworkDnsEdgesResolvers, + NetworkDnsItem?: NetworkDnsItemResolvers, + NetworkDsOverTimeData?: NetworkDsOverTimeDataResolvers, + NetworkEcsField?: NetworkEcsFieldResolvers, + NetworkHttpData?: NetworkHttpDataResolvers, + NetworkHttpEdges?: NetworkHttpEdgesResolvers, + NetworkHttpItem?: NetworkHttpItemResolvers, + NetworkTopCountriesData?: NetworkTopCountriesDataResolvers, + NetworkTopCountriesEdges?: NetworkTopCountriesEdgesResolvers, + NetworkTopCountriesItem?: NetworkTopCountriesItemResolvers, + NetworkTopNFlowData?: NetworkTopNFlowDataResolvers, + NetworkTopNFlowEdges?: NetworkTopNFlowEdgesResolvers, + NetworkTopNFlowItem?: NetworkTopNFlowItemResolvers, + NoteResult?: NoteResultResolvers, + OsEcsFields?: OsEcsFieldsResolvers, + OsFields?: OsFieldsResolvers, + Overview?: OverviewResolvers, + OverviewHostData?: OverviewHostDataResolvers, + OverviewNetworkData?: OverviewNetworkDataResolvers, + PackageEcsFields?: PackageEcsFieldsResolvers, + PageInfo?: PageInfoResolvers, + PageInfoPaginated?: PageInfoPaginatedResolvers, + PinnedEvent?: PinnedEventResolvers, + PrimarySecondary?: PrimarySecondaryResolvers, + ProcessEcsFields?: ProcessEcsFieldsResolvers, + ProcessHashData?: ProcessHashDataResolvers, + Query?: QueryResolvers, + QueryMatchResult?: QueryMatchResultResolvers, + ResponseFavoriteTimeline?: ResponseFavoriteTimelineResolvers, + ResponseNote?: ResponseNoteResolvers, + ResponseNotes?: ResponseNotesResolvers, + ResponseTimeline?: ResponseTimelineResolvers, + ResponseTimelines?: ResponseTimelinesResolvers, + RuleEcsField?: RuleEcsFieldResolvers, + RuleField?: RuleFieldResolvers, + SayMyName?: SayMyNameResolvers, + SerializedFilterQueryResult?: SerializedFilterQueryResultResolvers, + SerializedKueryQueryResult?: SerializedKueryQueryResultResolvers, + SignalField?: SignalFieldResolvers, + SortTimelineResult?: SortTimelineResultResolvers, + Source?: SourceResolvers, + SourceConfiguration?: SourceConfigurationResolvers, + SourceEcsFields?: SourceEcsFieldsResolvers, + SourceFields?: SourceFieldsResolvers, + SourceStatus?: SourceStatusResolvers, + SshEcsFields?: SshEcsFieldsResolvers, + Summary?: SummaryResolvers, + SuricataAlertData?: SuricataAlertDataResolvers, + SuricataEcsFields?: SuricataEcsFieldsResolvers, + SuricataEveData?: SuricataEveDataResolvers, + SystemEcsField?: SystemEcsFieldResolvers, + Thread?: ThreadResolvers, + TimelineData?: TimelineDataResolvers, + TimelineDetailsData?: TimelineDetailsDataResolvers, + TimelineEdges?: TimelineEdgesResolvers, + TimelineItem?: TimelineItemResolvers, + TimelineNonEcsData?: TimelineNonEcsDataResolvers, + TimelineResult?: TimelineResultResolvers, + TlsClientCertificateData?: TlsClientCertificateDataResolvers, + TlsData?: TlsDataResolvers, + TlsEcsFields?: TlsEcsFieldsResolvers, + TlsEdges?: TlsEdgesResolvers, + TlsFingerprintsData?: TlsFingerprintsDataResolvers, + TlsJa3Data?: TlsJa3DataResolvers, + TlsNode?: TlsNodeResolvers, + TlsServerCertificateData?: TlsServerCertificateDataResolvers, + ToAny?: GraphQLScalarType, + ToBooleanArray?: GraphQLScalarType, + ToDateArray?: GraphQLScalarType, + ToNumberArray?: GraphQLScalarType, + TopCountriesItemDestination?: TopCountriesItemDestinationResolvers, + TopCountriesItemSource?: TopCountriesItemSourceResolvers, + TopNetworkTablesEcsField?: TopNetworkTablesEcsFieldResolvers, + TopNFlowItemDestination?: TopNFlowItemDestinationResolvers, + TopNFlowItemSource?: TopNFlowItemSourceResolvers, + ToStringArray?: GraphQLScalarType, + UncommonProcessesData?: UncommonProcessesDataResolvers, + UncommonProcessesEdges?: UncommonProcessesEdgesResolvers, + UncommonProcessItem?: UncommonProcessItemResolvers, + UrlEcsFields?: UrlEcsFieldsResolvers, + UserEcsFields?: UserEcsFieldsResolvers, + UsersData?: UsersDataResolvers, + UsersEdges?: UsersEdgesResolvers, + UsersItem?: UsersItemResolvers, + UsersNode?: UsersNodeResolvers, + WinlogEcsFields?: WinlogEcsFieldsResolvers, + ZeekConnectionData?: ZeekConnectionDataResolvers, + ZeekDnsData?: ZeekDnsDataResolvers, + ZeekEcsFields?: ZeekEcsFieldsResolvers, + ZeekFileData?: ZeekFileDataResolvers, + ZeekHttpData?: ZeekHttpDataResolvers, + ZeekNoticeData?: ZeekNoticeDataResolvers, + ZeekSslData?: ZeekSslDataResolvers, +}>; + + +/** + * @deprecated + * Use "Resolvers" root object instead. If you wish to get "IResolvers", add "typesPrefix: I" to your config. +*/ +export type IResolvers = Resolvers; diff --git a/x-pack/legacy/plugins/siem/server/graphql/uncommon_processes/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/uncommon_processes/resolvers.ts index 03d3c3d1a1fe4..00b34a0c5fbe5 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/uncommon_processes/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/uncommon_processes/resolvers.ts @@ -5,15 +5,8 @@ */ import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { UncommonProcesses } from '../../lib/uncommon_processes'; import { createOptionsPaginated } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -type QueryUncommonProcessesResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export interface UncommonProcessesResolversDeps { uncommonProcesses: UncommonProcesses; @@ -23,7 +16,7 @@ export const createUncommonProcessesResolvers = ( libs: UncommonProcessesResolversDeps ): { Source: { - UncommonProcesses: QueryUncommonProcessesResolver; + UncommonProcesses: SourceResolvers['UncommonProcesses']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/uncommon_processes/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/uncommon_processes/schema.gql.ts index 36a3da6779172..842ab80b5bd7c 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/uncommon_processes/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/uncommon_processes/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const uncommonProcessesSchema = gql` type UncommonProcessItem { diff --git a/x-pack/legacy/plugins/siem/server/graphql/who_am_i/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/who_am_i/resolvers.ts index 065edfb99ccea..8a2ecbdbd40bb 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/who_am_i/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/who_am_i/resolvers.ts @@ -5,17 +5,10 @@ */ import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; -import { QuerySourceResolver } from '../sources/resolvers'; - -export type QueryWhoAmIResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; export const createWhoAmIResolvers = (): { Source: { - whoAmI: QueryWhoAmIResolver; + whoAmI: SourceResolvers['whoAmI']; }; } => ({ Source: { diff --git a/x-pack/legacy/plugins/siem/server/graphql/who_am_i/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/who_am_i/schema.gql.ts index 0a264cd2988fe..e2c57fe4b5634 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/who_am_i/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/who_am_i/schema.gql.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; export const whoAmISchema = gql` type SayMyName { diff --git a/x-pack/legacy/plugins/siem/server/init_server.ts b/x-pack/legacy/plugins/siem/server/init_server.ts index 6158a33c25cfa..83c5f0c171c8a 100644 --- a/x-pack/legacy/plugins/siem/server/init_server.ts +++ b/x-pack/legacy/plugins/siem/server/init_server.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 { IResolvers, makeExecutableSchema } from 'graphql-tools'; +import { IResolvers, makeExecutableSchema } from '@kamilkisiela/graphql-tools'; import { schemas } from './graphql'; import { createAuthenticationsResolvers } from './graphql/authentications'; diff --git a/x-pack/legacy/plugins/siem/server/lib/framework/types.ts b/x-pack/legacy/plugins/siem/server/lib/framework/types.ts index 7d049d1dcd195..b72dc9ef580d7 100644 --- a/x-pack/legacy/plugins/siem/server/lib/framework/types.ts +++ b/x-pack/legacy/plugins/siem/server/lib/framework/types.ts @@ -6,6 +6,7 @@ import { IndicesGetMappingParams } from 'elasticsearch'; import { GraphQLSchema } from 'graphql'; +import * as runtimeTypes from 'io-ts'; import { RequestHandlerContext, KibanaRequest } from '../../../../../../../src/core/server'; import { AuthenticatedUser } from '../../../../../../plugins/security/common/model'; @@ -20,8 +21,6 @@ import { HistogramType, } from '../../graphql/types'; -export * from '../../utils/typed_resolvers'; - export const internalFrameworkRequest = Symbol('internalFrameworkRequest'); export interface FrameworkAdapter { @@ -133,3 +132,6 @@ export interface RequestOptionsPaginated extends RequestBasicOptions { fields: readonly string[]; sortField?: SortField; } + +export const unionWithNullType = (type: T) => + runtimeTypes.union([type, runtimeTypes.null]); diff --git a/x-pack/legacy/plugins/siem/server/utils/typed_resolvers.ts b/x-pack/legacy/plugins/siem/server/utils/typed_resolvers.ts deleted file mode 100644 index da38e8a1e1bf2..0000000000000 --- a/x-pack/legacy/plugins/siem/server/utils/typed_resolvers.ts +++ /dev/null @@ -1,111 +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 * as runtimeTypes from 'io-ts'; -import { GraphQLResolveInfo } from 'graphql'; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type Resolver = ( - parent: Parent, - args: Args, - context: TContext, - info: GraphQLResolveInfo -) => Promise | Result; - -type ResolverResult = R | Promise; - -type AppResolverResult = - | Promise - | Promise<{ [P in keyof R]: () => Promise }> - | { [P in keyof R]: () => Promise } - | { [P in keyof R]: () => R[P] } - | R; - -export type ResultOf = Resolver_ extends Resolver> - ? Result - : never; - -export type SubsetResolverWithFields = R extends Resolver< - Array, - infer ParentInArray, - infer ContextInArray, - infer ArgsInArray -> - ? Resolver< - Array>>, - ParentInArray, - ContextInArray, - ArgsInArray - > - : R extends Resolver - ? Resolver>, Parent, Context, Args> - : never; - -export type SubsetResolverWithoutFields = R extends Resolver< - Array, - infer ParentInArray, - infer ContextInArray, - infer ArgsInArray -> - ? Resolver< - Array>>, - ParentInArray, - ContextInArray, - ArgsInArray - > - : R extends Resolver - ? Resolver>, Parent, Context, Args> - : never; - -export type ResolverWithParent = Resolver_ extends Resolver< - infer Result, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - any, - infer Context, - infer Args -> - ? Resolver - : never; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type AppResolver = Resolver< - AppResolverResult, - Parent, - Context, - Args ->; - -export type AppResolverOf = Resolver_ extends Resolver< - ResolverResult, - never, - infer ContextWithNeverParent, - infer ArgsWithNeverParent -> - ? AppResolver - : Resolver_ extends Resolver< - ResolverResult, - infer Parent, - infer Context, - infer Args - > - ? AppResolver - : never; - -export type AppResolverWithFields = AppResolverOf< - SubsetResolverWithFields ->; - -export type AppResolverWithoutFields = AppResolverOf< - SubsetResolverWithoutFields ->; - -export type ChildResolverOf = ResolverWithParent< - Resolver_, - ResultOf ->; - -export const unionWithNullType = (type: T) => - runtimeTypes.union([type, runtimeTypes.null]); diff --git a/x-pack/package.json b/x-pack/package.json index 96e06dd71b3fe..5d0ac156f87fa 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -27,6 +27,17 @@ }, "devDependencies": { "@cypress/webpack-preprocessor": "^4.1.0", + "@graphql-codegen/add": "^1.12.2", + "@graphql-codegen/core": "^1.12.2", + "@graphql-codegen/typescript": "^1.12.2", + "@graphql-codegen/typescript-compatibility": "^1.12.2", + "@graphql-codegen/typescript-operations": "^1.12.2", + "@graphql-codegen/typescript-resolvers": "^1.12.2", + "@graphql-codegen/typescript-react-apollo": "^1.12.2", + "@graphql-toolkit/code-file-loader": "^0.9.7", + "@graphql-toolkit/common":"^0.9.7", + "@graphql-toolkit/core": "^0.9.7", + "@graphql-toolkit/graphql-file-loader": "^0.9.7", "@kbn/dev-utils": "1.0.0", "@kbn/es": "1.0.0", "@kbn/expect": "1.0.0", @@ -62,7 +73,6 @@ "@types/getos": "^3.0.0", "@types/git-url-parse": "^9.0.0", "@types/glob": "^7.1.1", - "@types/graphql": "^0.13.2", "@types/gulp": "^4.0.6", "@types/hapi__wreck": "^15.0.1", "@types/hoist-non-react-statics": "^3.3.1", @@ -173,6 +183,8 @@ "yargs": "4.8.1" }, "dependencies": { + "@apollo/client": "^3.0.0-beta.37", + "@apollo/react-components": "^3.2.0-beta.1", "@babel/core": "^7.5.5", "@babel/register": "^7.7.0", "@babel/runtime": "^7.5.5", @@ -184,6 +196,7 @@ "@elastic/maki": "6.1.0", "@elastic/node-crypto": "^1.0.0", "@elastic/numeral": "2.4.0", + "@kamilkisiela/graphql-tools": "^4.0.6", "@kbn/babel-preset": "1.0.0", "@kbn/config-schema": "1.0.0", "@kbn/i18n": "1.0.0", @@ -201,8 +214,8 @@ "angular-ui-ace": "0.2.3", "apollo-cache-inmemory": "1.6.2", "apollo-client": "^2.3.8", - "apollo-link": "^1.2.3", - "apollo-link-error": "^1.1.7", + "apollo-link": "^1.2.13", + "apollo-link-error": "^2.0.0-beta.0", "apollo-link-http": "^1.5.16", "apollo-link-schema": "^1.1.0", "apollo-link-state": "^0.4.1", @@ -241,10 +254,10 @@ "git-url-parse": "11.1.2", "github-markdown-css": "^2.10.0", "glob": "^7.1.2", - "graphql": "^0.13.2", + "graphql": "^14.6.0", "graphql-fields": "^1.0.2", - "graphql-tag": "^2.9.2", - "graphql-tools": "^3.0.2", + "graphql-tag": "^2.10.3", + "graphql-tools": "^4.0.6", "h2o2": "^8.1.2", "handlebars": "4.5.3", "history": "4.9.0", diff --git a/x-pack/test/api_integration/apis/siem/feature_controls.ts b/x-pack/test/api_integration/apis/siem/feature_controls.ts index 1623a2b286f79..35a8bbca2ff5d 100644 --- a/x-pack/test/api_integration/apis/siem/feature_controls.ts +++ b/x-pack/test/api_integration/apis/siem/feature_controls.ts @@ -5,7 +5,7 @@ */ import expect from '@kbn/expect'; -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; import { FtrProviderContext } from '../../ftr_provider_context'; const introspectionQuery = gql` diff --git a/x-pack/test/api_integration/apis/siem/saved_objects/notes.ts b/x-pack/test/api_integration/apis/siem/saved_objects/notes.ts index 5aa7a10e07c2a..97ed58ae0a45e 100644 --- a/x-pack/test/api_integration/apis/siem/saved_objects/notes.ts +++ b/x-pack/test/api_integration/apis/siem/saved_objects/notes.ts @@ -5,7 +5,7 @@ */ import expect from '@kbn/expect'; -import gql from 'graphql-tag'; +import { gql } from '@apollo/client'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { persistTimelineNoteMutation } from '../../../../../legacy/plugins/siem/public/containers/timeline/notes/persist.gql_query'; diff --git a/x-pack/test/api_integration/apis/siem/saved_objects/timeline.ts b/x-pack/test/api_integration/apis/siem/saved_objects/timeline.ts index a6ced270e2132..98fc86632a3fd 100644 --- a/x-pack/test/api_integration/apis/siem/saved_objects/timeline.ts +++ b/x-pack/test/api_integration/apis/siem/saved_objects/timeline.ts @@ -11,7 +11,7 @@ */ import expect from '@kbn/expect'; -import ApolloClient from 'apollo-client'; +import { ApolloClient } from '@apollo/client'; import { FtrProviderContext } from '../../../ftr_provider_context'; diff --git a/x-pack/test/api_integration/services/siem_graphql_client.ts b/x-pack/test/api_integration/services/siem_graphql_client.ts index 7d6aa5e8a9dd5..6668aa89852a3 100644 --- a/x-pack/test/api_integration/services/siem_graphql_client.ts +++ b/x-pack/test/api_integration/services/siem_graphql_client.ts @@ -6,12 +6,9 @@ import { format as formatUrl } from 'url'; import fetch from 'node-fetch'; -import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; -import { ApolloClient } from 'apollo-client'; -import { HttpLink } from 'apollo-link-http'; +import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'; import { FtrProviderContext } from '../ftr_provider_context'; -import introspectionQueryResultData from '../../../legacy/plugins/siem/public/graphql/introspection.json'; interface SiemGraphQLClientFactoryOptions { username?: string; @@ -44,11 +41,7 @@ export function SiemGraphQLClientFactoryProvider({ getService }: FtrProviderCont }); return new ApolloClient({ - cache: new InMemoryCache({ - fragmentMatcher: new IntrospectionFragmentMatcher({ - introspectionQueryResultData, - }), - }), + cache: new InMemoryCache({}), link: httpLink, }); }; diff --git a/yarn.lock b/yarn.lock index 7f38495c20f4a..f3777830ecce2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,49 @@ # yarn lockfile v1 +"@apollo/client@^3.0.0-beta.10", "@apollo/client@^3.0.0-beta.23", "@apollo/client@^3.0.0-beta.37": + version "3.0.0-beta.37" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.0.0-beta.37.tgz#24d4eacebc2dd0d6c27e87b8aacbb5323c0d29d6" + integrity sha512-EVarxDX4dG51IHs9DyivYZQN51U2eu9deWRyAI9xkp6Y5vwmTfAcfMYQIxc/ZZhiFAq4MEk0EPLtU2kOfTILjQ== + dependencies: + "@types/zen-observable" "^0.8.0" + "@wry/equality" "^0.1.9" + fast-json-stable-stringify "^2.0.0" + graphql-tag "^2.10.2" + optimism "^0.11.5" + symbol-observable "^1.2.0" + ts-invariant "^0.4.4" + tslib "^1.10.0" + zen-observable "^0.8.14" + +"@apollo/react-common@^3.2.0-beta.1": + version "3.2.0-beta.1" + resolved "https://registry.yarnpkg.com/@apollo/react-common/-/react-common-3.2.0-beta.1.tgz#91227dde37759d9af577a8f397749deb0c5286eb" + integrity sha512-ZXkzQHZOA5WrIrIzYmltEXc22iZNWcgTdFEyMi2AwhoMdv/w89UXO7+QQ+2Fav7LgJ8zEE+znv+6D7DmKpJVvg== + dependencies: + "@apollo/client" "^3.0.0-beta.23" + +"@apollo/react-components@^3.2.0-beta.1": + version "3.2.0-beta.1" + resolved "https://registry.yarnpkg.com/@apollo/react-components/-/react-components-3.2.0-beta.1.tgz#21e2bf33ad52d9c8b46c0fa922cc3f6251775390" + integrity sha512-klPUqS8JMR57xuVUvY53EFwa4SrNBGczSL44eNc37MC4nnYGm8oH/yg73zqAf+XsiJZfXq/cgNJi5LBy0p69Lg== + dependencies: + "@apollo/react-common" "^3.2.0-beta.1" + prop-types "^15.7.2" + ts-invariant "^0.4.4" + tslib "^1.10.0" + +"@ardatan/graphql-tools@4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@ardatan/graphql-tools/-/graphql-tools-4.1.0.tgz#183508ef4e3d4966f763cb1634a81be1c1255f8d" + integrity sha512-0b+KH5RZN9vCMpEjxrwFwZ7v3K6QDjs1EH+R6eRrgKMR2X274JWqYraHKLWE1uJ8iwrkRaOYfCV12jLVuvWS+A== + dependencies: + apollo-link "^1.2.3" + apollo-utilities "^1.0.1" + deprecated-decorator "^0.1.6" + iterall "^1.1.3" + uuid "^3.1.0" + "@babel/cli@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.5.5.tgz#bdb6d9169e93e241a08f5f7b0265195bf38ef5ec" @@ -26,6 +69,13 @@ dependencies: "@babel/highlight" "^7.0.0" +"@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + "@babel/core@7.5.5", "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.4.3", "@babel/core@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" @@ -77,6 +127,16 @@ source-map "^0.5.0" trim-right "^1.0.1" +"@babel/generator@^7.5.0", "@babel/generator@^7.8.3", "@babel/generator@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e" + integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA== + dependencies: + "@babel/types" "^7.8.3" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/generator@^7.6.0", "@babel/generator@^7.6.2": version "7.6.2" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.2.tgz#dac8a3c2df118334c2a29ff3446da1636a8f8c03" @@ -121,6 +181,13 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-annotate-as-pure@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" + integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" @@ -171,6 +238,15 @@ "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-call-delegate@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz#de82619898aa605d409c42be6ffb8d7204579692" + integrity sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A== + dependencies: + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/helper-create-class-features-plugin@^7.4.4", "@babel/helper-create-class-features-plugin@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.5.tgz#401f302c8ddbc0edd36f7c6b2887d8fa1122e5a4" @@ -195,6 +271,18 @@ "@babel/helper-replace-supers" "^7.7.4" "@babel/helper-split-export-declaration" "^7.7.4" +"@babel/helper-create-class-features-plugin@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz#5b94be88c255f140fd2c10dd151e7f98f4bff397" + integrity sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/helper-create-regexp-features-plugin@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz#6d5762359fd34f4da1500e4cff9955b5299aaf59" @@ -221,6 +309,15 @@ "@babel/types" "^7.7.4" lodash "^4.17.13" +"@babel/helper-define-map@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" + integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/types" "^7.8.3" + lodash "^4.17.13" + "@babel/helper-explode-assignable-expression@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" @@ -255,6 +352,15 @@ "@babel/template" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" + integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/helper-get-function-arity@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" @@ -269,6 +375,13 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-hoist-variables@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" @@ -283,6 +396,13 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-hoist-variables@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" + integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-member-expression-to-functions@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" @@ -297,6 +417,13 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" + integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-module-imports@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" @@ -311,6 +438,13 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-module-imports@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" + integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" @@ -323,10 +457,22 @@ "@babel/types" "^7.5.5" lodash "^4.17.13" -"@babel/helper-module-transforms@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.4.tgz#8d7cdb1e1f8ea3d8c38b067345924ac4f8e0879a" - integrity sha512-ehGBu4mXrhs0FxAqN8tWkzF8GSIGAiEumu4ONZ/hD9M88uHcD+Yu2ttKfOCgwzoesJOJrtQh7trI5YPbRtMmnA== +"@babel/helper-module-transforms@^7.7.4", "@babel/helper-module-transforms@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz#d305e35d02bee720fbc2c3c3623aa0c316c01590" + integrity sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + lodash "^4.17.13" + +"@babel/helper-module-transforms@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835" + integrity sha512-A7pSxyJf1gN5qXVcidwLWydjftUN878VkalhXX5iQDuGyiGK3sOrrKKHF4/A4fwHtnsotv/NipwAeLzY4KQPvw== dependencies: "@babel/helper-module-imports" "^7.7.4" "@babel/helper-simple-access" "^7.7.4" @@ -349,11 +495,23 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" + integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== +"@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" + integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== + "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" @@ -361,6 +519,13 @@ dependencies: lodash "^4.17.13" +"@babel/helper-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" + integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== + dependencies: + lodash "^4.17.13" + "@babel/helper-remap-async-to-generator@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" @@ -372,16 +537,16 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-remap-async-to-generator@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz#c68c2407350d9af0e061ed6726afb4fff16d0234" - integrity sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw== +"@babel/helper-remap-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" + integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== dependencies: - "@babel/helper-annotate-as-pure" "^7.7.4" - "@babel/helper-wrap-function" "^7.7.4" - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-wrap-function" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" "@babel/helper-replace-supers@^7.5.5": version "7.5.5" @@ -403,6 +568,16 @@ "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-replace-supers@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc" + integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/helper-simple-access@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" @@ -419,6 +594,14 @@ "@babel/template" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-simple-access@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" + integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== + dependencies: + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/helper-split-export-declaration@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" @@ -433,6 +616,13 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-wrap-function@^7.1.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" @@ -443,15 +633,15 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.2.0" -"@babel/helper-wrap-function@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz#37ab7fed5150e22d9d7266e830072c0cdd8baace" - integrity sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg== +"@babel/helper-wrap-function@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" + integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== dependencies: - "@babel/helper-function-name" "^7.7.4" - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" + "@babel/helper-function-name" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" "@babel/helpers@^7.5.5": version "7.5.5" @@ -480,30 +670,49 @@ esutils "^2.0.2" js-tokens "^4.0.0" +"@babel/highlight@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" + integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@babel/parser@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.3.tgz#790874091d2001c9be6ec426c2eed47bc7679081" + integrity sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ== + "@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== -"@babel/parser@^7.2.0", "@babel/parser@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" - integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== +"@babel/parser@^7.2.0", "@babel/parser@^7.7.4": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71" + integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig== "@babel/parser@^7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b" integrity sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ== +"@babel/parser@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" + integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== + "@babel/parser@^7.6.3": version "7.6.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81" integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A== -"@babel/parser@^7.7.4": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71" - integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig== +"@babel/parser@^7.8.3", "@babel/parser@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" + integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" @@ -515,15 +724,15 @@ "@babel/plugin-syntax-async-generators" "^7.2.0" "@babel/plugin-proposal-async-generator-functions@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz#0351c5ac0a9e927845fffd5b82af476947b7ce6d" - integrity sha512-1ypyZvGRXriY/QP668+s8sFr2mqinhkRDMPSQLNghCQE+GAkFtp+wkHVvg2+Hdki8gwP+NFzJBJ/N1BfzCCDEw== + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" + integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.7.4" - "@babel/plugin-syntax-async-generators" "^7.7.4" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@7.5.5", "@babel/plugin-proposal-class-properties@^7.3.3", "@babel/plugin-proposal-class-properties@^7.5.1", "@babel/plugin-proposal-class-properties@^7.5.5": +"@babel/plugin-proposal-class-properties@7.5.5", "@babel/plugin-proposal-class-properties@^7.3.3": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz#a974cfae1e37c3110e71f3c6a2e48b8e71958cd4" integrity sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A== @@ -531,7 +740,7 @@ "@babel/helper-create-class-features-plugin" "^7.5.5" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-proposal-class-properties@^7.7.0": +"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.5.1", "@babel/plugin-proposal-class-properties@^7.5.5": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.7.4.tgz#2f964f0cb18b948450362742e33e15211e77c2ba" integrity sha512-EcuXeV4Hv1X3+Q1TsuOmyyxeTRiSqurGJ26+I/FW1WbymmRRapVORm6x1Zl3iDIHyRxEs+VXWp6qnlcfcJSbbw== @@ -539,6 +748,14 @@ "@babel/helper-create-class-features-plugin" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-proposal-class-properties@^7.7.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" + integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-decorators@7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.4.4.tgz#de9b2a1a8ab0196f378e2a82f10b6e2a36f21cc0" @@ -581,12 +798,12 @@ "@babel/plugin-syntax-json-strings" "^7.7.4" "@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.4.4.tgz#41c360d59481d88e0ce3a3f837df10121a769b39" - integrity sha512-Amph7Epui1Dh/xxUxS2+K22/MUi6+6JVTvy3P58tja3B6yKTSjwwx0/d83rF7551D6PVSSoplQb8GCwqec7HRw== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.7.4.tgz#7db302c83bc30caa89e38fee935635ef6bd11c28" + integrity sha512-TbYHmr1Gl1UC7Vo2HVuj/Naci5BEGNZ0AJhzqD2Vpr6QPFWpUmBRLrIDjedzx7/CShq0bRDS2gI4FIs77VHLVQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.2.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.7.4" "@babel/plugin-proposal-object-rest-spread@7.5.5", "@babel/plugin-proposal-object-rest-spread@^7.3.2", "@babel/plugin-proposal-object-rest-spread@^7.5.5": version "7.5.5" @@ -596,7 +813,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" -"@babel/plugin-proposal-object-rest-spread@^7.6.2", "@babel/plugin-proposal-object-rest-spread@^7.7.4": +"@babel/plugin-proposal-object-rest-spread@^7.0.0": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.4.tgz#cc57849894a5c774214178c8ab64f6334ec8af71" integrity sha512-rnpnZR3/iWKmiQyJ3LKJpSwLDcX/nSXhdLk4Aq/tXOApIvyu7qoabrige0ylsAJffaUC51WiBu209Q0U+86OWQ== @@ -604,6 +821,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.7.4" +"@babel/plugin-proposal-object-rest-spread@^7.6.2", "@babel/plugin-proposal-object-rest-spread@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz#eb5ae366118ddca67bed583b53d7554cad9951bb" + integrity sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-proposal-optional-catch-binding@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" @@ -621,12 +846,12 @@ "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" "@babel/plugin-proposal-optional-chaining@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.6.0.tgz#e9bf1f9b9ba10c77c033082da75f068389041af8" - integrity sha512-kj4gkZ6qUggkprRq3Uh5KP8XnE1MdIO0J7MhdDX8+rAbB6dJ2UrensGIS+0NPZAaaJ1Vr0PN6oLUgXMU1uMcSg== + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.7.5.tgz#f0835f044cef85b31071a924010a2a390add11d4" + integrity sha512-sOwFqT8JSchtJeDD+CjmWCaiFoLxY4Ps7NjvwHC/U7l4e9i5pTRNt8nDMIFSOUL+ncFbYSwruHM8WknYItWdXw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-chaining" "^7.2.0" + "@babel/plugin-syntax-optional-chaining" "^7.7.4" "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.4.4" @@ -652,10 +877,17 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-async-generators@^7.7.4": +"@babel/plugin-syntax-async-generators@^7.7.4", "@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.0.0": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.7.4.tgz#331aaf310a10c80c44a66b238b6e49132bd3c889" - integrity sha512-Li4+EjSpBgxcsmeEF8IFcfV/+yJGxHXDirDkEoyFjumuwbmfCVHUt0HuowD/iGM7OhIRyXJH9YXxqiH6N815+g== + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.7.4.tgz#6048c129ea908a432a1ff85f1dc794dc62ddaa5e" + integrity sha512-JH3v5ZOeKT0qqdJ9BeBcZTFQiJOMax8RopSr1bH6ASkZKo2qWsvBML7W1mp89sszBRDBBRO8snqcByGdrMTdMg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -674,9 +906,16 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-dynamic-import@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-flow@^7.0.0": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz#29ca3b4415abfe4a5ec381e903862ad1a54c3aec" - integrity sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg== + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.4.tgz#6d91b59e1a0e4c17f36af2e10dd64ef220919d7b" + integrity sha512-2AMAWl5PsmM5KPkB22cvOkUyWk6MjUaqhHNU5nSPUl/ns3j5qLfw2SuYP5RbVZ0tfLvePr4zUScbICtDP2CUNw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -687,17 +926,17 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" - integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== +"@babel/plugin-syntax-json-strings@^7.2.0", "@babel/plugin-syntax-json-strings@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz#86e63f7d2e22f9e27129ac4e83ea989a382e86cc" + integrity sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-json-strings@^7.7.4": +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.7.4": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz#86e63f7d2e22f9e27129ac4e83ea989a382e86cc" - integrity sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg== + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz#dab2b56a36fb6c3c222a1fbc71f7bf97f327a9ec" + integrity sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -708,17 +947,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-jsx@^7.7.4": +"@babel/plugin-syntax-nullish-coalescing-operator@^7.7.4": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz#dab2b56a36fb6c3c222a1fbc71f7bf97f327a9ec" - integrity sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.2.0.tgz#f75083dfd5ade73e783db729bbd87e7b9efb7624" - integrity sha512-lRCEaKE+LTxDQtgbYajI04ddt6WW0WJq57xqkAZ+s11h4YgfRHhVA/Y2VhfPzzFD4qeLHWg32DMp9HooY4Kqlg== + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.7.4.tgz#e53b751d0c3061b1ba3089242524b65a7a9da12b" + integrity sha512-XKh/yIRPiQTOeBg0QJjEus5qiSKucKAiApNtO1psqG7D17xmE+X2i5ZqBEuSvo0HRuyPaKaSN/Gy+Ha9KFQolw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -736,6 +968,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" @@ -744,16 +983,16 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-optional-catch-binding@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz#a3e38f59f4b6233867b4a92dcb0ee05b2c334aa6" - integrity sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ== + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-chaining@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.2.0.tgz#a59d6ae8c167e7608eaa443fda9fa8fa6bf21dff" - integrity sha512-HtGCtvp5Uq/jH/WNUPkK6b7rufnCPLLlDAFN7cmACoIjaOOiXxUt3SswU5loHqrhtqTsa/WoLQ1OQ1AGuZqaWA== +"@babel/plugin-syntax-optional-chaining@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.7.4.tgz#c91fdde6de85d2eb8906daea7b21944c3610c901" + integrity sha512-2MqYD5WjZSbJdUagnJvIdSfkb/ucOC9/1fRJxm7GAxY6YQLWlUvkfxoNbUPcPLHJyetKUDQ4+yyuUyAoc0HriA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -778,6 +1017,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12" + integrity sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-arrow-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" @@ -785,13 +1031,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-arrow-functions@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12" - integrity sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-async-to-generator@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e" @@ -802,13 +1041,20 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-transform-async-to-generator@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" + integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + +"@babel/plugin-transform-block-scoped-functions@^7.0.0": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz#694cbeae6d613a34ef0292713fa42fb45c4470ba" - integrity sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b" + integrity sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ== dependencies: - "@babel/helper-module-imports" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.7.4" "@babel/plugin-transform-block-scoped-functions@^7.2.0": version "7.2.0" @@ -818,11 +1064,19 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-block-scoped-functions@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" + integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-block-scoping@^7.0.0": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b" - integrity sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224" + integrity sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" + lodash "^4.17.13" "@babel/plugin-transform-block-scoping@^7.5.5": version "7.5.5" @@ -841,12 +1095,26 @@ lodash "^4.17.13" "@babel/plugin-transform-block-scoping@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" + integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + lodash "^4.17.13" + +"@babel/plugin-transform-classes@^7.0.0": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224" - integrity sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec" + integrity sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg== dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-define-map" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - lodash "^4.17.13" + "@babel/helper-replace-supers" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + globals "^11.1.0" "@babel/plugin-transform-classes@^7.5.5": version "7.5.5" @@ -863,18 +1131,25 @@ globals "^11.1.0" "@babel/plugin-transform-classes@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz#46fd7a9d2bb9ea89ce88720477979fe0d71b21b8" + integrity sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-define-map" "^7.8.3" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.7.4": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec" - integrity sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d" + integrity sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.7.4" - "@babel/helper-define-map" "^7.7.4" - "@babel/helper-function-name" "^7.7.4" - "@babel/helper-optimise-call-expression" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.7.4" - "@babel/helper-split-export-declaration" "^7.7.4" - globals "^11.1.0" "@babel/plugin-transform-computed-properties@^7.2.0": version "7.2.0" @@ -883,13 +1158,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-computed-properties@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d" - integrity sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-destructuring@7.5.0", "@babel/plugin-transform-destructuring@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz#f6c09fdfe3f94516ff074fe877db7bc9ef05855a" @@ -897,6 +1165,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-destructuring@^7.0.0", "@babel/plugin-transform-destructuring@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267" + integrity sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-destructuring@^7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" @@ -904,13 +1179,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-destructuring@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267" - integrity sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" @@ -966,6 +1234,13 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-flow" "^7.2.0" +"@babel/plugin-transform-for-of@^7.0.0": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz#248800e3a5e507b1f103d8b4ca998e77c63932bc" + integrity sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-for-of@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" @@ -974,10 +1249,18 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-for-of@^7.7.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz#6fe8eae5d6875086ee185dd0b098a8513783b47d" + integrity sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-function-name@^7.0.0": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz#248800e3a5e507b1f103d8b4ca998e77c63932bc" - integrity sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1" + integrity sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g== dependencies: + "@babel/helper-function-name" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-function-name@^7.4.4": @@ -989,11 +1272,18 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-function-name@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" + integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-literals@^7.0.0": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1" - integrity sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e" + integrity sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw== dependencies: - "@babel/helper-function-name" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-literals@^7.2.0": @@ -1004,9 +1294,16 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-literals@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" + integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-member-expression-literals@^7.0.0", "@babel/plugin-transform-member-expression-literals@^7.7.4": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e" - integrity sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a" + integrity sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -1017,13 +1314,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-member-expression-literals@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a" - integrity sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-modules-amd@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" @@ -1034,12 +1324,22 @@ babel-plugin-dynamic-import-node "^2.3.0" "@babel/plugin-transform-modules-amd@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.4.tgz#276b3845ca2b228f2995e453adc2e6f54d72fb71" - integrity sha512-/542/5LNA18YDtg1F+QHvvUSlxdvjZoD/aldQwkq+E3WCkbEjNSN9zdrOXaSlfg3IfGi22ijzecklF/A7kVZFQ== + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz#65606d44616b50225e76f5578f33c568a0b876a5" + integrity sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ== dependencies: - "@babel/helper-module-transforms" "^7.7.4" + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-commonjs@^7.0.0": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz#1d27f5eb0bcf7543e774950e5b2fa782e637b345" + integrity sha512-9Cq4zTFExwFhQI6MT1aFxgqhIsMWQWDVwOgLzl7PTWJHsNaqFvklAU+Oz6AQLAS0dJKTwZSOCo20INwktxpi3Q== + dependencies: + "@babel/helper-module-transforms" "^7.7.5" "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-simple-access" "^7.7.4" babel-plugin-dynamic-import-node "^2.3.0" "@babel/plugin-transform-modules-commonjs@^7.5.0": @@ -1135,11 +1435,19 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-new-target@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" + integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-object-super@^7.0.0": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz#4a0753d2d60639437be07b592a9e58ee00720167" - integrity sha512-CnPRiNtOG1vRodnsyGX37bHQleHE14B9dnnlgSeEs3ek3fHN1A1SScglTCg1sfbe7sRQ2BUcpgpTpWSfMKz3gg== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262" + integrity sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.7.4" "@babel/plugin-transform-object-super@^7.5.5": version "7.5.5" @@ -1150,12 +1458,21 @@ "@babel/helper-replace-supers" "^7.5.5" "@babel/plugin-transform-object-super@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" + integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.0.0": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262" - integrity sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.4.tgz#da4555c97f39b51ac089d31c7380f03bca4075ce" + integrity sha512-VJwhVePWPa0DqE9vcfptaJSzNDKrWU/4FbYCjZERtmqEs05g3UMXnYMZoXja7JAJ7Y7sPZipwm/pGApZt7wHlw== dependencies: + "@babel/helper-call-delegate" "^7.7.4" + "@babel/helper-get-function-arity" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.7.4" "@babel/plugin-transform-parameters@^7.4.4": version "7.4.4" @@ -1167,12 +1484,19 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-parameters@^7.7.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz#1d5155de0b65db0ccf9971165745d3bb990d77d3" + integrity sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA== + dependencies: + "@babel/helper-call-delegate" "^7.8.3" + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-property-literals@^7.0.0", "@babel/plugin-transform-property-literals@^7.7.4": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.4.tgz#da4555c97f39b51ac089d31c7380f03bca4075ce" - integrity sha512-VJwhVePWPa0DqE9vcfptaJSzNDKrWU/4FbYCjZERtmqEs05g3UMXnYMZoXja7JAJ7Y7sPZipwm/pGApZt7wHlw== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz#2388d6505ef89b266103f450f9167e6bd73f98c2" + integrity sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ== dependencies: - "@babel/helper-call-delegate" "^7.7.4" - "@babel/helper-get-function-arity" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-property-literals@^7.2.0": @@ -1182,13 +1506,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-property-literals@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz#2388d6505ef89b266103f450f9167e6bd73f98c2" - integrity sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-react-constant-elements@^7.0.0", "@babel/plugin-transform-react-constant-elements@^7.2.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.5.0.tgz#4d6ae4033bc38f8a65dfca2b6235c44522a422fc" @@ -1307,6 +1624,13 @@ resolve "^1.8.1" semver "^5.5.1" +"@babel/plugin-transform-shorthand-properties@^7.0.0": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e" + integrity sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-shorthand-properties@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" @@ -1315,9 +1639,16 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-shorthand-properties@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" + integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.7.4": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e" - integrity sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578" + integrity sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -1328,13 +1659,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-spread@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578" - integrity sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-sticky-regex@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" @@ -1344,12 +1668,20 @@ "@babel/helper-regex" "^7.0.0" "@babel/plugin-transform-sticky-regex@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" + integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + +"@babel/plugin-transform-template-literals@^7.0.0", "@babel/plugin-transform-template-literals@^7.7.4": version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz#ffb68c05090c30732076b1285dc1401b404a123c" - integrity sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A== + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604" + integrity sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ== dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" "@babel/plugin-transform-template-literals@^7.4.4": version "7.4.4" @@ -1359,14 +1691,6 @@ "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-template-literals@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604" - integrity sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-typeof-symbol@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" @@ -1624,9 +1948,9 @@ "@babel/plugin-transform-typescript" "^7.3.2" "@babel/preset-typescript@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.7.4.tgz#780059a78e6fa7f7a4c87f027292a86b31ce080a" - integrity sha512-rqrjxfdiHPsnuPur0jKrIIGQCIgoTWMTjlbWE69G4QJ6TIOVnnRnIJhUxNTL/VwDmEAVX08Tq3B1nirer5341w== + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.7.7.tgz#69ddea54e8b4e491ccbf94147e673b2ac6e11e2e" + integrity sha512-Apg0sCTovsSA+pEaI8efnA44b9x4X/7z4P8vsWMiN8rSUaM4y4+Shl5NMWnMl6njvt96+CEb6jwpXAKYAVCSQA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-typescript" "^7.7.4" @@ -1721,6 +2045,30 @@ "@babel/parser" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/template@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" + integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/traverse@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.3.tgz#a826215b011c9b4f73f3a893afbc05151358bf9a" + integrity sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.3" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/types" "^7.8.3" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" @@ -1736,17 +2084,17 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.1.6", "@babel/traverse@^7.6.0": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" - integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ== +"@babel/traverse@^7.1.6", "@babel/traverse@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" + integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.2" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.6.2" - "@babel/types" "^7.6.0" + "@babel/generator" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" @@ -1766,21 +2114,45 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" - integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== +"@babel/traverse@^7.6.0": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" + integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.4" - "@babel/helper-function-name" "^7.7.4" - "@babel/helper-split-export-declaration" "^7.7.4" - "@babel/parser" "^7.7.4" - "@babel/types" "^7.7.4" + "@babel/generator" "^7.6.2" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.6.2" + "@babel/types" "^7.6.0" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.8.3": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c" + integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.4" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.8.4" + "@babel/types" "^7.8.3" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@7.8.3", "@babel/types@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" + integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" @@ -2168,6 +2540,200 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc" integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA== +"@graphql-codegen/add@^1.12.2": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/add/-/add-1.12.2.tgz#d018f307520525bfbb59fde0d0ecca0b53714212" + integrity sha512-r4O3aXsi8gwm1v27C3T00HnPdn1mZzmp7ZfeEcsG8KymrVgHwh2VUPIevXRr0G6qPu8AnyqxBGWGm+mZme9Eag== + dependencies: + "@graphql-codegen/plugin-helpers" "1.12.2" + tslib "1.10.0" + +"@graphql-codegen/core@^1.12.2": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/core/-/core-1.12.2.tgz#85dcef3a9205f11aa910f0527c272967ed5c4427" + integrity sha512-n7OENe0lXIg40AGokO0W5v/OKo+bd4gjdKCRVp8N9Pu0o0uYm11rtCoL1JESJqUSt/LESbq+FH14fUqdXU048Q== + dependencies: + "@graphql-codegen/plugin-helpers" "1.12.2" + "@graphql-toolkit/common" "0.9.7" + "@graphql-toolkit/schema-merging" "0.9.7" + tslib "1.10.0" + +"@graphql-codegen/plugin-helpers@1.12.2": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.12.2.tgz#44ffeefb21515b021f99c6e5be28699d740af560" + integrity sha512-N294rqdBh+mCi4HWHbhPV9wE0XLCVKx524pYL4yp8qWiSdAs3Iz9+q9C9QNsLBvHypZdqml44M8kBMG41A9I/Q== + dependencies: + "@graphql-toolkit/common" "0.9.7" + camel-case "4.1.1" + common-tags "1.8.0" + constant-case "3.0.3" + import-from "3.0.0" + lower-case "2.0.1" + param-case "3.0.3" + pascal-case "3.1.1" + tslib "1.10.0" + upper-case "2.0.1" + +"@graphql-codegen/typescript-compatibility@^1.12.2": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-compatibility/-/typescript-compatibility-1.12.2.tgz#3dce0545acaab072b4069134b32954bca5e0cba1" + integrity sha512-DK2ovG9fcoUqkOiCCXFZ5E32eakcrbH+em8NIP2WEtB9hhk1FL0NEockpacaRAXvuqOqxygMYR24GWNssvdFKw== + dependencies: + "@graphql-codegen/plugin-helpers" "1.12.2" + "@graphql-codegen/visitor-plugin-common" "1.12.2" + pascal-case "3.1.1" + tslib "1.10.0" + +"@graphql-codegen/typescript-operations@^1.12.2": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-operations/-/typescript-operations-1.12.2.tgz#d5d495f237b1bb93839e28da0ddecc5f4ce9f877" + integrity sha512-U4wp9H5sbCP3kWEXI5SbGYeXUyDKidHi2kBRoQochEdsTXugF+6dr5WuUY3IvLIYS9qNKHKq6dm/9nl3DpBD+Q== + dependencies: + "@graphql-codegen/plugin-helpers" "1.12.2" + "@graphql-codegen/typescript" "1.12.2" + "@graphql-codegen/visitor-plugin-common" "1.12.2" + auto-bind "4.0.0" + tslib "1.10.0" + +"@graphql-codegen/typescript-react-apollo@^1.12.2": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-react-apollo/-/typescript-react-apollo-1.12.2.tgz#6a25bd07550ea795c023c98bffcf8a57b1240a33" + integrity sha512-oMRRmHTtd8LdAG8FN7msp7O9T960Oxm04L2JNYDoWc1GuxcMXo3ZVR7bRGgcvgDSmV391k5PSCtA3B8T/QgXjA== + dependencies: + "@graphql-codegen/plugin-helpers" "1.12.2" + "@graphql-codegen/visitor-plugin-common" "1.12.2" + auto-bind "4.0.0" + camel-case "4.1.1" + pascal-case "3.1.1" + tslib "1.10.0" + +"@graphql-codegen/typescript-resolvers@^1.12.2": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-1.12.2.tgz#17ed56be4d249ce961f5e6135d1c1ba5461ccfe9" + integrity sha512-+YJIAMck3X4DPC4Bwt8Ht4mlHxdYzMemHtRZjur0V6+WnxMxjE1NDylZ0bynhbbHd6bM1yoA3JpU5jCBcxF1Gw== + dependencies: + "@graphql-codegen/plugin-helpers" "1.12.2" + "@graphql-codegen/typescript" "1.12.2" + "@graphql-codegen/visitor-plugin-common" "1.12.2" + "@graphql-toolkit/common" "0.9.7" + auto-bind "4.0.0" + tslib "1.10.0" + +"@graphql-codegen/typescript@1.12.2", "@graphql-codegen/typescript@^1.12.2": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript/-/typescript-1.12.2.tgz#4b63ab80dcac7624711459e776201c6a5d0f7373" + integrity sha512-G2H91ocAEcZ86TFNQWV2HZUdXSR7v/Ntjq0ChqDvz/a7PTJxa5Pe5j4sQ9q13vGR5CedAMbBZkZ8zTKLAqY5sg== + dependencies: + "@graphql-codegen/plugin-helpers" "1.12.2" + "@graphql-codegen/visitor-plugin-common" "1.12.2" + auto-bind "4.0.0" + tslib "1.10.0" + +"@graphql-codegen/visitor-plugin-common@1.12.2": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-1.12.2.tgz#a32ed6ed2554bd2df125675e296d110d7ec00420" + integrity sha512-+DOnCNvgsMvVVXgAqA2Kqvcy9g0V5xiMAmpgNfrRE1tJ2PGXFsYP4HElBu+PQZCTn5AR8Tfw037zhfbUuF5oDw== + dependencies: + "@graphql-codegen/plugin-helpers" "1.12.2" + "@graphql-toolkit/relay-operation-optimizer" "0.9.7" + auto-bind "4.0.0" + dependency-graph "0.8.1" + graphql-tag "2.10.1" + pascal-case "3.1.1" + tslib "1.10.0" + +"@graphql-toolkit/code-file-loader@^0.9.7": + version "0.9.7" + resolved "https://registry.yarnpkg.com/@graphql-toolkit/code-file-loader/-/code-file-loader-0.9.7.tgz#3a1ee8dfd8029dbfba1ee4178dca1cbe3c313e04" + integrity sha512-Vs2E7ojJ2gmhTz+U0MRLMib8yPz4+U1THCE3QgP4Pqnrqnkp/kEI7qpt3G3XI7JRRBWDHU2gdwOydnHmM/Cjow== + dependencies: + "@graphql-toolkit/common" "0.9.7" + "@graphql-toolkit/graphql-tag-pluck" "0.9.7" + tslib "1.10.0" + +"@graphql-toolkit/common@0.9.7", "@graphql-toolkit/common@^0.9.7": + version "0.9.7" + resolved "https://registry.yarnpkg.com/@graphql-toolkit/common/-/common-0.9.7.tgz#63bc6233c4fd88bc94dfe6a3ec85b8f961f780f9" + integrity sha512-dpSRBMLeIiRct2gkjj24bp0EV7hbK/7dpJAPqNgvDH2535LhOkprYiCXQJyP4N1LODAEkpN/zzlJfKMVn773MQ== + dependencies: + "@ardatan/graphql-tools" "4.1.0" + aggregate-error "3.0.1" + lodash "4.17.15" + +"@graphql-toolkit/core@^0.9.7": + version "0.9.7" + resolved "https://registry.yarnpkg.com/@graphql-toolkit/core/-/core-0.9.7.tgz#a68fff000f3aedb6584c22f3f6b641885aec0f56" + integrity sha512-w1WU0iOq6AEBTICDxcu1xjFruFfGCHg6ERdWTWdIBOTn30qysIC0ek+XWN67vF9yV9QIdAxNu66gXKjUUWm2Tg== + dependencies: + "@graphql-toolkit/common" "0.9.7" + "@graphql-toolkit/schema-merging" "0.9.7" + aggregate-error "3.0.1" + globby "11.0.0" + import-from "^3.0.0" + is-glob "4.0.1" + lodash "4.17.15" + resolve-from "5.0.0" + tslib "1.10.0" + unixify "1.0.0" + valid-url "1.0.9" + +"@graphql-toolkit/graphql-file-loader@^0.9.7": + version "0.9.7" + resolved "https://registry.yarnpkg.com/@graphql-toolkit/graphql-file-loader/-/graphql-file-loader-0.9.7.tgz#1f15dfcf50342ab9e480fbbe2b16896395f36c45" + integrity sha512-t7CfYjghuXAtIqzwHhkUoE/u0a918UTOOVtHdLHh8rojjIUfsSeLeqMcFacRv+/z+kyKl9lgi4TE/qiyIpyR5A== + dependencies: + "@graphql-toolkit/common" "0.9.7" + tslib "1.10.0" + +"@graphql-toolkit/graphql-tag-pluck@0.9.7": + version "0.9.7" + resolved "https://registry.yarnpkg.com/@graphql-toolkit/graphql-tag-pluck/-/graphql-tag-pluck-0.9.7.tgz#772c5f15fb9b8e5f61d2816c4cfb1dcd1e3ba34e" + integrity sha512-hfHs9m/6rK0JRPrZg9LW8fPmQiNy7zvueey+TUH+qLHOkQiklDVDtQ/2yje35B16bwiyk3axxmHZ/H3fb5nWiQ== + dependencies: + "@babel/parser" "7.8.3" + "@babel/traverse" "7.8.3" + "@babel/types" "7.8.3" + "@graphql-toolkit/common" "0.9.7" + optionalDependencies: + vue-template-compiler "^2.6.11" + +"@graphql-toolkit/json-file-loader@^0.9.7": + version "0.9.7" + resolved "https://registry.yarnpkg.com/@graphql-toolkit/json-file-loader/-/json-file-loader-0.9.7.tgz#3f68dfbbc0c55c2b1531b6e200d5cd76ef85bb59" + integrity sha512-MNnCX201p011FPOm/rlDLkBTpx4LvooG9pdMU1ijRD/sqpHSkhZ2U/aKyoiDDKrLUgK7cvHws1KXBvLcg7r6aQ== + dependencies: + "@graphql-toolkit/common" "0.9.7" + tslib "1.10.0" + +"@graphql-toolkit/relay-operation-optimizer@0.9.7": + version "0.9.7" + resolved "https://registry.yarnpkg.com/@graphql-toolkit/relay-operation-optimizer/-/relay-operation-optimizer-0.9.7.tgz#e13034f835231b268ee355bfac6228dd34f9b951" + integrity sha512-IPFAbKMOX3RdjyDuamK9ziuTFD5tsCiTVvHACHA2wgg+32krJZJsV6STKhFLqIwytS40vt5zhZydQCFxIrCD5g== + dependencies: + "@graphql-toolkit/common" "0.9.7" + relay-compiler "8.0.0" + +"@graphql-toolkit/schema-merging@0.9.7", "@graphql-toolkit/schema-merging@^0.9.7": + version "0.9.7" + resolved "https://registry.yarnpkg.com/@graphql-toolkit/schema-merging/-/schema-merging-0.9.7.tgz#241ddd2c9ba79dd4444014057d0765777ab3cd12" + integrity sha512-RLhP0+XT4JGoPGCvlcTPdCE8stA7l0D5+gZ8ZP0snqzZOdsDFG4cNxpJtwf48i7uArsXkfu5OjOvTwh0MR0Wrw== + dependencies: + "@ardatan/graphql-tools" "4.1.0" + "@graphql-toolkit/common" "0.9.7" + deepmerge "4.2.2" + tslib "1.10.0" + +"@graphql-toolkit/url-loader@^0.9.7": + version "0.9.7" + resolved "https://registry.yarnpkg.com/@graphql-toolkit/url-loader/-/url-loader-0.9.7.tgz#222af4f8bb6d87735760555dd100c55fd3d36281" + integrity sha512-cOT2XJVZLWOKG4V9ucVtUTqJMW0BJqEqrHvpR8YcIWffrEChmzZQX+ug3BkRNomaUe8ywgExJ80aZuKWeSHvew== + dependencies: + "@ardatan/graphql-tools" "4.1.0" + "@graphql-toolkit/common" "0.9.7" + cross-fetch "3.0.4" + tslib "1.10.0" + valid-url "1.0.9" + "@gulp-sourcemaps/identity-map@1.X": version "1.0.2" resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz#1e6fe5d8027b1f285dc0d31762f566bccd73d5a9" @@ -2655,6 +3221,17 @@ dependencies: core-js "^2.5.7" +"@kamilkisiela/graphql-tools@^4.0.6": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@kamilkisiela/graphql-tools/-/graphql-tools-4.0.6.tgz#6dcf4d18bedaf34f6ab1d5bad2414e530d0875d1" + integrity sha512-IPWa+dOFCE4zaCsrJrAMp7yWXnfOZLNhqoMEOmn958WkLM0mmsDc/W/Rh7/7xopIT6P0oizb6/N1iH5HnNXOUA== + dependencies: + apollo-link "^1.2.3" + apollo-utilities "^1.0.1" + deprecated-decorator "^0.1.6" + iterall "^1.1.3" + uuid "^3.1.0" + "@mapbox/extent@0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@mapbox/extent/-/extent-0.4.0.tgz#3e591f32e1f0c3981c864239f7b0ac06e610f8a9" @@ -2847,38 +3424,25 @@ resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.12.14.tgz#0e0810a0a174e50e22dfe8edb30599840712f22d" integrity sha512-518yewjSga1jLdiLrcmpMFlaba5P+50b0TWNFUpC+SL9Yzf0kMi57qw+bMl+rQ08cGqH1vLx4eg9YFUbZXgZ0Q== -"@mrmlnc/readdir-enhanced@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== - dependencies: - call-me-maybe "^1.0.1" - glob-to-regexp "^0.3.0" - -"@nodelib/fs.scandir@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz#7fa8fed654939e1a39753d286b48b4836d00e0eb" - integrity sha512-NT/skIZjgotDSiXs0WqYhgcuBKhUMgfekCmCGtkUAiLqZdOnrdjmZr9wRl3ll64J9NF79uZ4fk16Dx0yMc/Xbg== +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== dependencies: - "@nodelib/fs.stat" "2.0.1" + "@nodelib/fs.stat" "2.0.3" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.1", "@nodelib/fs.stat@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.1.tgz#814f71b1167390cfcb6a6b3d9cdeb0951a192c14" - integrity sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw== - -"@nodelib/fs.stat@^1.1.2": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" - integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== -"@nodelib/fs.walk@^1.2.1": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz#6a6450c5e17012abd81450eb74949a4d970d2807" - integrity sha512-J/DR3+W12uCzAJkw7niXDcqcKBg6+5G5Q/ZpThpGNzAUz70eOR6RV4XnnSN01qHZiVl0eavoxJsBypQoKsV2QQ== +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== dependencies: - "@nodelib/fs.scandir" "2.1.1" + "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" "@oclif/color@^0.0.0": @@ -4120,11 +4684,6 @@ resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.33.tgz#2728669427cdd74a99e53c9f457ca2866a37c52d" integrity sha512-VQgHxyPMTj3hIlq9SY1mctqx+Jj8kpQfoLvDlVSDNOyuYs8JYfkuY3OW/4+dO657yPmNhHpePRx0/Tje5ImNVQ== -"@types/async@2.0.49": - version "2.0.49" - resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.49.tgz#92e33d13f74c895cb9a7f38ba97db8431ed14bc0" - integrity sha512-Benr3i5odUkvpFkOpzGqrltGdbSs+EVCkEBGXbuR7uT0VzhXKIkhem6PDzHdx5EonA+rfbB3QvP6aDOw5+zp5Q== - "@types/babel-types@*", "@types/babel-types@^7.0.0": version "7.0.4" resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.4.tgz#bfd5b0d0d1ba13e351dff65b6e52783b816826c8" @@ -4297,9 +4856,11 @@ integrity sha512-EIjmpvnHj+T4nMcKwHwxZKUfDmphIKJc2qnEMhSoOvr1lYEQpuRKRz8orWr//krYIIArS/KGGLfL2YGVUYXmIA== "@types/cp-file@*": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@types/cp-file/-/cp-file-4.2.0.tgz#2b12186b50dad407b11021284627bdf4adb87a87" - integrity sha512-nkd9c0L2aWfsDFrkpxfGJ5bCKeiAv6lccbH9vxKeWYw9YuyqskjtRTrBEBAiea9R08OSiboQ4ssmwAVJMHmHHA== + version "6.1.2" + resolved "https://registry.yarnpkg.com/@types/cp-file/-/cp-file-6.1.2.tgz#3c579201715ca6177d34f3e14f2b29861c470c4c" + integrity sha512-wvqCNhHt+GMfEglZ83cQ+8dEv5Oh8DwEq6IBBBL7+hWISR+82l/bSmssCo5zGHg7HpW6+kjZwDby9zGkCStN5w== + dependencies: + cp-file "*" "@types/cpy@^5.1.0": version "5.1.0" @@ -4499,11 +5060,6 @@ dependencies: "@types/node" "*" -"@types/graphql@^0.13.2": - version "0.13.4" - resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.13.4.tgz#55ae9c29f0fd6b85ee536f5c72b4769d5c5e06b1" - integrity sha512-B4yel4ro2nTb3v0pYO8vO6SjgvFJSrwUY+IO6TUSLdOSB+gQFslylrhRCHxvXMIhxB71mv5PEE9dAX+24S8sew== - "@types/gulp@^4.0.6": version "4.0.6" resolved "https://registry.yarnpkg.com/@types/gulp/-/gulp-4.0.6.tgz#68fe0e1f0ff3657cfca46fb564806b744a1bf899" @@ -5694,7 +6250,14 @@ "@types/node" "^12.0.2" tslib "^1.9.3" -"@wry/equality@^0.1.2": +"@wry/context@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.5.0.tgz#5ff84d0d5726b62c07045af8465f890eb3823c8c" + integrity sha512-yW5XFrWbRvv2/f86+g0YAfko7671SQg7Epn8lYjux4MZmIvtPvK2ts+vG1QAPu2w6GuBioEJknRa7K2LFj2kQw== + dependencies: + tslib "^1.9.3" + +"@wry/equality@^0.1.2", "@wry/equality@^0.1.9": version "0.1.9" resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.1.9.tgz#b13e18b7a8053c6858aa6c85b54911fb31e3a909" integrity sha512-mB6ceGjpMGz1ZTza8HYnrPGos2mC6So4NhS1PtZ8s4Qt0K7fBiIGhpSxUbQmhwcSWE3no+bYxmI2OL6KuXYmoQ== @@ -5958,6 +6521,14 @@ aggregate-error@2.1.0: clean-stack "^2.0.0" indent-string "^3.0.0" +aggregate-error@3.0.1, aggregate-error@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + aggregate-error@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-1.0.0.tgz#888344dad0220a72e3af50906117f48771925fac" @@ -5966,14 +6537,6 @@ aggregate-error@^1.0.0: clean-stack "^1.0.0" indent-string "^3.0.0" -aggregate-error@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" - integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - "airbnb-js-shims@^1 || ^2": version "2.1.1" resolved "https://registry.yarnpkg.com/airbnb-js-shims/-/airbnb-js-shims-2.1.1.tgz#a509611480db7e6d9db62fe2acfaeb473b6842ac" @@ -6293,7 +6856,7 @@ ansi-styles@^3.2.0: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0, ansi-styles@^4.1.0: +ansi-styles@^4.0.0: version "4.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== @@ -6301,6 +6864,14 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: "@types/color-name" "^1.1.1" color-convert "^2.0.1" +ansi-styles@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.0.tgz#5681f0dcf7ae5880a7841d8831c4724ed9cc0172" + integrity sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + ansi-styles@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" @@ -6377,59 +6948,34 @@ apollo-cache-inmemory@1.6.2: ts-invariant "^0.4.0" tslib "^1.9.3" -apollo-cache@^1.1.14: - version "1.1.14" - resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.1.14.tgz#c7d54cdbc7f544161f78fa5e4bae56650e22f7ad" - integrity sha512-Zmo9nVqpWFogki2QyulX6Xx6KYXMyYWX74grwgsYYUOukl4pIAdtYyK8e874o0QDgzSOq5AYPXjtfkoVpqhCRw== - dependencies: - apollo-utilities "^1.0.18" - -apollo-cache@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.3.2.tgz#df4dce56240d6c95c613510d7e409f7214e6d26a" - integrity sha512-+KA685AV5ETEJfjZuviRTEImGA11uNBp/MJGnaCvkgr+BYRrGLruVKBv6WvyFod27WEB2sp7SsG8cNBKANhGLg== +apollo-cache@1.3.4, apollo-cache@^1.3.2: + version "1.3.4" + resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.3.4.tgz#0c9f63c793e1cd6e34c450f7668e77aff58c9a42" + integrity sha512-7X5aGbqaOWYG+SSkCzJNHTz2ZKDcyRwtmvW4mGVLRqdQs+HxfXS4dUS2CcwrAj449se6tZ6NLUMnjko4KMt3KA== dependencies: - apollo-utilities "^1.3.2" - tslib "^1.9.3" + apollo-utilities "^1.3.3" + tslib "^1.10.0" apollo-client@^2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.3.8.tgz#0384a7210eb601ab88b1c13750da076fc9255b95" - integrity sha512-X5wsBD1be1P/mScGsH5H+2hIE8d78WAfqOvFvBpP+C+jzJ9387uHLyFmYYMLRRqDQ3ihjI4iSID7KEOW2gyCcQ== + version "2.6.8" + resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.6.8.tgz#01cebc18692abf90c6b3806414e081696b0fa537" + integrity sha512-0zvJtAcONiozpa5z5zgou83iEKkBaXhhSSXJebFHRXs100SecDojyUWKjwTtBPn9HbM6o5xrvC5mo9VQ5fgAjw== dependencies: "@types/zen-observable" "^0.8.0" - apollo-cache "^1.1.14" + apollo-cache "1.3.4" apollo-link "^1.0.0" - apollo-link-dedup "^1.0.0" - apollo-utilities "^1.0.18" + apollo-utilities "1.3.3" symbol-observable "^1.0.2" + ts-invariant "^0.4.0" + tslib "^1.10.0" zen-observable "^0.8.0" - optionalDependencies: - "@types/async" "2.0.49" -apollo-link-dedup@^1.0.0: - version "1.0.9" - resolved "https://registry.yarnpkg.com/apollo-link-dedup/-/apollo-link-dedup-1.0.9.tgz#3c4e4af88ef027cbddfdb857c043fd0574051dad" - integrity sha512-RbuEKpmSHVMtoREMPh2wUFTeh65q+0XPVeqgaOP/rGEAfvLyOMvX0vT2nVaejMohoMxuUnfZwpldXaDFWnlVbg== +apollo-link-error@^2.0.0-beta.0: + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/apollo-link-error/-/apollo-link-error-2.0.0-beta.0.tgz#58a06f0bc8658abe3490cb6fa7ed0f6d6c10cf98" + integrity sha512-eoTy/PG2JG+co+yOuLoTrk7PFiiIRDByrBytnAI/WGk67ez8px1wKsq3/EoPjAL+ty2IxgET+blu7zqQogEJwA== dependencies: - apollo-link "^1.2.2" - -apollo-link-error@^1.1.7: - version "1.1.10" - resolved "https://registry.yarnpkg.com/apollo-link-error/-/apollo-link-error-1.1.10.tgz#ce57f0793f0923b598655de5bf5e028d4cf4fba6" - integrity sha512-itG5UV7mQqaalmRkuRsF0cUS4zW2ja8XCbxkMZnIEeN24X3yoJi5hpJeAaEkXf0KgYNsR0+rmtCQNruWyxDnZQ== - dependencies: - apollo-link "^1.2.11" - apollo-link-http-common "^0.2.13" - tslib "^1.9.3" - -apollo-link-http-common@^0.2.13: - version "0.2.13" - resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.13.tgz#c688f6baaffdc7b269b2db7ae89dae7c58b5b350" - integrity sha512-Uyg1ECQpTTA691Fwx5e6Rc/6CPSu4TB4pQRTGIpwZ4l5JDOQ+812Wvi/e3IInmzOZpwx5YrrOfXrtN8BrsDXoA== - dependencies: - apollo-link "^1.2.11" - ts-invariant "^0.3.2" + "@apollo/client" "^3.0.0-beta.10" tslib "^1.9.3" apollo-link-http-common@^0.2.15: @@ -6458,32 +7004,14 @@ apollo-link-schema@^1.1.0: apollo-link "^1.2.2" apollo-link-state@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/apollo-link-state/-/apollo-link-state-0.4.1.tgz#65e9e0e12c67936b8c4b12b8438434f393104579" - integrity sha512-69/til4ENfl/Fvf7br2xSsLSBcxcXPbOHVNkzLLejvUZickl93HLO4/fO+uvoBi4dCYRgN17Zr8FwI41ueRx0g== + version "0.4.2" + resolved "https://registry.yarnpkg.com/apollo-link-state/-/apollo-link-state-0.4.2.tgz#ac00e9be9b0ca89eae0be6ba31fe904b80bbe2e8" + integrity sha512-xMPcAfuiPVYXaLwC6oJFIZrKgV3GmdO31Ag2eufRoXpvT0AfJZjdaPB4450Nu9TslHRePN9A3quxNueILlQxlw== dependencies: apollo-utilities "^1.0.8" graphql-anywhere "^4.1.0-alpha.0" -apollo-link@^1.0.0, apollo-link@^1.2.2, apollo-link@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.3.tgz#9bd8d5fe1d88d31dc91dae9ecc22474d451fb70d" - integrity sha512-iL9yS2OfxYhigme5bpTbmRyC+Htt6tyo2fRMHT3K1XRL/C5IQDDz37OjpPy4ndx7WInSvfSZaaOTKFja9VWqSw== - dependencies: - apollo-utilities "^1.0.0" - zen-observable-ts "^0.8.10" - -apollo-link@^1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.11.tgz#493293b747ad3237114ccd22e9f559e5e24a194d" - integrity sha512-PQvRCg13VduLy3X/0L79M6uOpTh5iHdxnxYuo8yL7sJlWybKRJwsv4IcRBJpMFbChOOaHY7Og9wgPo6DLKDKDA== - dependencies: - apollo-utilities "^1.2.1" - ts-invariant "^0.3.2" - tslib "^1.9.3" - zen-observable-ts "^0.8.18" - -apollo-link@^1.2.13: +apollo-link@^1.0.0, apollo-link@^1.2.13, apollo-link@^1.2.2, apollo-link@^1.2.3: version "1.2.13" resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.13.tgz#dff00fbf19dfcd90fddbc14b6a3f9a771acac6c4" integrity sha512-+iBMcYeevMm1JpYgwDEIDt/y0BB7VWyvlm/7x+TIPNLHCTCMgcEgDuW5kH86iQZWo0I7mNwQiTOz+/3ShPFmBw== @@ -6493,10 +7021,10 @@ apollo-link@^1.2.13: tslib "^1.9.3" zen-observable-ts "^0.8.20" -apollo-server-core@^1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.3.6.tgz#08636243c2de56fa8c267d68dd602cb1fbd323e3" - integrity sha1-CGNiQ8LeVvqMJn1o3WAssfvTI+M= +apollo-server-core@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.4.0.tgz#4faff7f110bfdd6c3f47008302ae24140f94c592" + integrity sha512-BP1Vh39krgEjkQxbjTdBURUjLHbFq1zeOChDJgaRsMxGtlhzuLWwwC6lLdPatN8jEPbeHq8Tndp9QZ3iQZOKKA== dependencies: apollo-cache-control "^0.1.0" apollo-tracing "^0.1.0" @@ -6508,18 +7036,18 @@ apollo-server-errors@^2.0.2: integrity sha512-zyWDqAVDCkj9espVsoUpZr9PwDznM8UW6fBfhV+i1br//s2AQb07N6ektZ9pRIEvkhykDZW+8tQbDwAO0vUROg== apollo-server-hapi@^1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/apollo-server-hapi/-/apollo-server-hapi-1.3.6.tgz#44dea128b64c1c10fdd35ac8307896a57ba1f4a8" - integrity sha1-RN6hKLZMHBD901rIMHiWpXuh9Kg= + version "1.4.0" + resolved "https://registry.yarnpkg.com/apollo-server-hapi/-/apollo-server-hapi-1.4.0.tgz#df63dcac17120490cde756370bdb5ea965141bc3" + integrity sha512-wChLPugWVcJM6gcSUuoHV6rO5pJUMrjkO5KcvPy4JXgpAbIGewpQvqJO8mk1y3C48WEhTOlgiFPquzGTnk6yFg== dependencies: - apollo-server-core "^1.3.6" - apollo-server-module-graphiql "^1.3.4" + apollo-server-core "^1.4.0" + apollo-server-module-graphiql "^1.4.0" boom "^7.1.0" -apollo-server-module-graphiql@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.3.4.tgz#50399b7c51b7267d0c841529f5173e5fc7304de4" - integrity sha1-UDmbfFG3Jn0MhBUp9Rc+X8cwTeQ= +apollo-server-module-graphiql@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.4.0.tgz#c559efa285578820709f1769bb85d3b3eed3d8ec" + integrity sha512-GmkOcb5he2x5gat+TuiTvabnBf1m4jzdecal3XbXBh/Jg+kx4hcvO3TTDFQ9CuTprtzdcVyA11iqG7iOMOt7vA== apollo-tracing@^0.1.0: version "0.1.4" @@ -6528,23 +7056,17 @@ apollo-tracing@^0.1.0: dependencies: graphql-extensions "~0.0.9" -apollo-utilities@^1.0.0, apollo-utilities@^1.0.1, apollo-utilities@^1.0.18, apollo-utilities@^1.0.8: - version "1.0.18" - resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.0.18.tgz#e4ee91534283fde2b744a26caaea120fe6a94f67" - integrity sha512-hHrmsoMYzzzfUlTOPpxr0qRpTLotMkBIQ93Ub7ki2SWdLfYYKrp6/KB8YOUkbCwXxSFvYSV24ccuwUEqZIaHIA== - dependencies: - fast-json-stable-stringify "^2.0.0" - -apollo-utilities@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.2.1.tgz#1c3a1ebf5607d7c8efe7636daaf58e7463b41b3c" - integrity sha512-Zv8Udp9XTSFiN8oyXOjf6PMHepD4yxxReLsl6dPUy5Ths7jti3nmlBzZUOxuTWRwZn0MoclqL7RQ5UEJN8MAxg== +apollo-utilities@1.3.3, apollo-utilities@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.3.3.tgz#f1854715a7be80cd810bc3ac95df085815c0787c" + integrity sha512-F14aX2R/fKNYMvhuP2t9GD9fggID7zp5I96MF5QeKYWDWTrkRdHRp4+SVfXUVN+cXOaB/IebfvRtzPf25CM0zw== dependencies: + "@wry/equality" "^0.1.2" fast-json-stable-stringify "^2.0.0" - ts-invariant "^0.2.1" - tslib "^1.9.3" + ts-invariant "^0.4.0" + tslib "^1.10.0" -apollo-utilities@^1.3.0, apollo-utilities@^1.3.2: +apollo-utilities@^1.0.1, apollo-utilities@^1.0.8, apollo-utilities@^1.3.0, apollo-utilities@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.3.2.tgz#8cbdcf8b012f664cd6cb5767f6130f5aed9115c9" integrity sha512-JWNHj8XChz7S4OZghV6yc9FNnzEXj285QYp/nLNh943iObycI5GTDO3NGR9Dth12LRrSFMeDOConPfPln+WGfg== @@ -7078,6 +7600,11 @@ attr-accept@^1.1.3: dependencies: core-js "^2.5.0" +auto-bind@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" + integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ== + autobind-decorator@^1.3.4: version "1.4.3" resolved "https://registry.yarnpkg.com/autobind-decorator/-/autobind-decorator-1.4.3.tgz#4c96ffa77b10622ede24f110f5dbbf56691417d1" @@ -7471,10 +7998,15 @@ babel-plugin-syntax-jsx@^6.18.0: resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= +babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: + version "7.0.0-beta.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" + integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== + babel-plugin-transform-define@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-define/-/babel-plugin-transform-define-1.3.1.tgz#b21b7bad3b84cf8e3f07cdc8c660b99cbbc01213" - integrity sha512-JXZ1xE9jIbKCGYZ4wbSMPSI5mdS4DRLi5+SkTHgZqWn5YIf/EucykkzUsPmzJlpkX8fsMVdLnA5vt/LvT97Zbg== + version "1.3.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-define/-/babel-plugin-transform-define-1.3.2.tgz#4bdbfe35a839fc206e0f60a7a9ae3b82d5e11808" + integrity sha512-fieU/nFuZjTxIttXoucN1fOIrej8I989IXqATMvKVcgTnfi53BjEwLzkw2KA6Q4gRRl4Cf3iiRVpwiB4PHFuWA== dependencies: lodash "^4.17.11" traverse "0.6.6" @@ -7552,6 +8084,39 @@ babel-polyfill@^6.26.0: core-js "^2.5.0" regenerator-runtime "^0.10.5" +babel-preset-fbjs@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.3.0.tgz#a6024764ea86c8e06a22d794ca8b69534d263541" + integrity sha512-7QTLTCd2gwB2qGoi5epSULMHugSVgpcVt5YAeiFO9ABLrutDQzKfGwzxgZHLpugq8qMdg/DhRZDZ5CLKxBkEbw== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-class-properties" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoped-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-member-expression-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-property-literals" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" + babel-preset-jest@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz#192b521e2217fb1d1f67cf73f70c336650ad3cdc" @@ -8109,7 +8674,7 @@ braces@^0.1.2: dependencies: expand-range "^0.1.0" -braces@^2.3.0, braces@^2.3.1, braces@^2.3.2: +braces@^2.3.1, braces@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== @@ -8563,11 +9128,6 @@ caching-transform@^3.0.2: package-hash "^3.0.0" write-file-atomic "^2.4.2" -call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= - call@5.x.x: version "5.0.1" resolved "https://registry.yarnpkg.com/call/-/call-5.0.1.tgz#ac1b5c106d9edc2a17af2a4a4f74dd4f0c06e910" @@ -8637,6 +9197,14 @@ camel-case@3.0.x, camel-case@^3.0.0: no-case "^2.2.0" upper-case "^1.1.1" +camel-case@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547" + integrity sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q== + dependencies: + pascal-case "^3.1.1" + tslib "^1.10.0" + camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" @@ -9850,6 +10418,15 @@ const-pinf-float64@^1.0.0: resolved "https://registry.yarnpkg.com/const-pinf-float64/-/const-pinf-float64-1.0.0.tgz#f6efb0d79f9c0986d3e79f2923abf9b70b63d726" integrity sha1-9u+w15+cCYbT558pI6v5twtj1yY= +constant-case@3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-3.0.3.tgz#ac910a99caf3926ac5112f352e3af599d8c5fc0a" + integrity sha512-FXtsSnnrFYpzDmvwDGQW+l8XK3GV1coLyBN0eBz16ZUzGaZcT2ANVCJmLeuw2GQgxKHQIe9e0w2dzkSfaRlUmA== + dependencies: + no-case "^3.0.3" + tslib "^1.10.0" + upper-case "^2.0.1" + constant-case@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-2.0.0.tgz#4175764d389d3fa9c8ecd29186ed6005243b6a46" @@ -10079,11 +10656,16 @@ core-js@^1.0.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= -core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.1, core-js@^2.5.3, core-js@^2.5.7, core-js@^2.6.5, core-js@^2.6.9: +core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.1, core-js@^2.5.7, core-js@^2.6.5, core-js@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== +core-js@^2.4.1, core-js@^2.5.3: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + core-js@^3.0.1, core-js@^3.0.4, core-js@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" @@ -10140,6 +10722,16 @@ cosmiconfig@^5.2.0: js-yaml "^3.13.1" parse-json "^4.0.0" +cp-file@*, cp-file@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-7.0.0.tgz#b9454cfd07fe3b974ab9ea0e5f29655791a9b8cd" + integrity sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw== + dependencies: + graceful-fs "^4.1.2" + make-dir "^3.0.0" + nested-error-stacks "^2.0.0" + p-event "^4.1.0" + cp-file@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-6.2.0.tgz#40d5ea4a1def2a9acdd07ba5c0b0246ef73dc10d" @@ -10151,16 +10743,6 @@ cp-file@^6.2.0: pify "^4.0.1" safe-buffer "^5.0.1" -cp-file@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-7.0.0.tgz#b9454cfd07fe3b974ab9ea0e5f29655791a9b8cd" - integrity sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw== - dependencies: - graceful-fs "^4.1.2" - make-dir "^3.0.0" - nested-error-stacks "^2.0.0" - p-event "^4.1.0" - cpy@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/cpy/-/cpy-8.0.0.tgz#8195db0db19a9ea6aa4f229784cbf3e3f53c3158" @@ -10293,6 +10875,14 @@ cross-fetch@2.2.2: node-fetch "2.1.2" whatwg-fetch "2.0.4" +cross-fetch@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.4.tgz#7bef7020207e684a7638ef5f2f698e24d9eb283c" + integrity sha512-MSHgpjQqgbT/94D4CyADeNoYh52zMkCX4pcJvPP5WqPsLFMKjr2TCMg381ox5qI0ii2dPwaLx/00477knXqXVw== + dependencies: + node-fetch "2.6.0" + whatwg-fetch "3.0.0" + cross-spawn-async@^2.1.1: version "2.2.5" resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc" @@ -11034,6 +11624,11 @@ dateformat@^3.0.2: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= + debug-fabulous@1.X: version "1.1.0" resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-1.1.0.tgz#af8a08632465224ef4174a9f06308c3c2a1ebc8e" @@ -11229,7 +11824,7 @@ deep-object-diff@^1.1.0: resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.0.tgz#d6fabf476c2ed1751fc94d5ca693d2ed8c18bc5a" integrity sha512-b+QLs5vHgS+IoSNcUE4n9HP2NwcHj7aqnJWsjPtuG75Rh5TOaGt0OjAYInh77d5T16V5cRDC+Pw/6ZZZiETBGw== -deepmerge@3.2.0, deepmerge@^4.0.0, deepmerge@^4.2.2: +deepmerge@3.2.0, deepmerge@4.2.2, deepmerge@^4.0.0, deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== @@ -11389,6 +11984,11 @@ depd@~1.1.1, depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +dependency-graph@0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.8.1.tgz#9b8cae3aa2c7bd95ccb3347a09a2d1047a6c3c5a" + integrity sha512-g213uqF8fyk40W8SBjm079n3CZB4qSpCrA2ye1fLGzH/4HEgB6tzuW2CbLE7leb4t45/6h44Ud59Su1/ROTfqw== + dependency-tree@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/dependency-tree/-/dependency-tree-7.0.2.tgz#01df8bbdc51e41438f5bb93f4a53e1a9cf8301a1" @@ -11819,6 +12419,14 @@ dot-case@^2.1.0: dependencies: no-case "^2.2.0" +dot-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa" + integrity sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA== + dependencies: + no-case "^3.0.3" + tslib "^1.10.0" + dot-prop@^4.1.0, dot-prop@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" @@ -13429,20 +14037,6 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -extglob@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.3.tgz#55e019d0c95bf873949c737b7e5172dba84ebb29" - integrity sha512-AyptZexgu7qppEPq59DtN/XJGZDrLcVxSHai+4hdgMMS9EpF4GBvygcWWApno8lL9qSjVpYt7Raao28qzJX1ww== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -13545,38 +14139,15 @@ fast-equals@^2.0.0: resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-2.0.0.tgz#bef2c423af3939f2c54310df54c57e64cd2adefc" integrity sha512-u6RBd8cSiLLxAiC04wVsLV6GBFDOXcTCgWkd3wEoFXgidPSoAJENqC9m7Jb2vewSvjBIfXV6icKeh3GTKfIaXA== -fast-glob@2.2.7, fast-glob@^2.2.6: - version "2.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" - integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== - dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.1.2" - glob-parent "^3.1.0" - is-glob "^4.0.0" - merge2 "^1.2.3" - micromatch "^3.1.10" - -fast-glob@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.0.4.tgz#a4b9f49e36175f5ef1a3456f580226a6e7abcc9e" - integrity sha512-JAh0y6ScChRmATdQIsN416LK+bAFiGczD9A4zWBMPcTgkpj9SEOC7DEzpfbqoDKzieZw40dIAKx3PofGxukFqw== - dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - glob-parent "3.1.0" - merge2 "1.2.1" - micromatch "3.1.5" - -fast-glob@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.0.4.tgz#d484a41005cb6faeb399b951fd1bd70ddaebb602" - integrity sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg== +fast-glob@2.2.7, fast-glob@3.1.1, fast-glob@^2.0.2, fast-glob@^2.2.2, fast-glob@^2.2.6, fast-glob@^3.0.3, fast-glob@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" + integrity sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g== dependencies: - "@nodelib/fs.stat" "^2.0.1" - "@nodelib/fs.walk" "^1.2.1" - glob-parent "^5.0.0" - is-glob "^4.0.1" - merge2 "^1.2.3" + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" micromatch "^4.0.2" fast-json-stable-stringify@^2.0.0: @@ -13654,6 +14225,11 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" +fbjs-css-vars@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" + integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== + fbjs@^0.8.0, fbjs@^0.8.1, fbjs@^0.8.16: version "0.8.17" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" @@ -13680,6 +14256,20 @@ fbjs@^0.8.4, fbjs@^0.8.9: setimmediate "^1.0.5" ua-parser-js "^0.7.9" +fbjs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-1.0.0.tgz#52c215e0883a3c86af2a7a776ed51525ae8e0a5a" + integrity sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA== + dependencies: + core-js "^2.4.1" + fbjs-css-vars "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.18" + fd-slicer@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" @@ -14450,7 +15040,17 @@ fsevents@~2.1.0: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.0.tgz#ce1a5f9ac71c6d75278b0c5bd236d7dfece4cbaa" integrity sha512-+iXhW3LuDQsno8dOIrCIT/CBjeBWuP7PXe8w9shnj9Lebny/Gx1ZjVBYwexLz36Ri2jKuXMNpV6CYNh8lHHgrQ== -fstream@^1.0.0, fstream@^1.0.12: +fstream@^1.0.0: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +fstream@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== @@ -14804,7 +15404,7 @@ glob-all@^3.1.0: glob "^7.0.5" yargs "~1.2.6" -glob-parent@3.1.0, glob-parent@^3.1.0: +glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= @@ -14819,7 +15419,7 @@ glob-parent@^5.0.0: dependencies: is-glob "^4.0.1" -glob-parent@~5.1.0: +glob-parent@^5.1.0, glob-parent@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== @@ -14842,11 +15442,6 @@ glob-stream@^6.1.0: to-absolute-glob "^2.0.0" unique-stream "^2.0.2" -glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= - glob-to-regexp@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.0.tgz#49bd677b1671022bd10921c3788f23cdebf9c7e6" @@ -15025,6 +15620,18 @@ globals@^9.18.0, globals@^9.2.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globby@11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.0.tgz#56fd0e9f0d4f8fb0c456f1ab0dee96e1380bc154" + integrity sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globby@8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" @@ -15307,11 +15914,13 @@ graphlib@^2.1.7: lodash "^4.17.5" graphql-anywhere@^4.1.0-alpha.0: - version "4.1.16" - resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.1.16.tgz#82bb59643e30183cfb7b485ed4262a7b39d8a6c1" - integrity sha512-DNQGxrh2p8w4vQwHIW1Sw65ZDbOr6ktQCeol6itH3LeWy1a3IoZ67jxrhgrHM+Upg8oiazvteSr64VRxJ8n5+g== + version "4.2.4" + resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.2.4.tgz#7f1c08c9348c730c6bb5e818c81f0b72c13696a8" + integrity sha512-rN6Op5vle0Ucqo8uOVPuFzRz1L/MB+ZVa+XezhFcQ6iP13vy95HOXRysrRtWcu2kQQTLyukSGmfU08D8LXWSIw== dependencies: - apollo-utilities "^1.0.18" + apollo-utilities "^1.3.2" + ts-invariant "^0.3.2" + tslib "^1.9.3" graphql-code-generator@^0.18.2: version "0.18.2" @@ -15440,9 +16049,9 @@ graphql-extensions@^0.0.x, graphql-extensions@~0.0.9: source-map-support "^0.5.1" graphql-fields@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/graphql-fields/-/graphql-fields-1.2.1.tgz#3777112af0bd6f55cc3c7b8f6d7748ab7a1b23bb" - integrity sha512-ufg/dxb78IjQUblNfiaEMkZWD1CwcZjdK0nTEW0dBQyNArxKZI7N+zohZdIdqVJcihPWJod1yymx4NM+1bZjTw== + version "1.3.0" + resolved "https://registry.yarnpkg.com/graphql-fields/-/graphql-fields-1.3.0.tgz#902ae2fd525eb04ddede7565d447db54dfc56b54" + integrity sha512-juRLzsYgbcJ/YuwExYObDPXn725YyCiVqxx6JlUm4HI5Ytm2RKp6MScaTVieMKtJI+Z6JmNgzInMTNuw0/DbZg== graphql-import@0.7.1, graphql-import@^0.7.1: version "0.7.1" @@ -15470,11 +16079,16 @@ graphql-tag-pluck@0.6.0: source-map-support "^0.5.9" typescript "^3.2.2" -graphql-tag@2.10.1, graphql-tag@^2.9.2: +graphql-tag@2.10.1: version "2.10.1" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.1.tgz#10aa41f1cd8fae5373eaf11f1f67260a3cad5e02" integrity sha512-jApXqWBzNXQ8jYa/HLkZJaVw9jgwNqZkywa2zfFn16Iv1Zb7ELNHkJaXHR7Quvd5SIGsy6Ny7SUKATgnu05uEg== +graphql-tag@^2.10.2, graphql-tag@^2.10.3: + version "2.10.3" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.3.tgz#ea1baba5eb8fc6339e4c4cf049dabe522b0edf03" + integrity sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA== + graphql-toolkit@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/graphql-toolkit/-/graphql-toolkit-0.2.0.tgz#91364b69911d51bc915269a37963f4ea2d5f335c" @@ -15503,23 +16117,23 @@ graphql-tools@4.0.4: iterall "^1.1.3" uuid "^3.1.0" -graphql-tools@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-3.1.1.tgz#d593358f01e7c8b1671a17b70ddb034dea9dbc50" - integrity sha512-yHvPkweUB0+Q/GWH5wIG60bpt8CTwBklCSzQdEHmRUgAdEQKxw+9B7zB3dG7wB3Ym7M7lfrS4Ej+jtDZfA2UXg== +graphql-tools@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-4.0.6.tgz#0e729e73db05ade3df10a2f92511be544972a844" + integrity sha512-jHLQw8x3xmSNRBCsaZqelXXsFfUSUSktSCUP8KYHiX1Z9qEuwcMpAf+FkdBzk8aTAFqOlPdNZ3OI4DKKqGKUqg== dependencies: - apollo-link "^1.2.2" + apollo-link "^1.2.3" apollo-utilities "^1.0.1" deprecated-decorator "^0.1.6" iterall "^1.1.3" uuid "^3.1.0" -graphql@^0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.13.2.tgz#4c740ae3c222823e7004096f832e7b93b2108270" - integrity sha512-QZ5BL8ZO/B20VA8APauGBg3GyEgZ19eduvpLWoq5x7gMmWnHoy8rlQWPLmWgFvo1yNgjSEFMesmS4R6pPr7xog== +graphql@^14.6.0: + version "14.6.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.6.0.tgz#57822297111e874ea12f5cd4419616930cd83e49" + integrity sha512-VKzfvHEKybTKjQVpTFrA5yUq2S9ihcZvfJAtsDBBCuV6wauPu1xl/f9ehgVf0FcEJJs4vz6ysb/ZMkGigQZseg== dependencies: - iterall "^1.2.1" + iterall "^1.2.2" graphviz@^0.0.8: version "0.0.8" @@ -16068,7 +16682,7 @@ hawk@~6.0.2: hoek "4.x.x" sntp "2.x.x" -he@1.2.0, he@1.2.x, he@^1.1.1: +he@1.2.0, he@1.2.x, he@^1.1.0, he@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -16572,6 +17186,11 @@ ignore@^5.1.1: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.2.tgz#e28e584d43ad7e92f96995019cc43b9e1ac49558" integrity sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ== +ignore@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" + integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== + image-size@~0.5.0: version "0.5.5" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" @@ -16597,6 +17216,11 @@ immutable@^4.0.0-rc.9: resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0-rc.12.tgz#ca59a7e4c19ae8d9bf74a97bdf0f6e2f2a5d0217" integrity sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A== +immutable@~3.7.6: + version "3.7.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" + integrity sha1-E7TTyxK++hVIKib+Gy665kAHHks= + import-cwd@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" @@ -16627,6 +17251,13 @@ import-from@2.1.0, import-from@^2.1.0: dependencies: resolve-from "^3.0.0" +import-from@3.0.0, import-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-3.0.0.tgz#055cfec38cd5a27d8057ca51376d7d3bf0891966" + integrity sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ== + dependencies: + resolve-from "^5.0.0" + import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" @@ -17312,6 +17943,13 @@ is-glob@4.0.0, is-glob@^4.0.0: dependencies: is-extglob "^2.1.1" +is-glob@4.0.1, is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + is-glob@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" @@ -17326,13 +17964,6 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - is-hexadecimal@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz#6e084bbc92061fbb0971ec58b6ce6d404e24da69" @@ -17455,13 +18086,6 @@ is-observable@^1.1.0: dependencies: symbol-observable "^1.1.0" -is-odd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-1.0.0.tgz#3b8a932eb028b3775c39bb09e91767accdb69088" - integrity sha1-O4qTLrAos3dcObsJ6RdnrM22kIg= - dependencies: - is-number "^3.0.0" - is-odd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" @@ -17948,7 +18572,7 @@ items@2.x.x: resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198" integrity sha1-i9FtnIOxlSneWuoyGsqtp4NkoZg= -iterall@^1.1.3, iterall@^1.2.1: +iterall@^1.1.3, iterall@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA== @@ -19769,7 +20393,12 @@ lodash.uniqby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= -lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.5: +lodash@4.17.11: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== + +lodash@4.17.15, lodash@>4.17.4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.5: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -19909,6 +20538,13 @@ lower-case-first@^1.0.0: dependencies: lower-case "^1.1.2" +lower-case@2.0.1, lower-case@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" + integrity sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ== + dependencies: + tslib "^1.10.0" + lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" @@ -20417,16 +21053,16 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.1.tgz#271d2516ff52d4af7f7b710b8bf3e16e183fef66" - integrity sha512-wUqcG5pxrAcaFI1lkqkMnk3Q7nUxV/NWfpAFSeWUwG9TRODnBDCUHa75mi3o3vLWQ5N4CQERWCauSlP0I3ZqUg== - merge2@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== +merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + merge@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" @@ -20461,25 +21097,6 @@ micromatch@3.1.10, micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.5.tgz#d05e168c206472dfbca985bfef4f57797b4cd4ba" - integrity sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.0" - define-property "^1.0.0" - extend-shallow "^2.0.1" - extglob "^2.0.2" - fragment-cache "^0.2.1" - kind-of "^6.0.0" - nanomatch "^1.2.5" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - micromatch@^4.0.0, micromatch@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" @@ -21110,23 +21727,6 @@ nano-time@1.0.0: dependencies: big-integer "^1.6.16" -nanomatch@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.7.tgz#53cd4aa109ff68b7f869591fdc9d10daeeea3e79" - integrity sha512-/5ldsnyurvEw7wNpxLFgjVvBLMta43niEYOy0CJ4ntcYSbx6bugRUTQeFb4BR/WanEL1o3aQgHuVLHQaB6tOqg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - is-odd "^1.0.0" - kind-of "^5.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - nanomatch@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" @@ -21278,6 +21878,14 @@ no-case@^2.2.0, no-case@^2.3.2: dependencies: lower-case "^1.1.1" +no-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8" + integrity sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw== + dependencies: + lower-case "^2.0.1" + tslib "^1.10.0" + nock@10.0.6: version "10.0.6" resolved "https://registry.yarnpkg.com/nock/-/nock-10.0.6.tgz#e6d90ee7a68b8cfc2ab7f6127e7d99aa7d13d111" @@ -21321,16 +21929,16 @@ node-fetch@2.1.2: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U= +node-fetch@2.6.0, node-fetch@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" + integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== + node-fetch@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.3.0.tgz#1a1d940bbfb916a1d3e0219f037e89e71f8c5fa5" integrity sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA== -node-fetch@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== - node-forge@0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" @@ -21730,6 +22338,11 @@ null-loader@^3.0.0: loader-utils "^1.2.3" schema-utils "^1.0.0" +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" @@ -22107,10 +22720,17 @@ oppsy@2.x.x, oppsy@^2.0.0: dependencies: hoek "5.x.x" +optimism@^0.11.5: + version "0.11.5" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.11.5.tgz#4c5d45fa0fa1cc9dcf092729b5d6d661b53ff5c9" + integrity sha512-twCHmBb64DYzEZ8A3O+TLCuF/RmZPBhXPQYv4agoiALRLlW9SidMzd7lwUP9mL0jOZhzhnBmb8ajqA00ECo/7g== + dependencies: + "@wry/context" "^0.5.0" + optimism@^0.9.0: - version "0.9.5" - resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.9.5.tgz#b8b5dc9150e97b79ddbf2d2c6c0e44de4d255527" - integrity sha512-lNvmuBgONAGrUbj/xpH69FjMOz1d0jvMNoOCKyVynUPzq2jgVlGL4jFYJqrUHzUfBv+jAFSCP61x5UkfbduYJA== + version "0.9.6" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.9.6.tgz#5621195486b294c3bfc518d17ac47767234b029f" + integrity sha512-bWr/ZP32UgFCQAoSkz33XctHwpq2via2sBvGvO5JIlrU8gaiM0LvoKj3QMle9LWdSKlzKik8XGSerzsdfYLNxA== dependencies: "@wry/context" "^0.4.0" @@ -22534,6 +23154,14 @@ param-case@2.1.x, param-case@^2.1.0: dependencies: no-case "^2.2.0" +param-case@3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238" + integrity sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA== + dependencies: + dot-case "^3.0.3" + tslib "^1.10.0" + parent-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" @@ -22736,6 +23364,14 @@ parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +pascal-case@3.1.1, pascal-case@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f" + integrity sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA== + dependencies: + no-case "^3.0.3" + tslib "^1.10.0" + pascal-case@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e" @@ -25432,15 +26068,10 @@ regex-regex@^1.0.0: resolved "https://registry.yarnpkg.com/regex-regex/-/regex-regex-1.0.0.tgz#9048a1eaeb870f4d480dabc76fc42cdcc0bc3a72" integrity sha1-kEih6uuHD01IDavHb8Qs3MC8OnI= -regexp-tree@^0.1.13: - version "0.1.13" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.13.tgz#5b19ab9377edc68bc3679256840bb29afc158d7f" - integrity sha512-hwdV/GQY5F8ReLZWO+W1SRoN5YfpOKY6852+tBFcma72DKBIcHjPRIlIvQN35bCOljuAfP2G2iB0FC/w236mUw== - -regexp-tree@^0.1.6: - version "0.1.10" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.10.tgz#d837816a039c7af8a8d64d7a7c3cf6a1d93450bc" - integrity sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ== +regexp-tree@^0.1.13, regexp-tree@^0.1.6: + version "0.1.17" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.17.tgz#66d914a6ca21f95dd7660ed70a7dad47aeb2246a" + integrity sha512-UnOJjFS/EPZmfISmYx+0PcDtPzyFKTe+cZTS5sM5hifnRUDRxoB1j4DAmGwqzxjwBGlwOkGfb2cDGHtjuEwqoA== regexp.prototype.flags@^1.2.0: version "1.2.0" @@ -25541,6 +26172,36 @@ relative@^3.0.2: dependencies: isobject "^2.0.0" +relay-compiler@8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/relay-compiler/-/relay-compiler-8.0.0.tgz#567edebc857db5748142b57a78d197f976b5e3ac" + integrity sha512-JrS3Bv6+6S0KloHmXUyTcrdFRpI3NxWdiVQC146vD5jgay9EM464lyf9bEUsCol3na4JUrad4aQ/r+4wWxG1kw== + dependencies: + "@babel/core" "^7.0.0" + "@babel/generator" "^7.5.0" + "@babel/parser" "^7.0.0" + "@babel/runtime" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + babel-preset-fbjs "^3.3.0" + chalk "^2.4.1" + fast-glob "^2.2.2" + fb-watchman "^2.0.0" + fbjs "^1.0.0" + immutable "~3.7.6" + nullthrows "^1.1.1" + relay-runtime "8.0.0" + signedsource "^1.0.0" + yargs "^14.2.0" + +relay-runtime@8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-8.0.0.tgz#52585a7bf04a710bd1bc664bfb0a60dbff3ce6e1" + integrity sha512-lOaZ7K/weTuCIt3pWHkxUG8s7iohI4IyYj65YV4sB9iX6W0uMvt626BFJ4GvNXFmd+OrgNnXcvx1mqRFqJaV8A== + dependencies: + "@babel/runtime" "^7.0.0" + fbjs "^1.0.0" + release-zalgo@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" @@ -25937,6 +26598,11 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: expand-tilde "^2.0.0" global-modules "^1.0.0" +resolve-from@5.0.0, resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" @@ -25952,11 +26618,6 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - resolve-options@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" @@ -26994,6 +27655,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= +signedsource@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a" + integrity sha1-HdrOSYF5j5O9gzlzgD2A1S6TrWo= + simple-git@1.116.0: version "1.116.0" resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.116.0.tgz#ea6e533466f1e0152186e306e004d4eefa6e3e00" @@ -29228,13 +29894,6 @@ ts-easing@^0.2.0: resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec" integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ== -ts-invariant@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.2.1.tgz#3d587f9d6e3bded97bf9ec17951dd9814d5a9d3f" - integrity sha512-Z/JSxzVmhTo50I+LKagEISFJW3pvPCqsMWLamCTX8Kr3N5aMrnGOqcflbe5hLUzwjvgPfnLzQtHZv0yWQ+FIHg== - dependencies: - tslib "^1.9.3" - ts-invariant@^0.3.2: version "0.3.3" resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.3.3.tgz#b5742b1885ecf9e29c31a750307480f045ec0b16" @@ -29249,6 +29908,13 @@ ts-invariant@^0.4.0: dependencies: tslib "^1.9.3" +ts-invariant@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.4.4.tgz#97a523518688f93aafad01b0e80eb803eb2abd86" + integrity sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA== + dependencies: + tslib "^1.9.3" + ts-loader@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.0.4.tgz#bc331ad91a887a60632d94c9f79448666f2c4b63" @@ -29283,7 +29949,7 @@ tsd@^0.7.4: typescript "^3.0.1" update-notifier "^2.5.0" -tslib@^1, tslib@^1.10.0: +tslib@1.10.0, tslib@^1, tslib@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== @@ -30173,6 +30839,13 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +unixify@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090" + integrity sha1-OmQcjC/7zk2mg6XHDwOkYpQMIJA= + dependencies: + normalize-path "^2.1.1" + unlazy-loader@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/unlazy-loader/-/unlazy-loader-0.1.3.tgz#2efdf05c489da311055586bf3cfca0c541dd8fa5" @@ -30301,6 +30974,13 @@ upper-case-first@^1.1.0, upper-case-first@^1.1.2: dependencies: upper-case "^1.1.1" +upper-case@2.0.1, upper-case@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-2.0.1.tgz#6214d05e235dc817822464ccbae85822b3d8665f" + integrity sha512-laAsbea9SY5osxrv7S99vH9xAaJKrw5Qpdh4ENRLcaxipjKsiaBwiAsxfa8X5mObKNTQPsupSq0J/VIxsSJe3A== + dependencies: + tslib "^1.10.0" + upper-case@^1.0.3, upper-case@^1.1.0, upper-case@^1.1.1, upper-case@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" @@ -31184,6 +31864,14 @@ vt-pbf@^3.1.1: "@mapbox/vector-tile" "^1.3.1" pbf "^3.0.5" +vue-template-compiler@^2.6.11: + version "2.6.11" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz#c04704ef8f498b153130018993e56309d4698080" + integrity sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA== + dependencies: + de-indent "^1.0.2" + he "^1.1.0" + w3c-hr-time@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" @@ -31494,7 +32182,7 @@ whatwg-fetch@2.0.4: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== -whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0: +whatwg-fetch@3.0.0, whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== @@ -32455,21 +33143,6 @@ z-schema@~3.18.3: optionalDependencies: commander "^2.7.1" -zen-observable-ts@^0.8.10: - version "0.8.10" - resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.10.tgz#18e2ce1c89fe026e9621fd83cc05168228fce829" - integrity sha512-5vqMtRggU/2GhePC9OU4sYEWOdvmayp2k3gjPf4F0mXwB3CSbbNznfDUvDJx9O2ZTa1EIXdJhPchQveFKwNXPQ== - dependencies: - zen-observable "^0.8.0" - -zen-observable-ts@^0.8.18: - version "0.8.18" - resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.18.tgz#ade44b1060cc4a800627856ec10b9c67f5f639c8" - integrity sha512-q7d05s75Rn1j39U5Oapg3HI2wzriVwERVo4N7uFGpIYuHB9ff02P/E92P9B8T7QVC93jCMHpbXH7X0eVR5LA7A== - dependencies: - tslib "^1.9.3" - zen-observable "^0.8.0" - zen-observable-ts@^0.8.20: version "0.8.20" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.20.tgz#44091e335d3fcbc97f6497e63e7f57d5b516b163" @@ -32483,6 +33156,11 @@ zen-observable@^0.8.0: resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.8.tgz#1ea93995bf098754a58215a1e0a7309e5749ec42" integrity sha512-HnhhyNnwTFzS48nihkCZIJGsWGFcYUz+XPDlPK5W84Ifji8SksC6m7sQWOf8zdCGhzQ4tDYuMYGu5B0N1dXTtg== +zen-observable@^0.8.14: + version "0.8.15" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" + integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== + zip-stream@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-2.1.2.tgz#841efd23214b602ff49c497cba1a85d8b5fbc39c" From a0ffce715ad83d776853843afd058ae2ded7ba3e Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Thu, 27 Feb 2020 08:58:28 +0000 Subject: [PATCH 34/64] Fix plugin path (#58649) --- packages/kbn-plugin-generator/sao_template/sao.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/kbn-plugin-generator/sao_template/sao.js b/packages/kbn-plugin-generator/sao_template/sao.js index 8e5e106190194..9073ce865a963 100755 --- a/packages/kbn-plugin-generator/sao_template/sao.js +++ b/packages/kbn-plugin-generator/sao_template/sao.js @@ -135,8 +135,11 @@ module.exports = function({ name, targetPath }) { 'eslintrc.js': '.eslintrc.js', 'i18nrc.json': '.i18nrc.json', }, - data: answers => - Object.assign( + data: answers => { + const pathToPlugin = answers.customPath + ? resolve(answers.customPath, camelCase(name), 'public') + : resolve(targetPath, 'public'); + return Object.assign( { templateVersion: pkg.version, startCase, @@ -150,13 +153,11 @@ module.exports = function({ name, targetPath }) { hasUi: !!answers.generateApp, hasServer: !!answers.generateApi, hasScss: !!answers.generateScss, - relRoot: relative( - resolve(answers.customPath || targetPath, name, 'public'), - process.cwd() - ), + relRoot: relative(pathToPlugin, process.cwd()), }, answers - ), + ); + }, enforceNewFolder: true, installDependencies: false, async post({ log, answers }) { From 0ef17ca0af9854473fac78b20b7152b5173a3f20 Mon Sep 17 00:00:00 2001 From: ChanghunKang Date: Thu, 27 Feb 2020 19:03:35 +0900 Subject: [PATCH 35/64] [APM] Change naming for pods to "Kubernetes pods". (#54446) (#54538) --- .../apm/server/lib/ui_filters/local_ui_filters/config.ts | 2 +- x-pack/plugins/translations/translations/zh-CN.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/config.ts b/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/config.ts index 6363b996ce5bb..06e701e9928f6 100644 --- a/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/config.ts +++ b/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/config.ts @@ -34,7 +34,7 @@ const filtersByName = { }, podName: { title: i18n.translate('xpack.apm.localFilters.titles.podName', { - defaultMessage: 'Pod' + defaultMessage: 'Kubernetes pod' }), fieldName: POD_NAME }, diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 32f648826da84..bae8fef5ff280 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3747,7 +3747,7 @@ "xpack.apm.localFilters.titles.agentName": "代理名称", "xpack.apm.localFilters.titles.containerId": "容器 ID", "xpack.apm.localFilters.titles.host": "主机", - "xpack.apm.localFilters.titles.podName": "Pod", + "xpack.apm.localFilters.titles.podName": "Kubernetes pod", "xpack.apm.localFilters.titles.transactionResult": "事务结果", "xpack.apm.localFilters.titles.transactionType": "事务类型", "xpack.apm.localFiltersTitle": "筛选", From 2b4a9fd7d7d57723cede7c73e14fc932a4c148fe Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Thu, 27 Feb 2020 12:08:08 +0100 Subject: [PATCH 36/64] [State Management] State syncing helpers for query service I (#56128) Before this pr: Discover, Visualise and Dashboard in setup phase create own state containers which watch for pinned filters, time and refresh interval changes. This watching and state comparisons happen for each plugin separately and not only when a specific app is mounted. So we ended up with a bunch of similar synchronous work which happens every time query services state changes. After this pr: Query service exposes observable to watch for changes (state$). Discover, Visualise and Dashboard use this observable for sub url tracking instead of creating its own. --- .../state_containers_examples/common/index.ts | 21 + .../state_containers_examples/kibana.json | 4 +- .../public/plugin.ts | 23 +- .../public/{ => todo}/app.tsx | 0 .../public/{ => todo}/todo.tsx | 6 +- .../public/with_data_services/application.tsx | 49 ++ .../with_data_services/components/app.tsx | 243 +++++++++ .../public/with_data_services/types.ts | 31 ++ .../state_containers_examples/server/index.ts | 28 ++ .../server/plugin.ts | 56 +++ .../server/routes/index.ts | 36 ++ .../state_containers_examples/server/types.ts | 23 + .../state_containers_examples/tsconfig.json | 1 + .../np_ready/dashboard_app_controller.tsx | 31 +- .../public/dashboard/np_ready/legacy_app.js | 6 +- .../kibana/public/dashboard/plugin.ts | 22 +- .../kibana/public/discover/plugin.ts | 17 +- .../kibana/public/visualize/plugin.ts | 17 +- .../new_platform/new_platform.karma_mock.js | 1 + src/plugins/data/public/index.ts | 6 +- src/plugins/data/public/query/mocks.ts | 7 +- .../data/public/query/query_service.ts | 11 + .../data/public/query/state_sync/README.md | 3 + .../state_sync/connect_to_query_state.test.ts | 465 ++++++++++++++++++ .../state_sync/connect_to_query_state.ts | 194 ++++++++ .../create_global_query_observable.ts | 87 ++++ .../data/public/query/state_sync/index.ts | 5 +- .../query/state_sync/sync_app_filters.test.ts | 197 -------- .../query/state_sync/sync_app_filters.ts | 65 --- .../public/query/state_sync/sync_query.ts | 188 ------- ...ry.test.ts => sync_state_with_url.test.ts} | 95 +--- .../query/state_sync/sync_state_with_url.ts | 102 ++++ .../data/public/query/state_sync/types.ts | 38 ++ .../public/query/timefilter/timefilter.ts | 13 + .../timefilter/timefilter_service.mock.ts | 2 + .../query_string_input.test.tsx.snap | 30 ++ .../ui/search_bar/create_search_bar.tsx | 46 +- .../__snapshots__/zeek_details.test.tsx.snap | 5 + 38 files changed, 1581 insertions(+), 593 deletions(-) create mode 100644 examples/state_containers_examples/common/index.ts rename examples/state_containers_examples/public/{ => todo}/app.tsx (100%) rename examples/state_containers_examples/public/{ => todo}/todo.tsx (98%) create mode 100644 examples/state_containers_examples/public/with_data_services/application.tsx create mode 100644 examples/state_containers_examples/public/with_data_services/components/app.tsx create mode 100644 examples/state_containers_examples/public/with_data_services/types.ts create mode 100644 examples/state_containers_examples/server/index.ts create mode 100644 examples/state_containers_examples/server/plugin.ts create mode 100644 examples/state_containers_examples/server/routes/index.ts create mode 100644 examples/state_containers_examples/server/types.ts create mode 100644 src/plugins/data/public/query/state_sync/README.md create mode 100644 src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts create mode 100644 src/plugins/data/public/query/state_sync/connect_to_query_state.ts create mode 100644 src/plugins/data/public/query/state_sync/create_global_query_observable.ts delete mode 100644 src/plugins/data/public/query/state_sync/sync_app_filters.test.ts delete mode 100644 src/plugins/data/public/query/state_sync/sync_app_filters.ts delete mode 100644 src/plugins/data/public/query/state_sync/sync_query.ts rename src/plugins/data/public/query/state_sync/{sync_query.test.ts => sync_state_with_url.test.ts} (63%) create mode 100644 src/plugins/data/public/query/state_sync/sync_state_with_url.ts create mode 100644 src/plugins/data/public/query/state_sync/types.ts diff --git a/examples/state_containers_examples/common/index.ts b/examples/state_containers_examples/common/index.ts new file mode 100644 index 0000000000000..25dc2eacf9c75 --- /dev/null +++ b/examples/state_containers_examples/common/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 const PLUGIN_ID = 'stateContainersExampleWithDataServices'; +export const PLUGIN_NAME = 'State containers example - with data services'; diff --git a/examples/state_containers_examples/kibana.json b/examples/state_containers_examples/kibana.json index 9114a414a4da3..437e9a4fac63c 100644 --- a/examples/state_containers_examples/kibana.json +++ b/examples/state_containers_examples/kibana.json @@ -3,8 +3,8 @@ "version": "0.0.1", "kibanaVersion": "kibana", "configPath": ["state_containers_examples"], - "server": false, + "server": true, "ui": true, - "requiredPlugins": [], + "requiredPlugins": ["navigation", "data"], "optionalPlugins": [] } diff --git a/examples/state_containers_examples/public/plugin.ts b/examples/state_containers_examples/public/plugin.ts index beb7b93dbc5b6..38ebf315789c0 100644 --- a/examples/state_containers_examples/public/plugin.ts +++ b/examples/state_containers_examples/public/plugin.ts @@ -18,14 +18,16 @@ */ import { AppMountParameters, CoreSetup, Plugin } from 'kibana/public'; +import { AppPluginDependencies } from './with_data_services/types'; +import { PLUGIN_ID, PLUGIN_NAME } from '../common'; export class StateContainersExamplesPlugin implements Plugin { public setup(core: CoreSetup) { core.application.register({ - id: 'state-containers-example-browser-history', + id: 'stateContainersExampleBrowserHistory', title: 'State containers example - browser history routing', async mount(params: AppMountParameters) { - const { renderApp, History } = await import('./app'); + const { renderApp, History } = await import('./todo/app'); return renderApp(params, { appInstanceId: '1', appTitle: 'Routing with browser history', @@ -34,10 +36,10 @@ export class StateContainersExamplesPlugin implements Plugin { }, }); core.application.register({ - id: 'state-containers-example-hash-history', + id: 'stateContainersExampleHashHistory', title: 'State containers example - hash history routing', async mount(params: AppMountParameters) { - const { renderApp, History } = await import('./app'); + const { renderApp, History } = await import('./todo/app'); return renderApp(params, { appInstanceId: '2', appTitle: 'Routing with hash history', @@ -45,6 +47,19 @@ export class StateContainersExamplesPlugin implements Plugin { }); }, }); + + core.application.register({ + id: PLUGIN_ID, + title: PLUGIN_NAME, + async mount(params: AppMountParameters) { + // Load application bundle + const { renderApp } = await import('./with_data_services/application'); + // Get start services as specified in kibana.json + const [coreStart, depsStart] = await core.getStartServices(); + // Render the application + return renderApp(coreStart, depsStart as AppPluginDependencies, params); + }, + }); } public start() {} diff --git a/examples/state_containers_examples/public/app.tsx b/examples/state_containers_examples/public/todo/app.tsx similarity index 100% rename from examples/state_containers_examples/public/app.tsx rename to examples/state_containers_examples/public/todo/app.tsx diff --git a/examples/state_containers_examples/public/todo.tsx b/examples/state_containers_examples/public/todo/todo.tsx similarity index 98% rename from examples/state_containers_examples/public/todo.tsx rename to examples/state_containers_examples/public/todo/todo.tsx index 84f64f99d0179..c0617620bde53 100644 --- a/examples/state_containers_examples/public/todo.tsx +++ b/examples/state_containers_examples/public/todo/todo.tsx @@ -42,14 +42,14 @@ import { syncStates, getStateFromKbnUrl, BaseState, -} from '../../../src/plugins/kibana_utils/public'; -import { useUrlTracker } from '../../../src/plugins/kibana_react/public'; +} from '../../../../src/plugins/kibana_utils/public'; +import { useUrlTracker } from '../../../../src/plugins/kibana_react/public'; import { defaultState, pureTransitions, TodoActions, TodoState, -} from '../../../src/plugins/kibana_utils/demos/state_containers/todomvc'; +} from '../../../../src/plugins/kibana_utils/demos/state_containers/todomvc'; interface GlobalState { text: string; diff --git a/examples/state_containers_examples/public/with_data_services/application.tsx b/examples/state_containers_examples/public/with_data_services/application.tsx new file mode 100644 index 0000000000000..1de3cbbc5f988 --- /dev/null +++ b/examples/state_containers_examples/public/with_data_services/application.tsx @@ -0,0 +1,49 @@ +/* + * 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 ReactDOM from 'react-dom'; +import { createBrowserHistory } from 'history'; +import { AppMountParameters, CoreStart } from '../../../../src/core/public'; +import { AppPluginDependencies } from './types'; +import { StateDemoApp } from './components/app'; +import { createKbnUrlStateStorage } from '../../../../src/plugins/kibana_utils/public/'; + +export const renderApp = ( + { notifications, http }: CoreStart, + { navigation, data }: AppPluginDependencies, + { appBasePath, element }: AppMountParameters +) => { + const history = createBrowserHistory({ basename: appBasePath }); + const kbnUrlStateStorage = createKbnUrlStateStorage({ useHash: false, history }); + + ReactDOM.render( + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/examples/state_containers_examples/public/with_data_services/components/app.tsx b/examples/state_containers_examples/public/with_data_services/components/app.tsx new file mode 100644 index 0000000000000..c820929d8a61d --- /dev/null +++ b/examples/state_containers_examples/public/with_data_services/components/app.tsx @@ -0,0 +1,243 @@ +/* + * 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, { useEffect, useRef, useState, useCallback } from 'react'; +import { History } from 'history'; +import { FormattedMessage, I18nProvider } from '@kbn/i18n/react'; +import { Router } from 'react-router-dom'; + +import { + EuiFieldText, + EuiPage, + EuiPageBody, + EuiPageContent, + EuiPageHeader, + EuiTitle, +} from '@elastic/eui'; + +import { CoreStart } from '../../../../../src/core/public'; +import { NavigationPublicPluginStart } from '../../../../../src/plugins/navigation/public'; +import { + connectToQueryState, + syncQueryStateWithUrl, + DataPublicPluginStart, + IIndexPattern, + QueryState, + Filter, + esFilters, + Query, +} from '../../../../../src/plugins/data/public'; +import { + BaseState, + BaseStateContainer, + createStateContainer, + createStateContainerReactHelpers, + IKbnUrlStateStorage, + ReduxLikeStateContainer, + syncState, +} from '../../../../../src/plugins/kibana_utils/public'; +import { PLUGIN_ID, PLUGIN_NAME } from '../../../common'; + +interface StateDemoAppDeps { + notifications: CoreStart['notifications']; + http: CoreStart['http']; + navigation: NavigationPublicPluginStart; + data: DataPublicPluginStart; + history: History; + kbnUrlStateStorage: IKbnUrlStateStorage; +} + +interface AppState { + name: string; + filters: Filter[]; + query?: Query; +} +const defaultAppState: AppState = { + name: '', + filters: [], +}; +const { + Provider: AppStateContainerProvider, + useState: useAppState, + useContainer: useAppStateContainer, +} = createStateContainerReactHelpers>(); + +const App = ({ + notifications, + http, + navigation, + data, + history, + kbnUrlStateStorage, +}: StateDemoAppDeps) => { + const appStateContainer = useAppStateContainer(); + const appState = useAppState(); + + useGlobalStateSyncing(data.query, kbnUrlStateStorage); + useAppStateSyncing(appStateContainer, data.query, kbnUrlStateStorage); + + const onQuerySubmit = useCallback( + ({ query }) => { + appStateContainer.set({ ...appState, query }); + }, + [appStateContainer, appState] + ); + + const indexPattern = useIndexPattern(data); + if (!indexPattern) + return
No index pattern found. Please create an intex patter before loading...
; + + // Render the application DOM. + // Note that `navigation.ui.TopNavMenu` is a stateful component exported on the `navigation` plugin's start contract. + return ( + + + <> + + + + + +

+ +

+
+
+ + appStateContainer.set({ ...appState, name: e.target.value })} + aria-label="My name" + /> + +
+
+ +
+
+ ); +}; + +export const StateDemoApp = (props: StateDemoAppDeps) => { + const appStateContainer = useCreateStateContainer(defaultAppState); + + return ( + + + + ); +}; + +function useCreateStateContainer( + defaultState: State +): ReduxLikeStateContainer { + const stateContainerRef = useRef | null>(null); + if (!stateContainerRef.current) { + stateContainerRef.current = createStateContainer(defaultState); + } + return stateContainerRef.current; +} + +function useIndexPattern(data: DataPublicPluginStart) { + const [indexPattern, setIndexPattern] = useState(); + useEffect(() => { + const fetchIndexPattern = async () => { + const defaultIndexPattern = await data.indexPatterns.getDefault(); + if (defaultIndexPattern) { + setIndexPattern(defaultIndexPattern); + } + }; + fetchIndexPattern(); + }, [data.indexPatterns]); + + return indexPattern; +} + +function useGlobalStateSyncing( + query: DataPublicPluginStart['query'], + kbnUrlStateStorage: IKbnUrlStateStorage +) { + // setup sync state utils + useEffect(() => { + // sync global filters, time filters, refresh interval from data.query to url '_g' + const { stop } = syncQueryStateWithUrl(query, kbnUrlStateStorage); + return () => { + stop(); + }; + }, [query, kbnUrlStateStorage]); +} + +function useAppStateSyncing( + appStateContainer: BaseStateContainer, + query: DataPublicPluginStart['query'], + kbnUrlStateStorage: IKbnUrlStateStorage +) { + // setup sync state utils + useEffect(() => { + // sync app filters with app state container from data.query to state container + const stopSyncingQueryAppStateWithStateContainer = connectToQueryState( + query, + appStateContainer, + { filters: esFilters.FilterStateStore.APP_STATE } + ); + + // sets up syncing app state container with url + const { start: startSyncingAppStateWithUrl, stop: stopSyncingAppStateWithUrl } = syncState({ + storageKey: '_a', + stateStorage: kbnUrlStateStorage, + stateContainer: { + ...appStateContainer, + // stateSync utils requires explicit handling of default state ("null") + set: state => state && appStateContainer.set(state), + }, + }); + + // merge initial state from app state container and current state in url + const initialAppState: AppState = { + ...appStateContainer.get(), + ...kbnUrlStateStorage.get('_a'), + }; + // trigger state update. actually needed in case some data was in url + appStateContainer.set(initialAppState); + + // set current url to whatever is in app state container + kbnUrlStateStorage.set('_a', initialAppState); + + // finally start syncing state containers with url + startSyncingAppStateWithUrl(); + + return () => { + stopSyncingQueryAppStateWithStateContainer(); + stopSyncingAppStateWithUrl(); + }; + }, [query, kbnUrlStateStorage, appStateContainer]); +} diff --git a/examples/state_containers_examples/public/with_data_services/types.ts b/examples/state_containers_examples/public/with_data_services/types.ts new file mode 100644 index 0000000000000..c63074a7a3810 --- /dev/null +++ b/examples/state_containers_examples/public/with_data_services/types.ts @@ -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 { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public'; +import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface StateDemoPublicPluginSetup {} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface StateDemoPublicPluginStart {} + +export interface AppPluginDependencies { + data: DataPublicPluginStart; + navigation: NavigationPublicPluginStart; +} diff --git a/examples/state_containers_examples/server/index.ts b/examples/state_containers_examples/server/index.ts new file mode 100644 index 0000000000000..51005d78462a2 --- /dev/null +++ b/examples/state_containers_examples/server/index.ts @@ -0,0 +1,28 @@ +/* + * 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 { PluginInitializerContext } from '../../../src/core/server'; +import { StateDemoServerPlugin } from './plugin'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new StateDemoServerPlugin(initializerContext); +} + +export { StateDemoServerPlugin as Plugin }; +export * from '../common'; diff --git a/examples/state_containers_examples/server/plugin.ts b/examples/state_containers_examples/server/plugin.ts new file mode 100644 index 0000000000000..1c3fa9bfb290e --- /dev/null +++ b/examples/state_containers_examples/server/plugin.ts @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + PluginInitializerContext, + CoreSetup, + CoreStart, + Plugin, + Logger, +} from '../../../src/core/server'; + +import { StateDemoPluginSetup, StateDemoPluginStart } from './types'; +import { defineRoutes } from './routes'; + +export class StateDemoServerPlugin implements Plugin { + private readonly logger: Logger; + + constructor(initializerContext: PluginInitializerContext) { + this.logger = initializerContext.logger.get(); + } + + public setup(core: CoreSetup) { + this.logger.debug('State_demo: Ssetup'); + const router = core.http.createRouter(); + + // Register server side APIs + defineRoutes(router); + + return {}; + } + + public start(core: CoreStart) { + this.logger.debug('State_demo: Started'); + return {}; + } + + public stop() {} +} + +export { StateDemoServerPlugin as Plugin }; diff --git a/examples/state_containers_examples/server/routes/index.ts b/examples/state_containers_examples/server/routes/index.ts new file mode 100644 index 0000000000000..f6da48ae62c61 --- /dev/null +++ b/examples/state_containers_examples/server/routes/index.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. + */ + +import { IRouter } from '../../../../src/core/server'; + +export function defineRoutes(router: IRouter) { + router.get( + { + path: '/api/state_demo/example', + validate: false, + }, + async (context, request, response) => { + return response.ok({ + body: { + time: new Date().toISOString(), + }, + }); + } + ); +} diff --git a/examples/state_containers_examples/server/types.ts b/examples/state_containers_examples/server/types.ts new file mode 100644 index 0000000000000..6acfc27bd681b --- /dev/null +++ b/examples/state_containers_examples/server/types.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. + */ + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface StateDemoPluginSetup {} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface StateDemoPluginStart {} diff --git a/examples/state_containers_examples/tsconfig.json b/examples/state_containers_examples/tsconfig.json index 091130487791b..3f43072c2aade 100644 --- a/examples/state_containers_examples/tsconfig.json +++ b/examples/state_containers_examples/tsconfig.json @@ -9,6 +9,7 @@ "public/**/*.ts", "public/**/*.tsx", "server/**/*.ts", + "common/**/*.ts", "../../typings/**/*" ], "exclude": [] diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app_controller.tsx b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app_controller.tsx index 075516d52bab6..84dd73882d134 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app_controller.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app_controller.tsx @@ -31,18 +31,18 @@ import { DashboardEmptyScreen, DashboardEmptyScreenProps } from './dashboard_emp import { migrateLegacyQuery, subscribeWithScope } from '../legacy_imports'; import { + connectToQueryState, esFilters, IndexPattern, IndexPatternsContract, Query, SavedQuery, - syncAppFilters, - syncQuery, + syncQueryStateWithUrl, } from '../../../../../../plugins/data/public'; import { + getSavedObjectFinder, SaveResult, showSaveModal, - getSavedObjectFinder, } from '../../../../../../plugins/saved_objects/public'; import { @@ -129,9 +129,9 @@ export class DashboardAppController { // starts syncing `_g` portion of url with query services // note: dashboard_state_manager.ts syncs `_a` portion of url const { - stop: stopSyncingGlobalStateWithUrl, + stop: stopSyncingQueryServiceStateWithUrl, hasInheritedQueryFromUrl: hasInheritedGlobalStateFromUrl, - } = syncQuery(queryService, kbnUrlStateStorage); + } = syncQueryStateWithUrl(queryService, kbnUrlStateStorage); let lastReloadRequestTime = 0; @@ -148,11 +148,20 @@ export class DashboardAppController { history, }); - const stopSyncingAppFilters = syncAppFilters(filterManager, { - set: filters => dashboardStateManager.setFilters(filters), - get: () => dashboardStateManager.appState.filters, - state$: dashboardStateManager.appState$.pipe(map(state => state.filters)), - }); + // sync initial app filters from state to filterManager + filterManager.setAppFilters(_.cloneDeep(dashboardStateManager.appState.filters)); + // setup syncing of app filters between appState and filterManager + const stopSyncingAppFilters = connectToQueryState( + queryService, + { + set: ({ filters }) => dashboardStateManager.setFilters(filters || []), + get: () => ({ filters: dashboardStateManager.appState.filters }), + state$: dashboardStateManager.appState$.pipe(map(state => ({ filters: state.filters }))), + }, + { + filters: esFilters.FilterStateStore.APP_STATE, + } + ); // The hash check is so we only update the time filter on dashboard open, not during // normal cross app navigation. @@ -899,7 +908,7 @@ export class DashboardAppController { $scope.$on('$destroy', () => { updateSubscription.unsubscribe(); - stopSyncingGlobalStateWithUrl(); + stopSyncingQueryServiceStateWithUrl(); stopSyncingAppFilters(); visibleSubscription.unsubscribe(); $scope.timefilterSubscriptions$.unsubscribe(); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js index ce9cc85be57b2..35b510894179d 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js @@ -33,7 +33,7 @@ import { } from '../../../../../../plugins/kibana_utils/public'; import { DashboardListing, EMPTY_FILTER } from './listing/dashboard_listing'; import { addHelpMenuToAppChrome } from './help_menu/help_menu_util'; -import { syncQuery } from '../../../../../../plugins/data/public'; +import { syncQueryStateWithUrl } from '../../../../../../plugins/data/public'; export function initDashboardApp(app, deps) { initDashboardAppDirective(app, deps); @@ -98,7 +98,7 @@ export function initDashboardApp(app, deps) { const dashboardConfig = deps.dashboardConfig; // syncs `_g` portion of url with query services - const { stop: stopSyncingGlobalStateWithUrl } = syncQuery( + const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl( deps.data.query, kbnUrlStateStorage ); @@ -132,7 +132,7 @@ export function initDashboardApp(app, deps) { $scope.core = deps.core; $scope.$on('$destroy', () => { - stopSyncingGlobalStateWithUrl(); + stopSyncingQueryServiceStateWithUrl(); }); }, resolve: { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts b/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts index 7d64ee969212f..9e645b7fb3c5f 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts @@ -18,6 +18,7 @@ */ import { BehaviorSubject } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; import { App, AppMountParameters, @@ -29,7 +30,11 @@ import { } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { RenderDeps } from './np_ready/application'; -import { DataPublicPluginStart, DataPublicPluginSetup } from '../../../../../plugins/data/public'; +import { + DataPublicPluginStart, + DataPublicPluginSetup, + esFilters, +} from '../../../../../plugins/data/public'; import { IEmbeddableStart } from '../../../../../plugins/embeddable/public'; import { Storage } from '../../../../../plugins/kibana_utils/public'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; @@ -46,7 +51,6 @@ import { } from '../../../../../plugins/kibana_legacy/public'; import { createSavedDashboardLoader } from './saved_dashboard/saved_dashboards'; import { createKbnUrlTracker } from '../../../../../plugins/kibana_utils/public'; -import { getQueryStateContainer } from '../../../../../plugins/data/public'; export interface DashboardPluginStartDependencies { data: DataPublicPluginStart; @@ -78,9 +82,6 @@ export class DashboardPlugin implements Plugin { constructor(private initializerContext: PluginInitializerContext) {} public setup(core: CoreSetup, { home, kibanaLegacy, data }: DashboardPluginSetupDependencies) { - const { querySyncStateContainer, stop: stopQuerySyncStateContainer } = getQueryStateContainer( - data.query - ); const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({ baseUrl: core.http.basePath.prepend('/app/kibana'), defaultSubUrl: `#${DashboardConstants.LANDING_PAGE_PATH}`, @@ -97,12 +98,19 @@ export class DashboardPlugin implements Plugin { stateParams: [ { kbnUrlKey: '_g', - stateUpdate$: querySyncStateContainer.state$, + stateUpdate$: data.query.state$.pipe( + filter( + ({ changes }) => !!(changes.globalFilters || changes.time || changes.refreshInterval) + ), + map(({ state }) => ({ + ...state, + filters: state.filters?.filter(esFilters.isFilterPinned), + })) + ), }, ], }); this.stopUrlTracking = () => { - stopQuerySyncStateContainer(); stopUrlTracker(); }; const app: App = { diff --git a/src/legacy/core_plugins/kibana/public/discover/plugin.ts b/src/legacy/core_plugins/kibana/public/discover/plugin.ts index e8ded9d99f892..3ba0418d35f71 100644 --- a/src/legacy/core_plugins/kibana/public/discover/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/discover/plugin.ts @@ -18,6 +18,7 @@ */ import { BehaviorSubject } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; import { i18n } from '@kbn/i18n'; import { AppMountParameters, CoreSetup, CoreStart, Plugin } from 'kibana/public'; import angular, { auto } from 'angular'; @@ -25,7 +26,7 @@ import { UiActionsSetup, UiActionsStart } from 'src/plugins/ui_actions/public'; import { DataPublicPluginStart, DataPublicPluginSetup, - getQueryStateContainer, + esFilters, } from '../../../../../plugins/data/public'; import { registerFeature } from './np_ready/register_feature'; import './kibana_services'; @@ -103,9 +104,6 @@ export class DiscoverPlugin implements Plugin { public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>; setup(core: CoreSetup, plugins: DiscoverSetupPlugins): DiscoverSetup { - const { querySyncStateContainer, stop: stopQuerySyncStateContainer } = getQueryStateContainer( - plugins.data.query - ); const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({ baseUrl: core.http.basePath.prepend('/app/kibana'), defaultSubUrl: '#/discover', @@ -115,12 +113,19 @@ export class DiscoverPlugin implements Plugin { stateParams: [ { kbnUrlKey: '_g', - stateUpdate$: querySyncStateContainer.state$, + stateUpdate$: plugins.data.query.state$.pipe( + filter( + ({ changes }) => !!(changes.globalFilters || changes.time || changes.refreshInterval) + ), + map(({ state }) => ({ + ...state, + filters: state.filters?.filter(esFilters.isFilterPinned), + })) + ), }, ], }); this.stopUrlTracking = () => { - stopQuerySyncStateContainer(); stopUrlTracker(); }; diff --git a/src/legacy/core_plugins/kibana/public/visualize/plugin.ts b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts index 9f2283d29c203..b9e4487ae84fb 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts @@ -19,6 +19,7 @@ import { BehaviorSubject } from 'rxjs'; import { i18n } from '@kbn/i18n'; +import { filter, map } from 'rxjs/operators'; import { AppMountParameters, @@ -33,7 +34,7 @@ import { Storage, createKbnUrlTracker } from '../../../../../plugins/kibana_util import { DataPublicPluginStart, DataPublicPluginSetup, - getQueryStateContainer, + esFilters, } from '../../../../../plugins/data/public'; import { IEmbeddableStart } from '../../../../../plugins/embeddable/public'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; @@ -85,9 +86,6 @@ export class VisualizePlugin implements Plugin { core: CoreSetup, { home, kibanaLegacy, usageCollection, data }: VisualizePluginSetupDependencies ) { - const { querySyncStateContainer, stop: stopQuerySyncStateContainer } = getQueryStateContainer( - data.query - ); const { appMounted, appUnMounted, stop: stopUrlTracker, setActiveUrl } = createKbnUrlTracker({ baseUrl: core.http.basePath.prepend('/app/kibana'), defaultSubUrl: '#/visualize', @@ -97,12 +95,19 @@ export class VisualizePlugin implements Plugin { stateParams: [ { kbnUrlKey: '_g', - stateUpdate$: querySyncStateContainer.state$, + stateUpdate$: data.query.state$.pipe( + filter( + ({ changes }) => !!(changes.globalFilters || changes.time || changes.refreshInterval) + ), + map(({ state }) => ({ + ...state, + filters: state.filters?.filter(esFilters.isFilterPinned), + })) + ), }, ], }); this.stopUrlTracking = () => { - stopQuerySyncStateContainer(); stopUrlTracker(); }; 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 cf8537ba7ab3e..75f48beb140a2 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 @@ -104,6 +104,7 @@ export const npSetup = { getProvider: sinon.fake(), }, query: { + state$: mockObservable(), filterManager: { getFetches$: sinon.fake(), getFilters: sinon.fake(), diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 978f140eb1d26..5dcf51ecc81eb 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -294,11 +294,11 @@ export { Filter, Query, RefreshInterval, TimeRange } from '../common'; export { createSavedQueryService, - syncAppFilters, - syncQuery, + connectToQueryState, + syncQueryStateWithUrl, + QueryState, getTime, getQueryLog, - getQueryStateContainer, FilterManager, SavedQuery, SavedQueryService, diff --git a/src/plugins/data/public/query/mocks.ts b/src/plugins/data/public/query/mocks.ts index 2710dadaa23a3..47b0a5b871ce2 100644 --- a/src/plugins/data/public/query/mocks.ts +++ b/src/plugins/data/public/query/mocks.ts @@ -17,7 +17,8 @@ * under the License. */ -import { QueryService, QuerySetup } from '.'; +import { Observable } from 'rxjs'; +import { QueryService, QuerySetup, QueryStart } from '.'; import { timefilterServiceMock } from './timefilter/timefilter_service.mock'; type QueryServiceClientContract = PublicMethodsOf; @@ -26,16 +27,18 @@ const createSetupContractMock = () => { const setupContract: jest.Mocked = { filterManager: jest.fn() as any, timefilter: timefilterServiceMock.createSetupContract(), + state$: new Observable(), }; return setupContract; }; const createStartContractMock = () => { - const startContract = { + const startContract: jest.Mocked = { filterManager: jest.fn() as any, timefilter: timefilterServiceMock.createStartContract(), savedQueries: jest.fn() as any, + state$: new Observable(), }; return startContract; diff --git a/src/plugins/data/public/query/query_service.ts b/src/plugins/data/public/query/query_service.ts index ebef8b8d45050..c885d596f1943 100644 --- a/src/plugins/data/public/query/query_service.ts +++ b/src/plugins/data/public/query/query_service.ts @@ -17,11 +17,13 @@ * under the License. */ +import { share } from 'rxjs/operators'; import { CoreStart } from 'src/core/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { FilterManager } from './filter_manager'; import { TimefilterService, TimefilterSetup } from './timefilter'; import { createSavedQueryService } from './saved_query/saved_query_service'; +import { createQueryStateObservable } from './state_sync/create_global_query_observable'; /** * Query Service @@ -36,6 +38,8 @@ export class QueryService { filterManager!: FilterManager; timefilter!: TimefilterSetup; + state$!: ReturnType; + public setup({ uiSettings, storage }: QueryServiceDependencies) { this.filterManager = new FilterManager(uiSettings); @@ -45,9 +49,15 @@ export class QueryService { storage, }); + this.state$ = createQueryStateObservable({ + filterManager: this.filterManager, + timefilter: this.timefilter, + }).pipe(share()); + return { filterManager: this.filterManager, timefilter: this.timefilter, + state$: this.state$, }; } @@ -55,6 +65,7 @@ export class QueryService { return { filterManager: this.filterManager, timefilter: this.timefilter, + state$: this.state$, savedQueries: createSavedQueryService(savedObjects.client), }; } diff --git a/src/plugins/data/public/query/state_sync/README.md b/src/plugins/data/public/query/state_sync/README.md new file mode 100644 index 0000000000000..6b9b158100573 --- /dev/null +++ b/src/plugins/data/public/query/state_sync/README.md @@ -0,0 +1,3 @@ +# Query state syncing utilities + +Set of helpers to connect data services to state containers and state syncing utilities diff --git a/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts b/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts new file mode 100644 index 0000000000000..5da929c441cde --- /dev/null +++ b/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts @@ -0,0 +1,465 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Subscription } from 'rxjs'; +import { FilterManager } from '../filter_manager'; +import { getFilter } from '../filter_manager/test_helpers/get_stub_filter'; +import { Filter, FilterStateStore } from '../../../common'; +import { coreMock } from '../../../../../core/public/mocks'; +import { BaseStateContainer, createStateContainer, Storage } from '../../../../kibana_utils/public'; +import { QueryService, QueryStart } from '../query_service'; +import { StubBrowserStorage } from '../../../../../test_utils/public/stub_browser_storage'; +import { connectToQueryState } from './connect_to_query_state'; +import { TimefilterContract } from '../timefilter'; +import { QueryState } from './types'; + +const connectToQueryGlobalState = (query: QueryStart, state: BaseStateContainer) => + connectToQueryState(query, state, { + refreshInterval: true, + time: true, + filters: FilterStateStore.GLOBAL_STATE, + }); + +const connectToQueryAppState = (query: QueryStart, state: BaseStateContainer) => + connectToQueryState(query, state, { + filters: FilterStateStore.APP_STATE, + }); + +const setupMock = coreMock.createSetup(); +const startMock = coreMock.createStart(); + +setupMock.uiSettings.get.mockImplementation((key: string) => { + switch (key) { + case 'filters:pinnedByDefault': + return true; + case 'timepicker:timeDefaults': + return { from: 'now-15m', to: 'now' }; + case 'timepicker:refreshIntervalDefaults': + return { pause: false, value: 0 }; + default: + throw new Error(`sync_query test: not mocked uiSetting: ${key}`); + } +}); + +describe('connect_to_global_state', () => { + let queryServiceStart: QueryStart; + let filterManager: FilterManager; + let timeFilter: TimefilterContract; + let globalState: BaseStateContainer; + let globalStateSub: Subscription; + let globalStateChangeTriggered = jest.fn(); + let filterManagerChangeSub: Subscription; + let filterManagerChangeTriggered = jest.fn(); + + let gF1: Filter; + let gF2: Filter; + let aF1: Filter; + let aF2: Filter; + + beforeEach(() => { + const queryService = new QueryService(); + queryService.setup({ + uiSettings: setupMock.uiSettings, + storage: new Storage(new StubBrowserStorage()), + }); + queryServiceStart = queryService.start(startMock.savedObjects); + filterManager = queryServiceStart.filterManager; + timeFilter = queryServiceStart.timefilter.timefilter; + + globalState = createStateContainer({}); + globalStateChangeTriggered = jest.fn(); + globalStateSub = globalState.state$.subscribe(globalStateChangeTriggered); + + filterManagerChangeTriggered = jest.fn(); + filterManagerChangeSub = filterManager.getUpdates$().subscribe(filterManagerChangeTriggered); + + gF1 = getFilter(FilterStateStore.GLOBAL_STATE, true, true, 'key1', 'value1'); + gF2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'key2', 'value2'); + aF1 = getFilter(FilterStateStore.APP_STATE, true, true, 'key3', 'value3'); + aF2 = getFilter(FilterStateStore.APP_STATE, false, false, 'key4', 'value4'); + }); + afterEach(() => { + globalStateSub.unsubscribe(); + filterManagerChangeSub.unsubscribe(); + }); + + test('state is initialized with state from query service', () => { + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + + expect(globalState.get()).toEqual({ + filters: filterManager.getGlobalFilters(), + refreshInterval: timeFilter.getRefreshInterval(), + time: timeFilter.getTime(), + }); + + stop(); + }); + + test('when time range changes, state container contains updated time range', () => { + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + timeFilter.setTime({ from: 'now-30m', to: 'now' }); + expect(globalState.get().time).toEqual({ + from: 'now-30m', + to: 'now', + }); + stop(); + }); + + test('when refresh interval changes, state container contains updated refresh interval', () => { + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + timeFilter.setRefreshInterval({ pause: true, value: 100 }); + expect(globalState.get().refreshInterval).toEqual({ + pause: true, + value: 100, + }); + stop(); + }); + + test('state changes should propagate to services', () => { + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + globalStateChangeTriggered.mockClear(); + globalState.set({ + ...globalState.get(), + filters: [gF1, gF2], + refreshInterval: { pause: true, value: 100 }, + time: { from: 'now-30m', to: 'now' }, + }); + + expect(globalStateChangeTriggered).toBeCalledTimes(1); + + expect(filterManager.getGlobalFilters()).toHaveLength(2); + expect(timeFilter.getRefreshInterval()).toEqual({ pause: true, value: 100 }); + expect(timeFilter.getTime()).toEqual({ from: 'now-30m', to: 'now' }); + stop(); + }); + + describe('sync from filterManager to global state', () => { + test('should sync global filters to global state when new global filters set to filterManager', () => { + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + + filterManager.setFilters([gF1, aF1]); + + expect(globalState.get().filters).toHaveLength(1); + stop(); + }); + + test('should not sync app filters to global state ', () => { + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + + filterManager.setFilters([aF1, aF2]); + + expect(globalState.get().filters).toHaveLength(0); + stop(); + }); + + test("should not trigger changes when global filters didn't change", () => { + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + globalStateChangeTriggered.mockClear(); + + filterManager.setFilters([gF1, aF1]); + filterManager.setFilters([gF1, aF2]); + + expect(globalStateChangeTriggered).toBeCalledTimes(1); + expect(globalState.get().filters).toHaveLength(1); + + stop(); + }); + + test('should trigger changes when global filters change', () => { + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + globalStateChangeTriggered.mockClear(); + + filterManager.setFilters([gF1, aF1]); + filterManager.setFilters([gF2, aF1]); + + expect(globalStateChangeTriggered).toBeCalledTimes(2); + expect(globalState.get().filters).toHaveLength(1); + + stop(); + }); + + test('resetting filters should sync to global state', () => { + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + + filterManager.setFilters([gF1, aF1]); + + expect(globalState.get().filters).toHaveLength(1); + + filterManager.removeAll(); + + expect(globalState.get().filters).toHaveLength(0); + + stop(); + }); + + test("shouldn't sync filters when syncing is stopped", () => { + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + + filterManager.setFilters([gF1, aF1]); + + expect(globalState.get().filters).toHaveLength(1); + + stop(); + + filterManager.removeAll(); + + expect(globalState.get().filters).toHaveLength(1); + }); + + test('should pick up initial state from filterManager', () => { + globalState.set({ filters: [gF1] }); + filterManager.setFilters([aF1]); + + globalStateChangeTriggered.mockClear(); + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + expect(globalStateChangeTriggered).toBeCalledTimes(1); + expect(globalState.get().filters).toHaveLength(0); + + stop(); + }); + }); + describe('sync from global state to filterManager', () => { + test('changes to global state should be synced to global filters', () => { + filterManager.setFilters([aF1]); + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + globalStateChangeTriggered.mockClear(); + + globalState.set({ ...globalState.get(), filters: [gF1] }); + + expect(filterManager.getFilters()).toHaveLength(2); + expect(filterManager.getAppFilters()).toHaveLength(1); + expect(filterManager.getGlobalFilters()).toHaveLength(1); + expect(globalStateChangeTriggered).toBeCalledTimes(1); + stop(); + }); + + test('app filters should remain untouched', () => { + filterManager.setFilters([gF1, gF2, aF1, aF2]); + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + globalStateChangeTriggered.mockClear(); + + globalState.set({ ...globalState.get(), filters: [] }); + + expect(filterManager.getFilters()).toHaveLength(2); + expect(filterManager.getAppFilters()).toHaveLength(2); + expect(filterManager.getGlobalFilters()).toHaveLength(0); + expect(globalStateChangeTriggered).toBeCalledTimes(1); + stop(); + }); + + test("if filters are not changed, filterManager shouldn't trigger update", () => { + filterManager.setFilters([gF1, gF2, aF1, aF2]); + filterManagerChangeTriggered.mockClear(); + + globalState.set({ ...globalState.get(), filters: [gF1, gF2] }); + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + globalState.set({ ...globalState.get(), filters: [gF1, gF2] }); + + expect(filterManagerChangeTriggered).toBeCalledTimes(0); + stop(); + }); + + test('stop() should stop syncing', () => { + filterManager.setFilters([gF1, gF2, aF1, aF2]); + const stop = connectToQueryGlobalState(queryServiceStart, globalState); + globalState.set({ ...globalState.get(), filters: [] }); + expect(filterManager.getFilters()).toHaveLength(2); + stop(); + globalState.set({ ...globalState.get(), filters: [gF1] }); + expect(filterManager.getFilters()).toHaveLength(2); + }); + }); +}); + +describe('connect_to_app_state', () => { + let queryServiceStart: QueryStart; + let filterManager: FilterManager; + let appState: BaseStateContainer; + let appStateSub: Subscription; + let appStateChangeTriggered = jest.fn(); + let filterManagerChangeSub: Subscription; + let filterManagerChangeTriggered = jest.fn(); + + let gF1: Filter; + let gF2: Filter; + let aF1: Filter; + let aF2: Filter; + + beforeEach(() => { + const queryService = new QueryService(); + queryService.setup({ + uiSettings: setupMock.uiSettings, + storage: new Storage(new StubBrowserStorage()), + }); + queryServiceStart = queryService.start(startMock.savedObjects); + filterManager = queryServiceStart.filterManager; + + appState = createStateContainer({}); + appStateChangeTriggered = jest.fn(); + appStateSub = appState.state$.subscribe(appStateChangeTriggered); + + filterManagerChangeTriggered = jest.fn(); + filterManagerChangeSub = filterManager.getUpdates$().subscribe(filterManagerChangeTriggered); + + gF1 = getFilter(FilterStateStore.GLOBAL_STATE, true, true, 'key1', 'value1'); + gF2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'key2', 'value2'); + aF1 = getFilter(FilterStateStore.APP_STATE, true, true, 'key3', 'value3'); + aF2 = getFilter(FilterStateStore.APP_STATE, false, false, 'key4', 'value4'); + }); + afterEach(() => { + appStateSub.unsubscribe(); + filterManagerChangeSub.unsubscribe(); + }); + + describe('sync from filterManager to app state', () => { + test('should sync app filters to app state when new app filters set to filterManager', () => { + const stop = connectToQueryAppState(queryServiceStart, appState); + + filterManager.setFilters([gF1, aF1]); + + expect(appState.get().filters).toHaveLength(1); + stop(); + }); + + test('should not sync global filters to app state ', () => { + const stop = connectToQueryAppState(queryServiceStart, appState); + + filterManager.setFilters([gF1, gF2]); + + expect(appState.get().filters).toHaveLength(0); + stop(); + }); + + test("should not trigger changes when app filters didn't change", () => { + const stop = connectToQueryAppState(queryServiceStart, appState); + appStateChangeTriggered.mockClear(); + + filterManager.setFilters([gF1, aF1]); + filterManager.setFilters([gF2, aF1]); + + expect(appStateChangeTriggered).toBeCalledTimes(1); + expect(appState.get().filters).toHaveLength(1); + + stop(); + }); + + test('should trigger changes when app filters change', () => { + const stop = connectToQueryAppState(queryServiceStart, appState); + appStateChangeTriggered.mockClear(); + + filterManager.setFilters([gF1, aF1]); + filterManager.setFilters([gF1, aF2]); + + expect(appStateChangeTriggered).toBeCalledTimes(2); + expect(appState.get().filters).toHaveLength(1); + + stop(); + }); + + test('resetting filters should sync to app state', () => { + const stop = connectToQueryAppState(queryServiceStart, appState); + + filterManager.setFilters([gF1, aF1]); + + expect(appState.get().filters).toHaveLength(1); + + filterManager.removeAll(); + + expect(appState.get().filters).toHaveLength(0); + + stop(); + }); + + test("shouldn't sync filters when syncing is stopped", () => { + const stop = connectToQueryAppState(queryServiceStart, appState); + + filterManager.setFilters([gF1, aF1]); + + expect(appState.get().filters).toHaveLength(1); + + stop(); + + filterManager.removeAll(); + + expect(appState.get().filters).toHaveLength(1); + }); + + test('should pick up initial state from filterManager', () => { + appState.set({ filters: [aF1] }); + filterManager.setFilters([gF1]); + + appStateChangeTriggered.mockClear(); + const stop = connectToQueryAppState(queryServiceStart, appState); + expect(appStateChangeTriggered).toBeCalledTimes(1); + expect(appState.get().filters).toHaveLength(0); + + stop(); + }); + }); + describe('sync from app state to filterManager', () => { + test('changes to app state should be synced to app filters', () => { + filterManager.setFilters([gF1]); + const stop = connectToQueryAppState(queryServiceStart, appState); + appStateChangeTriggered.mockClear(); + + appState.set({ filters: [aF1] }); + + expect(filterManager.getFilters()).toHaveLength(2); + expect(filterManager.getAppFilters()).toHaveLength(1); + expect(filterManager.getGlobalFilters()).toHaveLength(1); + expect(appStateChangeTriggered).toBeCalledTimes(1); + stop(); + }); + + test('global filters should remain untouched', () => { + filterManager.setFilters([gF1, gF2, aF1, aF2]); + const stop = connectToQueryAppState(queryServiceStart, appState); + appStateChangeTriggered.mockClear(); + + appState.set({ filters: [] }); + + expect(filterManager.getFilters()).toHaveLength(2); + expect(filterManager.getGlobalFilters()).toHaveLength(2); + expect(appStateChangeTriggered).toBeCalledTimes(1); + stop(); + }); + + test("if filters are not changed, filterManager shouldn't trigger update", () => { + filterManager.setFilters([gF1, gF2, aF1, aF2]); + filterManagerChangeTriggered.mockClear(); + + appState.set({ filters: [aF1, aF2] }); + const stop = connectToQueryAppState(queryServiceStart, appState); + appState.set({ filters: [aF1, aF2] }); + + expect(filterManagerChangeTriggered).toBeCalledTimes(0); + stop(); + }); + + test('stop() should stop syncing', () => { + filterManager.setFilters([gF1, gF2, aF1, aF2]); + const stop = connectToQueryAppState(queryServiceStart, appState); + appState.set({ filters: [] }); + expect(filterManager.getFilters()).toHaveLength(2); + stop(); + appState.set({ filters: [aF1] }); + expect(filterManager.getFilters()).toHaveLength(2); + }); + }); +}); diff --git a/src/plugins/data/public/query/state_sync/connect_to_query_state.ts b/src/plugins/data/public/query/state_sync/connect_to_query_state.ts new file mode 100644 index 0000000000000..a22e66860c765 --- /dev/null +++ b/src/plugins/data/public/query/state_sync/connect_to_query_state.ts @@ -0,0 +1,194 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Subscription } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; +import _ from 'lodash'; +import { BaseStateContainer } from '../../../../kibana_utils/public'; +import { COMPARE_ALL_OPTIONS, compareFilters } from '../filter_manager/lib/compare_filters'; +import { QuerySetup, QueryStart } from '../query_service'; +import { QueryState, QueryStateChange } from './types'; +import { FilterStateStore } from '../../../common/es_query/filters'; + +/** + * Helper to setup two-way syncing of global data and a state container + * @param QueryService: either setup or start + * @param stateContainer to use for syncing + */ +export const connectToQueryState = ( + { + timefilter: { timefilter }, + filterManager, + state$, + }: Pick, + stateContainer: BaseStateContainer, + syncConfig: { time?: boolean; refreshInterval?: boolean; filters?: FilterStateStore | boolean } +) => { + const syncKeys: Array = []; + if (syncConfig.time) { + syncKeys.push('time'); + } + if (syncConfig.refreshInterval) { + syncKeys.push('refreshInterval'); + } + if (syncConfig.filters) { + switch (syncConfig.filters) { + case true: + syncKeys.push('filters'); + break; + case FilterStateStore.APP_STATE: + syncKeys.push('appFilters'); + break; + case FilterStateStore.GLOBAL_STATE: + syncKeys.push('globalFilters'); + break; + } + } + + // initial syncing + // TODO: + // data services take precedence, this seems like a good default, + // and apps could anyway set their own value after initialisation, + // but maybe maybe this should be a configurable option? + const initialState: QueryState = { ...stateContainer.get() }; + let initialDirty = false; + if (syncConfig.time && !_.isEqual(initialState.time, timefilter.getTime())) { + initialState.time = timefilter.getTime(); + initialDirty = true; + } + if ( + syncConfig.refreshInterval && + !_.isEqual(initialState.refreshInterval, timefilter.getRefreshInterval()) + ) { + initialState.refreshInterval = timefilter.getRefreshInterval(); + initialDirty = true; + } + + if (syncConfig.filters) { + if (syncConfig.filters === true) { + if ( + !initialState.filters || + !compareFilters(initialState.filters, filterManager.getFilters(), COMPARE_ALL_OPTIONS) + ) { + initialState.filters = filterManager.getFilters(); + initialDirty = true; + } + } else if (syncConfig.filters === FilterStateStore.GLOBAL_STATE) { + if ( + !initialState.filters || + !compareFilters(initialState.filters, filterManager.getGlobalFilters(), COMPARE_ALL_OPTIONS) + ) { + initialState.filters = filterManager.getGlobalFilters(); + initialDirty = true; + } + } else if (syncConfig.filters === FilterStateStore.APP_STATE) { + if ( + !initialState.filters || + !compareFilters(initialState.filters, filterManager.getAppFilters(), COMPARE_ALL_OPTIONS) + ) { + initialState.filters = filterManager.getAppFilters(); + initialDirty = true; + } + } + } + + if (initialDirty) { + stateContainer.set({ ...stateContainer.get(), ...initialState }); + } + + // to ignore own state updates + let updateInProgress = false; + + const subs: Subscription[] = [ + state$ + .pipe( + filter(({ changes, state }) => { + if (updateInProgress) return false; + return syncKeys.some(syncKey => changes[syncKey]); + }), + map(({ changes }) => { + const newState: QueryState = {}; + if (syncConfig.time && changes.time) { + newState.time = timefilter.getTime(); + } + if (syncConfig.refreshInterval && changes.refreshInterval) { + newState.refreshInterval = timefilter.getRefreshInterval(); + } + if (syncConfig.filters) { + if (syncConfig.filters === true && changes.filters) { + newState.filters = filterManager.getFilters(); + } else if ( + syncConfig.filters === FilterStateStore.GLOBAL_STATE && + changes.globalFilters + ) { + newState.filters = filterManager.getGlobalFilters(); + } else if (syncConfig.filters === FilterStateStore.APP_STATE && changes.appFilters) { + newState.filters = filterManager.getAppFilters(); + } + } + return newState; + }) + ) + .subscribe(newState => { + stateContainer.set({ ...stateContainer.get(), ...newState }); + }), + stateContainer.state$.subscribe(state => { + updateInProgress = true; + + // cloneDeep is required because services are mutating passed objects + // and state in state container is frozen + if (syncConfig.time) { + const time = state.time || timefilter.getTimeDefaults(); + if (!_.isEqual(time, timefilter.getTime())) { + timefilter.setTime(_.cloneDeep(time)); + } + } + + if (syncConfig.refreshInterval) { + const refreshInterval = state.refreshInterval || timefilter.getRefreshIntervalDefaults(); + if (!_.isEqual(refreshInterval, timefilter.getRefreshInterval())) { + timefilter.setRefreshInterval(_.cloneDeep(refreshInterval)); + } + } + + if (syncConfig.filters) { + const filters = state.filters || []; + if (syncConfig.filters === true) { + if (!compareFilters(filters, filterManager.getFilters(), COMPARE_ALL_OPTIONS)) { + filterManager.setFilters(_.cloneDeep(filters)); + } + } else if (syncConfig.filters === FilterStateStore.APP_STATE) { + if (!compareFilters(filters, filterManager.getAppFilters(), COMPARE_ALL_OPTIONS)) { + filterManager.setAppFilters(_.cloneDeep(filters)); + } + } else if (syncConfig.filters === FilterStateStore.GLOBAL_STATE) { + if (!compareFilters(filters, filterManager.getGlobalFilters(), COMPARE_ALL_OPTIONS)) { + filterManager.setGlobalFilters(_.cloneDeep(filters)); + } + } + } + + updateInProgress = false; + }), + ]; + + return () => { + subs.forEach(s => s.unsubscribe()); + }; +}; diff --git a/src/plugins/data/public/query/state_sync/create_global_query_observable.ts b/src/plugins/data/public/query/state_sync/create_global_query_observable.ts new file mode 100644 index 0000000000000..d0d97bfaaeb36 --- /dev/null +++ b/src/plugins/data/public/query/state_sync/create_global_query_observable.ts @@ -0,0 +1,87 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Observable, Subscription } from 'rxjs'; +import { map, tap } from 'rxjs/operators'; +import { TimefilterSetup } from '../timefilter'; +import { COMPARE_ALL_OPTIONS, compareFilters, FilterManager } from '../filter_manager'; +import { QueryState, QueryStateChange } from './index'; +import { createStateContainer } from '../../../../kibana_utils/public'; +import { isFilterPinned } from '../../../common/es_query/filters'; + +export function createQueryStateObservable({ + timefilter: { timefilter }, + filterManager, +}: { + timefilter: TimefilterSetup; + filterManager: FilterManager; +}): Observable<{ changes: QueryStateChange; state: QueryState }> { + return new Observable(subscriber => { + const state = createStateContainer({ + time: timefilter.getTime(), + refreshInterval: timefilter.getRefreshInterval(), + filters: filterManager.getFilters(), + }); + + let currentChange: QueryStateChange = {}; + const subs: Subscription[] = [ + timefilter.getTimeUpdate$().subscribe(() => { + currentChange.time = true; + state.set({ ...state.get(), time: timefilter.getTime() }); + }), + timefilter.getRefreshIntervalUpdate$().subscribe(() => { + currentChange.refreshInterval = true; + state.set({ ...state.get(), refreshInterval: timefilter.getRefreshInterval() }); + }), + filterManager.getUpdates$().subscribe(() => { + currentChange.filters = true; + + const { filters } = state.get(); + const globalOld = filters?.filter(f => isFilterPinned(f)); + const appOld = filters?.filter(f => !isFilterPinned(f)); + const globalNew = filterManager.getGlobalFilters(); + const appNew = filterManager.getAppFilters(); + + if (!globalOld || !compareFilters(globalOld, globalNew, COMPARE_ALL_OPTIONS)) { + currentChange.globalFilters = true; + } + + if (!appOld || !compareFilters(appOld, appNew, COMPARE_ALL_OPTIONS)) { + currentChange.appFilters = true; + } + + state.set({ + ...state.get(), + filters: filterManager.getFilters(), + }); + }), + state.state$ + .pipe( + map(newState => ({ state: newState, changes: currentChange })), + tap(() => { + currentChange = {}; + }) + ) + .subscribe(subscriber), + ]; + return () => { + subs.forEach(s => s.unsubscribe()); + }; + }); +} diff --git a/src/plugins/data/public/query/state_sync/index.ts b/src/plugins/data/public/query/state_sync/index.ts index 27e02940765cf..e1a3561e022db 100644 --- a/src/plugins/data/public/query/state_sync/index.ts +++ b/src/plugins/data/public/query/state_sync/index.ts @@ -17,5 +17,6 @@ * under the License. */ -export { syncQuery, getQueryStateContainer } from './sync_query'; -export { syncAppFilters } from './sync_app_filters'; +export { connectToQueryState } from './connect_to_query_state'; +export { syncQueryStateWithUrl } from './sync_state_with_url'; +export { QueryState, QueryStateChange } from './types'; diff --git a/src/plugins/data/public/query/state_sync/sync_app_filters.test.ts b/src/plugins/data/public/query/state_sync/sync_app_filters.test.ts deleted file mode 100644 index e01547b1c0fd8..0000000000000 --- a/src/plugins/data/public/query/state_sync/sync_app_filters.test.ts +++ /dev/null @@ -1,197 +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 { Subscription } from 'rxjs'; -import { FilterManager } from '../filter_manager'; -import { getFilter } from '../filter_manager/test_helpers/get_stub_filter'; -import { Filter, FilterStateStore } from '../../../common'; -import { syncAppFilters } from './sync_app_filters'; -import { coreMock } from '../../../../../core/public/mocks'; -import { BaseStateContainer, createStateContainer } from '../../../../kibana_utils/public'; - -const setupMock = coreMock.createSetup(); - -setupMock.uiSettings.get.mockImplementation((key: string) => { - return true; -}); - -describe('sync_app_filters', () => { - let filterManager: FilterManager; - let appState: BaseStateContainer; - let appStateSub: Subscription; - let appStateChangeTriggered = jest.fn(); - let filterManagerChangeSub: Subscription; - let filterManagerChangeTriggered = jest.fn(); - - let gF1: Filter; - let gF2: Filter; - let aF1: Filter; - let aF2: Filter; - - beforeEach(() => { - filterManager = new FilterManager(setupMock.uiSettings); - appState = createStateContainer([] as Filter[]); - appStateChangeTriggered = jest.fn(); - appStateSub = appState.state$.subscribe(appStateChangeTriggered); - - filterManagerChangeTriggered = jest.fn(); - filterManagerChangeSub = filterManager.getUpdates$().subscribe(filterManagerChangeTriggered); - - gF1 = getFilter(FilterStateStore.GLOBAL_STATE, true, true, 'key1', 'value1'); - gF2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'key2', 'value2'); - aF1 = getFilter(FilterStateStore.APP_STATE, true, true, 'key3', 'value3'); - aF2 = getFilter(FilterStateStore.APP_STATE, false, false, 'key4', 'value4'); - }); - afterEach(() => { - appStateSub.unsubscribe(); - filterManagerChangeSub.unsubscribe(); - }); - - describe('sync from filterManager to app state', () => { - test('should sync app filters to app state when new app filters set to filterManager', () => { - const stop = syncAppFilters(filterManager, appState); - - filterManager.setFilters([gF1, aF1]); - - expect(appState.get()).toHaveLength(1); - stop(); - }); - - test('should not sync global filters to app state ', () => { - const stop = syncAppFilters(filterManager, appState); - - filterManager.setFilters([gF1, gF2]); - - expect(appState.get()).toHaveLength(0); - stop(); - }); - - test("should not trigger changes when app filters didn't change", () => { - const stop = syncAppFilters(filterManager, appState); - - filterManager.setFilters([gF1, aF1]); - - filterManager.setFilters([gF2, aF1]); - - expect(appStateChangeTriggered).toBeCalledTimes(1); - expect(appState.get()).toHaveLength(1); - - stop(); - }); - - test('should trigger changes when app filters change', () => { - const stop = syncAppFilters(filterManager, appState); - - filterManager.setFilters([gF1, aF1]); - filterManager.setFilters([gF1, aF2]); - - expect(appStateChangeTriggered).toBeCalledTimes(2); - expect(appState.get()).toHaveLength(1); - - stop(); - }); - - test('resetting filters should sync to app state', () => { - const stop = syncAppFilters(filterManager, appState); - - filterManager.setFilters([gF1, aF1]); - - expect(appState.get()).toHaveLength(1); - - filterManager.removeAll(); - - expect(appState.get()).toHaveLength(0); - - stop(); - }); - - test("shouldn't sync filters when syncing is stopped", () => { - const stop = syncAppFilters(filterManager, appState); - - filterManager.setFilters([gF1, aF1]); - - expect(appState.get()).toHaveLength(1); - - stop(); - - filterManager.removeAll(); - - expect(appState.get()).toHaveLength(1); - }); - }); - describe('sync from app state to filterManager', () => { - test('should pick up initial state from app state', () => { - appState.set([aF1]); - filterManager.setFilters([gF1]); - - const stop = syncAppFilters(filterManager, appState); - expect(filterManager.getFilters()).toHaveLength(2); - expect(appStateChangeTriggered).toBeCalledTimes(1); - - stop(); - }); - - test('changes to app state should be synced to app filters', () => { - filterManager.setFilters([gF1]); - const stop = syncAppFilters(filterManager, appState); - - appState.set([aF1]); - - expect(filterManager.getFilters()).toHaveLength(2); - expect(filterManager.getAppFilters()).toHaveLength(1); - expect(filterManager.getGlobalFilters()).toHaveLength(1); - expect(appStateChangeTriggered).toBeCalledTimes(1); - stop(); - }); - - test('global filters should remain untouched', () => { - filterManager.setFilters([gF1, gF2, aF1, aF2]); - const stop = syncAppFilters(filterManager, appState); - - appState.set([]); - - expect(filterManager.getFilters()).toHaveLength(2); - expect(filterManager.getGlobalFilters()).toHaveLength(2); - expect(appStateChangeTriggered).toBeCalledTimes(1); - stop(); - }); - - test("if filters are not changed, filterManager shouldn't trigger update", () => { - filterManager.setFilters([gF1, gF2, aF1, aF2]); - filterManagerChangeTriggered.mockClear(); - - appState.set([aF1, aF2]); - const stop = syncAppFilters(filterManager, appState); - appState.set([aF1, aF2]); - - expect(filterManagerChangeTriggered).toBeCalledTimes(0); - stop(); - }); - - test('stop() should stop syncing', () => { - filterManager.setFilters([gF1, gF2, aF1, aF2]); - const stop = syncAppFilters(filterManager, appState); - appState.set([]); - expect(filterManager.getFilters()).toHaveLength(2); - stop(); - appState.set([aF1]); - expect(filterManager.getFilters()).toHaveLength(2); - }); - }); -}); diff --git a/src/plugins/data/public/query/state_sync/sync_app_filters.ts b/src/plugins/data/public/query/state_sync/sync_app_filters.ts deleted file mode 100644 index d9956fcc0f6ae..0000000000000 --- a/src/plugins/data/public/query/state_sync/sync_app_filters.ts +++ /dev/null @@ -1,65 +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 { filter, map } from 'rxjs/operators'; -import { COMPARE_ALL_OPTIONS, compareFilters } from '../filter_manager/lib/compare_filters'; -import { Filter } from '../../../common'; -import { FilterManager } from '../filter_manager'; -import { BaseStateContainer } from '../../../../../plugins/kibana_utils/public'; - -/** - * Helper utility to sync application's state filters, with filter manager - * @param filterManager - * @param appState - */ -export function syncAppFilters( - filterManager: FilterManager, - appState: BaseStateContainer -) { - // make sure initial app filters are picked by filterManager - filterManager.setAppFilters(_.cloneDeep(appState.get())); - - const subs = [ - filterManager - .getUpdates$() - .pipe( - map(() => filterManager.getAppFilters()), - filter( - // continue only if app state filters updated - appFilters => !compareFilters(appFilters, appState.get(), COMPARE_ALL_OPTIONS) - ) - ) - .subscribe(appFilters => { - appState.set(appFilters); - }), - - // if appFilters in dashboardStateManager changed (e.g browser history update), - // sync it to filterManager - appState.state$.subscribe(() => { - if (!compareFilters(appState.get(), filterManager.getAppFilters(), COMPARE_ALL_OPTIONS)) { - filterManager.setAppFilters(_.cloneDeep(appState.get())); - } - }), - ]; - - return () => { - subs.forEach(s => s.unsubscribe()); - }; -} diff --git a/src/plugins/data/public/query/state_sync/sync_query.ts b/src/plugins/data/public/query/state_sync/sync_query.ts deleted file mode 100644 index 373f9aa0a5668..0000000000000 --- a/src/plugins/data/public/query/state_sync/sync_query.ts +++ /dev/null @@ -1,188 +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 { Subscription } from 'rxjs'; -import _ from 'lodash'; -import { filter, map } from 'rxjs/operators'; -import { - createStateContainer, - IKbnUrlStateStorage, - syncState, -} from '../../../../kibana_utils/public'; -import { COMPARE_ALL_OPTIONS, compareFilters } from '../filter_manager/lib/compare_filters'; -import { Filter, RefreshInterval, TimeRange } from '../../../common'; -import { QuerySetup, QueryStart } from '../query_service'; - -const GLOBAL_STATE_STORAGE_KEY = '_g'; - -export interface QuerySyncState { - time?: TimeRange; - refreshInterval?: RefreshInterval; - filters?: Filter[]; -} - -/** - * Helper utility to set up syncing between query services and url's '_g' query param - */ -export const syncQuery = (queryStart: QueryStart, urlStateStorage: IKbnUrlStateStorage) => { - const { - timefilter: { timefilter }, - filterManager, - } = queryStart; - // retrieve current state from `_g` url - const initialStateFromUrl = urlStateStorage.get(GLOBAL_STATE_STORAGE_KEY); - - // remember whether there were info in the URL - const hasInheritedQueryFromUrl = Boolean( - initialStateFromUrl && Object.keys(initialStateFromUrl).length - ); - - const { - querySyncStateContainer, - stop: stopPullQueryState, - initialState, - } = getQueryStateContainer(queryStart, initialStateFromUrl || {}); - - const pushQueryStateSubscription = querySyncStateContainer.state$.subscribe( - ({ time, filters: globalFilters, refreshInterval }) => { - // cloneDeep is required because services are mutating passed objects - // and state in state container is frozen - if (time && !_.isEqual(time, timefilter.getTime())) { - timefilter.setTime(_.cloneDeep(time)); - } - - if (refreshInterval && !_.isEqual(refreshInterval, timefilter.getRefreshInterval())) { - timefilter.setRefreshInterval(_.cloneDeep(refreshInterval)); - } - - if ( - globalFilters && - !compareFilters(globalFilters, filterManager.getGlobalFilters(), COMPARE_ALL_OPTIONS) - ) { - filterManager.setGlobalFilters(_.cloneDeep(globalFilters)); - } - } - ); - - // if there weren't any initial state in url, - // then put _g key into url - if (!initialStateFromUrl) { - urlStateStorage.set(GLOBAL_STATE_STORAGE_KEY, initialState, { - replace: true, - }); - } - - // trigger initial syncing from state container to services if needed - querySyncStateContainer.set(initialState); - - const { start, stop: stopSyncState } = syncState({ - stateStorage: urlStateStorage, - stateContainer: { - ...querySyncStateContainer, - set: state => { - if (state) { - // syncState utils requires to handle incoming "null" value - querySyncStateContainer.set(state); - } - }, - }, - storageKey: GLOBAL_STATE_STORAGE_KEY, - }); - - start(); - return { - stop: () => { - stopSyncState(); - pushQueryStateSubscription.unsubscribe(); - stopPullQueryState(); - }, - hasInheritedQueryFromUrl, - }; -}; - -export const getQueryStateContainer = ( - { timefilter: { timefilter }, filterManager }: QuerySetup, - initialStateOverrides: Partial = {} -) => { - const defaultState: QuerySyncState = { - time: timefilter.getTime(), - refreshInterval: timefilter.getRefreshInterval(), - filters: filterManager.getGlobalFilters(), - }; - - const initialState: QuerySyncState = { - ...defaultState, - ...initialStateOverrides, - }; - - // create state container, which will be used for syncing with syncState() util - const querySyncStateContainer = createStateContainer( - initialState, - { - setTime: (state: QuerySyncState) => (time: TimeRange) => ({ ...state, time }), - setRefreshInterval: (state: QuerySyncState) => (refreshInterval: RefreshInterval) => ({ - ...state, - refreshInterval, - }), - setFilters: (state: QuerySyncState) => (filters: Filter[]) => ({ - ...state, - filters, - }), - }, - { - time: (state: QuerySyncState) => () => state.time, - refreshInterval: (state: QuerySyncState) => () => state.refreshInterval, - filters: (state: QuerySyncState) => () => state.filters, - } - ); - - const subs: Subscription[] = [ - timefilter.getTimeUpdate$().subscribe(() => { - querySyncStateContainer.transitions.setTime(timefilter.getTime()); - }), - timefilter.getRefreshIntervalUpdate$().subscribe(() => { - querySyncStateContainer.transitions.setRefreshInterval(timefilter.getRefreshInterval()); - }), - filterManager - .getUpdates$() - .pipe( - map(() => filterManager.getGlobalFilters()), // we need to track only global filters here - filter(newGlobalFilters => { - // continue only if global filters changed - // and ignore app state filters - const oldGlobalFilters = querySyncStateContainer.get().filters; - return ( - !oldGlobalFilters || - !compareFilters(newGlobalFilters, oldGlobalFilters, COMPARE_ALL_OPTIONS) - ); - }) - ) - .subscribe(newGlobalFilters => { - querySyncStateContainer.transitions.setFilters(newGlobalFilters); - }), - ]; - - return { - querySyncStateContainer, - stop: () => { - subs.forEach(s => s.unsubscribe()); - }, - initialState, - }; -}; diff --git a/src/plugins/data/public/query/state_sync/sync_query.test.ts b/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts similarity index 63% rename from src/plugins/data/public/query/state_sync/sync_query.test.ts rename to src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts index 1e7db2b9fd22f..50dc35ea955ee 100644 --- a/src/plugins/data/public/query/state_sync/sync_query.test.ts +++ b/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts @@ -31,7 +31,8 @@ import { import { QueryService, QueryStart } from '../query_service'; import { StubBrowserStorage } from 'test_utils/stub_browser_storage'; import { TimefilterContract } from '../timefilter'; -import { getQueryStateContainer, QuerySyncState, syncQuery } from './sync_query'; +import { syncQueryStateWithUrl } from './sync_state_with_url'; +import { QueryState } from './types'; const setupMock = coreMock.createSetup(); const startMock = coreMock.createStart(); @@ -49,7 +50,7 @@ setupMock.uiSettings.get.mockImplementation((key: string) => { } }); -describe('sync_query', () => { +describe('sync_query_state_with_url', () => { let queryServiceStart: QueryStart; let filterManager: FilterManager; let timefilter: TimefilterContract; @@ -90,7 +91,7 @@ describe('sync_query', () => { }); test('url is actually changed when data in services changes', () => { - const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + const { stop } = syncQueryStateWithUrl(queryServiceStart, kbnUrlStateStorage); filterManager.setFilters([gF, aF]); kbnUrlStateStorage.flush(); // sync force location change expect(history.location.hash).toMatchInlineSnapshot( @@ -100,16 +101,16 @@ describe('sync_query', () => { }); test('when filters change, global filters synced to urlStorage', () => { - const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + const { stop } = syncQueryStateWithUrl(queryServiceStart, kbnUrlStateStorage); filterManager.setFilters([gF, aF]); - expect(kbnUrlStateStorage.get('_g')?.filters).toHaveLength(1); + expect(kbnUrlStateStorage.get('_g')?.filters).toHaveLength(1); stop(); }); test('when time range changes, time synced to urlStorage', () => { - const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + const { stop } = syncQueryStateWithUrl(queryServiceStart, kbnUrlStateStorage); timefilter.setTime({ from: 'now-30m', to: 'now' }); - expect(kbnUrlStateStorage.get('_g')?.time).toEqual({ + expect(kbnUrlStateStorage.get('_g')?.time).toEqual({ from: 'now-30m', to: 'now', }); @@ -117,9 +118,9 @@ describe('sync_query', () => { }); test('when refresh interval changes, refresh interval is synced to urlStorage', () => { - const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + const { stop } = syncQueryStateWithUrl(queryServiceStart, kbnUrlStateStorage); timefilter.setRefreshInterval({ pause: true, value: 100 }); - expect(kbnUrlStateStorage.get('_g')?.refreshInterval).toEqual({ + expect(kbnUrlStateStorage.get('_g')?.refreshInterval).toEqual({ pause: true, value: 100, }); @@ -127,7 +128,7 @@ describe('sync_query', () => { }); test('when url is changed, filters synced back to filterManager', () => { - const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + const { stop } = syncQueryStateWithUrl(queryServiceStart, kbnUrlStateStorage); kbnUrlStateStorage.cancel(); // stop initial syncing pending update history.push(pathWithFilter); expect(filterManager.getGlobalFilters()).toHaveLength(1); @@ -137,14 +138,17 @@ describe('sync_query', () => { test('initial url should be synced with services', () => { history.push(pathWithFilter); - const { stop, hasInheritedQueryFromUrl } = syncQuery(queryServiceStart, kbnUrlStateStorage); + const { stop, hasInheritedQueryFromUrl } = syncQueryStateWithUrl( + queryServiceStart, + kbnUrlStateStorage + ); expect(hasInheritedQueryFromUrl).toBe(true); expect(filterManager.getGlobalFilters()).toHaveLength(1); stop(); }); test("url changes shouldn't trigger services updates if data didn't change", () => { - const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + const { stop } = syncQueryStateWithUrl(queryServiceStart, kbnUrlStateStorage); filterManagerChangeTriggered.mockClear(); history.push(pathWithFilter); @@ -156,76 +160,11 @@ describe('sync_query', () => { }); test("if data didn't change, kbnUrlStateStorage.set shouldn't be called", () => { - const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + const { stop } = syncQueryStateWithUrl(queryServiceStart, kbnUrlStateStorage); filterManager.setFilters([gF, aF]); const spy = jest.spyOn(kbnUrlStateStorage, 'set'); filterManager.setFilters([gF]); // global filters didn't change expect(spy).not.toBeCalled(); stop(); }); - - describe('getQueryStateContainer', () => { - test('state is initialized with state from query service', () => { - const { stop, querySyncStateContainer, initialState } = getQueryStateContainer( - queryServiceStart - ); - expect(querySyncStateContainer.getState()).toMatchInlineSnapshot(` - Object { - "filters": Array [], - "refreshInterval": Object { - "pause": true, - "value": 0, - }, - "time": Object { - "from": "now-15m", - "to": "now", - }, - } - `); - expect(initialState).toEqual(querySyncStateContainer.getState()); - stop(); - }); - - test('state takes initial overrides into account', () => { - const { stop, querySyncStateContainer, initialState } = getQueryStateContainer( - queryServiceStart, - { - time: { from: 'now-99d', to: 'now' }, - } - ); - expect(querySyncStateContainer.getState().time).toEqual({ - from: 'now-99d', - to: 'now', - }); - expect(initialState).toEqual(querySyncStateContainer.getState()); - stop(); - }); - - test('when filters change, state container contains updated global filters', () => { - const { stop, querySyncStateContainer } = getQueryStateContainer(queryServiceStart); - filterManager.setFilters([gF, aF]); - expect(querySyncStateContainer.getState().filters).toHaveLength(1); - stop(); - }); - - test('when time range changes, state container contains updated time range', () => { - const { stop, querySyncStateContainer } = getQueryStateContainer(queryServiceStart); - timefilter.setTime({ from: 'now-30m', to: 'now' }); - expect(querySyncStateContainer.getState().time).toEqual({ - from: 'now-30m', - to: 'now', - }); - stop(); - }); - - test('when refresh interval changes, state container contains updated refresh interval', () => { - const { stop, querySyncStateContainer } = getQueryStateContainer(queryServiceStart); - timefilter.setRefreshInterval({ pause: true, value: 100 }); - expect(querySyncStateContainer.getState().refreshInterval).toEqual({ - pause: true, - value: 100, - }); - stop(); - }); - }); }); diff --git a/src/plugins/data/public/query/state_sync/sync_state_with_url.ts b/src/plugins/data/public/query/state_sync/sync_state_with_url.ts new file mode 100644 index 0000000000000..cd7058b9f8f1c --- /dev/null +++ b/src/plugins/data/public/query/state_sync/sync_state_with_url.ts @@ -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. + */ + +import { + createStateContainer, + IKbnUrlStateStorage, + syncState, +} from '../../../../kibana_utils/public'; +import { QuerySetup, QueryStart } from '../query_service'; +import { connectToQueryState } from './connect_to_query_state'; +import { QueryState } from './types'; +import { FilterStateStore } from '../../../common/es_query/filters'; + +const GLOBAL_STATE_STORAGE_KEY = '_g'; + +/** + * Helper to setup syncing of global data with the URL + * @param QueryService: either setup or start + * @param kbnUrlStateStorage to use for syncing + */ +export const syncQueryStateWithUrl = ( + query: Pick, + kbnUrlStateStorage: IKbnUrlStateStorage +) => { + const { + timefilter: { timefilter }, + filterManager, + } = query; + const defaultState: QueryState = { + time: timefilter.getTime(), + refreshInterval: timefilter.getRefreshInterval(), + filters: filterManager.getGlobalFilters(), + }; + + // retrieve current state from `_g` url + const initialStateFromUrl = kbnUrlStateStorage.get(GLOBAL_STATE_STORAGE_KEY); + + // remember whether there was info in the URL + const hasInheritedQueryFromUrl = Boolean( + initialStateFromUrl && Object.keys(initialStateFromUrl).length + ); + + // prepare initial state, whatever was in URL takes precedences over current state in services + const initialState: QueryState = { + ...defaultState, + ...initialStateFromUrl, + }; + + const globalQueryStateContainer = createStateContainer(initialState); + const stopSyncingWithStateContainer = connectToQueryState(query, globalQueryStateContainer, { + refreshInterval: true, + time: true, + filters: FilterStateStore.GLOBAL_STATE, + }); + + // if there weren't any initial state in url, + // then put _g key into url + if (!initialStateFromUrl) { + kbnUrlStateStorage.set(GLOBAL_STATE_STORAGE_KEY, initialState, { + replace: true, + }); + } + + // trigger initial syncing from state container to services if needed + globalQueryStateContainer.set(initialState); + + const { start, stop: stopSyncingWithUrl } = syncState({ + stateStorage: kbnUrlStateStorage, + stateContainer: { + ...globalQueryStateContainer, + set: state => { + globalQueryStateContainer.set(state || defaultState); + }, + }, + storageKey: GLOBAL_STATE_STORAGE_KEY, + }); + + start(); + return { + stop: () => { + stopSyncingWithStateContainer(); + stopSyncingWithUrl(); + }, + hasInheritedQueryFromUrl, + }; +}; diff --git a/src/plugins/data/public/query/state_sync/types.ts b/src/plugins/data/public/query/state_sync/types.ts new file mode 100644 index 0000000000000..747d4d45fe29b --- /dev/null +++ b/src/plugins/data/public/query/state_sync/types.ts @@ -0,0 +1,38 @@ +/* + * 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 { Filter, RefreshInterval, TimeRange } from '../../../common'; + +/** + * All query state service state + */ +export interface QueryState { + time?: TimeRange; + refreshInterval?: RefreshInterval; + filters?: Filter[]; +} + +type QueryStateChangePartial = { + [P in keyof QueryState]?: boolean; +}; + +export interface QueryStateChange extends QueryStateChangePartial { + appFilters?: boolean; // specifies if app filters change + globalFilters?: boolean; // specifies if global filters change +} diff --git a/src/plugins/data/public/query/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts index 58806a9328b1c..4fbdac47fb3b0 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.ts @@ -50,8 +50,13 @@ export class Timefilter { private _autoRefreshIntervalId: number = 0; + private readonly timeDefaults: TimeRange; + private readonly refreshIntervalDefaults: RefreshInterval; + constructor(config: TimefilterConfig, timeHistory: TimeHistoryContract) { this._history = timeHistory; + this.timeDefaults = config.timeDefaults; + this.refreshIntervalDefaults = config.refreshIntervalDefaults; this._time = config.timeDefaults; this.setRefreshInterval(config.refreshIntervalDefaults); } @@ -208,6 +213,14 @@ export class Timefilter { this.enabledUpdated$.next(false); }; + public getTimeDefaults(): TimeRange { + return _.cloneDeep(this.timeDefaults); + } + + public getRefreshIntervalDefaults(): RefreshInterval { + return _.cloneDeep(this.refreshIntervalDefaults); + } + private getForceNow = () => { const forceNow = parseQueryString().forceNow as string; if (!forceNow) { diff --git a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts index 80c13464ad98a..7863000b1ace4 100644 --- a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts +++ b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts @@ -43,6 +43,8 @@ const createSetupContractMock = () => { getBounds: jest.fn(), calculateBounds: jest.fn(), createFilter: jest.fn(), + getRefreshIntervalDefaults: jest.fn(), + getTimeDefaults: jest.fn(), }; const historyMock: jest.Mocked = { diff --git a/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap b/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap index b411d27a2a965..58f00ff9ed657 100644 --- a/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap +++ b/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap @@ -197,6 +197,9 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA "query": Object { "filterManager": [MockFunction], "savedQueries": [MockFunction], + "state$": Observable { + "_isScalar": false, + }, "timefilter": Object { "history": Object { "add": [MockFunction], @@ -215,8 +218,10 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA "getEnabledUpdated$": [MockFunction], "getFetch$": [MockFunction], "getRefreshInterval": [MockFunction], + "getRefreshIntervalDefaults": [MockFunction], "getRefreshIntervalUpdate$": [MockFunction], "getTime": [MockFunction], + "getTimeDefaults": [MockFunction], "getTimeUpdate$": [MockFunction], "isAutoRefreshSelectorEnabled": [MockFunction], "isTimeRangeSelectorEnabled": [MockFunction], @@ -855,6 +860,9 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA "query": Object { "filterManager": [MockFunction], "savedQueries": [MockFunction], + "state$": Observable { + "_isScalar": false, + }, "timefilter": Object { "history": Object { "add": [MockFunction], @@ -873,8 +881,10 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA "getEnabledUpdated$": [MockFunction], "getFetch$": [MockFunction], "getRefreshInterval": [MockFunction], + "getRefreshIntervalDefaults": [MockFunction], "getRefreshIntervalUpdate$": [MockFunction], "getTime": [MockFunction], + "getTimeDefaults": [MockFunction], "getTimeUpdate$": [MockFunction], "isAutoRefreshSelectorEnabled": [MockFunction], "isTimeRangeSelectorEnabled": [MockFunction], @@ -1495,6 +1505,9 @@ exports[`QueryStringInput Should pass the query language to the language switche "query": Object { "filterManager": [MockFunction], "savedQueries": [MockFunction], + "state$": Observable { + "_isScalar": false, + }, "timefilter": Object { "history": Object { "add": [MockFunction], @@ -1513,8 +1526,10 @@ exports[`QueryStringInput Should pass the query language to the language switche "getEnabledUpdated$": [MockFunction], "getFetch$": [MockFunction], "getRefreshInterval": [MockFunction], + "getRefreshIntervalDefaults": [MockFunction], "getRefreshIntervalUpdate$": [MockFunction], "getTime": [MockFunction], + "getTimeDefaults": [MockFunction], "getTimeUpdate$": [MockFunction], "isAutoRefreshSelectorEnabled": [MockFunction], "isTimeRangeSelectorEnabled": [MockFunction], @@ -2150,6 +2165,9 @@ exports[`QueryStringInput Should pass the query language to the language switche "query": Object { "filterManager": [MockFunction], "savedQueries": [MockFunction], + "state$": Observable { + "_isScalar": false, + }, "timefilter": Object { "history": Object { "add": [MockFunction], @@ -2168,8 +2186,10 @@ exports[`QueryStringInput Should pass the query language to the language switche "getEnabledUpdated$": [MockFunction], "getFetch$": [MockFunction], "getRefreshInterval": [MockFunction], + "getRefreshIntervalDefaults": [MockFunction], "getRefreshIntervalUpdate$": [MockFunction], "getTime": [MockFunction], + "getTimeDefaults": [MockFunction], "getTimeUpdate$": [MockFunction], "isAutoRefreshSelectorEnabled": [MockFunction], "isTimeRangeSelectorEnabled": [MockFunction], @@ -2790,6 +2810,9 @@ exports[`QueryStringInput Should render the given query 1`] = ` "query": Object { "filterManager": [MockFunction], "savedQueries": [MockFunction], + "state$": Observable { + "_isScalar": false, + }, "timefilter": Object { "history": Object { "add": [MockFunction], @@ -2808,8 +2831,10 @@ exports[`QueryStringInput Should render the given query 1`] = ` "getEnabledUpdated$": [MockFunction], "getFetch$": [MockFunction], "getRefreshInterval": [MockFunction], + "getRefreshIntervalDefaults": [MockFunction], "getRefreshIntervalUpdate$": [MockFunction], "getTime": [MockFunction], + "getTimeDefaults": [MockFunction], "getTimeUpdate$": [MockFunction], "isAutoRefreshSelectorEnabled": [MockFunction], "isTimeRangeSelectorEnabled": [MockFunction], @@ -3445,6 +3470,9 @@ exports[`QueryStringInput Should render the given query 1`] = ` "query": Object { "filterManager": [MockFunction], "savedQueries": [MockFunction], + "state$": Observable { + "_isScalar": false, + }, "timefilter": Object { "history": Object { "add": [MockFunction], @@ -3463,8 +3491,10 @@ exports[`QueryStringInput Should render the given query 1`] = ` "getEnabledUpdated$": [MockFunction], "getFetch$": [MockFunction], "getRefreshInterval": [MockFunction], + "getRefreshIntervalDefaults": [MockFunction], "getRefreshIntervalUpdate$": [MockFunction], "getTime": [MockFunction], + "getTimeDefaults": [MockFunction], "getTimeUpdate$": [MockFunction], "isAutoRefreshSelectorEnabled": [MockFunction], "isTimeRangeSelectorEnabled": [MockFunction], diff --git a/src/plugins/data/public/ui/search_bar/create_search_bar.tsx b/src/plugins/data/public/ui/search_bar/create_search_bar.tsx index 632385e019e4c..7d65e947c0f04 100644 --- a/src/plugins/data/public/ui/search_bar/create_search_bar.tsx +++ b/src/plugins/data/public/ui/search_bar/create_search_bar.tsx @@ -17,7 +17,7 @@ * under the License. */ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { CoreStart } from 'src/core/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { KibanaContextProvider } from '../../../../kibana_react/public'; @@ -117,13 +117,28 @@ export function createSearchBar({ core, storage, data }: StatefulSearchBarDeps) // App name should come from the core application service. // Until it's available, we'll ask the user to provide it for the pre-wired component. return (props: StatefulSearchBarProps) => { + const { useDefaultBehaviors } = props; // Handle queries - const [query, setQuery] = useState( - props.query || { - query: '', - language: core.uiSettings.get('search:queryLanguage'), + const queryRef = useRef(props.query); + const onQuerySubmitRef = useRef(props.onQuerySubmit); + const defaultQuery = { + query: '', + language: core.uiSettings.get('search:queryLanguage'), + }; + const [query, setQuery] = useState(props.query || defaultQuery); + + useEffect(() => { + if (props.query !== queryRef.current) { + queryRef.current = props.query; + setQuery(props.query || defaultQuery); } - ); + }, [defaultQuery, props.query]); + + useEffect(() => { + if (props.onQuerySubmit !== onQuerySubmitRef.current) { + onQuerySubmitRef.current = props.onQuerySubmit; + } + }, [props.onQuerySubmit]); // handle service state updates. // i.e. filters being added from a visualization directly to filterManager. @@ -150,16 +165,15 @@ export function createSearchBar({ core, storage, data }: StatefulSearchBarDeps) // Fire onQuerySubmit on query or timerange change useEffect(() => { - if (!props.useDefaultBehaviors) return; - if (props.onQuerySubmit) - props.onQuerySubmit( - { - dateRange: timeRange, - query, - }, - true - ); - }, [props, props.onQuerySubmit, props.useDefaultBehaviors, query, timeRange]); + if (!useDefaultBehaviors || !onQuerySubmitRef.current) return; + onQuerySubmitRef.current( + { + dateRange: timeRange, + query, + }, + true + ); + }, [query, timeRange, useDefaultBehaviors]); return ( Date: Thu, 27 Feb 2020 16:08:37 +0100 Subject: [PATCH 37/64] [Discover] Fix incorrect filter generated by "Filter for field present" (#58586) * Fix _exists_ filter handling * Add functional test --- .../filter_manager/lib/generate_filters.ts | 5 +++-- test/functional/apps/context/_filters.js | 16 +++++++++++++--- test/functional/services/doc_table.ts | 19 +++++++++++++++++-- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts b/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts index 105e932f696f0..4220df7b1a49b 100644 --- a/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts +++ b/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts @@ -103,11 +103,12 @@ export function generateFilters( filter = existing; } else { const tmpIndexPattern = { id: index } as IIndexPattern; - + // exists filter special case: fieldname = '_exists' and value = fieldname const filterType = fieldName === '_exists_' ? FILTERS.EXISTS : FILTERS.PHRASE; + const actualFieldObj = fieldName === '_exists_' ? ({ name: value } as IFieldType) : fieldObj; filter = buildFilter( tmpIndexPattern, - fieldObj, + actualFieldObj, filterType, negate, false, diff --git a/test/functional/apps/context/_filters.js b/test/functional/apps/context/_filters.js index 4cd3f1a54b771..c9499f5a805ab 100644 --- a/test/functional/apps/context/_filters.js +++ b/test/functional/apps/context/_filters.js @@ -39,14 +39,13 @@ export default function({ getService, getPageObjects }) { }); }); - it('should be addable via expanded doc table rows', async function() { + it('inclusive filter should be addable via expanded doc table rows', async function() { await docTable.toggleRowExpanded({ isAnchorRow: true }); await retry.try(async () => { const anchorDetailsRow = await docTable.getAnchorDetailsRow(); await docTable.addInclusiveFilter(anchorDetailsRow, TEST_ANCHOR_FILTER_FIELD); await PageObjects.context.waitUntilContextLoadingHasFinished(); - // await docTable.toggleRowExpanded({ isAnchorRow: true }); expect( await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, TEST_ANCHOR_FILTER_VALUE, true) ).to.be(true); @@ -58,7 +57,7 @@ export default function({ getService, getPageObjects }) { }); }); - it('should be toggleable via the filter bar', async function() { + it('inclusive filter should be toggleable via the filter bar', async function() { await filterBar.addFilter(TEST_ANCHOR_FILTER_FIELD, 'IS', TEST_ANCHOR_FILTER_VALUE); await PageObjects.context.waitUntilContextLoadingHasFinished(); // disable filter @@ -76,5 +75,16 @@ export default function({ getService, getPageObjects }) { expect(hasOnlyFilteredRows).to.be(false); }); }); + + it('filter for presence should be addable via expanded doc table rows', async function() { + await docTable.toggleRowExpanded({ isAnchorRow: true }); + + await retry.try(async () => { + const anchorDetailsRow = await docTable.getAnchorDetailsRow(); + await docTable.addExistsFilter(anchorDetailsRow, TEST_ANCHOR_FILTER_FIELD); + await PageObjects.context.waitUntilContextLoadingHasFinished(); + expect(await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, 'exists', true)).to.be(true); + }); + }); }); } diff --git a/test/functional/services/doc_table.ts b/test/functional/services/doc_table.ts index 6957b0fa99929..2530831e0f6f9 100644 --- a/test/functional/services/doc_table.ts +++ b/test/functional/services/doc_table.ts @@ -98,13 +98,12 @@ export function DocTableProvider({ getService, getPageObjects }: FtrProviderCont const $ = await table.parseDomContent(); const rowLocator = options.isAnchorRow ? '~docTableAnchorRow' : '~docTableRow'; const rows = $.findTestSubjects(rowLocator).toArray(); - const fields = rows.map((row: any) => + return rows.map((row: any) => $(row) .find('[data-test-subj~="docTableField"]') .toArray() .map((field: any) => $(field).text()) ); - return fields; } public async getHeaderFields(): Promise { @@ -144,6 +143,22 @@ export function DocTableProvider({ getService, getPageObjects }: FtrProviderCont await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); } + public async getAddExistsFilterButton( + tableDocViewRow: WebElementWrapper + ): Promise { + return await tableDocViewRow.findByCssSelector(`[data-test-subj~="addExistsFilterButton"]`); + } + + public async addExistsFilter( + detailsRow: WebElementWrapper, + fieldName: WebElementWrapper + ): Promise { + const tableDocViewRow = await this.getTableDocViewRow(detailsRow, fieldName); + const addInclusiveFilterButton = await this.getAddExistsFilterButton(tableDocViewRow); + await addInclusiveFilterButton.click(); + await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); + } + public async toggleRowExpanded( options: SelectOptions = { isAnchorRow: false, rowIndex: 0 } ): Promise { From a06cc315832b178ab7b3f46610d92e4b5a491837 Mon Sep 17 00:00:00 2001 From: "Devin W. Hurley" Date: Thu, 27 Feb 2020 11:09:43 -0500 Subject: [PATCH 38/64] [SIEM] [Detection Engine] Remove unnecessary ts-ignores (#58689) * fixes from comments on previous PR * replaces any with unknown, adds test to show how optional chaining of array items can result in undefined even though typescript says its not --- .../routes/rules/find_rules_status_route.ts | 4 ++++ .../lib/detection_engine/routes/utils.test.ts | 16 ++++++++++++++++ .../server/lib/detection_engine/routes/utils.ts | 5 +++-- .../detection_engine/rules/read_rules.test.ts | 9 ++++----- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts index c496c7b7ce59c..5687c5d4095db 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts @@ -59,6 +59,10 @@ export const createFindRulesStatusRoute = (getClients: GetScopedClients): Hapi.S searchFields: ['alertId'], }); const accumulated = await acc; + + // Array accessors can result in undefined but + // this is not represented in typescript for some reason, + // https://github.com/Microsoft/TypeScript/issues/11122 const currentStatus = convertToSnakeCase( lastFiveErrorsForId.saved_objects[0]?.attributes ); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts index 3148083b4db26..a382c4a323671 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts @@ -6,6 +6,8 @@ import Boom from 'boom'; +import { SavedObjectsFindResponse } from 'kibana/server'; +import { IRuleSavedAttributesSavedObjectAttributes, IRuleStatusAttributes } from '../rules/types'; import { transformError, transformBulkError, @@ -323,5 +325,19 @@ describe('utils', () => { const values = {}; expect(convertToSnakeCase(values)).toEqual({}); }); + it('returns null when passed in undefined', () => { + // Array accessors can result in undefined but + // this is not represented in typescript for some reason, + // https://github.com/Microsoft/TypeScript/issues/11122 + const values: SavedObjectsFindResponse = { + page: 0, + per_page: 5, + total: 0, + saved_objects: [], + }; + expect( + convertToSnakeCase(values.saved_objects[0]?.attributes) // this is undefined, but it says it's not + ).toEqual(null); + }); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts index aaa5db7966b2b..65c9141619cb9 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts @@ -222,8 +222,9 @@ export const getIndex = (getSpaceId: () => string, config: LegacyServices['confi return `${signalsIndex}-${spaceId}`; }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const convertToSnakeCase = >(obj: T): Partial | null => { +export const convertToSnakeCase = >( + obj: T +): Partial | null => { if (!obj) { return null; } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.test.ts index aa1cce6f15238..862ea9d2dcbe5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.test.ts @@ -39,9 +39,9 @@ describe('read_rules', () => { }); test('should return null if saved object found by alerts client given id is not alert type', async () => { const alertsClient = alertsClientMock.create(); - const { alertTypeId, ...rest } = getResult(); - // @ts-ignore - alertsClient.get.mockImplementation(() => rest); + const result = getResult(); + delete result.alertTypeId; + alertsClient.get.mockResolvedValue(result); const rule = await readRules({ alertsClient, @@ -109,8 +109,7 @@ describe('read_rules', () => { test('should return null if the output from alertsClient with ruleId set is empty', async () => { const alertsClient = alertsClientMock.create(); alertsClient.get.mockResolvedValue(getResult()); - // @ts-ignore - alertsClient.find.mockResolvedValue({ data: [] }); + alertsClient.find.mockResolvedValue({ data: [], page: 0, perPage: 1, total: 0 }); const rule = await readRules({ alertsClient, From 515348438bce26b3c09989ba85b58dd79f6de0da Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Thu, 27 Feb 2020 08:14:45 -0800 Subject: [PATCH 39/64] Fixed connector and alerts view flashing empty state before loading list (#58693) --- .../components/actions_connectors_list.tsx | 4 +++- .../sections/alerts_list/components/alerts_list.tsx | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index bed285f668e01..f48e27791419d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -14,6 +14,7 @@ import { EuiEmptyPrompt, EuiTitle, EuiLink, + EuiLoadingSpinner, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -370,8 +371,9 @@ export const ActionsConnectorsList: React.FunctionComponent = () => { /> {/* Render the view based on if there's data or if they can save */} + {(isLoadingActions || isLoadingActionTypes) && } {data.length !== 0 && table} - {data.length === 0 && canSave && emptyPrompt} + {data.length === 0 && canSave && !isLoadingActions && !isLoadingActionTypes && emptyPrompt} {data.length === 0 && !canSave && noPermissionPrompt} { {convertAlertsToTableItems(alertsState.data, alertTypesState.data).length !== 0 && table} {convertAlertsToTableItems(alertsState.data, alertTypesState.data).length === 0 && + !alertTypesState.isLoading && + !alertsState.isLoading && emptyPrompt} + {(alertTypesState.isLoading || alertsState.isLoading) && } Date: Thu, 27 Feb 2020 08:28:08 -0800 Subject: [PATCH 40/64] [DOCS] Fixes outdated monitoring links (#58556) --- docs/user/monitoring/elasticsearch-details.asciidoc | 2 +- .../server/spec/generated/monitoring.bulk.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user/monitoring/elasticsearch-details.asciidoc b/docs/user/monitoring/elasticsearch-details.asciidoc index 2990e965be03c..c0e804672d298 100644 --- a/docs/user/monitoring/elasticsearch-details.asciidoc +++ b/docs/user/monitoring/elasticsearch-details.asciidoc @@ -14,7 +14,7 @@ the <>, <>, [role="screenshot"] image::user/monitoring/images/monitoring-elasticsearch.jpg["Monitoring clusters"] -See also {ref}/es-monitoring.html[Monitoring {es}]. +See also {ref}/monitor-elasticsearch-cluster.html[Monitor a cluster]. [float] [[cluster-overview-page]] diff --git a/x-pack/plugins/console_extensions/server/spec/generated/monitoring.bulk.json b/x-pack/plugins/console_extensions/server/spec/generated/monitoring.bulk.json index 2b27950e7b097..26a9078f73ce8 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/monitoring.bulk.json +++ b/x-pack/plugins/console_extensions/server/spec/generated/monitoring.bulk.json @@ -12,6 +12,6 @@ "patterns": [ "_monitoring/bulk" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/es-monitoring.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/monitor-elasticsearch-cluster.html" } } From 43be649f5006219421edaf151115d8240b0d7d57 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 27 Feb 2020 09:32:44 -0700 Subject: [PATCH 41/64] [Metrics UI] Ensure inventory view buckets never drop below 60 seconds (#58503) * [Metrics UI] Ensure inventory view buckets never drop below 60 seconds * Fixing tests * Fixing tests... again * Fixing tests... rounding issue? * Trying to fix the tests... again * updating test for custom metric Co-authored-by: Elastic Machine --- .../create_timerange_with_interval.ts | 6 +++-- .../test/api_integration/apis/infra/waffle.ts | 24 +++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts b/x-pack/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts index 6f036475a1e1c..cf2b1e59b2a22 100644 --- a/x-pack/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts +++ b/x-pack/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts @@ -21,7 +21,7 @@ export const createTimeRangeWithInterval = async ( ): Promise => { const aggregations = getMetricsAggregations(options); const modules = await aggregationsToModules(framework, requestContext, aggregations, options); - const interval = + const interval = Math.max( (await calculateMetricInterval( framework, requestContext, @@ -32,7 +32,9 @@ export const createTimeRangeWithInterval = async ( }, modules, options.nodeType - )) || 60000; + )) || 60, + 60 + ); return { interval: `${interval}s`, from: options.timerange.to - interval * 5000, // We need at least 5 buckets worth of data diff --git a/x-pack/test/api_integration/apis/infra/waffle.ts b/x-pack/test/api_integration/apis/infra/waffle.ts index 3413fc283556c..26d8c9d265a6a 100644 --- a/x-pack/test/api_integration/apis/infra/waffle.ts +++ b/x-pack/test/api_integration/apis/infra/waffle.ts @@ -192,9 +192,9 @@ export default function({ getService }: FtrProviderContext) { expect(firstNode).to.have.property('metric'); expect(firstNode.metric).to.eql({ name: 'cpu', - value: 0.009285714285714286, - max: 0.009285714285714286, - avg: 0.0015476190476190477, + value: 0.0032, + max: 0.0038333333333333336, + avg: 0.0027944444444444444, }); } }); @@ -231,9 +231,9 @@ export default function({ getService }: FtrProviderContext) { expect(firstNode).to.have.property('metric'); expect(firstNode.metric).to.eql({ name: 'custom', - value: 0.0041964285714285714, - max: 0.0041964285714285714, - avg: 0.0006994047619047619, + value: 0.0016, + max: 0.0018333333333333333, + avg: 0.0013666666666666669, }); } }); @@ -320,9 +320,9 @@ export default function({ getService }: FtrProviderContext) { expect(firstNode).to.have.property('metric'); expect(firstNode.metric).to.eql({ name: 'cpu', - value: 0.009285714285714286, - max: 0.009285714285714286, - avg: 0.0015476190476190477, + value: 0.0032, + max: 0.0038333333333333336, + avg: 0.0027944444444444444, }); const secondNode = nodes[1]; expect(secondNode).to.have.property('path'); @@ -332,9 +332,9 @@ export default function({ getService }: FtrProviderContext) { expect(secondNode).to.have.property('metric'); expect(secondNode.metric).to.eql({ name: 'cpu', - value: 0.009285714285714286, - max: 0.009285714285714286, - avg: 0.0015476190476190477, + value: 0.0032, + max: 0.0038333333333333336, + avg: 0.0027944444444444444, }); } }); From 235b3535e2fb59894a4624f4d56183502adbee47 Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Thu, 27 Feb 2020 10:40:07 -0600 Subject: [PATCH 42/64] [DOCS] Consolidates map content (#57736) * [DOCS] Consolidates map content * Section reorganization * Navigation options * Added images and cleaned up text * Added tilemap.html to redirects * Review comments --- .../visualize_coordinate_map_example.png | Bin 0 -> 397956 bytes docs/images/visualize_heat_map_example.png | Bin 0 -> 51515 bytes docs/images/visualize_region_map_example.png | Bin 0 -> 437327 bytes docs/redirects.asciidoc | 5 +- docs/setup/settings.asciidoc | 8 +- docs/user/visualize.asciidoc | 8 +- docs/visualize/heatmap.asciidoc | 40 ----- docs/visualize/metric.asciidoc | 16 -- docs/visualize/regionmap.asciidoc | 53 ------- docs/visualize/tilemap.asciidoc | 139 +++++++++++++++--- 10 files changed, 128 insertions(+), 141 deletions(-) create mode 100644 docs/images/visualize_coordinate_map_example.png create mode 100644 docs/images/visualize_heat_map_example.png create mode 100644 docs/images/visualize_region_map_example.png delete mode 100644 docs/visualize/heatmap.asciidoc delete mode 100644 docs/visualize/metric.asciidoc delete mode 100644 docs/visualize/regionmap.asciidoc diff --git a/docs/images/visualize_coordinate_map_example.png b/docs/images/visualize_coordinate_map_example.png new file mode 100644 index 0000000000000000000000000000000000000000..24f03376adadeb3bdc32ca480a8054977ac41242 GIT binary patch literal 397956 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 z z!*kC)XU?NP`?Ei@*-^aZ->zkKU;gr!tux51ADm}5CT5>=ardk|KAZ6}YmwPY%+kU+rVUag*Cq|l zlchP}gL4b4aH4r|9rNE@U6=e?_3Sg&Zh;|=)!TB0ff03kd2uG}-2YVA|M271W}LgM z8K2BR_Onw`9VRa6^P#A$JWjo5owh5?6xy-1M|z=UT3WWu(go}W`7A8m4p(l@Ygy?* z)e-F}wPVCsbPV7V*<8nP`1mt?GXw1Dmj>b%VbONKEpoVc9$d{iF5V|+mcp?1Z(<|w zfxf$8aOaT9Y(7lPENb6BEep%_!8?sB@)m{lEZcT?h@ELM|MmE;_pFO+f?^p)W%o%{ z@7YGcwT!>A`}JgM+YYFnkzYQv!vi!rg)0uNh7O>jhQS5FKB>*gyxcS)Old^0-8+Wl z*~aklT#Dj}y4NlOT?D!abP;G90qiTY6_T*Y27>+SK$@NH8_*zkIP5t%rlq;Jh{H?ZxgJoejV_3d{1IPn2WuR5>G_F|3aoFH&ffnfqMI9*akq##d&KDdy zIBwV{h_uwX4?p}+CoSpJJn1s^&(m;auO0RsVSg>0HFH}2eo3?O&dCAA9z4+c<3Ijm z`we|&B0=}+)vM-k`kTM`8$14;eOaD+{<-i|KlM}Lhd=yb_>JHA4cn B|z(z{W5>qATW`M={`G(Mud^8u z(EDHixBta3xdb;XyS9_KE$`O>b&Co)N z+0dJlLHCR>c1m*KQe4xL=iR?u1iA=x5oiYi99lj9okBh_29W8HbZClQ%LnwmqrwHN&fj2i8clPBBlfjE8n*g6|?8RwENw7Rj_Ba8(&neqCHU zr?0LnU0h`cZV6Y-Y|QIdJ9fZvWvOhQ-dfrL@=89*%!DP`h-A9`CJhRQbb8p9@bTpd zb&&hQkUrMIl-;EKv7gv>1_03Lm>n=&;VbEU%WUeq2FtR&i#mOT4GrVG+#a@S+d7V` z_->VlhPooeV_C7c;NEJRVfvNB6mUE|ALa1+QTXB)zZkytt#5^&`I(=wfhzqheuKfk`8WSI{K~KVO8ETeK5tI1 z*I$3#oKAoEhkqD;?bm+IoJBa1e)YfjRnd7NeD!Nz4L|pDKNo)YcYoLVYrpqJf;kSSLx5EoBykL&0gNKqM;Q#bb|J3>`U;5IQ!e9UOUx#1(#b3;p!y!wv0lmW! z$1Eetf>~9*;V!r^g9iuDv(G(i&)5TPMoV^XPS1twH)q0j*{A&M2J%POxq{&b?|)#9 zvqOgtYZKok%`opX*@#0P=zBdoK%WU(R#vh{mCYmJ&?EmzIQrnvYWY`k`X)=}ZcZf21oLHI4_BTMk}|Nb_Ghhd^#cWN z$vL9;8G7M-M|H73>&x3Fxq1t&S0d7p!SJyTu9??{*t>U*SbJ09uu{Ki`>;1SUymI- zW_E;lIDlMl`0e%;S!0Z-@8G~Sk3-fU$fbcEX}}3vK^RndF;-$PNy8O=P1{a=wJ<%q zXwTT_J0D0xeooJy*W`j5fvhgLxjJ(`Xm@!I?uk(;lOAIVDxsTB? z!>xx5K&;@|q)36znTH}Cc$UeeDb@_`j26r(WITvZ9rl?uAUq?VJP+K5p3B5{GxVvE zH+nf-NkbqF)4ZAXXoFT=32x*KA2ok$6zic#rlxR(2k}O8%E=HOOeSq|Wjw4FSLu!& z!B~W=rYG}^H$JyE)xnhx9j{Ons&G|0Is~RfdbS!|?X6QMaiz`_;kpj`>be3}lx2ME zYn8s%!L_CiwyCep;+ikpLOb9*6yaK=uXMDO2D_r-NRB5>>tI!#5e{qs>A~w@-VS8A zO7Fm@5w2v#8_3KKr0GaYXjflNChVmCVF%ctaEq4S?jPM6KK$rXxVoVXrse5pUwJ2v@!GXlP%_(`}pM+OIP8P^Pc6&BnLeS9r*^8U9ASP+yfn zhO2~X*cN*o%;5?Tbo7y*{E_AGp~KqWWmCAMO?`X%wej<&9vgHq7^6&>eG}u%fDESz z$A{xcVc^E{kBNzi@X05i$bob!!xvm!mvQ>wJfRF(_T^>3bB`zW(f@=m^v~~m+#xwB z*c*hr*@x(o4#dC-<^38x3+vEXYRNOd9kInfSoxU;M>igg^SDKMK!kc^&DG9zB}vcfw%z z+u#1SJ!4Ov-}#;23Gco8o;jN8@$YiPS2n!l#59)AFq4Rr)aXotBYJuMlk=9hFRuaT zMF!WJ9e(x3Y&fuIRPt8(U{2f9vo{MolK%3Q%SpLXTB#l*FOF3BAi%#5yzH6obEQ9O zr%37dl4gbs4)h2=92k}Us}ay2YX=q2>_FPb;Tbr)edTwopH+2GX{vch?LfZo=zSby z=s@2Q9()5*@Y^GsfAQMQFsi+PMzn9zo?}nh2i`q^&5~ZoqF-Pa+kq;X^b7}#F2bSG zZh;BuTyN^NTSd5HE3Hp18v!jsJzO`bE#|-(+6+!IW3%?%yZ0o&Gkbkkx~@|&RmPXE zUYFB#YZyPg&-B1D&>x(w?BRuD`0(Mw;d9S_&h{At4`hKCK9r;L9glUKPIa46YhS@C zk87;2loNT7FCXg9IAB{cJ5UE#j*h2pRz~?r{mlMCh(H665Ew!dm~txzIv;Mlxld5H z{{Lt1-Jbk9u6w`6W$pk5z~By$oB;@egm@7pin2&uj+9btl~c;`d9t5Ue(^(`awU1Q zt4{ucJe*YJJ!SjlR37qhl2lo-lk%}FiIy!=v`9+4fB*@A#AN^s=6=Bd`F>XKwSWEF zzrFYGGQSxB)HLv$-~R30m$kmVdUf~O-K(XTq(mREGKMsqv?vGALDHv^F`APVV z8AYTMvkr-8S$+UVg9B)kh|^$93J9Y?RRkE2A*shTQ{c%BCO$d57@MCJK84SHUr zfwVadyunWL;~H=F(6Dm9BtP-QzyX1$LNb;bGziz6h7w#2bKM6Eqd}d4;gHfGOm=Gp zmeEkgQw^?6Dq3(=X9|{JMBO&ws?%8dhO6@g4Q05B4y&gEt^=ARD5-URJJvxpb~b$H zbz6{?qP*s~dfiswx>J*_UT`&eE%IczMxI)5-AZ|t?9|Gu6o%s}cq}-sMOi7umDc8U z+Y7ELvC#&b+e{U%w4qMr)f=Jngl@~*V5$c+0N`Z57Fns1*LHd!!?mafT6CLesKqsF zgGD_+J2jrrMVTJBCz)gA&l5-Y+1vV|A-y5i#PP#Vu7yMUhV9KGCr2QUrERbZ*Mhv# zF=Bin3}*WJo>r_d09zJ4Gc$8q^)VAp9G;L-iV0(UGk?cT8wlgXld)#=xw z9-y9@X`s_??lWp}g>IAA<~{>l;i*y&G|6l1x7zj@Rk#-PYsA%HjWm??TXG^w=fYsE zQeMF!?K6t~7SB|F3A41aQTOd*k(#(#ruqGJYZ?i1ImxV7r4?7LW71JHgG;V zJ{*=;m&4odydTzA7iAPYAP36NSbsxVMvrJ>MGgLP$bB@Y-vynepdGKl+ia>Tz0FW%Td={r?oMT)h&0_+S0dRxMEgb-~IV{N7ys z>}p_j5A+s9VRiNmf)2|C(?>hh{V&pS$$}Bp<)>j5LXUby-mokl>FFbdd2>E0+c}cf!y` zei+F{WYl^s&~;{oT%Dz&L@v;15hR8G_bah?%%a)N7NjFZc2%2U}qR?nRVuiKob zsxi5+Et8ejv7>AhR8&es%h<7^&uD`y{*R4@GM-dqkte6Y^lMR8(tfK(UYqo5%2P^% z=%#Mbd#yb&R4C9n45~9BplmF%5^}`yT6MgBIBE`9m<oeQ;YnPH+1t&9!)%Ln1=r2im*dxOWpQ@>v{>Uk~44yJI56)`50CyuIdGOQ_6jl z718Fn@)j4PWIJ40%|^XFPpgVOP8&`}RaPr4ppl8M~$xnI-+mGT;K-E4UUn8;J?w;WfnLpP=J+Jq~5P4WPJ zO>IzVF#L0$u%5OV;<|3zy-9tB%WH~j-WQ|)rC-(Gm*HxCp=cZ%9SB!1-v|!|_J+~@ zhr+Rm#%WbxLLe^n3-4U>A>hargUIsIa+3kb(=o_>;>jm+X%75^@HIJ|3~mlP>&vVy8H_}Ry?lCSh1>?k3-r9bnk(Tp5puL*)w5&VNr%> zjJP_OMEZ!jgFa~DljCe-N5&V0Hk0-l1zl9x230n=Kzpv^k%hMURkSHBa6+5wHuCcP z_%^zI?3m#IPjOuPzz$!zdUGz!%`a*z*k17)^+bv{eYLM*s2mR`G^FE!oTs*WK)S7D zOb+I$K7^-A8l>CcmpR1UJ2zC9IBK6TK^t+y%RvcH+!4|L`;(zvT zT;(&Mj+(g@?=NO5f$5A?uO9j=Tax*d~K zC*9(@t9EW4^P_oEPi1<*a7gtlx=plu+ia@abc~be*RFBxM!!lCRLvp#GS_iEP-ruq z$Sc@Y;R=4WHjixlV(rJYVZ|SW0!2-RDo>VaRs=C1lNC~m>cNA?HVLxWr>MWbnb6 z8GDVnCft*fU6a*nfQn1DU)jU#Pt~9b8u*k28Ude{AUe~fU+Hu5@{TXP&vg|IOuPoP z^t3Eg(omCMEl=vm_*V>8*~#0C^m*TD=n+>e$z`FhxY9Xi0$ePs-?*Z{2TPW!Q*KW* zYyekUpbbtErmJY^NnU>oaorLb*|4mB=f;1D<^1RQPOqE}VYiSQyrz_0pwJ zV`nc}>PfG_lMFW=)}`M$s(IqTzHsLB3CmM&4Z?Lf!F^fApTlzEdrj8^LpmXH;eL4L z>}u<9^Y>vj_4sr!5|Xx}os6 z=z+4jO>s45vOje^Rq6o-UR&H}6nQGj7ta|>@Rn;*{x@#Uu7)e0-OLR@KKLUYfxgZ1 z)NjAXeViz}QG(7{`1$CKY5U-;N)V>{k;`E_C|87qFk z5Lz5N$DMnu=CTm0H9;!7t$YbM3MVdg`u5vzhwpvwd$#p&d1cx1M%VZ@Z>nZpO5g#8 zrTquPK5hG9(tJa!x9-Y+6S{9`Fi!Xv7PRspGZIh^H1R3QtANjWC0-h~ay(GgrrYTO z>Tpmq_q}omef9cnGXSMLaE*M)bZ@uGkAAQP2R&^^1346{({Z)T(?5#nGL+ut+G!}> z=QsIry4UorJK>Jn-ubgni~iWQNLLKB8RYJmPSoQ1?O**meD>KDO^9~dYQF2&u3KL- zG_2KOGGg-aG}SmT9^crQ9GsR{S;-XVR4Lua@qxX=VNmlWjF>orwih6Zv?@Kx{E4lM zV9^rla4i`Rc>1ck?P=_&Osn#9c`cW(-f=C@uQ4WZKKXVU(tCcr5qa%~hRwp&`AEOf zbK7&shK^6Mv1_%NcJkViMmKuFbu0UfZuF}eDaBKHiz(qA1%{$Rff2Ya1{4@!J$uL? z0%gq0cskaSBo=@B&o%d`%J11X_bX+Ea8=}9o3*{ zhfNIWG#CK;gfGR<^)>3dDoCw|1$pOWOE$$=#`m+wsX?Xqh*X`M#{^_6E zb})=UoWk|ZZ+_G8`OClj%kWo!^;hAK{^*Z#qtu`O`Jacs`J2D7Eip`zteuNjrya&H z65*o>pDFl6!g$1r3HPmZ?5GSjT6OcQU;WBf9bvHX0B*emt8Zb#$|qI=u>#197HZ>j z(kr{PJ!1dfu`oI^RGK|@fv8&=-&Xf6<_ZiLz0p`&@S|{3xSee1;6^;C|oqgu4 zC8I5~>WBELoc4l486CxY&@`mgOJ#v(!n}%U)4E=qXwO&J$qzlim4@?FmiBSE*Kb_= zonJ3FJ_Z3I97{atwq7)zpAMx0umO(#jcGC)t2W&_R#VQFPOT)(pv_KXb5 zqRkr?^jI8J*qfV1WV@oHP6r(6W1lFLmBq8N``+=FJ*&#Ej)r#mm6c;@OnZ z>8j}NH%~SoX;C?PduVS;<-0=z(9dtq*fGKQ-eFlg6FMf+#Wy10N;-75?~#U&6bI`M zbZ>T1zBQ!lPaZvFOWNU!$tymV*j{p14xrge$(zkPvux{##v=05e+yjG*Whz!NE6{f z(Zu&icC7X;`5PJ5M04`w5i|af$S3GSI-zM`XY5CyiBN@k+5MEKn7Z+|s!fxos&3om z_bAg)#ZwgyAhpppI6gKQ?#wNOPp@mTzi%}BTE~~))M_18fnb0@Hp`BEXB(BTe8Jem z$zT{N_~ygP7veCE!GPmq8vNw=xW@VAn-wfmlT&7hnVXxpRXbi+7*meQNJ%-J1jLZE zq$B*`_kLhU%5y!Yl`5=gfj^8K$T0>dRwiKxVq%Kn3uo7?lEM!XhAi3=$G%VBoDT1Q z@P0hre&UdAP5aijz7?K(_PKEWx%1ZU*zN*mIIxC)j3}%y;vOrZzzt&nm`qJgL6#YM zz{$5YIJ8FZ{r_#e9b`1@WnjgF9)2JF(pJ$MEbaYHIGa6>K z^?6nXvExS$njx1qW=2opP>HJ=G25KW>JN+vWzQ@>Z&T`4P*mbjLW6Gg+-H=PQ_oX;*;JOUt_?zCRhqJAwKTMm zm9lbrsaxpkm8U8iprhSt*mT;euXCLkFmfG5fe2T=qq@I z&(6)-Qd*q$aW5{rjLU)PP#FNYaweTQE|T+4Uc^4on^+vtQ4pDP+RM5o0PET^#?gna z%*dAk2;bzFg5`q~27l?&CgRe8@w|lwF-3ml!?QF%voB>%Cp(?c5GN*$Q!7YAetdXq z=YvVg16ZelXDLrk1D!HU%00B>iRJA@8b}L2Wi)ic(-#ugE@kDn1=l)Rad{<9u?^<( z`dH&iyY-=1+%Hf2q-|E~0orZjO{43gZrb2x;fl^J>b8a+(6O@G4&lM|06J(ylT3VN zV9Z%q(kdG*{+ye+VaIZxJNK;kjj3F>J&0UI-OpK33CzQgiq1)mhm6bP_Z_I|H za^(B;Q{c# zr!;DmJDl*cqRI0OTiwvDZZl`#;3_B8X>j?c|EZRh{`Ol{eMS`x$l0*AGi;{3y8QQq ztJ+afUdwQW{wvpRg}b+JhUd?p3n#KISj1(U(wDT744*t{;It@KcCa0c;Bo^dv=dg- zaGd;!<0niOSuw^*SZsN60=ej^t2cx;Elj@=mlS#PjhTN0mBV(NC$>ovpUGrAuHzVL4!ux3(qj#@J-+5$Fq~q zg31F^3;ACckw2+N&P$KBE&oP^4i{H1Hx~QO2yqHS`HO8&Q#CKBla+49jy`u<)e8}> z%Wz#&9o~~qBUZkS$k{dh8}vZ~FKT4U)1eM=P6f}j*Nxy>Mg#d3$2g8r8LlY}-Sk`i z!WA5#?@^N1t-^JC4jErw^jluL9^*Wwb92Tyg}3_$$dREjHTdVO$h^`v^It~Y`!c@ffjqTG~*uH{w0*2-%eTxnlTJc*uMRz$0s zWR!7zmC7q|^l8SmnJ1oE8N|(GOqWf#8V;F^cPy_~vNED+Wb%do9DY-`PB?ixu3WW#bFRzU7d7V*Oo zwDLy|rDqm3!I%t34(+$}uDh71u$6~5_xKy3eBQ>6jtraehj<>>2uuF>edzIPe{AXe zhrS(KU<3#FusGe~TB8S2SxIq)jPzM9E4puWOQq;PGks1`2Jg^;51aSj|BbC?VI0J2 z8jhT2rHhy2>FU0r2O2TpKm);Pq%7`ZoM13U8{{5_3LI6lG6(~Xr=?t{5jx116-%>s zXH6E!m(@Y!!E@3Q2Y%og9?0YNt=s0%8vc1sTyP;iSh0eKJXk@+HDx-_wBz)*^G?~+ z72o91k3e1o-cqu<@BgACpZ-cs-w$D@#74A(U zH)Q;Yv|%v1r|opB;jT_e+cOdkDUO5j0#A|`4=GQk+pK=t^OTQYBeSs|#9?c@i}Y8#q=9dxud7>5f5VCNJ~^Jp&_aN>a$Loe^l2Hcq;rfs55BEF z1QkcUudl_qiD8sg6#b>;Cz;7*%n~+_FYsA4GOW{|G;VgDppj~rmXAHO<*@v0<}~QO z%d68+&QoIyT{|WhO|j1Dn;RHawHbJVPWzY0N;wT3;tEe$UdV5;o|=99Pmb z_r>tx!R5>Ntl=rIi>%B#Tpz|9(&jp*ryBCVnYcQBsr=^{>0wW}s$ObwP1+!G>LH~e zl~*4-^8Da|gVig57)XD1ReOaQ=__Lzxp}@;XN+*s7)+>XAPNjL_%J{~7*|(y45!lK zou5J7lAK4M)f-|AL^$aqa2gZOy^-6^?2qS#!lE%pg+!Y8R=Si1DR~A9FbspP6p4#7 zCi0}w@z%^5i1_mSD3)jN=^>{)do{N zpuCxE=6WE*6@v(!Va}7{Sev$+P?WTpT0J1$;cbvKsk}O_x)00v<$(@#0Bu-$~MEtHRrVsg0|0l8)(JvTpRTUpQt6FO5} zCsv>EocJF2ts-NU>Y6ffER2DtY%3RAp70HVUmjKp;YSAp4XaRCfz(TY1`jE1+=F(G zJ%8cF7tFtj)6XgmPSbkfg%>K@3q~>g?mT_w>FAVNY{MVH%FGz2OvYoEE?qJV&z?PN zt8|F#v=N7EKAuOOk1m|K$vE)1T; zK@PyL3RmK!W0G7}deE;XD=LVl=(zI3`r?cNzD&QGY--h_j(KOSP(&Zr^>nUxE9&n!8^jkR%h*>gzWgOBet{edmhE4KXg{$s^M8|VT)rs*-ewp5* zzlXjY2l3xL#>wWzlq9;U#shhN#W`f19(X9Yb~Yvl*~T1FFE|-H5z4kFz?L z*PI4jwCyvxkXPyt8Q=v^W4{0>Bmsswo|eccO*>XB>pY3ZeHe4)%WnfoCxB^(fg0(K zaA=?Qy34Em9_{O&(viRW_KezFY4-E74b0Pce&of+?~@-Dv+I6bG34=h?$>2B;IQ8Y ztaJiuj>J#XkYAB*%TFBz3bpvmXb>G%k&0N%uat%?UdmHS14q4CImGJ#*S^poJTba$ zIj$UB{Y21DbSR+|Z?5r72QktAD&&z2q`|Z!j54zYY#>$+{ z3bbKXMe#vq+(^bXtAtp=#PRWyPfg}0u0bQ);o#9$L+N+t^4jItQL;-pd??R369k z%V|(QjGiG7r}r^=xgMw*lT#K3k>TN;VOaED{(L&%8*2Z7{U!rEhsGjCDGoeyJd8j6 zR-%?Po>x0uJwM{}p)5j?26#e$4A^|9K?Ct}Tr=9BZ&ikGwq5U(6XdDM?+N`Y@$JBJ(M|MU;v>206+jqL_t*K zX2@&OZW;6Q4_@z67V^b!UAykEXFcHBQQh_p*J@pq%7b558h{Wa7|A=7pb|Pp(gg^G}~L;}3D;vSaz9kYY@O3wCNth;qs}YLt3f17C!xKTF25h z{Cuc4lu+*qb9Zlr*<07bzGtS4oigK3$|rpWlXJG15bAJE)Af3dK>(+_Oh)nJ!sL(b zAFQ(S@Hoh8C=tIpy6c`jPV&kK>sP+=vdIw>e~dI3 z`FNZD(n~LzF~|orUeD>bKf~cU1_ZW%l?4WB#g#$e=My||?j?BnY1+BjIh)L-#vh)0 zT(-Nt_10VF2%7C%7*KHpO?%>lkqEE768S~+Q#rZq*p)6X_o zM?={&UZU*Lk?_=&(_!)CG#_K@lG+z9WN|`%^X7Cu*@1H6R|U_j_`Hk;kJC#U@*9*P z7~L>3xFZ~te)#Cp=i%g$akT?pQ1GNVw56dry8Wt4Q}?VLPrf=OEwYHKSkwyK`*M-7 z5)M!73nK$+lj;O+$OXq&zjRuCbKIgwyT|ZNU8W(@klu;cwRCU7T&GN0>S(BY)(+QJ zZZ}I_TT5z3cWa7xr=L94(NOoSpEST#ulbd!mRh7|Q5I zhw!h~0OT1J6^`FeztKsY05-92C~(>#d;V6{xs1sW^ns3eeet=|VV!LTnsBV@)r0z_ z?XZo&HUirSY$Nax5by~B1IqlAFDY@IMjLiYXQyLKhMV{UT3=lZdk-E7_jYJPp?g&- zoDPS;gp5@cY}LW12!mmKoG`f^*A|VqjUm3tvjjca!QdH>_Ewm4%aVYv|z!`{z-{&SoB;|P2MH}x^sLBw=iPT~W!2Qwlt12_ z@2nZa3xOAk7({Y<9rwgxY_0o;obK%H-`GSfZ{J885cYdsv^FJEDD_q?(a zS8vGYbNJ1L%i;NRlL4Pc$nu&#ySFD#RZwo<-$q~?fesO{6;4%g8T_PgPCcI8FRb42 zXG5}FvuxX)FEOxKk}sg~y<>8Ywi0gXO$|;9vu?6+KXuUmXqI>g!&4>KhFb1;!k#Oc>uY6qe^_!o0RYOwVfzOV+2edguG! z|Gph#?pu!PWC%ILXu>KLd~~q_s45WG#}(!bR1pn#(Zx3HUIUJ*fA+@D%>U3Ye(?)i zeS;CS=rGya3`R_@Il`S)HSi4G@BuwM^SIs61Wu&GX!5L_B(tIbe5u! zs_LnVC(=?*KlLjIDd6L<7^-N%h&7@&F9X(3MdO_I*=SXewt$WAHRBIDftM$#?T7sM z6hp1NR^Un=;LvS;RXllq{lvA~x@|{8l^$q|>-Lzuw#}FxDCtVt;))_F1mveo4|v`F zw#jR%>l~^&T+8N=^pD_5UX`bS-JY4#v8=bXb!#|((@Q~gtb8*V@wZW~L^15JUpM;h zh+WOPwuND_AJ*~jayVgcn|Fx-uRvA`K@1Mh*oQ}O1-7bZWBFGxKgTt#TX?68e&R|!)Zq&KWjs~ln$>&6RRg|ER(i%2 z`t&KIp$=E*Bb4H5?V{0Ui08QCx5VT>qq|97CHCa!p)F5Vw-q#~-Inpx39e~-YN9~{ zl|~z6pe)%FcJNTd!RoyST)UOmybadi8f9hUZ4m5mtXGa}rrU~oKp2pYG*!6zGwPkT ziX!hCSDo}?@~V1I{k51b%4i_}RQ4FS@D?w4o+T~oTl<_nbrL9GBEy-$2Y(EO*tm$kKGFUvqh-A1ufU*pMgmrnoe< z!Hg&P1rPG8l9f7n&2?LW2J#{uA*C;3wIYEuGw{PE` zaA16&d{ixj>$hgZA)O3H9bwdCI~R3+XyQ;?-!qgwC*uS>u#GC#eWb^T(jV?&5W#6V z*G#zJl@Hg0!y__qEQSTi7^^1cbpqa?jHPLvcwT(FTtX)XPaI3LS_X{Re)aOpFSl$> zqFlBtUDQ$Rv=LSdftLrT+rRyOH{Ya%Ht41;!W*lyF-Y;O+u-@}O*@BQ0$bJ`gKqPz zi=XC+@rU3Jx_QQUi~wI?30=+?zLVBgq7z{5waBaF!?3B8*UtN5WS{m#0Bfg#`m{DE z9g^w};&rSCIvG3G^ck!qxqn}6RvSfsw3)_Ov<_F~ zp{u!0jl6;x`Smi_*_1h?>L!)1cJd1CF5{(o09_;<;o)(>6`m^Rkc@{lmv7Po*&MP= z{*mKu^?=E1qC3iPho1sJpfF?l6wQ+N>Oka_YdyE{anA0IW*}j^@RmANr3YPXc+3~7T~sRyLLqRNjGq@r#s(*wQX`ars9Yjj%+uC8A*ecg54s$<_hxI1X> zD<{3{;oO;%nmoj#v5_6`e7H7wlg_LPwA**zeK$8YF=1rF#-x`coI4F(4l65896u3` zpNRfl{66`RFS>bYSw4a8%;-}8guy+v3r<}bkr7J0o8&GYPCy!$J;#V|?=u>>5>b6d z0oO`hRMKZa2mOhaqigz4?`K@MmC=y*gNjcct@7HcU)##7jJaS#cu7mqSR8jc6(8Vr{VCzxu-m7{_S~UOv3oXmPEGLbQ18-Lpn|%^L(n( z@tolC()L%DCXJ6w5$5OSZTl9hj5rm<@0X>oyXQ2p(vOq6UeZZzey=WFC(oR2j|-n4 ze)ypcaNYRh&-kXjLxZ1q<2>bUhI(flm^t_)|DM_)6P--Qkw@NdW%=cLKykcH8x5+q z;@Gh>8nUryGP%lms?!6ar%A710Mdj3gQplU9Y*=+HN&Aq54b+ec`Bo!54b`HdN0RS z_0)u`FgJ()W252fwdwHgJO3J9kuh~{VNSk+ z`k(j3%Hv_pAzSrI?{mm9TsON7Qf3pbN!@Oh9)O1S^7`oF+L63IEL^1zX;V{EQ?19q z13ZCkTr?nzAH12xn#5aZ=_peW2#5_R)#^|foGgG96UMPh(HI#_vTvR@WouZol?F={ z`htNOjnx#5e%mvpCK_=XBTdBwj2( zWz0X6fFIA8@ZgKi6|OgRTG*hBCg)C{v=dIyIfSLz&-G^ZcGz>^co-b1 z-f9zLxBkVq%hc4Att4oDT7Cz8fKKrv=b7NUuM~gA>K|l92eLk`*cZn>V~gcg zSf={5N)OPY%mAl0NbvT=SO8x?$T-Ktb5h;@{d>dNr%qTr{5xT^!Dz^8vSLv2@|$r_ zW02i)9(`5Yh2~^1dbTOrvV6s?XjK6#$f#@ghk|Z3{YoYZ$b$ZuEHR$>{MLMU;`kvm zN~IaP+;Mb0vdF3<@_~2P9hO&;$kVWLDW;iD-Zg|(lJh_dZ1-Y9>=y-dcfon;uUyX?Xq7w ze%*>Oj_5#7)7p4R%r%($JfnfD?n`e^&n$+!x37nj$BqcQ-C=Ta(p*e%s-@Khva7r{ z3s=fuOpadV1;Xvwm9VNE56_)_D(o2>(W;eIn>(TZeD#VVb~JW`a8|?amOkWkFzP1G zonn92NuN>LZzcM*A+O9^9`(6S)^8>AH?RbU4UfrHkFG;Df-Cbso0F2C{-HPNOK4{< zD+qV#*s)~}Su)q@Q4i!i6~^S7K8Ji1aP4+X-iJ9PhR--AZyr1LOJPF5R$EQbCdxCk(r^JdBl$p%C;8V~6pA-x};t7)K#71C#En!0B_rHL)g z%0!vcI6d@~U&3p@^Xn7`Qym%P5zqed)Hw~+b@=$=n()+TS$Sx))h995 z_WM9Xgf%w8hgY}aCecSJ9UE?r&v&j|2^gF6y@L zg#IX#GQ40vk;q_pVf6yeQD?M`@ZzOU?36HY^^>1?fyIO=ers@~0rs_PpW9Y~qbHvV z<#WkJOvlyO#=E<;M`K19v2&+_{mK=^` zeo7)AX{^Sz^U0}o$T01|?=@n@E5DCSvs#HU8O9d2an%L3XVK1Zs7*QK1K-fac1*&z zzy0m*jW(#m*h~V(8H`x0FnQwC6K4FfjBEZlKSW8dJqiAspqB|TJoEdjU-_z)>GA!0 zX6CMVjH@m@KhLL#KWRL4`mCokiTrn3P95$2rh&2;=R;ek^z}kR6HkS{m}hK9n^l{7 z;`oGo`wVNl<&xUxqG;l23{D^SZpq-XtTeB_bj}~!_qA)+rNdWpUObIQs-nH>KIzJy zp)Y7Z7@_a)8VP%J=)u&fqxq>_K6heEHSNp%0%bB+mS0&pM3?PN1eDW28bYV}#n|z0 zKhyM^hNk=qvQkBNQyTq9>%EsWP5C_vH1wIL*sdCls~3!VNwc}QlKaEu>5;&-jjW)X z>|hq)DhotFx%m;A46GO!r;RGTPV=a`Pn=$!^^_)#G*hzj>z?vUd!an1c(HZ)H4JG5 z61EIi%B|wJ>VCh|JnH%Nf!MqOZf) zWP21p^Z?>Ihj%19@D8Sd}i;3<%RfSi;0}C`YG~G+LQ)= zj&F|9;oatt_S4U&?TtV3Ojy*!_1fp6?bh8eu;)&A`U$hIH_i8h^+#%`Yj|E_->_Q<@FP zf01T>_nQXt1lO`qRaVt~^62&1fL8iFc(4|(-1zGg{%466&@dFS2m)mOg}&OCX{R_wU% z50`oRB8;@=`XVE!3ZvqE6%`vjJll^lj;fz+RT`+ODy!;#U7EUQz2w(RnlB;^UqqfB zg}QxQac$X{?wu-cT=3Drpn?$h3)^Mh@y1`B{q=myVpl$kn!YSaJq;DYlac6z|lg=_jrgc|k=T4Rz0Y!KjxsRWxuvj`dnc`BiCZ`RxIt zp314gyx08Tt1N6~e*LW5GG6@NmhmKc@TH$#wtx3RLoaD4Z&gd$@wdP+!UQ_t!Lh?~ zzMVa=@O^9y$rbL&MQmPf28!&tLfHf^Db4sKdaTNg*o%_%MmRB|mj1 zPo6M8CTs`0a^;Fmc9}#kE@=QRnwi)#8FjvW;K1aE{1~JYFbMICd#tKpOBy*WH2*u)!yfr2RE2~UeN+FpZ^zZi zJZns58?z_wyFt)t#!%#Op(hQU(l?)D!iS=-Cl>Q4J)88-5A>WNdDoZbn?5AD}U zsJkJzZNMnQhwWo8yzoLUb1r+H1rCt+ABfw_$aJraTkpK{ju~EXluh|}G=^gf8moht zlya{az=RJ0<0y``@s&gyqdm}G7zaN4+_U-1K;k+*juYFysE6-<_q#l{w~Mq*d~*>n z;JDGrZe)LGYq%J|cMyEzNcyf;@yu!!4-;q7;Gd`%yj=grh(&oG{J#HAzw4f*@zU$M zGpHqCpY=#XRetGxeCQm~QRr;*{NU2n@U*sh;%DoCPQaVdsxp%~ z8j;!;E6iwb7+q)Ooc-j{2^5jBht4OYdB@+TGVEFU$NJQYj;ff4<)c5ek6X9zSU+>< z&_tNNel>h{`J&nq&d)`gwhvDn6io^?cj7|ymF34H3l-S*J55!7RrjH-muJ1CsVl43 z{0!TYKXv)_wcVDK?YHV^sC(w=i{G_rdXTT${ECHVzw6ReJ*&D;mUYi6NT^Lym0!1d zpsH-YUsVpz>z;Y~;&(4;s^r*c(8HEfz`SE;ut4X_wl6wXI%llz490z6;BhT8DK|P{ zh-A=^1_oL@W3ZK`Ar7A6+2dPG!@z)N1oIPQSMd+!SJA*gXZ?X3#T9ALUO;G|d>{0A zmZYi5k2I<-rD^7g_@pc4NokdO`sClcr8yyJ~~#6s!$a$g9bJNt>bkzR@6_prNh27T!|EHdu|TIRUJb z*Ft`M#TA~~=mEx@MS1NvuFg}L9^e_Fj0R3~bDu~SNq>+lj<`jRZ_h31sBTSGM~0*; zc51-8FMROJ|2us2o1ccAqi4gpZ~Qm%1H_gTFdS6^Je1-p+(zYu9GQXksy>792Qr)1pN~nXhoZjDX;7MCJy8z%kRJgG zF@&1G5{+XRaJf@h?hna<>+~H?x06v+pEN(qAo)YSJV!<`IvzT7$og;kJY*0V#wfxV zf~{OQZT3|{v~QMl^FhvOPkd+tjNN=CcT!x_rI$@w3@+ru%RjCu6Td_RXuw!Q8{{S7 z^v!8=xJ(>yvt{L?g@7>!8u>s!?G@aipKt05C*JUi0gDwr7{0D*J0@kHI(5nnN0wRP zkK@QUPnZDqJ9O>wt7IcIv>zV8uF_g}*k_OiU1zpq*R}41ZW+;Q;G^DuFj>bj@?3BH0T0wVkTw68O z#*trSE@GrMsPyzt=37+te^7qG@Iy+#5Xr}}ZQ$BEFEClrK>$WWfu}NDDHlUDM&G6N z9pQl5%eTMvx|R2=e2Yy^PKIO0kAQ8?;<^cA@~SyxZ@6yJ9C9Ob9duDqUN-^Pwqx=F4Yhgz zd99geqxV+0kaYZ_g4!90&*{c<0J* zKPt`2lCXPzCSalg#Ygb_#B(5uX&6{L4fGsd4(Xi+Pvg({?L6T}AXR=TPmKXz?7&IG zbKU|PMwt%@uUzuw14cG_ga#(lszmM+Ql6X!Pvg&08thpKuAZOs)DBlBeZ0LW(olyh z^jSGQ;0i{a;+oUY1+K^n=^O{gj^DMoW@(7$*nvqZEBy9nO}Ii|iM)1$Ybq;IUKoyu#^xM~nVnO)(kx_~xoPijlflk0(Aajl~P95#$= zrU$kJ*IwkcM_d_bEv-pbc51?Te4^R00B^nVdfzx-c^(ec)|_OzL* zK)up|v5n;P>C<^M>WODeCeh)Cj~up@JPY#+cH-Bh2Hb9(@wl7-L_1*uNm?ckOi)?b zz^V!QvosKg&X^OJhVTO)7;tY%8E`ClWe4IkbGQLyxrEzs}!aF`^hZO zOn%m9WV})~!Sf>yA1{YzDGeKyR|xWct5RNRgGL{E1qz}w)5<^*7M!^>kk^qDF?~ zz*EI-efHVsw#5tM3kFS}1hXv>Bg|nLcg8fi zBzRh`iN~aqRW}$@tI8v;2j_*j(9btPk{1phIB0dlDj)KMK8&@LF{Uj#7+^Vx4Z1L1 zm2KrD9a}8%4}_tI(~+)fl^$)4le~D2!HYJB|D(f)4jUhx(2h}Rd1c8k;J9q+iFBUU zdGkJ_tFfcY;gv6c$>_Rp;bU9z zhy2r*Amj9Bv_IDm$X^+*eVyxcD6dt0Mp0g=gEjeCDw9`}6_saWGXdimkw@AFo98+O zdCfYLUgg#M49X;U8{~Iiaoxf>WRtuyDu0aTkk|*h(y!UV43{sjKkCx!mS@P8KWmZ| zwQ26V?3rH4beq&jjvZ-w!PWY8*Hfa&%W0xPdAI1-EDiCT?jle8_GeAYj`Tf!4-FcLoKd4S%!waA)Y$LRUNSn==*^yE4L)4 zm9kP+w<;g&`WFsYwVP^r)r7OE4VJZ;PH{CoKnp=h^43Cax-384C-AIXUNHidv_a*` ziB8mU+6Fn@Z_DJh23N7&m2PAEh8U@q*F?8P?HW6uPUMw*1yj^*x~|i&)D^4o2v#3i z2eYEnkEZ2(^O>nr;i$H@m@ZXZa2%MPAj<^r_FFmc8GyzPO;{!P44{xN+RT!+2^VukmF_cYX1?bgVhkR^H&( zxgLP3tS>IXRh6sUvhhVlpTVkt&A`>v@aagaj-lVFUQ$g!_3ur`|Ihs>uTeU{$u=GqOYzw9! z%qFKvJwXG{E5`%M$Hq8HgK&9WT7GT%E$f3^Ub8lc?3edjeH`N?ePhfTFnZAWg(qljJAO?tG8{xJ<020;3p(lR-h*&< z>IwN28`W0m0V|8uZLh!ndeotcOnad{xJ;7%VdI+9po?7oGmP5y85R1qV_cIq=(y%I zB(mpo$fAC2l2_GZIv0CfaINC0dQ9GdylytGnXI@TZfdt`7hUOrM`TRikse5JZL8bL z^y?!$hor3&o_y-b(BcEgp6CxC@ur72G1IV`-bo7jC8ZHgl@>_4t&z`AJzC8`JkmqwQCwOyvlgW zX%KDBJ9L9l`iy)0=6g$V6&}uSN(1AU#|KyBydnRc<4Svq+YjJ<>*Tdf8*D4D7|t?T zX=yX@I81MYv2Kz5&f4IvBtM3aDXwNz%5+XDE3NX{4p$UoLq}L!SN&0M(A|?BpbfUu zZQbBn&~0{fwm|G1*M@#=(QV?}+n^M+-pKC`GdeQ+@WJtd@dpjU1VV4&P$zJo9U|dod~I`6+EHVRBD>=OHVb0TppPa810asVSRe@^+RmJ$*}) z1vvy>m>0=W??DG|RhU>p3zKfrV-&)u!nNx|^6>U)_Y+x3ZkPH+VuK6QHFzRK}7!|}x6fIRXR-6pG|`GIs5aXc99%GZLb6q>k)PaYgwW8g?n z1!KhvE8)tFKjcB$eh1@0?Sk(d2l3*8GFhePTg1HGI4y=-7N2{pl;Gn5qZS4sj6YFk zl6LKpl5hG%{C+LTzZZG)+v#$B&9~J>s$UhC^1a@@tW;iW$Bqp4#Rt{pX&}pKXpyg^ z-?C?!&VmLr+L!cO0zhM&dU<8y#n{ngMJvo~44vU%v}dt4iJ2&S~jLkC8~=Q5sNy>UA{aqN(-x?$VrwAuyRdoXYh4(Q~We@f4plp1!P}I>WVdd9Cd;D*G+fRflt(PUn!$tJOu? zW`u`71Dm{Vw;I>&Iiz9lbnC@RxPu;Qnw) zE76#s^5KoQ%M`18kWmaFtX^XR`NkV>*s3^RRf8=4{O3OpU;EnEwp0!&_sw6tsjXJa z;kDOZvv%q20-pVv6+nEL5PQ2VV&d`rK5ZNfKK$@Q{UKYIa$}9OZzkoLUTM>6Ng3X#PaLma0puCE@+#|;iGymZ(?9+kB~_*e*;0U`MDk}KupPD$*hXL* zfo%jH4Fp*JzAXQgs}Ba{mt$O$&W-74A2@SL7jH+I05hTE$mntTRKQ^@1{i|(IX=n5 z_(PiSeCIpXS1`E7S*+*jh`BEjCI}dH@GF9G>6TXf?2(@cR<@Eirz6n`vg*f;I!wF? z7=pN$=DlZZk0zbk0-*iV+hH4lP7pxO_U)h0DuSKiU8*bT0Cu)_S`O%rKPO0;56_} z`^OMVaJ^8LX8Yb30|6vLww-YF;7IuV)^wFx z7H;2N2*3VlAx!Mksdti@GFdA_hj^cUdN~|aJ3MjhsPff{w+C9;rZ&58Y{;BC(=Xsy z9ofTZ$+lvD(cp6GdD|*2{qTOw@B266UN`0Oxs%5)ey?ioG`Kx?D#Eh;dmDjm1Uf)~ zRil+#z&t%lk%0-y&X>-k(0l-b<(=OsD_3}F$Bgn`mkFOZI6?G)@?$b_cYaylJEh?F znlew7HEH;r-XlGVHl@MyY3Q+Tf!iuh3Cd?{)fhw|thclk4)k|2Zt^&FI&@_KNh0 zj(gugaNWx!m&q-Ic<93kECXxarvBqU{-ZgS}98ULQ@^CRdqogW%>2B-%=S>`9XIT4el4k@vw;c11_ZNCr^wc*uGK>j~lLF!xpvA zZr;`kg`GOlXrJm=Cxb~okzGISZb1ei94NcI;fKlt#tsaW9%u{RF8tnRepBBVbTGa$ z=|1=Lxzgf@hg{)%g?3CR%1T*6^C{u45KC;!jtMk?g>UOo=GscfxU+nWQzhe@A+O!a z|D!+yby0^AG?wY2ht&q}X$~>INA2dWoTJ~kr4>Gh?d1V45VCH<4E?-3IIL}BZ@&Fb zxGKH$?76en&ft|$#*^cKOpWb7B>k@ZwYqe_4F1<|Oe?>AVOlz$t$*O+ZI!&(vdBvY zLQ&r7FX-Rs(=b#KQe2t;fTz!$NT24x-02=Np6LAQL(4z z>cf;*+KQJjwfg%&tiU^;M&4dN4Vloqcff`w(;h@h${m?JkOWm z>aqgQ;GN>&JQ=RgkPSXN$F(`XM+sLjVV}B(W}cEZs0h8tYv;H|JpdieG_d)#) zdL*rbi-Uv>zZzL7iLD%1t&rGCMN(~T%+YHG^-|3KrAmih0~M46@a zO!#mNi;o4igmF3;ljl?iFd^ig=S$vPGg;+GYxqC^rSo?B7h7(4#wQJ=LFZAo&_EhL z3C!cUOwz|O$;jokpjX=Ax|RABKKmiB=vP)g2`0nGF(H3&sN;z^sqFEa_+@GGeoJG8 zG!5lF3b@jaklRjiMP}gX>Xpl3Nv9I6DecV69peon2|N;zH71c5LEnA%UAy+vgOFL` zQ6~AZat>cu?mXEt*n~e`9{j%f=9_jB7$Ni} z0}b3uc_OZ#f>%s~lihCQ6^wf2sU5D2aZ~!Ji*9ip5GJ#7!n`g6u^&JH%^onga606w z^cBX|iHU<|Jf$pfsKb>lUu$yiydu9xM-NYgncFwR4Y|G;kRPwvS)D|tHp)u{+AS;L zXsaAXz>9*ko}3oGDVMnuThyFazVW4Jhbhb~=~Tcy)??z!ir{sNi>JjUd~WF_hxB1l z_VBlNlvH<%ewx7XxvI{x-DM#9{rxPVLpzU|mZySJeo~iwO-%+L^|n zba!#xl7B_e*94RVirgj|HXy~oVULVH?lTd=Ii9~oBtD&?f@+~XOva*YCUVKN%Tzw<$U7?#KdjGPAIyW&Y{AitESwlvi7lri6qCm`Yt zMv7~6Ae-P?;K}$CQ)}vkoTt9vO5KWX9~3x7Ww<)V8^IOY$p?%GdEM6GioBJ`iV|Br zyR0z0z?T+yJhS$KZ9HdQ!PndH`Jc@00h9$tz;4x4D__&E-F9gQhE6 zc#^K%H4v_R^pmji{{Irb@%j(Lo^cI|Z(R#-{N(=#li&WI!+}#@(Oc1L;k34=up-9; zw0fKMd;aauIN9jprHhu1v>1R)r%Tp6Z5%k?3-j9YaY%1b%T_(m=b$qfkdrro^jveF zZ{EH#XfNjPG^O88AAKHlr7JIp$6%6^T~?*zmANIQu1xppSF3)l?=zg&PTC-awbSv$ zfd}iiM3>cV(huhPwL?7+<+agwl6R9H0OO=Dc6kMxwNw`+G^G8Y2<)7vT6t~mi_3Av znR^@zrZgB&$xD)k9$>su(`U4_8PQOJD{cLz{Fm(BJs4hkZi*_hafJ7IE_2+!c=2NH zy9xs)!Jqp#MpNo>a&pq1Z`L0#kJS#8$(A*O-}iD&c7@Yt+K!1+^_O)rnSQp!^Y~TY zw7CyH{2;vgwO6gJ`dABNE5;uJe3#a3jc!Zj)#V=op)r?N<(;;{zVyYN^jj*IHeEJ$ ztfB$6!wc48zl9zGn~ugf8jqw{7WE44()x^S{3@tgbXyCqWqP2`xWeDk%6-il*5r@p zWEkH&W^@^T=sjV+w7eAV+`eP|Co%+|b#;qzhV;n8;@WyxlHKs!nJ0A&J%<5ctYP(C zvmsqK@<4kaxLoEBbio!*d4XyH6P5EeudXZPk z>qx&ku8L2n)UR$2QJkW@c7&_yr>D8ObmF@3JALMKwE+miX>>R+1UOe>-f1q%F$BJQ zux6tu2|TlgLPwn`6F~DcUXI2wu1LLw_8HV%>5Y z5)+Te6GxXuSxD*KLceblL_pS+Tql`D(4F z6xUP_#5PzeuU*pMdcb*Vr2+Ym1Nd@z<>Wk8FO=79QC1vRcrWUrS{gFBY>}0MydrZ^ zgErc28Be=aw=3(r!i9hO-@<|Qx5L-J^Mi0-&R=&94TqopfB#nq6WlKTc;uuS*F}tW{H;?fuI=R2Wu>a$;#8p6 z52pGWn!Az}`XFIbC$FyCkQaDss|SQb+GjwM%j-tGwP`{RR_NRtRCx zWNXQ025+l4N5?M~r+RS@ndif5+`C#Cfl-t;%@(m;Bm2V%`P4eA5>VY`+ zfrj!n7*~6B&6DU%$2id9ZLo|6qfZ!?(U9WmV*&EZ+hFb3kuh`}lczLnL=TV;bhxj! zD>vt~a%L<%_jGJeE<=3tp>EOD%Q~?V1qQF)FIC}+A$xv#O)s_YhtsEyg~QsBP!%YH zP$%QeXV~UUT;v9tpr8I?No{9%aJLyhSiQ9)qc0y1NH$1Ed*7uw71um-y<+-bX%xeJ z0I{Ngc3^d-GHFeWO4kedIF2GHrRE)wUxL+w>|{NHLqLesYVa<9aq&m?ZC$a zb-Jw+Tw8cj9l>wj22=UcGs>-&SK4?Y|7C5^^DE%$n1XZOW?IHL?Z%EiH!q)OwDen9 zy)s^J>}P<2LI4neHf5x1mL+qo|62JoN}IFa{J+?SbpBt(? zU7iLSL|=ZND}E^K94hA5c!u)!@`>A&pLp_MS!MjzrfH(VGPEpq4vK~*T$^ctSm(J& z17#a_#S_4hL_9&5M@{)bgY)a<5Z5~pPv_4}7g-y0o)p9Dy|xWv zu#PovIC+{DT=g^q(%u>G z3LY=LS-i(@%E8Ek0f=oP47!mY28C>?VbF!Yo^As;(rJ>nZyTe$BRYDUl}QBhCJ=|X zzTywasX~_(i=;nRtyz7zycX-0xOIAEhv}78eeG!|!*scqgM3xBnWDUAX`lgFA;f+m zV@SV^r>1_Z@yz=SYkQ>h{0eO_Z<|?uX}!8kQnt%K*G<^9@YJBe`(om!IFN^9#5KXo zYH2f+W(C%#sT>bvxRO8H!{@Z5U`@_ikLnbms^A!4M8%MTbMjQ~$cxD!fmH=nhSRG2 zd%5p4QTFi2uw?;O1SWgax26q4m-9i%+1`C)Y99+>MxO)YaaEq@V+l+Cq|g1DJl)x| zm8tq*JjXcDLn=qLveMKSD|IH9j2-iSsYYHAhAfE<(3|>ih{+zN@@3+a-FJK%bT`s8 z^gwG{tIaRP!HHA0-WO9=$27RSDuv;Z zfZXWnY5m*F^WSCPU_?Cn3Hm83S9H*X#s^1b%uy=+9@I+}YK!L0%Yy;^^H3(^By-*7 zY{9FCGz~P+FGZu%JsF)aL{Ltor;$ciS!OP;c{xP#XI0}YMM-frv^|Yzpxu_q(crFh zo1E6F0a3jsHf(CDcL?<{6K7NgN<6nQ~b(_-=6Ivvf z*Zf&ZgN+?q+j=Dp$`M@CkkSxwZOv~`t4(8@ZO96F)Yff2&uGohd5V=F>{FgnT|^~$ zJr!le>nYO%M2q#5q{-Th^XujCyB3E^Tnlq^r$PC}F;2B^%W2>uOPAtm&vP8GU!=OS zk*3w&(BL<=8K)shLz`(Dw>8qZtmODPPdTnJKj?G(iZt+yF)Qt;)CUj=dB}izes12b zEkpgmlDr^G`Jz69GR6>(z%1J-VuWFJ4{sK1ke2l$P8s(Y5Hnz9=_=c)jvkE;V?9nM-`+pn)-k_q z@nWUUyd3E=F(t5li_Vqud?k=O-0dWP;$T!FZ}Rd!j{DHghy3_p^r9bHT)C$=L^71A zKXdwsza4&i5n$qVcYZ~Ftp@G*YBv&AA;KyfPPSv9p8ELlwuC<{3_~YQoM@8Cs{A%` zpE4Q$u`&mPEq=H#%3uKHns1Ds$Up6VTHCZnNB4zYgF|6r|6a9`IFU`;P8mJkR@er^ ziU~gjkQI2~upPD$ND=Uf52tcnzcm+DB%=ox@LtEx>$#Hn%fZFJY z^^@Ckr_SneJJvP=Uql4Zk@y~L>0!M?URhqrmoTOPpwL)}!yZe!#G$t=ct_DMI?Bq}zPF9Q zHUirSd=U^ZeJN#mPx^dDlh%p-d&1EZli`(r`@e=A2VM=I-^j=}7QQhOv7M@yfv69vj~qT?&Nx5N))C6b z5QO0-U6IOthc33?002M$Nkl&KP=yn?5jl6utPs)Q|LpyI%cj(RW(yAPjs!zg+ zEsjBb@veWVW^dn@O4`V;#ay>RSDqlgLgq4MvuxBi;7=ljEtBOA7g~2H8 zjZ?%hENzEv1j-Pg6|wdbqshen(Qtiw##Zd4agiyEsYOTrX`HfaWOe`EA@xaX;ghR3 zG96wPv-%!+%-o%^EyTrG&~+Cl*7ETKZEWdf+u8K2wuB9jnm-^#>06*5pVdm*rmVsAHZRT*@6KsT*vk0YM= z$3}<46DN+wH=*`cRK9>#7ENgu-`p@j;B6B3y~FoB8QidkwQPwO&jz%t4_^~EZru&H zX6AJa?>_TILwY>qlQzwha!|qpdIQV=-QLQo-1}Uw$(z2Gx;cHsBQ5cKFzP?jIqRnfpRLN`2B(a?^kG8!m*D{*Ci z=A()$bwNEA>-KTL723;|7gov2R?6#Rk86pptirWUR=}aG4U&dugjk1msXuZ`sW+fI z<&5&6ws8!P$*;%R*Ta*~|G>TnhWFXP)#dfW4?na4C0nkzhY<#yjFV@KA*pUEUSGL# z#a1(TUQR(L-z>2v9R?oyDpp3&htST8y46?zaNIUnqz0n8vV65qk#5hQ@|m=ij{$|Lls<=h3w4q`fc7*HAKJ@!>ZiO?X0Lq) zJQwM%YcudvhJ({U+ID>>Q>$Ip&+8P``DK%hF>R$HZ7NT!s`2e}k42TRgq4M@;sk;pX0sk#I!5g7(QF z?T1PSPqazL-T5vf)9}pN5-SL4!~SxwXL+p{xAj|ID`iCjkhhsF7(2F=*FwAP71y-S zNb7RTa8;rARJW|I!;j92`l|Vb<#6QC{=98L7jlREK`;FS{PJ;mblQcYyv_77b}Yl8js~6)+Ue_zH2b36;_7O@tl2~?0+ATB14JIFkn)dD{`bZt8EGF28AIPBD~}C zW@RdZA8#Nz4N|^bdm4D4p+O%GqbS>- z5zl$z8V~Kfs(>eJXma?*a{^_1gR?YxMjX$NIOJhU9vZRUpX zB1c`&p%{G$4Rt&@4Wx%BgqlG9UQcjo3O%a}@}sOOT%88Tj{KYkzMZEi5K$RH2XvDr z=SeiA^3{SXb)M7{<+Q~$t0$+yF{gY!MO?`b9GpH=z=8-&oF}hadzR4P`L)9p9CUz$ z>bn|O!=XZ6tu7K=;R(7^d2PW}yjIGqCPeoiE z2elD%mYCF2lf0s*fR$OR{;aG@e`*Ej@xup|_nHkb(a#bWyr2IXUPn|z`FVKy1Ea-UY{kFvtUih%O=KuUp|H+Jq z$mdl#ROjB)XP!2hp?nNP7=WIA_St-*$NkL;U`_tC5z2n;wb!g%PU5m-+E1Ob?KMnv zi8mwn zLtdU=+GfBZZBLda(F5e=`L)U`sUr<3MrFAA1URLEG<*m)wk`6ccGf>!8E3V&!5mj< zH@0YDoSBiah7*TJhjr?3CciFgV22}d(shDs#oz z!H4p^EUyb>c}{bud+YKgCx2jj#^MVLPWf71T(EInl%s~Br>NV?q>YczPA~t!Sw+5J-;Fi{){wrdZ37_=a=HjJ^zqjEv`O? z6rfH6bw(OKCX=Zy>SPXCr3b*ZgE=I1OPzsHRbNcqw#7B$$@6Q)m4f2jq*Gkex-H^L zIi}+idF6K}xVo(Pyf~G;qO26<)$6I<95R&^jN-U&XgLNRLWnpwKNqfEzN&3q(K)kj zt5T#)wfaY{Hp2_&rtI{tWhs?48I@=5%;+(b?WD6-5(J0<2yQTmj-`1fHKPuifvU8S z#j#>^jfEfO?&)zhI-LT{wB zG?^o52^fE7=Vr48rXz;MBVaPw) zE7q-JNnV7goIAxek(CTr5pGyg7nI+`)5FA7GEF@~)8mM%$QIpk8_PDXvE8}6mbJmM zHbeYe{&PLBL0qMOI&Fg~O|5zWgDt0pWNoIMyrPEnZ{^+t4WZK8%_l!|n3lo0wqcpu-V6+wFOK>c74x}r(E5YiFA_iYe9AY9NLj+tSoxU|VsZ&Dw* zdsQK!CVg^xbe-x$>m$UJzk#LRk+K$^jD{}dRXG{& z!T|m|rNL+_&;Wf#cL#lO+UAg#^taQ1QIJU^eBy9&T0XS~2L{8Jo_R_u1g67VZ@v|d z9Y1Ey${E11YT)CGAKP*3IDvM#yl~-y87ohnI+fp}%*_rMa53QEljp6s-m=NScfb2x zTj7VFq9sjcF>JBI8i&t!m)32v_{`MFoHUHSpM3I($bLJ4GfKh7oM3EW}4i}__Lyy>33&zY`sh_b}~^B*LJdE`jom*Im)F;zh>=+eww+{ zk|z5LGX5NqFQCtE+zNZNS`V7xfe+O>qq!6FA?8k_GXAUzKVJB(uErf9yyT~iF6g99 zR{0HU6%&*C7I{^Ejk!*oD}h@(dBv#5ya{^D2b1wskXO;{ZIBmWrTrE>2^*s!(IZBK zek+F!_Zdz@uX+HvshvY6JV19*UX{Gj2K%80I>Z%ztLDXnyUv+|59Z!A5mG-LgCMPGW4M4o9WjS(lN4zWCl2RO&f_VO!C-wZgt)982w_AHOMUa^b^Eq~mXycMyUR9UIbj==S^^bLxrs(Csw9PtKF%0gMPS zKhXyc##4erCJ%MEl1IuDZxM1?=@C~}jrkj%oF~;ke5O40imR(hxW*%q$$N8fWyN58quEznYun%#8&~RSPy=2DU!UEam2rQEjQvk( z067%c?!~Gdj2rvqjGygZ1lloewivjN%%`h!`2F*r|Fc#X%!aRj{p+?`sF-due?t?K zSM;NA4eMul436+~y=p|sDa?ThtRyH*bf zmnPjN83&`b{Z>D4RbNd1#CD3SYESs%*l}+uyz|aG;rrkJe%?n?cNk1qHD;^TxS@ct zg-Ip;wW``#jM<;RUIyj<@|VA~cK-C~GvSg9Ijq*hAcWjfHyD3-W63I@U7BR#7Qh2_ z>-`GjNb+Ol-|5q*n|LNZhGNDQ)FBgg>D** ziz8>`K9zaujs6jX6SC}Me6CUGH#9dntkpkfWL&u_nP1cPwQIK*%;EIdFh-X60=-UN zy>ozW>WTRcb0^x0%`sGzy>wQ2$TxEaU21&0BV3zV3Qs?IEF9Cy-g)ViTQ_goe9bV> zIQsgXCEF(U%;X6h57UO}D=+|&H}z^eFT~^J%bx~LE#z6;k{6Gu2ZK6XDT@!GUBAVc zT%_0Qfr_~fMm#&cO5dBU2by>)_FLkW)#NQS^fK3}k=G^~I_$UddJ;x;eQ~ObkcY~? zxKOtn)vrxF6>#Ml^!EkV$6yW#zusmximQ*u%|(L%jJ=~}FZDvBQzc^nx+w)gBf@G< z;68h9XBO7N;e+xZeP2uLq$ICP`JOyF5yr;`!(Ax{;(4}Qr-8!e<&|DzB74hBJQ_NK z36z+nRe2npI;?G99z4G}IiOxxSr2EW$o7x#)kI=JO5%a6`}0}~x@srbJg>KGbk21F z<#XY}1v}va$BPWId@xQ2;UT5pX-MzIcI0+tdMlM3e@`_p}}6Zk!A&6UUMK zyqvPUtDbS6kmlp*E7No!D_!N+0}aqvNgw&uv_aAq>FWiDjnLrbgTA_dJ1m0(Em*a@ zICnctO`Q&hj~tF~sx|iUkkZK*g%?y?wF1cTrk(ueH@~rVf>ZM!|M@B_2ni5Bz`UO@X0tFJvNH1$!jC;los14t! zKGU3Rk9g7&w96CoI?P~gc+H(h;w($ojw8!8pMU=OaOB7ln+!0cy3KM?Y(^Yn89Z(L z+^_4NaUWS2&`U#Ynm+0bvIYX#qm1h4Ro#cLCLH?WyMc#6({q`yh4{do5f*Z)2xcOqL7Wk7Scb7Z ze{mul+&vmL=yZ#%8u+ad+G(G+$QQ;nBS<6KySD8JyZ3CcQFNO+*iZ?fOWuIsfpzM9xQDaC0GN+Z zyDa|gX*%DGl6QW^R}7x8?v|;UzNwl&ucue7l%!j(G);LS6aTBiir}xVFvM^je|7hf zv7cvsrC9;E_QQ7*M*Yz1Cru*{ec(E99{SM9Mw$Ac*Q(yiF3zzhnjFdF8f0hihfW%U zx7aZ98B;Jz0^HZlUhTAviwXyPuER+6K_&VgvOf{Baz4482<8q*Z2-T)p{hG=_j5mtdch0|W)ZS%6dgyeO~0`bQF*q- z)p_ynx^#8-op(*2_Og|k!9 zH*b%mwQ+G5*Nz|h%wUSmK-0Cxedvap&JvmY2-mfl^5v`AWLmR0>B7V|p65=F>&+wU zt?zVEn@jK8IU0t=!-zJVK6iOseW@))+&B&CJWxlr=s+Ae_xfiue~R%D^^w+V=8Krm zt6i2<>DF7{iG5VHB<{*(+qUDf2A_@`Dmnjw^3$SXzs@YF`kUV;eMPB!!)D;AdIKc(1DQqwvU8Mm#>7Ar_O2MX4c}* zsslrMK6P?*&?pCtbH^PCNeYmInE%0_mzkH+ub~Y09e~di|ssI1d%@b;EAZJPexNO2GAtQKl+f zsg_N$`ZK<*EAxwP^2QQ-N=K4?aTxT# zo-*LUOdy|%8YNlMOJrn_W}}u{4Jz0)bs8fDW=zx#{>1q)0||$j!5_kU^)BEm4aA`x z0&mAXjpOB4b-(FZ8lT_9Z%WhjtRH$+O~!KbFmRbFfN+`66*gqOSbWd3q3*f&2x_v-IkuqCgyz*Xz72U`<`ZF-XB@F zw$oRsq6J;j(|59RJZG4Zh;=GC)&)AJL@I1b+pZ4;3RD1sH z*)eLkFn+aX+i*C2_FQ=J>_xrgnX>_}c`ZYuZ%4g#8B_Y{Z|9Hp3?G3ui}hJx8retJfX19?FUoKkw^$usEk zEDqgpbsn5&(sGXt-3Tc?lSywf*yAWpL*BkeQksUcxUO#If5AH$WhRoWESLZ*s3(+{q$E98@wEqIe(Pq<1? z*o8l(w-|jzm#XN^H|T3Et||-m4`W}2I25=hy3(({I);9x3vJs1eU-hs zuBqYRn(E4;aILW`F|Ig$I9V*`-LrGMj)32y&ge@vFhOUOy*ujcq|2OsBOe`FX8p{m zJlOAoY2yqgu}lhQG1kR2{h)qR7UaWh1MGdO=l$k`V@l_hSw$?DK5^oN&E#pK=a?YB zx2-HQfDQ*PR0a5D78bf2+gS9g$-cs0YF7$L*DRMAmya~MRYz72kJ?e& zKihpnB0hP7^& zbmR*y?h&{K2R5tY+6<=}0IrG4GvEE)(&YKXJouZAn4a^%y#iO29rVZp{7Sg$J{=LB z8Gi_*01wFIJaDf>Pvt~le~^?OJQzLw@ib1aiU*eoZ6LpxUco~~u%L%QbeYmLj;kdB z^B!@nlgY|SJi1IY>hM=3Q_2H_1k@+TVL5TNa$3Q-N{L{xz|}G81y{eaN|V0Iw%MkYRsoczM}4iT(=HRr={!{7N_FQxn_ceNvp3vz zV$23=IO?6{NelqRb^)220$8)>2c109vUx0n9t0>5<*Y74egLvk0v+oeIJ83Hh z5wOSBaaZS^Wo5|LgptcjCz!z~pDlD^|*GMVk@x$#tQx)WNp;syee&`U)OiZdLjUPVjw$I-~tK{I_FVk_mwnoL;HT z5REtu^lk~`0>3(3^Y)Q^yxpqe!R-q1EU-_9Y_J?DI}PmO`E#}x*3qL!!`RrE?MaB! z@5=*8=lo>^mgg@RF=KD%u3cet%MSTunr*Eku@}RO0}QT8`uL9WNoRh zDXvbtRJKW5=WVeSh4LGueQm3+O}bL5gDU1qnIe4vuh#lnfvag`N-u8*U0*ACKz}3s zcU-;BU|&gZ^;Vtij*p|#&216;oZXNgPiShldchSw;9-MCQ#Q-rpVc8Tr_W!}s)1~S za@r!6D3xTY@dqd;w{51EksTl(m#HUxRUMj`*6IY|GphaoblJq2m&5EWbp8swY5yKw zVC?27j(j>EuME-=H;Z^i8-=`KB^e_H`7O z*@do?ISd63lr4GjiS;!uTbGwOW><1u8I-=JeMs^nuaX_eNH?Z$aV3DzO!2mXNpDY+}mWR7TO+bBE2O zFO1LX=)-Mxw4uvEespel8_h_z-!B-5E-+f0d~x;4Rmnb=;UM1NuVYZ*EZdBYQwiAA z`iwTEW0use?VD{tiwGu@@L`aP9rVc;zLB>qQ^o-IFrrihaL`XzUo+fbu_U-!*>!k; zZ+Nu|p22Moi*m|kvT{;9*A*gJ*=D5d??RcRUwJvAD+LaV;X(AObtPkDArBo~DGw{# zSYM%sUI_C-wY z`;gTMzvtg94dP8J14LOFXO0pxbU9s&GSBR1mV$PLlVGp|cDj;&V{zK)D<>M&w8e3q zvHDik7CR4lyCp}w+-A_$b?j?NU&Ucv9dz5~{s1z@GNDW64~Q>QX86nV0rxTwSvyUc zHQE7ih(c-y_-!^+eA^7b2K!1?F4_!TBPSiyFFbQHyzOmo4SRQPvw97$)Hg!b-eIh3HUaP4amjbM$CprN6o&p*4MP{Y|z(kZ3cys2P<2> z?4(nJPGFk+soTG-6I#<|B)U@8SMS(Fbx`_?K2YA4nR0`Ne%j)q&cFjq=Vmq4*W$kG zYs7=e3oCh@fli^XIYy3y*TJ~$TovP7wkzZZe?%^w(fT6N3kH1Wbkf;H^_|A<*lYW&f*C#=FC-WoX3(1U)Y~=3C;q16Py8!- zNy4ef=sNizQ>On}Y<@#~ND~Lxr|6|i*E9=xBy8I}Vkb?TeIPoNvK%;Go`sSVw%2_$)p^_hnzGAzi|JHQ$kLf8sOqi^~DBu`XANK`!dvY zBy2QO=sT}WtGuR0W?0Wh^=6BsA(?tge2ktANXfw|$#g4QRyHdm%WSFa=*kSE0te*J zWkR;KFJ}WraOt!hBhv8UcZ>u07xaXer{lX0SDtyA1@!a`xlulAEEuq%oS`R~98Z4p zabBIC-*>u&Owbc8PXli_8qo8&d=q$9MUS*?c!=pitKdPjp+V#7GLa9TI1M~>#WioF zTwY5f+Rk@MuOm}6uFgXpJ-_dCQ<-?~JS-Ki-FSdEKE%s#%?z2RbN(D7zwc?lsGEMd z{CqpTCDB(Acm6z|I@{JM+ssyyu8^tMIzzsZ9dLP_hZt9!U~Hs4YqSHIjuZd3j(w+Y z(=jLb6mPGGcC*DFUp7Wmc#5%Vk$hlLTo34MGUauU0ouoo9Sh7XVs;Zt!Rm0zbTG4J zv?1)15C>Zt9N*A2X?W90V8#S9P|+ovIc6L2VQ`4{sH)Box6qZuzEU1#JAh7Rx?&w9 zl^OYax%Hy2(D8wM;{m-wsT61nY18al_nmM5O@4mu&ld2|j~$TyXK&1N`>K3;ktyW? z`(MbE({g%scEH;VlTSFD*K)57qVxIBem1ymvHfA#vB)g`BaEOxE3FW13N`IBcYy@-btqpCD9 zuE=G-OFZ=HlXt~6vI8-$;=%Zq{O)J9@!MQhbcJi=K%NxWTWZ5h$24fNNlTnI>WHnG zYZHpE{($-?b9(#D(jPmSS9F}N@es*G+evLCA1^15>paxjfuwAShc0c~%pha-5(nO) zXZ%a1O?rXAzzca5^!>TMy==X%@Gb6)hUsesuAav75DoGp6{yW?2G)qM;TjpCN4qZ$ z?3z7;IN;}nGZ*zDTeJ2y$sQBReoCnu0kIOd!zMVf$<9YU4XQ1W&K!$%-=1#AU zhpxB+zJl}T*Uon;6Y=Ww6`6X))n)R0q3_pqGA$LZo^Q+p^0-Xo>t#D|Ttz$Evy8GR z>uanl@BsesQ9A>O>5}YgfU`;Dl^8Ij9Id!jMxYyyr!HIzyY-gsu44yH6y9tz1Bj#0 z`dMes8*UtV3YLIldsEkpn&Z?l80(!ci%{{00>I#NwBsfjThgseq$`+Ty|s$KDgs}0 z2ynbDHg(%pZG^8SA3put8?811-}jn}>Gb?z`{StcD932-;;%o5$nZyhDCd&95?p#($>5eAPoK97|rhBe`FTVIh*05h~+YK#GWABl9=_8{e z`0yU+^3adu4lk3v&QUjB?E#rM)}FSWQ^ovcPbwF1+|)^Er_N7?V|VNehxcbEtI;=n zUUp$jZ4iURZZFdGb-!sZv3-suxEnv}I}K^DneAh{^_@sFuK_-0RBh2Ji@5CS@?E{Z ziohxY83OnT2M!(x*-%*nDl6ICQR&+Z{vh5aZ45W9*+Lv~Okf0=K^z9SdJPyrJ~%;c z#9mgz06*lzNoD?)vxzo_m*W{(1B{_%=E+LNyGfSSXR8RTBJk=*U|2IIcWTDuxb}a0 z{26sTuT7WiT$6-u3pwg}@7}%E!E1`Y)X%Wb{>G6RG=#-;Tw{Kr!{7^VHW~bxnV!+$ z%%x%!`4Z$;oR)Jm-fcVV5pmD&7>47i|p7lecc$8n$Ra4yXAOpZG+W)SFb^ zY%${F9h23DBQBj+$Mts2NIQDRVe6P))Tu@6hr_I4-kS5_n)2PHeRy!#&}DvmJwr;a zc~SSm3oqC}B+t<)*Q>=Karp4zuu1i1di;X+B?;lN&poS|&Sk%+ANtJt@t1D>q+d<5 zia@^z;9t+p>xHXkv{3)3TeMXhRo|FNNgZQG|E*iv=jNLB5Y= zz4aC0iY_BR`0DMP>+DkW~+OQ!(nfek_hgIB)9D+29oD#prX4Y zo<1Xfona+S6Fq3T5plXzhMMV6nGu_@>7T@9`Yxl_gR5qV%#o#3+8(T!!o zxN6+Tmaq*o&014ajSdf@FmPPElv9*-aao0{KSZXq9C)_UbjA7g?>d>h4C`bfT~&z7 zHh%8(;(LBw#{HI25dhKGJ+TFG_*yTCSo z?yg<28A@lhsV>iA9(p8iY1s&!0WPQ2PuVV)z9L_vzSj7V{m8VE^)8@I_$*Di@3g$WslDqVMIhuZ=QEC#z)Q-WLMKM69b!E$bQ1M!M(vb$UdjW%`_@;LEuEWJ0$2F1 zE2k!0UB6Z~uDQNyb3S*t;<6p2zJf!lEB)x}io#VJ7P?)bUKF~LpFYJ&kB%#Ah~0j1 zT=f;%O@i;87TZXBkpF=u&z^Yl33Kr1I9|AL!E}=QJm(YJ6;Bh>X}XT%dpQw5z8|Oe z`#7BN!ahB9{Kx5dD(+Q(PoH7%tMn*b#`De zxU#t`vaob~`?k%tW07hZVw+;h*FZn2>wgOTiUGCnaLrl+P& zmkgvn{*WhSNM6jIJA3A=bbEW4l`pkx`xf!j*+-xc@}`H(22ky7rLXW4my_!X-`wXp z0ZiaK^|N@^RJM!K*TmODCj2tj*O)(epzO%6s?NYS^&XoX%T%YY#3fA?y{`Hy9(%@B z%ccl%Su7o{<+3H;I+5QaPRTMVT<-q^+4Z{w$A&9uB$wUZ`wZU_vP_xhAI6f2HHl1p+B>|eY7;&0|$Uq z)tNe6;g2$4HWHgM$MwwZ0Lx9Ok99tIRUNG3!RufhuC+Y$)7KH-)a_Iz=i!y_>ooTv zS#l4y9vbZ{`YIb%i|ebk57~zu;N&`Vw@zQdXtB6bKk+Z|Uu*XOqVnQ!49lTlX%bTf zsi0gF`0Gsi#$_;Or+g`nIf{yd663(aIAh}36u+FFj4AgCHXTW$&HRQz8g`TjFszd5 z839EyLL?JGc3(HzdBg8%xW}{WoC2nGzq@yC4aYSAG&Or&l}faf_SC5t!X1YX+jL~| zH2y_rN^jE`9O9k_=v|qd3pa0TE&TC=lIdkLaJ=26l6qSBBQBv)Ch_2Dkkw@ZKTa{& z$Xa`4kE2Yymo-%g?ASPpK>pzF@^atlwc#N562s%}B+QrI9YVF*jMoTpg|^Q(hKIl*=RrQe8opeMf%9L#N4$&?HmO zxQbq;uLH(a8m>&|75<~KU z{Ka*qq^}}d*p)W1%4 zLvnzp=H$$&(|7l=Lt*Qd`V&7WAMD=AlPB%;uXn%u-KLx5g^lC`#tgz><2K3(_cp@Q z!e?E84!Gk0;qc+4(f*8%jM@p5b?LZIWB0uFEZ_|MMq_rLGip&=L%$&9K1`W5I~}M$%3C$^c5%5zE?%R3?`d zY^d*im+gS`Dr&z=c0gPhy(U~0hcs4>c{`Z$K%RuUI>?fTtJ60$&@vkC89QWg<3BDR z1B8?{`h-p++a@hLJbwIm(SDJRC1L0VOA{9x&^hYcQ%`+CCxLAY8@KGyULZSd50xr? zZkrz`9=)V}fCvlPi~+U9@Mrc~<&Ir#ZC_PheyUGewsmbrUDYwhuo1ne))-<4`}V+G2RXC&!*v_-&-=rmu^_m9p*P4`hR)2ABTen=R}Y;Ol{_ z`|_zwmAK}Wl&9S`OY2NbcoC*`G}NXhUuK@!@T-J=rGHWvisTW zh8S0Lh!@S+8rIbNA_vp?RuD)oCvepRNiDV%oCaV@X5i7e+){&i(zEA(xFyaNZ*m2y5zVj zddJsmz_r|F$gW5yu`S36Jr9%*?TNKB6}X~zgw(Dy>1$m%IS(jo)_)UW7-*8oaaEkO z&Nw|}YGVgVeMn_X8ml}i&qf|xU&RCE1RqtlD8^OftSZgiTHxxslHw4Ttv!=X8aqB#KLEs(`IpX~Gh@SMVQl_4GMpVl3*bywW-x`L7Du#i zgqbxd7X{B0K9qv-?}-RSKP^KlbHgGLq_neQBuNKCKQ}PKqd+xlL>B=M*I~H zhgu!4n8bC%@0F78EYOH#$2JzzQS&E`9Y13pVqDp5(vJI$a4nQ4=OHI&oeMX1@a;Sx zQ`X33r&(k&WvNO$C=C^Y;5?95r<~9g3}=Q94G>NMIC+Ta(Frsjl*Sq>=@$I8!PR)k zb%k=Wfz4PZ(IGFRCmzgc%$bOJsK!m27C`Xei)>rZo4@704Z&A4B zGA+PWyd#Ut1aEb?7BVdbuCcDP!8PZ>F;DG)JAbVGHvP|WrKos&Ixt*gTa-H$MLD&^ zwa{1b#$cN{BVF{Baw_UfMcEcSECN^4l_q^v{bLa5(zs@$h=&L6K5F)!x++)}1Z(sp z7adiu@4N3l(`o9w2ka{jqR)b1FA$!)JaJsor1#I9Ib#F%%t~Mu4mhz_2^f1?w^e+T zA01ehT=6!L{d5Q(*M9Wy2YyJ)5*wDVusnz0_vtXh<9+wu7cO4Ds1C$Vt9u^DBI^${ z95341Cmw$yjE#-io)pLe-#&2UX&C%r)+vKO9?oAlAEvZKk3b8FoxvtAux%G8S-Lhj(*f_d1yzYU!o5N3f^vutes(CTKx5F2V$8jaV4j$pHXMqVq6U)^)oWN zmYt{w1%hKo87Zsc9-Bbt<1p6Fkk1~Vm*isIZla$43Zl})R>oFLb@dtV0^C6H1jL|X5 z9J=@!J^&{#BP&O6m0W~MpPVuow7wR;Be^!~Yb;ajJGSjZ;tw+$iQu>vWm}0WZ72P$ z8eD7o=57Z}UzL~HSLq}=z5rM3t8k}m3OkVNc+rOx54HWR3Vm(XmE0d_-DbFL>)tny zaa~|v^)S}gm!+?@GS%Rk_I2voE%=CSTQ7Y`$_PKQb_Nh{IM2Lv-h^STB?BnK>I~p? zP??#Lf)U%O&iC*}j2o59odH!`UDLpDgz1E)BwyBP7u$C1){gBPZ8RJsh6CZj8wN`! z=3vkR_xw5ctDd#J4^86oX6D(GFY4I#Z8}lqh|R8nS55|)6u)(Wv}Z3*nPYVST}Kq{ zmK^@GHUeu)oqFV(e87o+9!yqz7Tro^waTVvU~N<3^F#$kN`s;BfCsA&#zahu>;`nUX zqmzk_9qPP{0^?qSmp}T!AS|=V()OYaJ@o1m|NaTn-4iEHSci`KNLmybZO8^ZI#3SGW(J#8LP8|Ihe1AnO;_}j* zxQe39jkV-VFT8naj_<^YSDaqO01zktG2lTw^Q)AGbnw6c@uiCwGz(X!a&F&g2h7mP zvy}h|PtI4Jyy<;pAPt}NS>1h;TYO!=J|CWa{#4krcYio?_@K$YUTyB&>`a)_%kUU4 z(s%&5(-*I48;>)Ikbn#L%gekcnUu!rp#BVs9+)@rfGF9Eg>u~^-E#3@ zIS<&j!Mg`(N;_Ry0v@nA_~wlRKd;C?EzRL`#L@VrAb5dR0#9 zoQ&QTohYLbqHsb}l1DeLH-nd#e>u@I{sI8rsNj*`IRF4a07*naRNBcKdW)7742C=# z9BN_(!++uGtgYGSSb1jBT-DTUriP-{aUnO+>Gc^{12edjk5`6X>8!?IMPL)eNe^i^QFs|tdV3O=g5&GHkgBB?6!|@W+yNk$4(Y9Cxth7G)m%50`Qh5`w?t_ zhWzh5ai`6caa&De96L~Ta`A?dWjG8r`J2Z$E=Omx9}AsZXfv>bEVP>p^w9C;nx$|I z;&9FKF1|mfA?^7!>0k176^;8eUxpP-OTUQ+l({ z01z*fm{r^qyqwW3uLB<6f3t@a`o|2se!>@?{DSsI9I^UVmHzzsb74Y0-B}F=p~v^% zf4|LG+sJIByq;I3^Lx%G{+HJQf42I)iomN00c$^0kyGpIFT<%1Y}G*UwuUNVeJAxJ z%xoupC*odWa8yLkpSxhEOCCLTR5NktJ29|Cj8`f!3r91UG|O;Ed(zSFT98m0 zg*b)}_t}yITX#T9%8ne|V=sbePid10j*fcoa{&OMV131A$UL)s znN!C=3=SlDF#C~b45-+YX^gv#1Z6BUaKgSpOv`17gYThpUb9{2=Cgwj$d}m;*mK_6 zGF#N9_=^^uYw{znDkqZV&YZ%;zz^}_laA={A_Hj|C}Qav14*PIE*LNX1}2UT{4zMk z(b-%RpKo|XW@KFruTBIgIy?p5=+iN}Ha)KycH0|;p}f7!{X0&;J#>S*hAvSLJXGnc zKa0O@7POW!`rsur-KXK2<(IoO@WV-7pZUyZY{?_X(4RhiI$WMoeNkr%f3Ge-=bM?& zECKNW(wK+U>s16^%?P-Tt14K181>(VdfF)Gql1uf#OwII~nZ&4LU&wCBR6VHpa$=TrSU6sh>U#UxD}phqVHOThZYI1oQG z7};i9@iWpm5Al8O@eBjt#@YJ?&O;_^$MU#Le5X7>1G#v6&GI&!xNTdvX^$h}rV}`r z&KWyj@Zvm>Hl>HtRwa}3;4%$qEir>X1P0R>jW5Y$PqHc2jkqda%ERJtm17z?n;C!V zWT7t=Ws9taYm&x!sFg`?KvH@oToZb2am`_~FQ-?_LzBJ^7}q*o891&DG8qqFjJQ_F z1g_KzX>*|xUI+Wq*DnHGWyq;7@0gYiLjhNymC+;--1>n}HDG^MO}F8ZWymn>Dq+<>Jsyw(ydS>b{;6o?b<2j$qR04;%ZS{2U>3Zh! znzJol8I*!&=x|MYhP_;g`idMqwZ$Y*@U}R$@n8WxLQn0Mme6_IX^HbcZsWl{rH2lh z9Z;Ej*^vw$`fj%x?0{_mE5)7C3$q>DHy8U;#Qe6ohF5q*U*OYEzC%{-qr-e#yrLVr zkTUTuXn#Zoa0$fs55Jl3fPEw%_9CKAFbn9WupYm9B}~opf^4G(T06(QlP(VMK^a3A zUz57UHF?LOt3S|ytIdhq6%Xww?GzhG^9{Ys zw&}&L>IAb@Bzf4W*?^-X+PgI0(gEB%rQ4riwc+T*S2j80seR$D(O3>Na>^x!S!fieR3N||Ug#4>H|knKa0 z@qhE>?Bu)!x+3|(f&5Z>1rL-%VyBvL?XIsiGIi_gw6txmuZ=SGgR9E9PX8C+s<_?l zEA33#{q8Sn0T$y^dv){!$kBy0rs9IGH%HIMp7!@l+|v zFb$ajV^o`ec6_DH?(spMY=C6LdNuIce3K10F<-I504g*A(2QGdT-+eC84}mAL9)Wt zTUpjPQkCOp2*qe5gV&k zxF$HbOtyAZ^qmLtGF)qTuu4riktV9VF|N>XdL>-FY-3z;fS6vUd!B~$E)#DTV_h*^ z(T56M=@(a%DR-LLfXjpP(5SDy;_CVu8Q@r7$-6DCX&tl*qV!g_=2&La_S)d;<)Xa`US3$QH=G~>{R~Dalj6sYsPn~uhJDlOwV;C)mNw2 z6;~BrhhC1W%k&E13g7Ew)28R-Xl)n{TQ?2M&SKw8^vXY^VK9Wj8=P|U|$QF;JeNafJ0u_O{RQ+z-_!g1Ls;?h!!Upl7%$4LEVY2K$E0 zYB|`h9b1bsgQs4C)890@$!5`^Gu-3DAPYKZI-}op0Uc*^@!COGl??$p43aYQhrPA7 zXfX99Em_s(AQdAtNa0G z{YhWZ>HhV#(?Q|oUsrw2buWi3Ym0OL6&YQ>xGwaSfrVc66`53~P7jRh^%dVyom}(V zyz>qR9UgkY)$B?xQ@^-6-|&#O#i<=IpB!ANx49a}JU}C+SKykLh3g|S7W!3V2V7U3 zUV*FXEPBL!r^iyS60Q}#BQJ(+PayXG5kJr?>}zh@ptnT>Kg8vvG5C*h#eZsRU!CtZ zxZct%L};788ROc`cT8~=E{(X##?qcL2s9+0VqPxC>#O==?7hZnju@kMxR&*+mA;DaSSHigZn#$Ubq3srG+c!*dKlx-3Rf$Ojy;U) zAnFs-GhDm+ujMo`u9Uaa^Ey-50s5W2=xdL-f(3a}elZW+FL;RTK&-FJ(${Izhm3t3 z@y&S5j-7frDZym=I>80y?Ip*+Q&AC|`(_+O2oUVIQsVsSfjwgo0^w~FEENd9Q3~Qi zgKGi?#_7?af-a4b8~PHxs3A8FP*fU68ArgU;BC|}=Z`$e-wZHdlFoIW8=n5VTqx?R` z>$b4qNO+QT!Z|eY<(}*7VsI^ZsKHf01A9rPSpQ95Ri>2F zqH$GSv3jc<P$<0Ez!&EYfP_7UwJD%GOAM#FPsT8<1d8!?!G7N zJb0h@lf9IT8KaAcbA$Yu81dDENTWHaj+UJ6^b zZn2HovDbWJTU6*u;p?d|B6|oQRk)h1Y@sWC>uaPd2v_EzSzl9`7U)V2!iO;;Ry zWokH(J$nUOHmXm`)aV#JJw#_yzKw@mUke^mTyfekQ-~*uR<^z1s)S3?7WY&K;i07+ zh;;>B1G9eg)oq*MO4;ZivhdHB~&Ume$&2XZ@l^k^ur@8WJA$Q)-CfvqCw+m0N|3nVixK(4B; z0*47>SWNNElnuaj-v^Pn=9w4L1|8M6Mn(cKUtXJ~A$wasmD9VmE_*{p8m3Ni8X5FR zM1G!+8IcMephv!ZOqPfqMhaRu(l@l@+MJBo#vwJVs{Cs-GEEwn2?J+*lZN~H5G;T3 z!nY#WeFkQD>NpUumWK#eQ{0y^gxNq@9j+J`l&FyDRt2tJP7$scS@<@Y*2!q=jaVU* zaNxf20Is>C(HE|XOc(krou9-D$y0gK@Cq`*~T(; z#npJ|;0nHlzUI0DJwmFlg|0-n5)b`~d2n30SEPyR3~9K}CzS~tybkgV-s)s3#Hn!kQ@df*wsX>!dh)v>WLOUDcw zHo)Z`bYoh??KeP&4>Ou*bkUir0R9Zx_y82~`5-%?Ek70SN(R|294Ohmgq%xfOre^6-Qfn z;_UeGvW{6b4;}v^wF7IL>Y&;*W&jXMGWB3z9arlpiSP9sKde3e<}^D)Ln21I-#^U8 zp-%Y>Gj@g8`!T+GLh`!*b1g?zzXZc0H`)gX7$(!{|Hp znp2IYCohGko|z3hwv5<`cnt0`Q;2%WY$0ee@JqS}A9~P!!<&^;3tXvsb^ZYDmg5@x zj_{wh#f#EcF;URd^-c4$D)fJSbnG!ar0rIZ`Wnk*`r5Y5sKYg?gH5>B*?}d&)nyVx z*nvvlF~ZewsKr%wMlWjdW2InbZ>sD-jH}7yJV;mjvI7yW@Q1xF{MX!0k`H#XN?)l9 z^fT6}ous~$?Q1*V(d{epa`M=S`g7caHu7?x>$tzgZ}%PB;0j;Ns=F@LA6DOq!61&P zCm;A;fGhrR-sii0n?9dfQ}8f8NP}!Dr#AX3{5GhZtZa21w;8caF%R$rZ}81EHo#v3 zwC(FSu3$wd>;Uw{x9clBcwTLBg(oH!(B>`Z>!1%6xLP?S{fx!hHfCm4;ksOXNNkb& z16EEEt|fn6IZlv7xZdp0MVG!U;}_FI!rHTpni!*W0cy!@2fhEMi_)0n}=1=G6M!r zCXBwRlJE;qZ36=~SFX)!IaLS;cCk@4(`nnLUX8bkz$yZ(2z>D(z%0-88%DxQPktzj zKl%IN%isB5!>JcehG$=RCcN#x{C*hTyxVLpHn^9-Ql{shf8IKxq{D8fG`RPXk9;Js z3AFD?;&J&-<8zOJ5;~YRSW`ihIK2iMcRHy)u;XoFRsPKSVK0L{dv+JuRLNF6>~g^j zCzg~!qnCEA3)$7jD+mFq&iIs0+Pi)$+&y-vaTDc!*k);^pHRolpC_Jp!Uh#Nu@2q- z{O3P!1C9KC>ZzwRV6$0Ezz&+ukzcCkuFq^X%>d7xciyQD-%p0eKKbuj4z?+5+_X(6 z{p`?bVOOowLVT8ZF_`I2H4ZO<`a<1G^RS1je^wD#MWAN{RNYjcyx#JHTJ7TGtZl%& zMca3H-^uG7-_+4w+Zgh=pi{jVtlG0pdylE3?lgO5dNsi+0;>ot3j(zHY|BtP187;e zXvoA35r*u#MrPJ(_6MWO%-7qX)4R6q*s1l`tdGt13_zgkT0@U>!G@)59NN|pL3d{E zrZytehM-%vhD+)|xO39L;_9PS1XdAPMc_XL0t^BTjqWr@a$KFYDZS+%-f}FgT|d;5 z{LG%=Kem}op6QG-D}cR9ssiy|_qx|vhn1HS48V|v!5sp2-v&jDY&L+z@)qp3$El** z>pl2@-puTb%@Acqg9q9w55(g)o0t-~<{qD(17wwqH?lT;m(x~O!xtq2s1OHh(2-(4 zAVOa{lc3}JM;+nXX9O|(hnZ@;Ye7Tm*U8-%PeVXJP!bhXCBsH|T9XFvd3!bZ#VYgk^& zOcZ7St8)v$`dDgrAXf!YBeoCQ8<@cUJ7B5}qs9971naMTlmb@ZUmo;+7HGlJ_k+-*gsIKI-_RQ(}_J+1{Wj_wi2Tb!iZz zSD8Fb6-IS9G^J^JwitRzqqpsWsA(Pou+1IW6?hE7lzB+v3(T{}NYe&QAU0<)$O0tb!;j2wx zN^4xF7)W7bV+MfWHMQB?V{ae!E}?Tu$CM5$7(DpULj@LQ!}IjaG;oYkdTn^DiUS>% zyRa|bv17+9%9*og!h!tvd3x_8QR*hq5W3re`ZbSC)bYeBD&f`oV!RhQF%v>xW)HX_lP_ zEU4^g8kVA*dcl=J9F9Dnn7$G2*uP6JE{1dv&&{xRk51d#oGmT&mm>@Uf%Tm2DW}71 z=4QiO#mn=mvPEyKoYZ@wZV$1{t*B|4K5##+_lqjqRiE7I*}!o{X_Bz0avBi5mCl3p zAyp4j9S6#)I>Y@}S|)gP9%@ekqtT~vr*ZZ`BAjm;ew>O}XbcI@5SlkSabOC&JMFO{ zBQEzzo6?)ti1g_Ts@xxnW=MTBz&jY`q$A^5{$^>rEg|C!euedUFakCFx;eot( zH;12hkdV-T3jo1g)|tE1w1SPuCJuNqDti7bJ^y0rAc42<4LRam9mI+&vm6qU(+;A z`U*Wxyh!P}?WnSC&O<+TAgzP^hF%q}Jfq%L@leRrWCsd;&7Ise>QL<%3tJDqCG5NB zYr?IO!|JqN54-z3wFn-b*AlQ3Cr;S%5OgFiEB}og;LFkJY!uD@B`iC6L1`HrvCe8f zivS(t9-Y~^9ztue!A`Q2?PhryOS0I@VCveGVazfX%AAdM*#m%e+6-=`^7P6>(E*pi zk8Kf{Q0A0gu5LP*n#>!_n#U+CYP46!&QJXEsg-hko_O)3T(CljqPMHe05i?ccxO22()? z`oxU``%STdI(ze+JbBVKc7|{6bI${Vt#tITEvHVM3a@?bYpqUryUpou5ll-r@oHl#C8w{Vh3KueI4sVCi+VI==K%c)wbQbS@d<9 zaAjPh?6>vPhh%&Qzqxh*2%?kYlh)W^1l$nd*y0G%Xd@i=F>X{)0>34HaZRJa##qEH z(h^6JSiWWP`IWcQ{Kl}%sj*|t>X8F`>_iOm@Bpp&LmGaw&Yfw^XGM3xfgjyx>DBHR}k0SuAoC6 z;I~d+dDa?N5vbGHkgCy<OTZWmqO;0OPiEzePmJ5Z z4?HsP!XObm*U_xXr|BNN(k9S}##v$`J!U4o@WKmrTsCbFZ&m3i^U{QTeHKv62l|GM zY7;JAyktvo*bE=r=r};Hr2n~`+%J`_ek(f*JX?%?jddJ?3wV$oneEMai0fb-53x={ zua&+cQyyZOGXAn>+;@6J_1}IS+qOc-u>?xDoVdQMGQFWC6sIpvgu9L%)SfxJjEBYQ zEa@2lV&5$434@`>j~_REjh#{A#UIBBy+xNFee_W~4xYWYd;o|z1ky36M4(Qfch@u+ zdgjb&4HylF^;%A{W80>Z^J|f7{#?B}E_)-pQ>U-)cjjeV*KR>$YI-ir*bBWK>Y%KV zUg4W2W!q9;@gs}67uis7DD>5BCEvQgpbq9T^UUjDT%Wja^l0mJP2jhGx7Jr=Qn`?J z0S}AB)p>~dcK%9rrUBPnB;(KN8NYS7Dg)%GmB|pwuxi4!q$|sWYiip{JVf$34sCFC zywQ>CxnGp&P6mWs3$GdNKgWJzcOE@xFU(`#2`uAJ4x#PAH8ri57^-L17tsUg)!_%p)2rUeJXex5U#h?4uO^7;JA`Ec|<&v`;g7J zT3XQ}{o-+L&=un{5<({(YPSPa%lhFaQu$_mQTTl#V-GW51!j*f*Qf519L;h$wJNpZ)@St6vT~_ z(sAtj_zcU(LU_Z2CoB$c&3KbbM+3P~kj{XTWKCtlz<`7D@_gXQaDa(~2WUal(<}y8 zc)1C#F%Oi55y*Nkc3lFW{y*KGq0^1uK4 zzlYbq{`EG?plv$0_a2`aKiD5Ol4Z67GZN^;rtv&}Ki|+|bLri?%NsjGD{Y%-J9&w~ zz9`sbbSvhC>#B5iGyj8qW;u?v6S{|OrQR&4GkRwB6+4iJ!me~{i@j_kdkt@WwOdVX zM*h+P7QxEeNVNf+LfP65DE_*n%`keAPg2rXWXjw8UStBhwaSOVtfJjY?ezd~#fI>f zdzRThS7*ZOAGkAY-lP-egnz0}UaoDvJ^e>N`qA*#x4q4Ll{V?B;-Gub!(Z?a^Y+jG z^3Q=|;NSe_H=C|A82ijK&tx;OH*O90-+Ncsqy0v@1@d4f(E^{O$-d@o25C)SO}8@N z@%+`@pv^(SL2i)#zm;!O-jH%EUF&l^**#-F$NP<*CF~y5;_GYTHa- zbKAhy7?cHlC)$^+oHDm$UVWcSlXDtSKCA)don7sT+Y8!IUSgo%=n*>X_PW%6i`oo) z&5M)sYP&avhwmFxf?!LuXQp);V17zvqpl1XSHlRVy$-6*E>&Nr(GIAbEY#Qm9!2!_;3IP8(cMd3hs>a{GN$9c3myAI?9=uwz&V zR=}b`z-TeTHm(!5)H>?Kt?l8){G9Db&yn-wL#lBZuOVXuEdxLh zFoPw>u!;xX&f<9aGd3(^mD{{JBl9vyqx#JoWZy#w+N8mdc$!!y$H6&EF{(_X;}X~D z=yrdWrg0qF;<`cjLaUOVVV>a{(<9GVraB%}q6^C1^NDf5;NwvFvpRZZ9x?;%X<~Y$ zcfAAKl%AzgSu=3OGmFy_*OE*P`s%p)9s(sE5?l)&UO`+tJaosEdRD>#jH$OOLo>{M z;Ho65tNBchF1W7OF|J2jNTQwWQ(-EKG zzwJl0?=)-iEcb#a-+G`Q|tn z4|J^KI+)~RZKq&G4auh)4{L_h(Hk(X*ibA1H6iA~ai!SVr1iGScuITK9MV1=qgtXt zaDMH_BL09kGmO^a+z?Q;_Epo8xW3zu{10y&=`2!b_w3#iWT9=j7@aTb@&TPJg8%gR zlTU{iPHzsoc5G>76UYm!;<9!9Cu^P|lMmX&xcW2VUD4prj%{0Q@Q2^jMR+4lnkLhg z%;u!eD)lw-9n&;MPkA=^I8|xjlaM~E;-PgN%yr-Nsf!&jebtLu$J=!<^VhSt{Qk`N zY}0NbkMynZ2XgtUWJ-PV6o(jBo*55q?0_Psb&&K`JhZ|U8L(~nr(0X>d@tZ3_Z^X= zgsXUq^*_devbd?209UmtVxzXg*r|HOUOmJi4SCW2UYk-K)ajE9{y2TRsQE+wyolkY z1%bX%j1e11`;rsxlaGh2@01M7ijuyc3%4g-Mk&P@7xvkXx|7OjSsEh~o^B2j~uxp5vOC+?eZ3k9yVrzHnGhTxqPTtMroK zT1GVc)fYy6*dl4`!1Z-akM5XcWD1KZ&<2$@OvJI z&1P9%(#znF)8HFj@jyclmMm4FgSv0uzE-?=`nqrD_3W9mVc-62ntPmYoR0g%XQOHy zVfN5t;D>vhzC@>)nGPBz8cZ zkD?$u7cs6}Gy94CIu2|098T>59q1(O>#Brpr>gW!3%<^uKX0?^@RiU@e54~sj)eQ} zyU&(EvXm45i!wWY{DjS}ysG^{NUK6_%o9Fw{%w#n@8F~fh-30p087V=!Ectmu##ac zUycF|@2r)u(0zXQqhBc<=d)jWz4AbQ1J!?URmYiuyfiGAOyu*$h-+Qh_Jb=gTGYbX z9(a3qZL`4^+7tRc)G^CTy?6Rf%&sT2u_v^ftajkr%b=}(S$x$u{a0QzRO_srvwSt+ zF`?OkYi_@6FBZLz1z#Te!J#qD68o=GQ^}dx4#&!6@$W|d8f;sguGEzU`PDt^mxncL zGzjm4MBn|=>s2Q5;ZqfsiwE)^Jg%>-OhR=*Uxzx%zpev7L|jZDIqR^m&0N=>K6Bx| zJMXZL0yLQoG@_~cZ0yO~qnR1a3{rxF`?R+MYqAuop|eNDAC!YaYh&<=M7qcf*KKW% zw$4uAn7B4w>}7$&4qe`6O-*Hc3)Lw`Omih)Bk!CB;rxV-mCWlZZ>tEbBCxU%;F#IX zBiVj8PoF#!?$Ca1{^qff^W3PjXGlB<(wL^pLu@m%6F&2q&)D84U81*sOdEicy>7!g zTN2zY;p2}#ZnKc+%;EqsD~Z7%=rE&}83`;8;W+ura=d|pwkF;5((+kc)7y>J)#tA$ z0-B*CUx#HB3}CF}z>;_dRoPDn{q>{d;Tb2Afgtpo4k=5(*wbs5;%Xs(EB_6@tyogg zBM{_E9lAQDeShTJ+;ie^X(`?2P1%O={nGD|oz>{82n-AX%s(>)uc+UIZr^|R(XeSG zTWU?6pNnh^Jv$OY_=hLjzO2b zfhM#!AG3>I?R_U^SKYXNOUv#$t4CUcyc%&8ffa}VEobcj5F^5zW)d%#LI%69>F^ky zG%(eciti(Tsxzwi8vL1_59h~c!h?4oE8Y^5mS-3;;$zHsBQ`oZVvaV)qxKTmkQ1KR zrvV<}8(ut+5B!l=Y>bG*DI6GEPOb3ZX_vADQ3*npHCSG|>e-=uHCahO2m}k_p}& zhqP>Y<}y|Bkm@V(2~MvU9!OU!6Lm>gRMA^5T>Fv9)2!l})#=!_QQic{sH$vh^;On} zb@olTuGfi%S=T1Zhriu)rH+T5>tIWL#T+sSv}t&K7+OCXE?l}2u8dy`$B!P6W2mE{ z6~KpK{KypRraEj_uY_q0tY6Uv{Og7{+i|s7-0TgTCC>l&eSW%KPM>q10TyQd_{Ml? z+$uWUtBU9M*cX9vI&|<*oMq{n*$>cR=^341j;zNP5ZvzYoOXv73WSZC^}&8poLF@6 z;w9Z5HHVqO0OFB9AJS3oRl3q-UzftRRq^2VwMzF)UnK)e1>)c`Ri!bR)CRE0b{dw; zzPe0ab}=7yxU#olukF^P{Gu(|_b2u{;=EqzYh+~>8v~&DRrlU|Z^0565nNBXX8$cZ ze*~7NtkW|8*w?ZL(I51H^mGszFy$H@i$kg_N}_m~?+AaK7CSYkms%Q_y8rIOW_Mz` zEWeC{mu)}xwMze+>flP&*A&+nqq=sBILK6mgX6kE?UqU?CfBvys-oA3Yd`+0>@4jL zHYW~_LlqAlnHJijIy>O>>TDa&Qy$>QbVYp)Kj95Mr+;*LVkS(^-UzRK&51CoHiPs8 zZyT^t@D8u^q4w!F*B-|%8va0smlU*J)N_8P{5cM(O!y}=I$oYZ>}^}JSUsh7dD=VRe=oIm3nAH=ExI=L{tC>$A*I6CL+@wi7^ zu1W7S;2S)7P9Zui_;&tWCO16%=F~2Zdv{z5dg76MNK3ue^JV1-*gn|ck=(rd206ofgflTNK1KT>tM_S`dsLW z@@|7G{E-G8d(l^y$@Ax%5c2?SvnvU%#6y1;>dK8ueMMK?9u&Ar-@t(K=viNt2HtFN zR89?n-_Yt6S8yoofMjCtAg9+iu96ph1=BiQ(bv36XZqDx2YbL(IC$B{xKe}++*2KQ zZyO0STGH~wQ_pKj*mj!@lywL)97zYBe8c3t^lSH??cs$}=YpCF&HT(ZO|~+K^oIDB zMtPw}@ozBYx6?g(^r%iQx=`2ofPAF4qL;c)%$h*XcwD4j!;uo(Dht znwb$Sk9qLH2gBKy&K4bDuVWt1^ND|hjkS4l^lg@f+AlWt+@cvlBf}$wO~xKVkB`$~ z$u#;8y+(bNt@Ne2aUDbk=aK6r(O1w>4@ zo4l}zR!3>uRUZgd`pS%mo5JcE`$#J7HFb`6?c5Pg=)@y}ZWVztW&o(z#5Qh=#cyjL zM>7K)=Ns~V0a&!f)oGGufxa?`ovCuk zzNWZ>121LGchuf4V$}LhlRC}r^!cmdjSt;Z4E~VT1J``O3k<;*9^yD2m-6#xUiXN{ zH6ISV;pGIgiTIr{p4m{!owV$$M?UB(oAu6!@2RO7%?#XSygRKdJz``p&%xgL16T5Z z9v}P_p9tXgIKN30Du`RjsemW#tb}z4+v8 zI(}1S)!f(7fS3Fc*B$bJKl<9-^LC4}E$ORt&eJs2882JnF0ccVm*<1Pl}Rh`SLjL| zuCz0+SRYchh#HpSnwPuVfd#k@uy4-z1!Y-#3K(xbIbN5|nPG&;C@l)XfA-69h2j~2 zGkWbEGM=%iGH?H`PTdH19NZiB@7a-MDtd7+Mv{B+bFSOOiPP{l?uy!9IE-BL(#t*SF6 zTtyGr`4~p}Zl$k%<4UJeg2#4Xk+^!tV~tkUEXo3>oNBepV*B#^zFvZpY(i@imSUZI?Sp{N_2G z(aiopxqG02>zVuaPS8Ll;#%8+{eFY0IH`)ctgS=bW0p(Y!gW! zVjria9q6=M_*rz}v8}Sn3B5{xKzJ2Axc{nqec6Gi%`nWG>I`KmUcKIOU9yK2Jk;Te zACm1;Q-Q0?)CaEUQ_&6zOLVUnJ5b;%{dfxZ{*G3ogr@4WJ& z@5FujCA1Ut-2_73ZsopXWCvpXUk-hxt`M*rytvMMYw5pmLB2{mpjf58iTWv7x~R<% zP1n~{rghW{(bj*<*UCUNu!&$~dB*yR?&u%?OLayBz^G^k6~X-hvjckGT3?m6Bold7 z)WJIY>Ue==QD<8AAxkpFcAyKcY($AjsmL0?2c<*Pe?<4t#K7`((ozD zwh7lnrcT*{D|Iz1C&Ns?p&RR$@uz#o#>VOgfTlHz=KQ(yl$8liC7|JTV@zc=LZ+bE zbU6g(Z7`LD**|A5Plc^pHp#&`D5rRx-fnhg6B*&?&$)Bw!jn%vX;Tq#pzpftF8i1= z2~56e&_DON&zaMJ0olKQe;AVxmo$a`>1Up{4hX=*+kN-m7mge~V$&MgloN-9P5^Ie z0U2J;o;?$uefBv`#~%&v`0_8a^f)=>fm8CxBaehfKmMpyDhw2kId8bww}`jQI9bf( z!RhCljtBW$Aqrsl;I}J-=L>E;!>-ifYBonoXQP4Q)#Y+}6ngw-3+47S73IE=2hmemkp_CaB{LpWu0~H~P8#&VojC>s zc?K`!O`1Zc{F(6}d8%Yed2pHdj&Vh`ET7!rHXMYz@z)wxmTu)TDUD+UjVfGI9{R-< zI+S}QuENynpbExi0uve%^ntXmT3l6TC7C3P>k4JdsWuW-@b{;$C0wIAXu7gOaiwh0 zgEn@cR0m^y?TTx*T(ldmuK!JS5G)A{_^`Bga&}(M-iQqX`2aiVsoU6EZ00l1JgeCT zpH=5_I_%xEH$3$4LuRLu`wL(ALip6DK4lv#V}I$?e#w`7iS0weAkx45%fHyh%HRI& z-){Q}VWd;j!L|72--yGi*I7~H|Oqie+bwr~43>&&8K|M-vp7@m9X zx$uqO_>I=dMP@GpOWg2>8AG%&r0FF%eH>-lI5x(H)|Jawtggd%rET-$$|VQSGdkFg z+ztq5WaK^{FTZZ~75k5)M;h`bUCINxf-TQpaCF*?jE6q-Re)i?%sEYMTf~FeHkT>2 z0}I-W^+pe#VjN5+Frpny?Eo@W;99b;3B5MBiq*`v30DCdZYl4pQ!neq*q*R!YxW`v z{a$Qv{Fzb4ChKg{%pi>4hkktR`T0EtJEwi7^uAG zo_p*O7&8dOOdyViXMhNN!8;9f2C4hSn@G`zhq#<#T(ND}X6C{LEs447$iZ;Op=?9; zD*7%9J{*3f@h<$)ty+D}ecJ^*M1EGuzDgi#Z}BfueT~{;I$2q}MU81+2V)$-&-RL1 ztiD$HdJF1I=AWr3jPEvfATFo&zN7L{9i(ikaCN-{2e)mdI*9Ms+77r(Q5p$ocA&zx zp{wLy)z@LO_QKCf^)=EJ+P5nIHMRrjn)85e-q3&wX{c(aFJ7}5u?P0;(QN5;`gCT9 zz@O_l*VH%a9r}(9VW}oFVF@ZmX=kt*rl0@(=dFDq&f&v{ZLcoUo<4m#>pKZkuzuvV zk67Es;3+ob)TvYU`~Lgyx94E<+;h+B{+X~-1HfPUwzra%4Gw?$)1S7!(DCEP!^b}M zF?-2QJIz4xLk~S<`Op{RWyw~Z*7wN6kBBCNL^{D)0ow3Tl&vsYOkW3logQE;sDmy0 zI$j4slRoY(UaA5vJkyqRu>(cB1qa9^Ir%iT#qiDS9q^$H@u{$1sZ7QL_u)ax<8{XP zQ^GdBW3T#}^3X4?aoJYcfmXP#_8}LvoteJY_aU({2M-;p-vfw7&6N~|C0IjhSK0J& zzwgg@&Squu`@;@x4$5(y^D=6iwa%RY88S`-8+ZQ3Z~TTi>pa8p#R&c25B{Jz;_$&f z3&i=OKl&r9065BD`lVkQe*M>fJz#X+^KI`j19MILN}PP|Wca(k`#T!|Lizvf&;Bg@ z)^Gim8KFPs$|?{N!WdyTALp!@c+18~)$}e_$O8IuOK%r{DX%-wPl3 z!w-ayeB>i$xW4Cmz9+o?^{=-|_=!(^B7Ez&eyepze&ttwC4ALaf0Yb)wzLTu@Oc;% za*Sf^dc_rbq_3lgjL`H@Ct@fGi|4le1L)$n6K z_G95|zUFI+&MIl&``-7OL*4cyF*-?fPH=4LaL2YdL!zc{ANed7uE^kRF?Q!A z>E7i_<6&mvybX@>CY)I{ywobNhryaa`-mM#gX7DF%>+7H=p+N6(B-+u@w9%Q!4d{` zPMkPlOBv&M&J*9zy7SIEOcvzVQv+QFK53?A`e@Ru}T;rZ}g zwr!oX=-2G^+hO;P?cuOylN&$iYFK$_`Zf7fn1YDXx;=u^3ES+|jQlnM$@O=AlVn+xq0Wt}w7PtEDTvoZY%< zL)fmx2shM*ZXO+`*v&+Cxb5KZ&;R_-;WvNtH|=FK^^Z2>t#5s++SDHjZ-4vS&C}q8 z#;^YBuZF++tG}`~5}QD~_tQW9)8Qk3|B>+Df8@VgdrN(x5A(nNzyD<$zSAcC?(hC? z_|rfAQ|lZ3{_p?3*(loW4}bXY!%zLxPlf;OtG_zD|Nr?7y{x~}2B6;m{`cFa@IU;+ zKWyzX?K@@mqd)qi_VS!MPv7i^e&~n7Ti)^(rn5&i$NdyXm(&v-gk1{?wEf4+ZtNB?;KbCq(8`X8LdaQIPUL4YA5S`Gv)$Loi$biV1(OVU!G7{X$h|_b8 zk@>&}K45QhfAJT8F?{7$ex;2_|I#o0Qs6hv2(xxDLcjcf|8jW$ufIRM`&+(6Z=ZN` z{EY3-04M|uA|bB)HUK8$5`^EYmVje2u|LCc&+98Ypw80zG$yAOqao-J3JCjR>2 zVbJtec>vM=bf_uaDy{~r{mJUR27+V@M%0lQ))Lz@daL<@1~#_eHx?$ejD+?Ad;Ij% z&xH5A@7K&>W#$6+S!(h>|MGu^XZ5D>k3aaw;Y;51CFa~RkpHtk`?KL)?|PRxl+4o{ z^3(tTKmbWZK~%WGf%J|bWxzdVkmBt8!Y}+nnAHg>AN=DF+Q1J3L%fM3{Lb(EPO)T* zw`O!2ogQhMg12XUGx)vXK{KI!Y8)!lDO6FVwx zd26C)9pxU|g+_XHjf@iYBkxkB8I`VV9F?E6dq=qM?&J2>_Id5G!+=V+JgFb(%dum} zOkYh0<;&o^po>iRCJuu@=rseW3@&-SA|5m87@)!bLT7oQ#@qe}9(bU%zmM}0f0G}- zafms^&-15T7#!lI8iQSNpgyDDAm_3AT z`m!(kGJ63|8^sG2W*z;-U;McZ22r2A-vv$b{jTr&uJC=|_kH0zzw7 zc*#!t|He1I(QKCw09oexQ-@#OebV*wY`M}j@dpq3Z!gZUT|@GhSe}`M<>@>1gF`o& zasd{6^^@0fr5UtL{qVh9Jk$;VVRWjS&FaA%l$UmvX^b0WR9K=#paCYNAh=P(>A^vH z_q*R6zFMQnIN&%Y-}znN8NTrwzR{*1j*X3lk7~f>J>T-4@SgX)C$I_O9yv7JCs1Js zzPXr>;&BfnLmuDsP2Xf`{`PPGHhlfpe|;F0qjFOt&U^Rn(Xqkzn-Tl)hd*osIXEd8 zLJS%X4Zop@Ox$At=r@1!w`Aac$7Uw|!$16k<#ERyN3u6tqU-X(LmcYv6Q}l>a5bY3 z$VsS8(?E|jgtSb!S4Xc+8mMMQ?3Si#&xWx>ItupX>-IJ~&8rPP_(?+(e>95xPeWZA z;?+H?yWcGh&r?~O(lk9=<0c zYI$JSmT*x^IG%p~bU3H|<&J8JE}c{y*}wUlzp(*#AGl#k`^O*sc=+aT{^sz8H@?Bj z5xf88U;gDby`5!Y%*MnvWA_~!_@h05CV@`shHZMIsy2l;p>%e!>AdMAEge%FQcjWN z#Q_d4&MnWHg3IY;#q1^0l8*Gf1_r)(>3~E0;DZlY`;+ETMbq<7pE({*BYs|&hB$T4 z>h3qCX?oTVJ<%aMSzT$g+UH7c+eiJ>hkH9hUW{)QTLo4 z=8sumoN73(fxr`o_vs|XY1_^r<=xXjGYz%RM1RnBfV`VzN_iVpopHLzO6Z9P#jnGt z?ml_+^Q_-AH5o1PPiGCnG&~zTEWa@{9f*$+zB%u*kFN-8i zEK~dl13GA2!Mhu-QmU8@iw_@h9Uwx1Lq)yqhHI0qRFzW`uF$GVQ;Tb^U%m3sO{T86 zmQc-(wyedqrVe)Fp;wu@;o4QEvZ_S-n%P?yxnEsrr>~w%_RYrlbV6AMx^weTc=6=3 zVgA-yJ9&{#?;rfXe-J+Op%2;YgZI7feZ^jC?6JlhOn7x&=LG>vv*=Lzy>f1uqmw@K z-`@FzCbpXLVU{OvD1ZFNe>||XmpqV@KpfI~dcJwaz6eaW$H8TJ8P_<&y$=33UD7j% z1RiI!Cj)hbyi0W^DO=N(3Oistt^j@QM^`A1+B%56uCVbKemPJl$ZyQ29b2yEg{$>E_O>cUW`7I2DKK$^*Hn4eF{t_7BC$TpV1FGx?^4!Vi zZ0|&LltENxR`1%q%k+)Gr?IhProZTp*O4?&|Lr=0J8YPdD3E zhwI$jyd2f64$kS+)~4Vrkk`w%v|+2?$P+d3&`MX5%)M+K6Mwv<_SG{f$+XZPfTud& z5gkEZ_>2Q-T&DOw*Cm-cMQzaPPJ37WQ#BPQaN-B%+MjwMl$#VKj{0|*qGg?-knlgLfgWO90q?V!x&Sp z8KC+8@Be=5Co$WHrO}iPFShU3%kg(=l?1b9d3nwT@N7=a>6P@`cyZ4_&tLxKUs}J) zUzo#y=LIeJqOGKTWr^BrU;8>+?eXCc|DC-&AJITGfeoQ6aTSfe^|h(Z(DLm#fJa|; zKwFBSvoW^NE!CMgBV8k>%Y>Q2{*Ml?4+nN`3RlOk+Ou@}eDQ=FMfQvPCXamF_j#0eq5*{?`A`-kS$ol3Zn;p80a$ zm&&bj&&t}XL{&*DNvLJC8q_dm^w1dVjAjs`sYZkT=`mn{X?jriAZ(y*492F1>2AY7 zFvB_s8fZx^A*4cTwIrlMR;o?4Z&^!L?wKz$-+Q^u_d5|Mu18$=xcA1p?`2l$dFFj_ zZ+Q6eb3Q+Q{J4iNIoo#C`j9aY`fj?a+46DG{FLn_frHH&bsQt;umKvzk&QrE#)Yxttyxn^$Pam`uuP|X zlN>JIq9G#2kd32RmH;mdf}sFR$My{+;oA)aav&$qnp_ujOkXseby$<{|F=PuDFQ?3 zR#9qn4j3f@(kcz3I|fWTMu;$_r8}eqWOPW3?(UREx<}VH0GO8=K5LUH~04#!n5o#I1WTBfj=FD(G zlrfCm3$uZ!WdyW23W4+sU6EsYbF_UAfrkb#uE%ogSMRK2g!z7SE_}^=%Wmr%!{`as zd7YF)`mRh%C=pW-6 zwfW(o466m9;S8Y{*rW6wSlk(>=Qu6A=b z(`a-o7L|zg1da;on`WKP8&(gy)0yh)VgVRc9|4*XjiNf+wfiPB?~Rt&pSZTcPes9^ zDA~q0;(VH}ayQQ0liCRdj8p014qfD4)_nPv7^k$48{sj48pk=BL8EAdZo@mgE!y4i zH)B(hM;Q_(-q$?MZ7FhR)F!11dqnH9_08g<%?!|~oAXy`PTl>%vfq>NC-_&wy;_a$ z|63>~pD10PJYR~*xXCg3%GCdyk`DS{XchDMomd3bdbqlZC~BDIjTCSf9`@%rJ{EZP zgPLys@oL`j#ORQCFLX0wBj$Coj(G`uC^hSv$zw| zy98OoCF#l$ZE;U6=)-nFL)E>n2|YTu!_dNWoX4T?flII<;3>kahulrJA>xbO1ced7 zjy5+?ojsBz9U(IBd145X*{;)}W6zX)h&qf+cNh+3i|-f4s~GbzJ6K*K0_^2ZIKVLd z$fc{zp*7Sd+498^sTSZDV4xDx#yoUk@et!WE!5`vrt`Fyd{+d9xR?53L2?^F8J`!m z*wIn$_ygr3PJ@*&i3yCnw5P%B3SX4~vy6-s#_U38ioW* zr|zqitq|qXsz9&!;Yz&hP0*H2*ECfUnl!)c^h%T{DVCAy4{_Mfk{*d1C!N^wsa7}2 z+hTm+blW$83!%j0e=&r+GM}j)Bjrw=WEo+4Ax=T*J1|C6Ie*2LOfn*OAzoCTKGVL3 zJKly2s_uq^&g$xN%`e4!gJQeZYjdqcdxm3+@4f9V9T?4O6;G0KJSj+6z#}SxM;(<9 zZFhN1!3z8d_NfIb1%+N3* zp|%9KNh)I>=9@M#vQ8wq?pq6!$z?Af76eK|J@F_~$o+m zI_t+t>_{geP}q6tCs8IjN-qRS~-i9W^x1Rlzx-32`A&sHh8$pqc%b8 zNvdR1)_;dUj;4#2W%P7{c0jt8xDC%sBc=!cDnxG;l7op;~t#}B`2EpzkD+x zy-{CKG7XLl_3YkK6o#H)Z)c{KcblDRDXv}oOQxu6 zi94%*Rf0x8_C6po%zmT8ZxxDv{+%U*FU4nWuO{epyTNx`J)=-{`3i7w2Us@CxX>{^ zK`cn|U7Q4Q`?TzGq(OV1B4cuS`diI2NaH&pckQbt=cvEs+#NVo2_Ud>2FGTryHm4e zOnh^kwC{p>9e>})3BreIX^^7awxU+OJ$P3ao=}7op3%s8cRZHX1~aIxoMxpE8+wvD zZ3)VzLEWCw9BZlSibK3h;|>$%KVxWS;)rVvKMGA18(Fa2H5~T-aFXh3 z0flA-?nJT}H$UuuviSp0deXw^5(~_Chs{@x_;6W1hC7Zo6B?a!n*QBTIkTCN5&hP# z&h^la-$l@y{u&Qad$t3@OqCcuQ?>JK|E?b6w(F9bZ}H*orP`Q!+|e%y)uEvf52`Fq zIi$@W@Wa4?jN-vxoQ9APRP5el>6Kzy)?MObR4%UqTE4V!rf?R{2Pug8)(&pWsgBiq*zX;Vl8G51*s_x?PK zP7?3_i7&^VJ$HIHZFo~SG0KFN@T`3T%)k+BQ z-Y$j@k!GI4+l>BMA~-ks5BN(WY+jiAI!b8&`L*uKQ}4|yz11u%>>M^NaJJbNUrmg| zIrf~5;j@)#8I6V<@Q=HKHl6+1hzOIFZxUfk__e!U$BcsU?OKg@`2T=KHa@A<;L*#Xc>HKT0IRHwRGR44C)Y3;Of z@@>epY=-M^<=niALs{{Y$SUne^yETWhFtTOIgKvgQiTa$Fdnz_j4nlSw}|EX)Cjc3 z;!k5=z(dI9HN5T{ZAcB+qiK91XT-#yQGFNBo+nSUL0?QS$E;v$6BW9IxmZ}k1$@V4 z`m(X=S*Og(aryjUND~~(Z;uLUv=Z)TdI~D(HLkGh(DEpcz+>a9x zJzGo-yst|MgW1+4v66Z#p^SmVd&RNd`-!F-Z6WJGyn4AnVTtTv9WbhjS-s#4C#BIQQJe&)C=Q>YBGN_QDjOIPeqryyDo7_U1r86Tx3Om z90L+n_{+>cfO?&Ei?0VGbV7Zw>VGqhdwb>gpXh5I(cn>QN7W#3v7Z2E8hl6 z1YBL;oi{D27UwX&&DbcDXMEa(SvDeIyc$Nf5)+;AShw*N1APwzC!1E*%(pr4gt0qJ zl9n*)CXt6o2|Dh}ee{Ndm?q&B;hiyK=KV6zZ`yKSDzf^A@3V3AJPj76_hu(2hUK!4~K~>uA`kuBNLcXS9pH-ml2Dcd_)uuWMT&n0(lkdNBOUrDV&h zr}KmM(syMM+R<|3xyaYy2C-8s*nO481OJnu!3KML0A> z()yW)0~Nz(%r6hFF;>iqK<8qj6a9BU?~^4m(=bzA`JYq6=)TE0){ z%o69^5?Qg<0*NAlrzU&brZZ%LlG7vqjcSBC==2*M7bPkV`q3huD>*YJdC5)KC#nK` zw~6osrlIjoJTeO0&EOu}pf1>qQ;wAT8%GtPK)G!K2 znIi!9#A^UavID-kKt$H-U5R#A3tmR-8S-<*+vEr_Sr~PVTlN!Ad5H*Ge0r&e3{~eJ zN^2sSEYY=)h$X-H=GPq2qJ)WRQJ;FsLTa{i9u-bK>@qlPAo>}y;k7j+Si&$=!QFTh zeJMS>B5~RUF#hJAw0d*7@JPGPH2<_5zIrubay$Feq0=Qz?I5x961(MbdkN;6?D^NzN6aSi%m45P z@>P~ps$fQR_&3gw!DU$Gai>2;sB5UGLMC!l+kVy^&}LN>yf7YxkD|{ zJnCx;agljQ{fo8^FV{w7Sq-=Stn4FQZPCNm$WO106v}Q_E|17Am!*uMD{Otd)&l$B z6DoRqW1d$xom99u0UKGNF9ZGPUhN+RNYIi-M*tUj4TqVQ8lnJ|IuDxNH=bePUxcFB zD>+#*{w=1%AqD$)%tUqC{7V|2O8at3cNNIYJOnTGy1j7&9z8^RKFbVG{1E82hPf=2 z#*^?yEt&>i5gr>CmE9IddB3Bpp2BlWLOi1C?xHYrp21>b-h7>QI9c&OdzGgKk&8}x z20xs6e%7g-Mlky@)hJbCD5Kgx*J|pZ){viKTFE+y({rZIqG%x}&*Im5mcX<*ovroB z^R-l=eo3!g>xqbtA#NW(Gp57YCj)vTO4aoa;ymS6 zD;^)hgP*vt>i(0JAKi|A-sq;|8+GPH?Vc%v*zMOyL_3Mh=MkS2#@&^drIX%K(f0Tx4^GcQjXDN$d5$iAk#H%o^jm*b@g|7q8Y@_h-qL;i^l?KLNhaEa#cRPu z27*sCs4_6EpgTq>LgCUX)N9_$7yJ}&sfFlWLdXg^{RZCZx?@SE!l4JcO<+(W18fZb zjBDlZLPck7>f;j?ETE#-@azN;@XcMO=iJht0c_koeQ!OG{N~>~6}26evg1@%K+cK_ zB=kr4`YQ&#L+aIStc>Uom#fKfEKV>8tq}Rye_`gti=XpuvSjiJZh}`ZAwzeQLJ29* zG%r*+(8Id-YyZ+xqBd2mQQcuwho*ot2LGtk-_G&=d!Fw{ji_{O@V)i2+q%>0-B83rX_X4JA!4QS`GpGoYFii}{-TcPoLUS*ItNTuU2x)Sd(1)> zmL_*OI&FQ@6+Cdt5Mage%?RI`D)U(A>vhAQwQ!4hEuQxiIoc#!_eysU<7q1(NlrKI zM-nOhx6I7*OqE*%Hr-~at~{NUOPOf^?t1ufRCECmk_%Ef(zm>A^NFej@2H@f-m8BF zT4w+DdX8tuOOd{E$K6Zd+j#EUA~-#G3xGCPbGzIr%ibw&Y} zbX_n%^;T`;Ra|Z!_u5uf*MEn&^NhoMS#qv&>`7qO2J;rKniwGyJ%*TJsfy2Y3>MbUZs&w!w(c z@iqr(1EZj{<6O#rp#p7*{$XD&#miD;ZjM|ClZW$ns%>xMyFPS zRjBOJBSGRrpEEpSg-|*3&e_vBUB`G50|FXheTpoVt+5M<1Kof0IAuChU~a!zxZn2U z-M}T~BWq)o2W3>5J-%Nu8+8Rh8h`&;j05BY!gccCs|4b`uilV?Ik0Y&yB8>3I@6O70+!}=h%o686~~u z&v0I(4>y?7K6aq}Zq*z_4J4$4GkSV*srEUpI9XCxnkeYpgpCQVgi8*a_ukiHf!;ncyL z@3HhJYp-ZiN9-5m+T+9BBOv%+Bc%fDY8x!zDaCvt{kjoJS!rsLDCnvo#Jh#&be zn>Ihw@b@q4r8`{q1l zfM+1?m6Y{y^X=R7=U3eNNu%Uy{DsPg3$oguAhrA9y@53y_KTTsd6k!XENm%8hv~DC6RJdE7!E z?Z>JlQ9(3KaivyMRq1~}dO z=-{8bT40>9ZkvdT!9$mHJWwpM`P;E98>3hT6K&@^pvF*?oFsX^OFLT>MUZPpAOrlS z0zC3+VbjLH%d{7wfY(Sq8)Nf5f>B&h1eW63mOU02JQ6nQR1%qP-NiTI@y-1BnoHQG zIYBL2b_AlrIB81sj%|_Gp5;|_+Ry>ojNe1kkUGr0lf4RqJ|C-3 zz81OkFC;6njv@0W9a=LJpEGQ}paLjm(j~-2%)OS36HuUbzp<%g5P6^WbftS9no=QnOglZu zu!x@Oqmhbs@)bKh$ey;k?ibRy4<~rF%h8@&)z1VND$Tso2wO@@Zk+tBah-2P;3b=n z;JC8AIj!kXVVEbz@#&DEga+xR&|9x~DO41yG#vqAg>4eJ^`A#%h%m0g!Y69SMh_?)doK{(ubYySkZN?1l3f?97ZeS)3 zPLx&hVk6bB@Y0d_1xGK^Y_^+LpCTSi)ehF8MH}HY`qgyZdSU5{S{L9TG=*CxlK$pL zu-9VP2~)bRsU7%T^)EH%C@TD^awba*YZ2c->N5Mn+-?z7>F4BRv~i#$sFEzH%}MLG zj@D^f^CJnixeK!=U58yZ-ivJVe1o*!?|%KYJ9Ix@E3hqToUf3}xgj0v6(8bfSi%BT z!0va@KV(F|bBxNcaBwzlQ2|711G?})AWV&62G_cNQSP!}vrS>f4DzcZlt9eHLihMz zo%TdaEPY}en&OnvC-{WEgYAm_?y-Z|FIrR}qSk9JyeaysZ-%Y?bz^;iEf^%+7Zzd%DeDP|I@TS_d$6}E|Dp(QI6|UrB zr;2`nL(Hox5BW4J$iI`{65G06)|MF zzEyMR>L`O*9RLkCB+zF6(f69U#q}*8+|8=k-i$$`z^+z~557nQyuoxYX4denrA>{LM^({Q9!A;j1*Qki1;R<+KEhPn<4B^|mRq zMg)X`@Oyh)E3Ec9PXnzl3F$Gz=i#fhuHu_{uhs7hv&7H3J11 zvF7DRhhGezEhU@{w8dJ6naU?gx4=8)Bgw8oQAQSXuMD#IU3*|D-xAS^a^~TCpw^>u z{L3CmtI*)`l3suqKj>Ofq+sBEwf>XqSt~#?q_SJU?t1piPNv&a^j1G%xLrYZEYlvv zp0JXvs`B7_M$}h*;J$;w_G_&oe+T{#TYWDJ_%}by&lEB+90t`jON}}YiCZ};=_Y?) zaJGjWw{UlF1#nFPrpX?tB>6sIIb(v z9dlA)D-rRW8BXr@iMwrZGY@#i%^(YaWO^C?($XfR1i#Gs4$&puCVmdU^_Ez?6Kdkib^rU z&M$v!Tc1@a=vR}`_C|(U#t_#H_LH0)XVd3|=W`Sy+ELNyRu=9x5s7p(DadH@w>j|b zmHO@N1G^dx?1$2$=eUWIcFQaoNMu65_GFl6O}Arae%1~SI}CIZS58+a-?QJ88X#&5 zq1!OIw$7Rv+!Gl<_q(R)TMifQYFOdU(eLVBLt*=rDt+VEzis)xpZ^51UB8&s&IRfo zXZBQ@Obr^`rbvPA3Ll2C$q@qP!|&~>;Q33Jl<74C5%IQDw||J0i&ply9h>Z<-ch## z0)k&S5Y}ddgdW6j32nlmF$@=;neg=tz~~lz7@2Crw@3>VCW%0*;nDWrYN^ls(4 zbUpiSIAV20pncukRw*Vl^gza22b-kEiO|4g^->f^l^ybM0C^91<&F^6#7d4)%EKWi z%kHV#bd-x5e^epwE;{}jc6gAukH(F_iy*|?0W8d)P8rrgKyA(ns zVDk3hd5m?vftHmH525=`gwr zia`A}VF~5g32u2o*M^N$OI8i;x%-{F&!sc@9RmDF(x>n%$HnkrItxyVlDGNGMMk%_ z7sm-rzZYrjKh6I2c0<-Qt?r#&{}JpW(vu{4X5|LgSA z_5bB@8Fv}aH?Uc^YK8Us#oPTu*y0)Nmx-P669W1pT8G+}bThdJ^e&?P$`g-d4o%|m zYlkgMMe=v*62!jWrduUqzrK^*(sdV=%_2-Y+3%N*9Am@a*sE<1qEH#Gk_%sL=+-;3 zDi%kXEEU~pLSv#YlDDJZomSEGCixLTNWhxfqewIU&*r&8M=qFw@RQm@<;C`#x>xO4XUNvnh z?3boc#TU^~M9mhu|>O$_3&EdNlW@ zOo8XzitOks-SURNQ)LUG=T`nboceS`r|ojozNP_Yzil`l3@mhSOaQEBpM1_rABiYc zOFt2c2%~$&zy^mv;hv9^*KbJCN>jL4@} z(Y569+IntTA$Z07grPgqSEsjHTKEm=`4jj(XP5BM`pU{RgmUK{oiIBvwzFz@%H~*{ zHmTW4#|tizLraOuK5VWqu-E4&YSI@DV9vfI#IC>}_bN)F8j>_Kuf(_mT0j!&MfpXy z{vS{p*6eALG4*Ob`q1BDs(mHc9&EgeybhR7#Ou%X@Xqt8H$|5tkva>D!*ZkoaO0hfJ~eu)qF z*cp03LPSHngOt26sUPC_`oA*G{SEd9xE#oMlSvP}2i?z=Ojk5rG~N6p>h@V7&3JtN z*WG9u+a|pDFA6^QFd<3a(X&s#HTaZvS0D>pPFpMu0O5aLIErweZYKG>zD=@IXwxNe zJu@`B`$m=6Y^g6H^OE76OZkwR3X)9(4cF~jB=X->Wk ze{Q>Fv8Z_eoz?FB;?*kg3RH#h)w?!ZCJkuIY)*NPiNIBUYP*C~pd34GNaP(bW(C+e zLHW}ZEq6y+)~NBph%r~J>U~*k4)B4c03d{yyF3>DsXEbBXiVJOH<3(_0)Pw&-F5chUAkr^D8-0B>VM?j zXr!wj5|A3XMEuPApugYx#d}qC;)~0r{3HOkJ}J!pq%3Ih>0^!;*skp?c+uV^X_6x4Hzaw-Ft>Dk?t5@<-#Jure^r7+c%RQ48`uj~u?lL z4{F&q@koWaN+Ius6Cd%jW-7TPJ~rII&;7nCK42CpL6MHwpJ}!i-lhov$6HJvE8Q;C zxrSZ}QY2lJJgsyFTlZtQj-YWzvA6SAUDibk4^XQ1#7*ZEB+cY0cdRTXl zKhn-m0L_)H6e1`ooc7YDhh>dct6I|21<_LvP_Q~vS4*x_&B{imi&G?;fx&C(pw+;A zk<{VOY4zcsrc2s60qTZf_p@b_p&#;$p5yV!r4M&@jPC0=8%-l)z@^e}DgyrlB0aQx zScaj{tv%-8r=A{;Z=tgM`yuk8mfm7!!svFwD9G`4(vj%;{Gg_4p?}G(=baXwlqJLyxh*kqnkx)k(+x2TB_e`q75)aSkT;9Yn zmgn?RNYoybch*WHYv~$=7?ib5O|J&UH(#ppOBFo@vL($k&;ZTGr#ucI8yVrV>JXA4 z336ujKtPvZ5Z(|l6l6Z~WHZ-VB=RV3@Yl`{qty#(EI@uMKZ7_Q^Y0d$?Y64=8g`R~ zjon$yl#{znKN4{E{3tgeLGbY(3N*rbO>j#v#Tq>*aBcQ`c+MR^z);i&5>o6J9R%UguMq0RdO7)oMdV(FfY35h5Hp7!pOC)6w+?T}M?{Wb_< z7>WkkTn>usM`L{tNj)*w)j)NHp}5rR!+}m6aGJewx0heScj=PXKt&mrZ zhrl?Q4+2Zf>bhVyhUUR75n%PdYN%$jB@8R{T7yuD!?rDIZK+#dHQKCYBy_xhW|^fB z(-7O^e|!1ONfR>Up&J%#w@kG>96jj733u|kd05YY%K11Gf}}y^DsTQMagA`bAVDqR z0t4Z>9GHK4kY=+WyO|#PC)#7=H1CC?IL&EvjT-Iku9C3`n=m2Yde()J22m6?bGfV+ z&xs92#o@IC`)^7$4#ujM%;Cm2C!*u)Od;=FOF7PGwu^dl8hJ^k;Kf^ZB9Ag6QYMmK z?&72nsV}q9R;ZVu*_n>(UKC1F#KJT;L zvW;}FE4B&{l9;|6@t$h>s9DZydIB5#kgT2&bf1SK2N=EpCj~3UcP83Of>RvPA~!cf z_YIsKraWv5`VmPIgb&IXNxYF#k-ESe=2Gnuvq*8vhP}C_MHGj@bpYc9u5*~~bGgev zki~AmLBCvP!}R7%{NVedi}0|V<)muS=}5be0MK<|e?PHx5(&OvCc4o6$#k~_qKayB zL^>M1ZKP)O)Zk_KjP``QM@bbm>?(wQ_+&bwqrAlW>l`kv$43kO!p1C@`li3F)k*01 zJ*_cx9!B$Py!GXeu?o>uh%unI+;)3s#lj-+rBG?cf+b-f$m7kPRFK^WMa`-AE=gIay5=c3Pro1d;@q8Fc`?J}tA;{~Y}G`^Z*^+V90EVr8D# zANcaD!uBp`Vy+c^^t&gvt*X+I9Q6h$2*tvaCR}9DX42fp@LmByhW7e7Tve396}Ytp zAwSlFs^#LscQ$4U0+mZ=n6*ZxgP9iXY^E!Hi%mQP??0e1X-kf&xVK3MIOrlRRC%5E zO*{O=@h_TqQoBkJo+3@Z`?F-hvi43XqkC>!eRnl>3A0snL%&U3PFRU&tNsLbCsop< zdHCVfRbzk6?24vFe>BjG@wvXn)tch!UJbS@Ksj#C=Ors+j>cL^97E%f*CN=EmYJ(ujx+9cg83u9hwtK-Zx|utUW0t0>lx%@(}G?2M^?9FqQKjd|9Db)llZUd^In z+*I-(&q&ohycX?oPPCE+-&!=R^?%63*0dbf{>jLvCoAWNbrRB0u;2we(6yLwxFq8V z>i)$R5`t%f;gZM1b~=qa{~HHM(imjtw}W|ea1Rmz=#&TYiklFr$OBfPp=Ummfg|e4 z$;yYB13D_qt{mMZD$ITIn5=fa*SM^*;X3jV|CTvs1MFh_AhNMe6zITGh&}qTWdtKI{=@>kP|^c;mr#pN!%x ztr6in#`4gX7IT_W;!Kc|1;DzpIH1Vm8;0EAyFG2hV}27u#Hr>E`1n>B+f=HVk)RwW z;q~6QMju?8$DyW;dtfzxEdx1?u4kvhYW^dr26m$5#3>#60Ck4W5NQ1e@93h8?X?Ks_TwWxW5vcs;OF?E2g@I&veF z49%dm->;|9$Xl1!d4D%9HJaUd?q8B8{gMCkg?2fJ(&+Kd6uIMdnHlN4nz`aF3*$DO zx8Cwxd&>@slK4=n7C<+R*YJ7Lew@w6LcJMw#@?FZzvZIYRu9!Ur4k@;YZk$8*qGbW zUi?n_k$*q-)aF|dekd@^hnT3+G$J>OQD}%}w9t3t@60SAx+ZWFU;HTX{m@M;p|z^@ zpoH zjF+LJikVrFE=B=2T>xdpSv0LVEepj&%)zq6i_E(}mGGysDX98Lf-GzhQ#D@>Q-hD)s z$S_9ZjxeLL&s;Z)q8)o#gzKY^0isuH1?Y&mY6f6oe{{&=!x~uHm1wvxuG<%d7nAP2 z7}sOOi6N~l+)2-g;0f6a{75Go_{ZiYDO}Ep;3y$e(6vk#;LSfq{Cu#NR`x;y z0dirCLsx6f3=@kz|1+%ZK|XBJJ9;ohIC;Y19Iy}uA2A@rXk=`Teiew8HT#}g5UWge z{6uA|I)J|CfzU9M2ILzK{@98looP}S;4c!JR&j*}$*`$2qCOAupkt*u)PdRy-4Vec zzJRV>cz7>cD|whxUUcnG?S|XT6Vhedx=-<(S1tuvpgvQBmfG%*MXP$`9YXXuso)*;am&75<450d{e5!RQn1|Q<$eV$4qZndMQq45 zOE^mM*$wAv!Lr@WU%;>$GL}~&q_bcJATU%;{}L3!P#JTTTv3v}ZP!{&lwA@C-|HDC z$Ew?=iD{vB(^wT=8#$x={ii(&2#=Y2!R`fSi_H$NrP_%sq|WFDbua6PEsE5++G$d5 ztC2N97jJrB{2Nn~EN;ngU2Y}y4;|;k`$di@T31BCb8K+oRQH{=$n@%Os;XT_AVxGu`A1fT>OZ3PRNpb z)IlmiZ9V4Kz^^#iS`9UjUB-TXT`%R?l=MUr`~r-<+E?RwQR-esbnk<47Nx|7^Gn42 zG6iI@!FrUqkw9l$0;iT0>tc6TR!mX{)^Y0fVLAEG=!cC^?b)u>tb0yG$;5XTmLc2V zd>8n@wgbz4zyvt(`eHSwCo~K;R~-?v_Mx(re7vp0PULeVcsa~lX3Nf~UUOX9@OK|r z?+$f;vsr^@gP<>=XT{e=o&nlxs)))1bKtZ9p`~|JRX~O08H{Txa^~Fib!4AL1>Op` z*<1rqcP5}5xCN5~PIVh9dD^-Kp;a?rpu^(Tr( z2HPC|Ab{~%cy4|vVwa9Eqy>sVRhYwnnT0u7uJF)8)iHXWoBl;A@{!bBO=i~elT*B_ z1VFQiINeRVLXKINH~B_w)3`Ne@Upedsw1BF+MUemUqM71Zjpm4x5=_H#%_ayf3N$6 z{Qiw)5H8-|E;2HVOGp;EK6qR~P&&gQ`{w|Cz1zFg>zPLQHuFR_Gw`x362WnUQM+|n zr@EajxlQi)L76rz+_thcNIR_Mp{w=bk0tE{-5D3osln1>>bSvxQqssTq=i7>Pcz zX_OlN)SI$EUcK*KB(9C&^MZJIy~RV9!w(xo4a?gCJ&;%&J26{uvx5f zQ_(8roCwR%Vt%VHmbh;69=hdNqJtXD@mWJ=`0&oV9V$-OdCC+IzR^h@(~qS;9mKg>tKR(iaU=dQ;4__NH%La1{Tq|_Ed5Bj~w8ShUS7#Vx8c_k{5F@FkL=l>H9 z>ufaKl`1?u<} zaKD5_fVlh(wx%RH>SD%s3#H*XX7*s{4q^(9SvwD5p}0doduC01*RRzHA4}nsT%+&^lZ)LmvKKk(fwaK;^dauB2*v(fgMDAsAm0+Np#~BIU|#L-0>NxdTDBGb$vS5_D?0HP5%HLosx8gGOBM zQd>S=s^oRvK-KS;9I>6A3-t#JZ&1CqmxL5_)0t z;Wx2ooXO*#zO-g2y5g^f&DzgFk7zgUy)G6WA%&nuKtA{7ABFF4&E;quXMq3R0QpZ& zA8T|P9{%AZq2W6=3FioH{p9Le__047hs=@+ls_y52_LiT2nhC-Fn{j$=~CkMotA`w zORf?PhAZFOU^6_~lB-wf4XGn+cN0mq_3MsMagA{P^do$u(muA-ZwJq#MDn`ooIUy)aXY!jUbM>J5W1M&tSnAD zTe|W!lWlbHf4xZW8(rb0Zm?=@Z1{NOJbB}Do?g*uE9%J(E?q<#!8RXwkVH@%JJ;+83Aho2GnK5gNjCd>U^odjjZAUs(gCuZIBNbXaLW> zSzW@g%AmVm=7Jz^tvtR9eMz6pTz_W(??h@)$fLJ(p2%V;p0!{wQA@I0Gh*?Nue1El|%lwvWM-`iTf1nq!ATy!% z)@S`j*h(*h%tl;r_-}14qvxur$-iggX^uRva1AH!Os^sue6V)p3E}eV5$8J}AA=eP zm@Ejbrl(rl5CvvO%)g4EY&oX;pnCWFB&sM7f^^98?j{HLIye0age&KiJfT%fnV58_ znrtC!j7H|6KMhXzY9R)?V^;zOc8ZCaJ$S<8_IAQ(we5ZWn~$^4#Ygq@3FU(npa9I` zCx}PNj~sv;C*Pa7BwWZEMsSKE5Rb}SD765DE$*8N5sw``0cn#@NqY*b{iMS9&_%9F zyphN4@{*@IpwO`NK;X|6)0w*&`6G$Ce_TEOm(CZJ9^>62WE~gYR`W^WL7whvVS_DS$A1-8EPK6vFf15kF*+7U1FY!Kj2$`R!n&nCQNXVBOmpnn z5v%p9QR8usr;qe+HMFE2ivt=bTBuQY}_sfK!0X=Ec#`z_E*U=o_Q2S6p?*l($oW~qx zC*zuG2ScCVQtw49Zirw59`V^73+w{%4VUu`o)w%`%VLc2e|d1$sw*u4&ufzr^s+`1 zTW7b%!IRpJtVusAqRLAgD4{GZM1;d|%)pNEAo?dIo5&2x{ zk0l$Fi4H{9y{nf^v#F+b4!4`Jq58TbyPVh-r!L7XP%4u)v=w5KClqWMJCG@IH7_hK z)cRdA7LfM91wOPdE;P6CAM!PP0!RloUYFvtuCVXJYhoMvKbp=vobB)L!$wQ(wrUep zOHq3htJV#nTlJo)~v>$&{zN;se7ocFn3 z_bb2eV|enGGif)aJaw%-D?5#g?g*UoU~%Z3F=8e=eF zms%7b5yK*wk=8aY^mPvkH%S;2`4XruK=~17LhZE!hgNM?DA2a~ScGVr!8QKqM`5f#7bICg)ukmCA$4i{NlkG- z3Fg;Ik9yR4QSg`wnL_uPZcW91w{-sX7Hi16mG0(x@+SbM*gUvbDc~acBJaVy%oLw7 zv=

>m+|Fa4CI5 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

*r=!lU#7N=j{}^-m7=TjYxc3t z`77HvfPe$-M};koMegJ{)7Yj4NsX`RbdB?C7+*`;7Jh|x;1|YMXwE26Ca(k>;$u9# zLfh)Q^w<`4!mNETHoiiK_&AlSQ+dV#mCK*kNsYs)+oENwtwnxgtD^qmeb*a}`XwQu zz>kjttP|?iu4~0ri{0TVZ{yy*Av+d?v z?zG?E{C}=({H{!cuDaq934j{80Oz(l{$w56x3za=E`nwZw=xZW>1AnVv~Yn+&mPD5 zCN&&Jv577rL@Xvp7gM8JrkeS(Hzf}v(g~=1%b`zyf3k&@!bS|P{ zo$%&c!)3ZQMnVh(L$$TRU2b=1GtG@qtPe1?BCt_D^^~46p?S!r$)xG6x5wB$f4;*` zQ`}!~q!2;Mi|*-w6z4t2rK?RVZS=e|uO zXqX{CK6lw)|JKhZnGj~tXt2B`lR0pyS0_iNXmjlVwN1BUkC7?bJR3AcNbmM*ELuM4;t*6Y5DniYTMN^ zQMy&8YF)MNsHn2{leW<$3E7rgkK?+!@XHifQ`~&(?bcnq##*_l99OTDHWB`Ys_P&X z!N)7FzUCTa2r*ex<1?pgmm}rBCtsJ6)KS|lv!~_1Y4_cu_4vuXPP9Azc#nOyaG^}8 zM%m53zn-EzfHOCj?XgD{nQFDR;lp0C#~*!AS~SbNPL-wcg>Zh@n{TNi<)_y5 z=*}+u8znP5U=1xXp^@Y4r1!C zx!YD8z-?>l1g`Ns@j7h@hp^d?=b?^qc%|r&(AD_@;R)Ag2Yv|Gzz6


hGzb|Amf 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 diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx index 0749ae1d30e9e..1eabf2441da4f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx @@ -17,6 +17,7 @@ import { EuiButtonEmpty, EuiButton, EuiFlyoutBody, + EuiBetaBadge, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useActionsConnectorsContext } from '../../context/actions_connectors_context'; @@ -146,6 +147,17 @@ export const ConnectorAddFlyout = () => { actionTypeName: actionType.name, }} /> +   + @@ -159,6 +171,17 @@ export const ConnectorAddFlyout = () => { defaultMessage="Select a connector" id="xpack.triggersActionsUI.sections.addConnectorForm.selectConnectorFlyoutTitle" /> +   + )} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx index 55386ec6d61f9..6486292725660 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx @@ -5,7 +5,7 @@ */ import React, { useCallback, useReducer, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiTitle, EuiFlexItem, EuiIcon, EuiFlexGroup } from '@elastic/eui'; +import { EuiTitle, EuiFlexItem, EuiIcon, EuiFlexGroup, EuiBetaBadge } from '@elastic/eui'; import { EuiModal, EuiButton, @@ -129,6 +129,17 @@ export const ConnectorAddModal = ({ actionTypeName: actionType.name, }} /> +   + diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx index f7ad6f95d048f..6fe555fd74b39 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx @@ -16,6 +16,7 @@ import { EuiFlyoutFooter, EuiButtonEmpty, EuiButton, + EuiBetaBadge, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useActionsConnectorsContext } from '../../context/actions_connectors_context'; @@ -96,6 +97,17 @@ export const ConnectorEditFlyout = ({ initialConnector }: ConnectorEditProps) => defaultMessage="Edit connector" id="xpack.triggersActionsUI.sections.editConnectorForm.flyoutTitle" /> +   + diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_add/alert_add.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_add/alert_add.tsx index a88f916346985..20ba9f5a49715 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_add/alert_add.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_add/alert_add.tsx @@ -16,6 +16,7 @@ import { EuiButton, EuiFlyoutBody, EuiPortal, + EuiBetaBadge, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useAlertsContext } from '../../context/alerts_context'; @@ -136,6 +137,16 @@ export const AlertAdd = ({ consumer, canChangeTrigger, alertTypeId }: AlertAddPr defaultMessage="Create Alert" id="xpack.triggersActionsUI.sections.alertAdd.flyoutTitle" /> +   + diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx index d2cf2decc4a16..2625768dc7242 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx @@ -8,9 +8,17 @@ import uuid from 'uuid'; import { shallow } from 'enzyme'; import { AlertDetails } from './alert_details'; import { Alert, ActionType } from '../../../../types'; -import { EuiTitle, EuiBadge, EuiFlexItem, EuiButtonEmpty, EuiSwitch } from '@elastic/eui'; +import { + EuiTitle, + EuiBadge, + EuiFlexItem, + EuiButtonEmpty, + EuiSwitch, + EuiBetaBadge, +} from '@elastic/eui'; import { times, random } from 'lodash'; import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; jest.mock('../../../app_context', () => ({ useAppDependencies: jest.fn(() => ({ @@ -54,7 +62,19 @@ describe('alert_details', () => { ).containsMatchingElement( -

{alert.name}

+

+ {alert.name} +   + +

) ).toBeTruthy(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx index 9c3b69962879f..1952e35c22924 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx @@ -21,8 +21,10 @@ import { EuiSwitch, EuiCallOut, EuiSpacer, + EuiBetaBadge, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; import { useAppDependencies } from '../../../app_context'; import { hasSaveAlertsCapability } from '../../../lib/capabilities'; import { Alert, AlertType, ActionType } from '../../../../types'; @@ -66,7 +68,20 @@ export const AlertDetails: React.FunctionComponent = ({ -

{alert.name}

+

+ {alert.name} +   + +

diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts index 307f39382a236..f049406b639c7 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts @@ -23,7 +23,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await log.debug('Checking for section heading to say Triggers and Actions.'); const headingText = await pageObjects.triggersActionsUI.getSectionHeadingText(); - expect(headingText).to.be('Alerts and Actions'); + expect(headingText).to.be('Alerts and Actions BETA'); }); describe('Connectors tab', () => { From 841e64e0c1a56e00b50394ff85567f2f6a20faab Mon Sep 17 00:00:00 2001 From: Spencer Date: Thu, 27 Feb 2020 14:19:24 -0700 Subject: [PATCH 49/64] =?UTF-8?q?run=20jest=20with=20`--detectOpenHandles`?= =?UTF-8?q?=20on=20CI=20to=20figure=20out=20what=20i=E2=80=A6=20(#58543)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * run jest with `--detectOpenHandles` on CI to figure out what is happening with pauses * focus tests on jest integration * force kill child processes in config reload test * skip flaky suite * increase timeout for looking for installed packages * run all tests again --- .../reload_logging_config.test.ts | 318 +++++++++--------- .../installed_packages.test.ts | 2 +- tasks/test_jest.js | 2 +- test/scripts/jenkins_xpack.sh | 2 +- 4 files changed, 159 insertions(+), 165 deletions(-) diff --git a/src/cli/serve/integration_tests/reload_logging_config.test.ts b/src/cli/serve/integration_tests/reload_logging_config.test.ts index 2def3569828d3..9ad8438c312a1 100644 --- a/src/cli/serve/integration_tests/reload_logging_config.test.ts +++ b/src/cli/serve/integration_tests/reload_logging_config.test.ts @@ -84,180 +84,174 @@ function createConfigManager(configPath: string) { } describe('Server logging configuration', function() { - let child: Child.ChildProcess; + let child: undefined | Child.ChildProcess; + beforeEach(() => { Fs.mkdirSync(tempDir, { recursive: true }); }); afterEach(async () => { if (child !== undefined) { - child.kill(); - // wait for child to be killed otherwise jest complains that process not finished - await new Promise(res => setTimeout(res, 1000)); + const exitPromise = new Promise(resolve => child?.once('exit', resolve)); + child.kill('SIGKILL'); + await exitPromise; } + Del.sync(tempDir, { force: true }); }); - const isWindows = /^win/.test(process.platform); - if (isWindows) { + if (process.platform.startsWith('win')) { it('SIGHUP is not a feature of Windows.', () => { // nothing to do for Windows }); - } else { - describe('legacy logging', () => { - it( - 'should be reloadable via SIGHUP process signaling', - async function() { - const configFilePath = Path.resolve(tempDir, 'kibana.yml'); - Fs.copyFileSync(legacyConfig, configFilePath); - - child = Child.spawn(process.execPath, [ - kibanaPath, - '--oss', - '--config', - configFilePath, - '--verbose', - ]); - - const message$ = Rx.fromEvent(child.stdout, 'data').pipe( - map(messages => - String(messages) - .split('\n') - .filter(Boolean) - ) - ); - - await message$ - .pipe( - // We know the sighup handler will be registered before this message logged - filter(messages => messages.some(m => m.includes('setting up root'))), - take(1) - ) - .toPromise(); - - const lastMessage = await message$.pipe(take(1)).toPromise(); - expect(containsJsonOnly(lastMessage)).toBe(true); - - createConfigManager(configFilePath).modify(oldConfig => { - oldConfig.logging.json = false; - return oldConfig; - }); - - child.kill('SIGHUP'); - - await message$ - .pipe( - filter(messages => !containsJsonOnly(messages)), - take(1) - ) - .toPromise(); - }, - minute - ); - - it( - 'should recreate file handle on SIGHUP', - async function() { - const logPath = Path.resolve(tempDir, 'kibana.log'); - const logPathArchived = Path.resolve(tempDir, 'kibana_archive.log'); - - child = Child.spawn(process.execPath, [ - kibanaPath, - '--oss', - '--config', - legacyConfig, - '--logging.dest', - logPath, - '--verbose', - ]); - - await watchFileUntil(logPath, /setting up root/, 30 * second); - // once the server is running, archive the log file and issue SIGHUP - Fs.renameSync(logPath, logPathArchived); - child.kill('SIGHUP'); - - await watchFileUntil( - logPath, - /Reloaded logging configuration due to SIGHUP/, - 30 * second - ); - }, - minute - ); - }); - - describe('platform logging', () => { - it( - 'should be reloadable via SIGHUP process signaling', - async function() { - const configFilePath = Path.resolve(tempDir, 'kibana.yml'); - Fs.copyFileSync(configFileLogConsole, configFilePath); - - child = Child.spawn(process.execPath, [kibanaPath, '--oss', '--config', configFilePath]); - - const message$ = Rx.fromEvent(child.stdout, 'data').pipe( - map(messages => - String(messages) - .split('\n') - .filter(Boolean) - ) - ); - - await message$ - .pipe( - // We know the sighup handler will be registered before this message logged - filter(messages => messages.some(m => m.includes('setting up root'))), - take(1) - ) - .toPromise(); - - const lastMessage = await message$.pipe(take(1)).toPromise(); - expect(containsJsonOnly(lastMessage)).toBe(true); - - createConfigManager(configFilePath).modify(oldConfig => { - oldConfig.logging.appenders.console.layout.kind = 'pattern'; - return oldConfig; - }); - child.kill('SIGHUP'); - - await message$ - .pipe( - filter(messages => !containsJsonOnly(messages)), - take(1) - ) - .toPromise(); - }, - 30 * second - ); - it( - 'should recreate file handle on SIGHUP', - async function() { - const configFilePath = Path.resolve(tempDir, 'kibana.yml'); - Fs.copyFileSync(configFileLogFile, configFilePath); - - const logPath = Path.resolve(tempDir, 'kibana.log'); - const logPathArchived = Path.resolve(tempDir, 'kibana_archive.log'); - - createConfigManager(configFilePath).modify(oldConfig => { - oldConfig.logging.appenders.file.path = logPath; - return oldConfig; - }); - - child = Child.spawn(process.execPath, [kibanaPath, '--oss', '--config', configFilePath]); - - await watchFileUntil(logPath, /setting up root/, 30 * second); - // once the server is running, archive the log file and issue SIGHUP - Fs.renameSync(logPath, logPathArchived); - child.kill('SIGHUP'); - - await watchFileUntil( - logPath, - /Reloaded logging configuration due to SIGHUP/, - 30 * second - ); - }, - minute - ); - }); + return; } + + describe('legacy logging', () => { + it( + 'should be reloadable via SIGHUP process signaling', + async function() { + const configFilePath = Path.resolve(tempDir, 'kibana.yml'); + Fs.copyFileSync(legacyConfig, configFilePath); + + child = Child.spawn(process.execPath, [ + kibanaPath, + '--oss', + '--config', + configFilePath, + '--verbose', + ]); + + const message$ = Rx.fromEvent(child.stdout, 'data').pipe( + map(messages => + String(messages) + .split('\n') + .filter(Boolean) + ) + ); + + await message$ + .pipe( + // We know the sighup handler will be registered before this message logged + filter(messages => messages.some(m => m.includes('setting up root'))), + take(1) + ) + .toPromise(); + + const lastMessage = await message$.pipe(take(1)).toPromise(); + expect(containsJsonOnly(lastMessage)).toBe(true); + + createConfigManager(configFilePath).modify(oldConfig => { + oldConfig.logging.json = false; + return oldConfig; + }); + + child.kill('SIGHUP'); + + await message$ + .pipe( + filter(messages => !containsJsonOnly(messages)), + take(1) + ) + .toPromise(); + }, + minute + ); + + it( + 'should recreate file handle on SIGHUP', + async function() { + const logPath = Path.resolve(tempDir, 'kibana.log'); + const logPathArchived = Path.resolve(tempDir, 'kibana_archive.log'); + + child = Child.spawn(process.execPath, [ + kibanaPath, + '--oss', + '--config', + legacyConfig, + '--logging.dest', + logPath, + '--verbose', + ]); + + await watchFileUntil(logPath, /setting up root/, 30 * second); + // once the server is running, archive the log file and issue SIGHUP + Fs.renameSync(logPath, logPathArchived); + child.kill('SIGHUP'); + + await watchFileUntil(logPath, /Reloaded logging configuration due to SIGHUP/, 30 * second); + }, + minute + ); + }); + + describe('platform logging', () => { + it( + 'should be reloadable via SIGHUP process signaling', + async function() { + const configFilePath = Path.resolve(tempDir, 'kibana.yml'); + Fs.copyFileSync(configFileLogConsole, configFilePath); + + child = Child.spawn(process.execPath, [kibanaPath, '--oss', '--config', configFilePath]); + + const message$ = Rx.fromEvent(child.stdout, 'data').pipe( + map(messages => + String(messages) + .split('\n') + .filter(Boolean) + ) + ); + + await message$ + .pipe( + // We know the sighup handler will be registered before this message logged + filter(messages => messages.some(m => m.includes('setting up root'))), + take(1) + ) + .toPromise(); + + const lastMessage = await message$.pipe(take(1)).toPromise(); + expect(containsJsonOnly(lastMessage)).toBe(true); + + createConfigManager(configFilePath).modify(oldConfig => { + oldConfig.logging.appenders.console.layout.kind = 'pattern'; + return oldConfig; + }); + child.kill('SIGHUP'); + + await message$ + .pipe( + filter(messages => !containsJsonOnly(messages)), + take(1) + ) + .toPromise(); + }, + 30 * second + ); + it( + 'should recreate file handle on SIGHUP', + async function() { + const configFilePath = Path.resolve(tempDir, 'kibana.yml'); + Fs.copyFileSync(configFileLogFile, configFilePath); + + const logPath = Path.resolve(tempDir, 'kibana.log'); + const logPathArchived = Path.resolve(tempDir, 'kibana_archive.log'); + + createConfigManager(configFilePath).modify(oldConfig => { + oldConfig.logging.appenders.file.path = logPath; + return oldConfig; + }); + + child = Child.spawn(process.execPath, [kibanaPath, '--oss', '--config', configFilePath]); + + await watchFileUntil(logPath, /setting up root/, 30 * second); + // once the server is running, archive the log file and issue SIGHUP + Fs.renameSync(logPath, logPathArchived); + child.kill('SIGHUP'); + + await watchFileUntil(logPath, /Reloaded logging configuration due to SIGHUP/, 30 * second); + }, + minute + ); + }); }); diff --git a/src/dev/npm/integration_tests/installed_packages.test.ts b/src/dev/npm/integration_tests/installed_packages.test.ts index 5c942005d2eee..75cd0e5607698 100644 --- a/src/dev/npm/integration_tests/installed_packages.test.ts +++ b/src/dev/npm/integration_tests/installed_packages.test.ts @@ -41,7 +41,7 @@ describe('src/dev/npm/installed_packages', () => { includeDev: true, }), ]); - }, 60 * 1000); + }, 360 * 1000); it('reads all installed packages of a module', () => { expect(fixture1Packages).toEqual([ diff --git a/tasks/test_jest.js b/tasks/test_jest.js index ff1a941610ad9..bcb05a83675e5 100644 --- a/tasks/test_jest.js +++ b/tasks/test_jest.js @@ -33,7 +33,7 @@ module.exports = function(grunt) { function runJest(jestScript) { const serverCmd = { cmd: 'node', - args: [jestScript, '--ci'], + args: [jestScript, '--ci', '--detectOpenHandles'], opts: { stdio: 'inherit' }, }; diff --git a/test/scripts/jenkins_xpack.sh b/test/scripts/jenkins_xpack.sh index 3d30496ecb582..b629e064b39b5 100755 --- a/test/scripts/jenkins_xpack.sh +++ b/test/scripts/jenkins_xpack.sh @@ -11,7 +11,7 @@ if [[ -z "$CODE_COVERAGE" ]] ; then echo " -> Running jest tests" cd "$XPACK_DIR" - checks-reporter-with-killswitch "X-Pack Jest" node scripts/jest --ci --verbose + checks-reporter-with-killswitch "X-Pack Jest" node scripts/jest --ci --verbose --detectOpenHandles echo "" echo "" From 2a03dffdad6c1dbeaf9a541c4ea0fb84183a8ca8 Mon Sep 17 00:00:00 2001 From: patrykkopycinski Date: Thu, 27 Feb 2020 22:45:53 +0100 Subject: [PATCH 50/64] [SIEM] Fix Timeline registerProvider to be called only when it's needed (#58051) --- .../drag_and_drop/draggable_wrapper.test.tsx | 31 +++++- .../drag_and_drop/draggable_wrapper.tsx | 99 +++++++++++-------- 2 files changed, 90 insertions(+), 40 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx index 92adc1a9adb7a..d34f4cce9fea4 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx @@ -12,7 +12,7 @@ import { mockBrowserFields, mocksSource } from '../../containers/source/mock'; import { TestProviders } from '../../mock'; import { mockDataProviders } from '../timeline/data_providers/mock/mock_data_providers'; import { DragDropContextWrapper } from './drag_drop_context_wrapper'; -import { DraggableWrapper } from './draggable_wrapper'; +import { DraggableWrapper, ConditionalPortal } from './draggable_wrapper'; import { useMountAppended } from '../../utils/use_mount_appended'; describe('DraggableWrapper', () => { @@ -84,3 +84,32 @@ describe('DraggableWrapper', () => { }); }); }); + +describe('ConditionalPortal', () => { + const mount = useMountAppended(); + const props = { + usePortal: false, + registerProvider: jest.fn(), + isDragging: true, + }; + + it(`doesn't call registerProvider is NOT isDragging`, () => { + mount( + +
+ + + + + @@ -3407,7 +3371,7 @@ tr:hover .c3:focus::before {
- - - -
- - -
- - - - + - - -
- - - - - - + - + title="sha1: fa5195a..." + > - - sha1: fa5195a... - - + + - - - - - + viewBox="0 0 16 16" + width={16} + xmlns="http://www.w3.org/2000/svg" + /> + + - - - - - - - -
-
-
-
-
-
-
- -
-
-
-
-
-
-
+ + + + + + + + +
+ + + + + + + + + + + + + @@ -3709,7 +3655,7 @@ tr:hover .c3:focus::before {
- - - -
- - -
- - - - + - - -
- - - - - - + - + title="md5: f7653f1..." + > - - md5: f7653f1... - - + + - - - - - + viewBox="0 0 16 16" + width={16} + xmlns="http://www.w3.org/2000/svg" + /> + + - - - - - - - -
-
-
-
-
-
-
- -
-
-
-
-
-
-
+ + + + + + + + +
+ + + + + + + + + + + + + From b6dfcc7ad790cd85dd0071124dc23203281f3f87 Mon Sep 17 00:00:00 2001 From: igoristic Date: Thu, 27 Feb 2020 21:46:45 -0500 Subject: [PATCH 57/64] Removed unused indices (#57903) Co-authored-by: Elastic Machine --- .../plugins/monitoring/common/constants.ts | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/x-pack/legacy/plugins/monitoring/common/constants.ts b/x-pack/legacy/plugins/monitoring/common/constants.ts index 1fb6acdb915b8..9a4030f3eb214 100644 --- a/x-pack/legacy/plugins/monitoring/common/constants.ts +++ b/x-pack/legacy/plugins/monitoring/common/constants.ts @@ -141,23 +141,12 @@ export const CLUSTER_ALERTS_ADDRESS_CONFIG_KEY = 'cluster_alerts.email_notificat export const STANDALONE_CLUSTER_CLUSTER_UUID = '__standalone_cluster__'; -const INDEX_PATTERN_NEW = ',monitoring-*-7-*,monitoring-*-8-*'; -const INDEX_PATTERN_KIBANA_NEW = ',monitoring-kibana-7-*,monitoring-kibana-8-*'; -const INDEX_PATTERN_LOGSTASH_NEW = ',monitoring-logstash-7-*,monitoring-logstash-8-*'; -const INDEX_PATTERN_BEATS_NEW = ',monitoring-beats-7-*,monitoring-beats-8-*'; -const INDEX_ALERTS_NEW = ',monitoring-alerts-7,monitoring-alerts-8'; -const INDEX_PATTERN_ELASTICSEARCH_NEW = ',monitoring-es-7-*,monitoring-es-8-*'; - -export const INDEX_PATTERN = '.monitoring-*-6-*,.monitoring-*-7-*' + INDEX_PATTERN_NEW; -export const INDEX_PATTERN_KIBANA = - '.monitoring-kibana-6-*,.monitoring-kibana-7-*' + INDEX_PATTERN_KIBANA_NEW; -export const INDEX_PATTERN_LOGSTASH = - '.monitoring-logstash-6-*,.monitoring-logstash-7-*' + INDEX_PATTERN_LOGSTASH_NEW; -export const INDEX_PATTERN_BEATS = - '.monitoring-beats-6-*,.monitoring-beats-7-*' + INDEX_PATTERN_BEATS_NEW; -export const INDEX_ALERTS = '.monitoring-alerts-6,.monitoring-alerts-7' + INDEX_ALERTS_NEW; -export const INDEX_PATTERN_ELASTICSEARCH = - '.monitoring-es-6-*,.monitoring-es-7-*' + INDEX_PATTERN_ELASTICSEARCH_NEW; +export const INDEX_PATTERN = '.monitoring-*-6-*,.monitoring-*-7-*'; +export const INDEX_PATTERN_KIBANA = '.monitoring-kibana-6-*,.monitoring-kibana-7-*'; +export const INDEX_PATTERN_LOGSTASH = '.monitoring-logstash-6-*,.monitoring-logstash-7-*'; +export const INDEX_PATTERN_BEATS = '.monitoring-beats-6-*,.monitoring-beats-7-*'; +export const INDEX_ALERTS = '.monitoring-alerts-6,.monitoring-alerts-7'; +export const INDEX_PATTERN_ELASTICSEARCH = '.monitoring-es-6-*,.monitoring-es-7-*'; // This is the unique token that exists in monitoring indices collected by metricbeat export const METRICBEAT_INDEX_NAME_UNIQUE_TOKEN = '-mb-'; From 4fd3b45b44fb213c3c1251d3ccbcb471a434caf9 Mon Sep 17 00:00:00 2001 From: Spencer Date: Thu, 27 Feb 2020 20:22:42 -0700 Subject: [PATCH 58/64] fix some missing awaits in functional tests (#58807) --- test/functional/apps/context/_filters.js | 2 +- test/functional/apps/dashboard/panel_expand_toggle.js | 2 +- test/functional/apps/visualize/_tsvb_markdown.ts | 4 ++-- x-pack/test/functional/page_objects/uptime_page.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/functional/apps/context/_filters.js b/test/functional/apps/context/_filters.js index c9499f5a805ab..721f8a50d0e46 100644 --- a/test/functional/apps/context/_filters.js +++ b/test/functional/apps/context/_filters.js @@ -64,7 +64,7 @@ export default function({ getService, getPageObjects }) { await filterBar.toggleFilterEnabled(TEST_ANCHOR_FILTER_FIELD); await PageObjects.context.waitUntilContextLoadingHasFinished(); - retry.try(async () => { + await retry.try(async () => { expect( await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, TEST_ANCHOR_FILTER_VALUE, false) ).to.be(true); diff --git a/test/functional/apps/dashboard/panel_expand_toggle.js b/test/functional/apps/dashboard/panel_expand_toggle.js index 930445a67aa20..5e7d55706968d 100644 --- a/test/functional/apps/dashboard/panel_expand_toggle.js +++ b/test/functional/apps/dashboard/panel_expand_toggle.js @@ -56,7 +56,7 @@ export default function({ getService, getPageObjects }) { // Add a retry to fix https://github.com/elastic/kibana/issues/14574. Perhaps the recent changes to this // being a CSS update is causing the UI to change slower than grabbing the panels? - retry.try(async () => { + await retry.try(async () => { const panelCountAfterMaxThenMinimize = await PageObjects.dashboard.getPanelCount(); expect(panelCountAfterMaxThenMinimize).to.be(panelCount); }); diff --git a/test/functional/apps/visualize/_tsvb_markdown.ts b/test/functional/apps/visualize/_tsvb_markdown.ts index b7307ac9c6cab..d37404a3d60cb 100644 --- a/test/functional/apps/visualize/_tsvb_markdown.ts +++ b/test/functional/apps/visualize/_tsvb_markdown.ts @@ -121,7 +121,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await visualBuilder.markdownSwitchSubTab('data'); await visualBuilder.cloneSeries(); - retry.try(async function seriesCountCheck() { + await retry.try(async function seriesCountCheck() { const seriesLength = (await visualBuilder.getSeries()).length; expect(seriesLength).to.be.equal(2); }); @@ -131,7 +131,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await visualBuilder.markdownSwitchSubTab('data'); await visualBuilder.createNewAgg(); - retry.try(async function aggregationCountCheck() { + await retry.try(async function aggregationCountCheck() { const aggregationLength = await visualBuilder.getAggregationCount(); expect(aggregationLength).to.be.equal(2); }); diff --git a/x-pack/test/functional/page_objects/uptime_page.ts b/x-pack/test/functional/page_objects/uptime_page.ts index a5bd4cc480287..f6e93cd14e497 100644 --- a/x-pack/test/functional/page_objects/uptime_page.ts +++ b/x-pack/test/functional/page_objects/uptime_page.ts @@ -57,7 +57,7 @@ export function UptimePageProvider({ getPageObjects, getService }: FtrProviderCo } public async pageUrlContains(value: string, expected: boolean = true) { - retry.try(async () => { + await retry.try(async () => { expect(await uptimeService.urlContains(value)).to.eql(expected); }); } From 015c7abbca81887d6d2d18c3dc44613d8f9c4c71 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 27 Feb 2020 21:49:33 -0700 Subject: [PATCH 59/64] [Maps] remove getMetricFields from AbstractESSource (#58667) * [Maps] remove getMetricFields from AbstractESSource * do not use formaters for count and unique count * fix jest test --- .../maps/public/layers/fields/es_agg_field.js | 21 +++++++--- .../maps/public/layers/fields/field.js | 8 ++++ .../public/layers/sources/es_agg_source.js | 17 ++++++-- .../maps/public/layers/sources/es_source.js | 42 ++++--------------- .../public/layers/sources/es_term_source.js | 22 ++++------ .../layers/sources/es_term_source.test.js | 2 +- .../maps/public/layers/sources/source.js | 4 +- .../properties/dynamic_color_property.test.js | 3 ++ .../properties/dynamic_style_property.js | 20 +++------ .../tooltips/es_aggmetric_tooltip_property.js | 4 +- .../maps/public/layers/vector_layer.js | 11 +++-- 11 files changed, 72 insertions(+), 82 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js b/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js index 28c199b64d3ef..27ab8fc5bfb3a 100644 --- a/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js +++ b/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js @@ -21,13 +21,17 @@ export class ESAggMetricField extends AbstractField { } getName() { - return this._source.formatMetricKey(this.getAggType(), this.getESDocFieldName()); + return this._source.getAggKey(this.getAggType(), this.getRootName()); + } + + getRootName() { + return this._getESDocFieldName(); } async getLabel() { return this._label - ? await this._label - : this._source.formatMetricLabel(this.getAggType(), this.getESDocFieldName()); + ? this._label + : this._source.getAggLabel(this.getAggType(), this.getRootName()); } getAggType() { @@ -42,13 +46,13 @@ export class ESAggMetricField extends AbstractField { return this.getAggType() === AGG_TYPE.TERMS ? 'string' : 'number'; } - getESDocFieldName() { + _getESDocFieldName() { return this._esDocField ? this._esDocField.getName() : ''; } getRequestDescription() { return this.getAggType() !== AGG_TYPE.COUNT - ? `${this.getAggType()} ${this.getESDocFieldName()}` + ? `${this.getAggType()} ${this.getRootName()}` : AGG_TYPE.COUNT; } @@ -64,7 +68,7 @@ export class ESAggMetricField extends AbstractField { } getValueAggDsl(indexPattern) { - const field = getField(indexPattern, this.getESDocFieldName()); + const field = getField(indexPattern, this.getRootName()); const aggType = this.getAggType(); const aggBody = aggType === AGG_TYPE.TERMS ? { size: 1, shard_size: 1 } : {}; return { @@ -77,6 +81,11 @@ export class ESAggMetricField extends AbstractField { return !isMetricCountable(this.getAggType()); } + canValueBeFormatted() { + // Do not use field formatters for counting metrics + return ![AGG_TYPE.COUNT, AGG_TYPE.UNIQUE_COUNT].includes(this.getAggType()); + } + async getOrdinalFieldMetaRequest(config) { return this._esDocField.getOrdinalFieldMetaRequest(config); } diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/field.js b/x-pack/legacy/plugins/maps/public/layers/fields/field.js index b5d157ad1697a..2dd553f66755f 100644 --- a/x-pack/legacy/plugins/maps/public/layers/fields/field.js +++ b/x-pack/legacy/plugins/maps/public/layers/fields/field.js @@ -17,6 +17,14 @@ export class AbstractField { return this._fieldName; } + getRootName() { + return this.getName(); + } + + canValueBeFormatted() { + return true; + } + getSource() { return this._source; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js index bee35216f59da..775535d9e2299 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import { AbstractESSource } from './es_source'; import { ESAggMetricField } from '../fields/es_agg_field'; import { ESDocField } from '../fields/es_doc_field'; @@ -72,12 +73,22 @@ export class AbstractESAggSource extends AbstractESSource { return metrics; } - formatMetricKey(aggType, fieldName) { + getAggKey(aggType, fieldName) { return aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${fieldName}` : COUNT_PROP_NAME; } - formatMetricLabel(aggType, fieldName) { - return aggType !== AGG_TYPE.COUNT ? `${aggType} of ${fieldName}` : COUNT_PROP_LABEL; + getAggLabel(aggType, fieldName) { + switch (aggType) { + case AGG_TYPE.COUNT: + return COUNT_PROP_LABEL; + case AGG_TYPE.TERMS: + return i18n.translate('xpack.maps.source.esAggSource.topTermLabel', { + defaultMessage: `Top {fieldName}`, + values: { fieldName }, + }); + default: + return `${aggType} ${fieldName}`; + } } getValueAggsDsl(indexPattern) { 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 5074b218dd615..f575fd05c8061 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 @@ -17,7 +17,7 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import uuid from 'uuid/v4'; import { copyPersistentState } from '../../reducers/util'; -import { ES_GEO_FIELD_TYPE, AGG_TYPE } from '../../../common/constants'; +import { ES_GEO_FIELD_TYPE } from '../../../common/constants'; import { DataRequestAbortError } from '../util/data_request'; import { expandToTileBoundaries } from './es_geo_grid_source/geo_tile_utils'; @@ -72,10 +72,6 @@ export class AbstractESSource extends AbstractVectorSource { return clonedDescriptor; } - getMetricFields() { - return []; - } - async _runEsQuery({ requestId, requestName, @@ -254,23 +250,7 @@ export class AbstractESSource extends AbstractVectorSource { return this._descriptor.id; } - async getFieldFormatter(fieldName) { - const metricField = this.getMetricFields().find(field => field.getName() === fieldName); - - // Do not use field formatters for counting metrics - if ( - metricField && - (metricField.type === AGG_TYPE.COUNT || metricField.type === AGG_TYPE.UNIQUE_COUNT) - ) { - return null; - } - - // fieldName could be an aggregation so it needs to be unpacked to expose raw field. - const realFieldName = metricField ? metricField.getESDocFieldName() : fieldName; - if (!realFieldName) { - return null; - } - + async createFieldFormatter(field) { let indexPattern; try { indexPattern = await this.getIndexPattern(); @@ -278,7 +258,7 @@ export class AbstractESSource extends AbstractVectorSource { return null; } - const fieldFromIndexPattern = indexPattern.fields.getByName(realFieldName); + const fieldFromIndexPattern = indexPattern.fields.getByName(field.getRootName()); if (!fieldFromIndexPattern) { return null; } @@ -336,25 +316,19 @@ export class AbstractESSource extends AbstractVectorSource { return resp.aggregations; } - getValueSuggestions = async (fieldName, query) => { - // fieldName could be an aggregation so it needs to be unpacked to expose raw field. - const metricField = this.getMetricFields().find(field => field.getName() === fieldName); - const realFieldName = metricField ? metricField.getESDocFieldName() : fieldName; - if (!realFieldName) { - return []; - } - + getValueSuggestions = async (field, query) => { try { const indexPattern = await this.getIndexPattern(); - const field = indexPattern.fields.getByName(realFieldName); return await autocompleteService.getValueSuggestions({ indexPattern, - field, + field: indexPattern.fields.getByName(field.getRootName()), query, }); } catch (error) { console.warn( - `Unable to fetch suggestions for field: ${fieldName}, query: ${query}, error: ${error.message}` + `Unable to fetch suggestions for field: ${field.getRootName()}, query: ${query}, error: ${ + error.message + }` ); return []; } 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 9cc2919404a94..30f60f543d38d 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 @@ -67,7 +67,7 @@ export class ESTermSource extends AbstractESAggSource { return this._descriptor.whereQuery; } - formatMetricKey(aggType, fieldName) { + getAggKey(aggType, fieldName) { const metricKey = aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${fieldName}` : aggType; return `${FIELD_NAME_PREFIX}${metricKey}${GROUP_BY_DELIMITER}${ @@ -75,21 +75,13 @@ export class ESTermSource extends AbstractESAggSource { }.${this._termField.getName()}`; } - formatMetricLabel(type, fieldName) { - switch (type) { - case AGG_TYPE.COUNT: - return i18n.translate('xpack.maps.source.esJoin.countLabel', { + getAggLabel(aggType, fieldName) { + return aggType === AGG_TYPE.COUNT + ? i18n.translate('xpack.maps.source.esJoin.countLabel', { defaultMessage: `Count of {indexPatternTitle}`, values: { indexPatternTitle: this._descriptor.indexPatternTitle }, - }); - case AGG_TYPE.TERMS: - return i18n.translate('xpack.maps.source.esJoin.topTermLabel', { - defaultMessage: `Top {fieldName}`, - values: { fieldName }, - }); - default: - return `${type} ${fieldName}`; - } + }) + : super.getAggLabel(aggType, fieldName); } async getPropertiesMap(searchFilters, leftSourceName, leftFieldName, registerCancelCallback) { @@ -116,7 +108,7 @@ export class ESTermSource extends AbstractESAggSource { requestDescription: this._getRequestDescription(leftSourceName, leftFieldName), }); - const countPropertyName = this.formatMetricKey(AGG_TYPE.COUNT); + const countPropertyName = this.getAggKey(AGG_TYPE.COUNT); return { propertiesMap: extractPropertiesMap(rawEsData, countPropertyName), }; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js index 39cc301d458cb..d6f9f6d2911e9 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js @@ -54,7 +54,7 @@ describe('getMetricFields', () => { expect(metrics.length).toBe(2); expect(metrics[0].getAggType()).toEqual('sum'); - expect(metrics[0].getESDocFieldName()).toEqual(sumFieldName); + expect(metrics[0].getRootName()).toEqual(sumFieldName); expect(metrics[0].getName()).toEqual( '__kbnjoin__sum_of_myFieldGettingSummed_groupby_myIndex.myTermField' ); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/source.js b/x-pack/legacy/plugins/maps/public/layers/sources/source.js index 3c6ddb74bedeb..4fef52e731f9b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/source.js @@ -132,7 +132,7 @@ export class AbstractSource { } // Returns function used to format value - async getFieldFormatter(/* fieldName */) { + async createFieldFormatter(/* field */) { return null; } @@ -140,7 +140,7 @@ export class AbstractSource { throw new Error(`Source#loadStylePropsMeta not implemented`); } - async getValueSuggestions(/* fieldName, query */) { + async getValueSuggestions(/* field, query */) { return []; } } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js index 6b08fc2a105c3..8648b073a7b79 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js @@ -25,6 +25,9 @@ const mockField = { getName() { return 'foobar'; }, + getRootName() { + return 'foobar'; + }, supportsFieldMeta() { return true; }, diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js index af78c4c0e461e..e40c82e6276c7 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js @@ -13,7 +13,6 @@ import React from 'react'; import { OrdinalLegend } from './components/ordinal_legend'; import { CategoricalLegend } from './components/categorical_legend'; import { OrdinalFieldMetaOptionsPopover } from '../components/ordinal_field_meta_options_popover'; -import { ESAggMetricField } from '../../../fields/es_agg_field'; export class DynamicStyleProperty extends AbstractStyleProperty { static type = STYLE_TYPE.DYNAMIC; @@ -26,9 +25,9 @@ export class DynamicStyleProperty extends AbstractStyleProperty { } getValueSuggestions = query => { - const fieldName = this.getFieldName(); + const field = this.getField(); const fieldSource = this.getFieldSource(); - return fieldSource && fieldName ? fieldSource.getValueSuggestions(fieldName, query) : []; + return fieldSource && field ? fieldSource.getValueSuggestions(field, query) : []; }; getFieldMeta() { @@ -185,11 +184,7 @@ export class DynamicStyleProperty extends AbstractStyleProperty { } _pluckOrdinalStyleMetaFromFieldMetaData(fieldMetaData) { - const realFieldName = - this._field instanceof ESAggMetricField - ? this._field.getESDocFieldName() - : this._field.getName(); - const stats = fieldMetaData[realFieldName]; + const stats = fieldMetaData[this._field.getRootName()]; if (!stats) { return null; } @@ -209,15 +204,12 @@ export class DynamicStyleProperty extends AbstractStyleProperty { } _pluckCategoricalStyleMetaFromFieldMetaData(fieldMetaData) { - const realFieldName = - this._field instanceof ESAggMetricField - ? this._field.getESDocFieldName() - : this._field.getName(); - if (!fieldMetaData[realFieldName] || !fieldMetaData[realFieldName].buckets) { + const rootFieldName = this._field.getRootName(); + if (!fieldMetaData[rootFieldName] || !fieldMetaData[rootFieldName].buckets) { return null; } - const ordered = fieldMetaData[realFieldName].buckets.map(bucket => { + const ordered = fieldMetaData[rootFieldName].buckets.map(bucket => { return { key: bucket.key, count: bucket.doc_count, 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 229c84fe234bd..ea000a78331eb 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 @@ -27,9 +27,7 @@ export class ESAggMetricTooltipProperty extends ESTooltipProperty { ) { return this._rawValue; } - const indexPatternField = this._indexPattern.fields.getByName( - this._metricField.getESDocFieldName() - ); + const indexPatternField = this._indexPattern.fields.getByName(this._metricField.getRootName()); if (!indexPatternField) { return this._rawValue; } diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index e1a30c8aef1d3..c515feecc1551 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -561,10 +561,13 @@ export class VectorLayer extends AbstractLayer { startLoading(dataRequestId, requestToken, nextMeta); const formatters = {}; - const promises = fields.map(async field => { - const fieldName = field.getName(); - formatters[fieldName] = await source.getFieldFormatter(fieldName); - }); + const promises = fields + .filter(field => { + return field.canValueBeFormatted(); + }) + .map(async field => { + formatters[field.getName()] = await source.createFieldFormatter(field); + }); await Promise.all(promises); stopLoading(dataRequestId, requestToken, formatters, nextMeta); From 511a9c2bee83890a874c124f30231482e6a5773e Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 27 Feb 2020 22:18:00 -0700 Subject: [PATCH 60/64] Revert "Prep agg types for new platform (#57064)" This reverts commit 0cede6a705db65ef450426db3c584fcabab42780. --- packages/kbn-utility-types/README.md | 1 - packages/kbn-utility-types/index.ts | 2 +- .../filters/brush_event.test.mocks.ts} | 13 +- .../actions/filters/brush_event.test.ts | 49 +- src/legacy/core_plugins/data/public/index.ts | 12 +- src/legacy/core_plugins/data/public/plugin.ts | 6 +- .../public/search/aggs/agg_config.test.ts | 497 ------ .../data/public/search/aggs/agg_config.ts | 61 +- .../public/search/aggs/agg_configs.test.ts | 503 ------ .../data/public/search/aggs/agg_configs.ts | 76 +- .../public/search/aggs/agg_params.test.ts | 2 + .../data/public/search/aggs/agg_type.test.ts | 16 +- .../data/public/search/aggs/agg_type.ts | 5 +- .../search/aggs/agg_types_registry.test.ts | 91 -- .../public/search/aggs/agg_types_registry.ts | 68 - .../search/aggs/buckets/_bucket_agg_type.ts | 12 +- .../search/aggs/buckets/_interval_options.ts | 1 - .../create_filter/date_histogram.test.ts | 12 +- .../buckets/create_filter/date_range.test.ts | 7 +- .../buckets/create_filter/filters.test.ts | 13 +- .../buckets/create_filter/histogram.test.ts | 12 +- .../buckets/create_filter/ip_range.test.ts | 11 +- .../aggs/buckets/create_filter/range.test.ts | 12 +- .../aggs/buckets/create_filter/terms.test.ts | 11 +- .../search/aggs/buckets/date_histogram.ts | 8 +- .../search/aggs/buckets/date_range.test.ts | 25 +- .../public/search/aggs/buckets/date_range.ts | 12 +- .../data/public/search/aggs/buckets/filter.ts | 1 - .../public/search/aggs/buckets/filters.ts | 26 +- .../search/aggs/buckets/geo_hash.test.ts | 7 +- .../public/search/aggs/buckets/geo_tile.ts | 3 +- .../search/aggs/buckets/histogram.test.ts | 33 +- .../public/search/aggs/buckets/histogram.ts | 12 +- .../public/search/aggs/buckets/ip_range.ts | 12 +- .../buckets/migrate_include_exclude_format.ts | 4 +- .../public/search/aggs/buckets/range.test.ts | 12 +- .../aggs/buckets/significant_terms.test.ts | 9 +- .../public/search/aggs/buckets/terms.test.ts | 8 +- .../aggs/filter/agg_type_filters.test.ts | 5 +- .../search/aggs/filter/agg_type_filters.ts | 1 - .../search/aggs/filter/prop_filter.test.ts | 19 +- .../data/public/search/aggs/index.test.ts | 2 + .../data/public/search/aggs/index.ts | 9 +- .../public/search/aggs/metrics/bucket_avg.ts | 1 + .../public/search/aggs/metrics/bucket_max.ts | 1 + .../public/search/aggs/metrics/bucket_min.ts | 1 - .../public/search/aggs/metrics/cardinality.ts | 5 +- .../data/public/search/aggs/metrics/count.ts | 7 +- .../lib/get_response_agg_config_class.ts | 1 - .../metrics/lib/parent_pipeline_agg_helper.ts | 1 + .../lib/sibling_pipeline_agg_helper.ts | 1 + .../public/search/aggs/metrics/median.test.ts | 7 +- .../data/public/search/aggs/metrics/median.ts | 4 +- .../search/aggs/metrics/metric_agg_type.ts | 7 +- .../data/public/search/aggs/metrics/min.ts | 1 - .../aggs/metrics/parent_pipeline.test.ts | 18 +- .../aggs/metrics/percentile_ranks.test.ts | 8 +- .../search/aggs/metrics/percentile_ranks.ts | 7 +- .../search/aggs/metrics/percentiles.test.ts | 6 +- .../public/search/aggs/metrics/percentiles.ts | 4 + .../aggs/metrics/sibling_pipeline.test.ts | 22 +- .../search/aggs/metrics/std_deviation.test.ts | 6 +- .../search/aggs/metrics/top_hit.test.ts | 6 +- .../public/search/aggs/param_types/agg.ts | 4 +- .../public/search/aggs/param_types/base.ts | 4 +- .../search/aggs/param_types/field.test.ts | 2 + .../public/search/aggs/param_types/field.ts | 5 +- .../param_types/filter/field_filters.test.ts | 11 +- .../aggs/param_types/filter/field_filters.ts | 8 +- .../search/aggs/param_types/json.test.ts | 8 +- .../public/search/aggs/param_types/json.ts | 4 +- .../search/aggs/param_types/optioned.test.ts | 2 + .../search/aggs/param_types/optioned.ts | 6 +- .../search/aggs/param_types/string.test.ts | 8 +- .../public/search/aggs/param_types/string.ts | 4 +- .../test_helpers/mock_agg_types_registry.ts | 57 - .../aggs/test_helpers/mock_data_services.ts | 54 - .../data/public/search/aggs/types.ts | 2 +- .../data/public/search/aggs/utils.test.tsx | 2 + .../data/public/search/aggs/utils.ts | 39 +- .../data/public/search/expressions/esaggs.ts | 4 +- .../data/public/search/expressions/utils.ts | 5 +- .../core_plugins/data/public/search/mocks.ts | 85 - .../data/public/search/search_service.ts | 60 +- .../data/public/search/tabify/buckets.test.ts | 2 + .../public/search/tabify/get_columns.test.ts | 22 +- .../search/tabify/response_writer.test.ts | 20 +- .../data/public/search/tabify/tabify.test.ts | 16 +- .../components/sidebar/state/reducers.ts | 18 +- .../public/legacy_imports.ts | 2 +- .../public/table_vis_controller.test.ts | 4 +- .../visualizations/public/legacy_imports.ts | 2 +- .../public/np_ready/public/vis_impl.js | 6 +- src/legacy/ui/public/agg_types/index.ts | 9 +- .../ui/public/vis/__tests__/_agg_config.js | 485 ++++++ .../ui/public/vis/__tests__/_agg_configs.js | 420 +++++ .../public/vis/__tests__/index.js} | 4 +- .../data/common/field_formats/mocks.ts | 49 - src/plugins/data/public/mocks.ts | 28 +- .../data/public/search/search_source/mocks.ts | 19 + .../editor_frame_service/service.test.tsx | 4 + .../__snapshots__/zeek_details.test.tsx.snap | 1448 +++++++++-------- 102 files changed, 2101 insertions(+), 2646 deletions(-) rename src/legacy/core_plugins/data/public/{services.ts => actions/filters/brush_event.test.mocks.ts} (76%) delete mode 100644 src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts delete mode 100644 src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts delete mode 100644 src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts delete mode 100644 src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts delete mode 100644 src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts delete mode 100644 src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.ts delete mode 100644 src/legacy/core_plugins/data/public/search/mocks.ts create mode 100644 src/legacy/ui/public/vis/__tests__/_agg_config.js create mode 100644 src/legacy/ui/public/vis/__tests__/_agg_configs.js rename src/legacy/{core_plugins/data/public/search/aggs/test_helpers/index.ts => ui/public/vis/__tests__/index.js} (86%) delete mode 100644 src/plugins/data/common/field_formats/mocks.ts diff --git a/packages/kbn-utility-types/README.md b/packages/kbn-utility-types/README.md index b57e98e379707..829fd21e14366 100644 --- a/packages/kbn-utility-types/README.md +++ b/packages/kbn-utility-types/README.md @@ -18,7 +18,6 @@ type B = UnwrapPromise
; // string ## Reference -- `Assign` — From `U` assign properties to `T` (just like object assign). - `Ensure` — Makes sure `T` is of type `X`. - `ObservableLike` — Minimal interface for an object resembling an `Observable`. - `PublicContract` — Returns an object with public keys only. diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 657d9f547de66..808935ed4cb5b 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -18,7 +18,7 @@ */ import { PromiseType } from 'utility-types'; -export { $Values, Assign, Class, Optional, Required } from 'utility-types'; +export { $Values, Required, Optional, Class } from 'utility-types'; /** * A type that may or may not be a `Promise`. diff --git a/src/legacy/core_plugins/data/public/services.ts b/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.mocks.ts similarity index 76% rename from src/legacy/core_plugins/data/public/services.ts rename to src/legacy/core_plugins/data/public/actions/filters/brush_event.test.mocks.ts index 7ecd041c70e22..2cecfd0fe8b76 100644 --- a/src/legacy/core_plugins/data/public/services.ts +++ b/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.mocks.ts @@ -17,9 +17,12 @@ * under the License. */ -import { createGetterSetter } from '../../../../plugins/kibana_utils/public'; -import { SearchStart } from './search/search_service'; +import { chromeServiceMock } from '../../../../../../core/public/mocks'; -export const [getSearchServiceShim, setSearchServiceShim] = createGetterSetter( - 'searchShim' -); +jest.doMock('ui/new_platform', () => ({ + npStart: { + core: { + chrome: chromeServiceMock.createStartContract(), + }, + }, +})); diff --git a/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts b/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts index eb29530f92fee..0e18c7c707fa3 100644 --- a/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts +++ b/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts @@ -19,13 +19,33 @@ import moment from 'moment'; -import { onBrushEvent, BrushEvent } from './brush_event'; +jest.mock('../../search/aggs', () => ({ + AggConfigs: function AggConfigs() { + return { + createAggConfig: ({ params }: Record) => ({ + params, + getIndexPattern: () => ({ + timeFieldName: 'time', + }), + }), + }; + }, +})); + +jest.mock('../../../../../../plugins/data/public/services', () => ({ + getIndexPatterns: () => { + return { + get: async () => { + return { + id: 'logstash-*', + timeFieldName: 'time', + }; + }, + }; + }, +})); -import { mockDataServices } from '../../search/aggs/test_helpers'; -import { IndexPatternsContract } from '../../../../../../plugins/data/public'; -import { dataPluginMock } from '../../../../../../plugins/data/public/mocks'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { setIndexPatterns } from '../../../../../../plugins/data/public/services'; +import { onBrushEvent, BrushEvent } from './brush_event'; describe('brushEvent', () => { const DAY_IN_MS = 24 * 60 * 60 * 1000; @@ -39,28 +59,11 @@ describe('brushEvent', () => { }, getIndexPattern: () => ({ timeFieldName: 'time', - fields: { - getByName: () => undefined, - filter: () => [], - }, }), }, ]; beforeEach(() => { - mockDataServices(); - setIndexPatterns(({ - ...dataPluginMock.createStartContract().indexPatterns, - get: async () => ({ - id: 'indexPatternId', - timeFieldName: 'time', - fields: { - getByName: () => undefined, - filter: () => [], - }, - }), - } as unknown) as IndexPatternsContract); - baseEvent = { data: { ordered: { diff --git a/src/legacy/core_plugins/data/public/index.ts b/src/legacy/core_plugins/data/public/index.ts index 8d730d18a1755..8cde5d0a1fc11 100644 --- a/src/legacy/core_plugins/data/public/index.ts +++ b/src/legacy/core_plugins/data/public/index.ts @@ -35,18 +35,18 @@ export { } from '../../../../plugins/data/public'; export { // agg_types - AggParam, // only the type is used externally, only in vis editor - AggParamOption, // only the type is used externally - DateRangeKey, // only used in field formatter deserialization, which will live in data + AggParam, + AggParamOption, + DateRangeKey, IAggConfig, IAggConfigs, IAggType, IFieldParamType, IMetricAggType, - IpRangeKey, // only used in field formatter deserialization, which will live in data + IpRangeKey, ISchemas, - OptionedParamEditorProps, // only type is used externally - OptionedValueProp, // only type is used externally + OptionedParamEditorProps, + OptionedValueProp, } from './search/types'; /** @public static code */ diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index e2b8ca5dda78c..e13e8e34eaebe 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -36,7 +36,6 @@ import { setOverlays, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../plugins/data/public/services'; -import { setSearchServiceShim } from './services'; import { SELECT_RANGE_ACTION, selectRangeAction } from './actions/select_range_action'; import { VALUE_CLICK_ACTION, valueClickAction } from './actions/value_click_action'; import { @@ -113,9 +112,6 @@ export class DataPlugin } public start(core: CoreStart, { data, uiActions }: DataPluginStartDependencies): DataStart { - const search = this.search.start(core); - setSearchServiceShim(search); - setUiSettings(core.uiSettings); setQueryService(data.query); setIndexPatterns(data.indexPatterns); @@ -127,7 +123,7 @@ export class DataPlugin uiActions.attachAction(VALUE_CLICK_TRIGGER, VALUE_CLICK_ACTION); return { - search, + search: this.search.start(core), }; } diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts deleted file mode 100644 index 7769aa29184d3..0000000000000 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts +++ /dev/null @@ -1,497 +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 { identity } from 'lodash'; - -import { AggConfig, IAggConfig } from './agg_config'; -import { AggConfigs, CreateAggConfigParams } from './agg_configs'; -import { AggType } from './agg_types'; -import { AggTypesRegistryStart } from './agg_types_registry'; -import { mockDataServices, mockAggTypesRegistry } from './test_helpers'; -import { IndexPatternField, IndexPattern } from '../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { stubIndexPatternWithFields } from '../../../../../../plugins/data/public/stubs'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { dataPluginMock } from '../../../../../../plugins/data/public/mocks'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { setFieldFormats } from '../../../../../../plugins/data/public/services'; - -describe('AggConfig', () => { - let indexPattern: IndexPattern; - let typesRegistry: AggTypesRegistryStart; - - beforeEach(() => { - jest.restoreAllMocks(); - mockDataServices(); - indexPattern = stubIndexPatternWithFields as IndexPattern; - typesRegistry = mockAggTypesRegistry(); - }); - - describe('#toDsl', () => { - it('calls #write()', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); - const configStates = { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }; - const aggConfig = ac.createAggConfig(configStates); - - const spy = jest.spyOn(aggConfig, 'write').mockImplementation(() => ({ params: {} })); - aggConfig.toDsl(); - expect(spy).toHaveBeenCalledTimes(1); - }); - - it('uses the type name as the agg name', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); - const configStates = { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }; - const aggConfig = ac.createAggConfig(configStates); - - jest.spyOn(aggConfig, 'write').mockImplementation(() => ({ params: {} })); - const dsl = aggConfig.toDsl(); - expect(dsl).toHaveProperty('date_histogram'); - }); - - it('uses the params from #write() output as the agg params', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); - const configStates = { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }; - const aggConfig = ac.createAggConfig(configStates); - - const football = {}; - jest.spyOn(aggConfig, 'write').mockImplementation(() => ({ params: football })); - const dsl = aggConfig.toDsl(); - expect(dsl.date_histogram).toBe(football); - }); - - it('includes subAggs from #write() output', () => { - const configStates = [ - { - enabled: true, - type: 'avg', - schema: 'metric', - params: {}, - }, - { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }, - ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - - const histoConfig = ac.byName('date_histogram')[0]; - const avgConfig = ac.byName('avg')[0]; - const football = {}; - - jest - .spyOn(histoConfig, 'write') - .mockImplementation(() => ({ params: {}, subAggs: [avgConfig] })); - jest.spyOn(avgConfig, 'write').mockImplementation(() => ({ params: football })); - - const dsl = histoConfig.toDsl(); - expect(dsl).toHaveProperty('aggs'); - expect(dsl.aggs).toHaveProperty(avgConfig.id); - expect(dsl.aggs[avgConfig.id]).toHaveProperty('avg'); - expect(dsl.aggs[avgConfig.id].avg).toBe(football); - }); - }); - - describe('::ensureIds', () => { - it('accepts an array of objects and assigns ids to them', () => { - const objs = [{}, {}, {}, {}]; - AggConfig.ensureIds(objs); - expect(objs[0]).toHaveProperty('id', '1'); - expect(objs[1]).toHaveProperty('id', '2'); - expect(objs[2]).toHaveProperty('id', '3'); - expect(objs[3]).toHaveProperty('id', '4'); - }); - - it('assigns ids relative to the other only item in the list', () => { - const objs = [{ id: '100' }, {}]; - AggConfig.ensureIds(objs); - expect(objs[0]).toHaveProperty('id', '100'); - expect(objs[1]).toHaveProperty('id', '101'); - }); - - it('assigns ids relative to the other items in the list', () => { - const objs = [{ id: '100' }, { id: '200' }, { id: '500' }, { id: '350' }, {}]; - AggConfig.ensureIds(objs); - expect(objs[0]).toHaveProperty('id', '100'); - expect(objs[1]).toHaveProperty('id', '200'); - expect(objs[2]).toHaveProperty('id', '500'); - expect(objs[3]).toHaveProperty('id', '350'); - expect(objs[4]).toHaveProperty('id', '501'); - }); - - it('uses ::nextId to get the starting value', () => { - jest.spyOn(AggConfig, 'nextId').mockImplementation(() => 534); - const objs = AggConfig.ensureIds([{}]); - expect(objs[0]).toHaveProperty('id', '534'); - }); - - it('only calls ::nextId once', () => { - const start = 420; - const spy = jest.spyOn(AggConfig, 'nextId').mockImplementation(() => start); - const objs = AggConfig.ensureIds([{}, {}, {}, {}, {}, {}, {}]); - - expect(spy).toHaveBeenCalledTimes(1); - objs.forEach((obj, i) => { - expect(obj).toHaveProperty('id', String(start + i)); - }); - }); - }); - - describe('::nextId', () => { - it('accepts a list of objects and picks the next id', () => { - const next = AggConfig.nextId([{ id: '100' }, { id: '500' }] as IAggConfig[]); - expect(next).toBe(501); - }); - - it('handles an empty list', () => { - const next = AggConfig.nextId([]); - expect(next).toBe(1); - }); - - it('fails when the list is not defined', () => { - expect(() => { - AggConfig.nextId((undefined as unknown) as IAggConfig[]); - }).toThrowError(); - }); - }); - - describe('#toJsonDataEquals', () => { - const testsIdentical = [ - [ - { - enabled: true, - type: 'count', - schema: 'metric', - params: { field: '@timestamp' }, - }, - ], - [ - { - enabled: true, - type: 'avg', - schema: 'metric', - params: {}, - }, - { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }, - ], - ]; - - testsIdentical.forEach((configState, index) => { - it(`identical aggregations (${index})`, () => { - const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry }); - const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry }); - expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true); - }); - }); - - const testsIdenticalDifferentOrder = [ - { - config1: [ - { - enabled: true, - type: 'avg', - schema: 'metric', - params: {}, - }, - { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }, - ], - config2: [ - { - enabled: true, - schema: 'metric', - type: 'avg', - params: {}, - }, - { - enabled: true, - schema: 'segment', - type: 'date_histogram', - params: {}, - }, - ], - }, - ]; - - testsIdenticalDifferentOrder.forEach((test, index) => { - it(`identical aggregations (${index}) - init json is in different order`, () => { - const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry }); - const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry }); - expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true); - }); - }); - - const testsDifferent = [ - { - config1: [ - { - enabled: true, - type: 'avg', - schema: 'metric', - params: {}, - }, - { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }, - ], - config2: [ - { - enabled: true, - type: 'max', - schema: 'metric', - params: {}, - }, - { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }, - ], - }, - { - config1: [ - { - enabled: true, - type: 'count', - schema: 'metric', - params: { field: '@timestamp' }, - }, - ], - config2: [ - { - enabled: true, - type: 'count', - schema: 'metric', - params: { field: '@timestamp' }, - }, - { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }, - ], - }, - ]; - - testsDifferent.forEach((test, index) => { - it(`different aggregations (${index})`, () => { - const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry }); - const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry }); - expect(ac1.jsonDataEquals(ac2.aggs)).toBe(false); - }); - }); - }); - - describe('#toJSON', () => { - it('includes the aggs id, params, type and schema', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); - const configStates = { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }; - const aggConfig = ac.createAggConfig(configStates); - - expect(aggConfig.id).toBe('1'); - expect(typeof aggConfig.params).toBe('object'); - expect(aggConfig.type).toBeInstanceOf(AggType); - expect(aggConfig.type).toHaveProperty('name', 'date_histogram'); - expect(typeof aggConfig.schema).toBe('object'); - expect(aggConfig.schema).toHaveProperty('name', 'segment'); - - const state = aggConfig.toJSON(); - expect(state).toHaveProperty('id', '1'); - expect(typeof state.params).toBe('object'); - expect(state).toHaveProperty('type', 'date_histogram'); - expect(state).toHaveProperty('schema', 'segment'); - }); - - it('test serialization order is identical (for visual consistency)', () => { - const configStates = [ - { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: {}, - }, - ]; - const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry }); - const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry }); - - // this relies on the assumption that js-engines consistently loop over properties in insertion order. - // most likely the case, but strictly speaking not guaranteed by the JS and JSON specifications. - expect(JSON.stringify(ac1.aggs) === JSON.stringify(ac2.aggs)).toBe(true); - }); - }); - - describe('#makeLabel', () => { - let aggConfig: AggConfig; - - beforeEach(() => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); - aggConfig = ac.createAggConfig({ type: 'count' } as CreateAggConfigParams); - }); - - it('uses the custom label if it is defined', () => { - aggConfig.params.customLabel = 'Custom label'; - const label = aggConfig.makeLabel(); - expect(label).toBe(aggConfig.params.customLabel); - }); - - it('default label should be "Count"', () => { - const label = aggConfig.makeLabel(); - expect(label).toBe('Count'); - }); - - it('default label should be "Percentage of Count" when percentageMode is set to true', () => { - const label = aggConfig.makeLabel(true); - expect(label).toBe('Percentage of Count'); - }); - - it('empty label if the type is not defined', () => { - aggConfig.type = (undefined as unknown) as AggType; - const label = aggConfig.makeLabel(); - expect(label).toBe(''); - }); - }); - - describe('#fieldFormatter - custom getFormat handler', () => { - it('returns formatter from getFormat handler', () => { - setFieldFormats({ - ...dataPluginMock.createStartContract().fieldFormats, - getDefaultInstance: jest.fn().mockImplementation(() => ({ - getConverterFor: jest.fn().mockImplementation(() => (t: string) => t), - })) as any, - }); - - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); - const configStates = { - enabled: true, - type: 'count', - schema: 'metric', - params: { field: '@timestamp' }, - }; - const aggConfig = ac.createAggConfig(configStates); - - const fieldFormatter = aggConfig.fieldFormatter(); - expect(fieldFormatter).toBeDefined(); - expect(fieldFormatter('text')).toBe('text'); - }); - }); - - // TODO: Converting these field formatter tests from browser tests to unit - // tests makes them much less helpful due to the extensive use of mocking. - // We should revisit these and rewrite them into something more useful. - describe('#fieldFormatter - no custom getFormat handler', () => { - let aggConfig: AggConfig; - - beforeEach(() => { - setFieldFormats({ - ...dataPluginMock.createStartContract().fieldFormats, - getDefaultInstance: jest.fn().mockImplementation(() => ({ - getConverterFor: (t?: string) => t || identity, - })) as any, - }); - indexPattern.fields.getByName = name => - ({ - format: { - getConverterFor: (t?: string) => t || identity, - }, - } as IndexPatternField); - - const configStates = { - enabled: true, - type: 'histogram', - schema: 'bucket', - params: { - field: { - format: { - getConverterFor: (t?: string) => t || identity, - }, - }, - }, - }; - const ac = new AggConfigs(indexPattern, [configStates], { typesRegistry }); - aggConfig = ac.createAggConfig(configStates); - }); - - it("returns the field's formatter", () => { - expect(aggConfig.fieldFormatter().toString()).toBe( - aggConfig - .getField() - .format.getConverterFor() - .toString() - ); - }); - - it('returns the string format if the field does not have a format', () => { - const agg = aggConfig; - agg.params.field = { type: 'number', format: null }; - const fieldFormatter = agg.fieldFormatter(); - expect(fieldFormatter).toBeDefined(); - expect(fieldFormatter('text')).toBe('text'); - }); - - it('returns the string format if there is no field', () => { - const agg = aggConfig; - delete agg.params.field; - const fieldFormatter = agg.fieldFormatter(); - expect(fieldFormatter).toBeDefined(); - expect(fieldFormatter('text')).toBe('text'); - }); - - it('returns the html converter if "html" is passed in', () => { - const field = indexPattern.fields.getByName('bytes'); - expect(aggConfig.fieldFormatter('html').toString()).toBe( - field!.format.getConverterFor('html').toString() - ); - }); - }); -}); diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts index 659bec3f702e3..2b21c5c4868a5 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts @@ -17,8 +17,16 @@ * under the License. */ +/** + * @name AggConfig + * + * @description This class represents an aggregation, which is displayed in the left-hand nav of + * the Visualize app. + */ + import _ from 'lodash'; import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { IAggType } from './agg_type'; import { AggGroupNames } from './agg_groups'; import { writeParams } from './agg_params'; @@ -30,20 +38,18 @@ import { FieldFormatsContentType, KBN_FIELD_TYPES, } from '../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getFieldFormats } from '../../../../../../plugins/data/public/services'; export interface AggConfigOptions { - type: IAggType; - enabled?: boolean; + enabled: boolean; + type: string; + params: any; id?: string; - params?: Record; - schema?: string | Schema; + schema?: string; } const unknownSchema: Schema = { name: 'unknown', - title: 'Unknown', // only here for illustrative purposes + title: 'Unknown', hideCustomLabel: true, aggFilter: [], min: 1, @@ -59,6 +65,21 @@ const unknownSchema: Schema = { }, }; +const getTypeFromRegistry = (type: string): IAggType => { + // We need to inline require here, since we're having a cyclic dependency + // from somewhere inside agg_types back to AggConfig. + const aggTypes = require('../aggs').aggTypes; + const registeredType = + aggTypes.metrics.find((agg: IAggType) => agg.name === type) || + aggTypes.buckets.find((agg: IAggType) => agg.name === type); + + if (!registeredType) { + throw new Error('unknown type'); + } + + return registeredType; +}; + const getSchemaFromRegistry = (schemas: any, schema: string): Schema => { let registeredSchema = schemas ? schemas.byName[schema] : null; if (!registeredSchema) { @@ -69,13 +90,6 @@ const getSchemaFromRegistry = (schemas: any, schema: string): Schema => { return registeredSchema; }; -/** - * @name AggConfig - * - * @description This class represents an aggregation, which is displayed in the left-hand nav of - * the Visualize app. - */ - // TODO need to make a more explicit interface for this export type IAggConfig = AggConfig; @@ -87,9 +101,9 @@ export class AggConfig { * @param {array[object]} list - a list of objects, objects can be anything really * @return {array} - the list that was passed in */ - static ensureIds(list: any[]) { - const have: IAggConfig[] = []; - const haveNot: AggConfigOptions[] = []; + static ensureIds(list: AggConfig[]) { + const have: AggConfig[] = []; + const haveNot: AggConfig[] = []; list.forEach(function(obj) { (obj.id ? have : haveNot).push(obj); }); @@ -107,7 +121,7 @@ export class AggConfig { * * @return {array} list - a list of objects with id properties */ - static nextId(list: IAggConfig[]) { + static nextId(list: AggConfig[]) { return ( 1 + list.reduce(function(max, obj) { @@ -147,10 +161,10 @@ export class AggConfig { // set the params to the values from opts, or just to the defaults this.setParams(opts.params || {}); - // @ts-ignore - this.__schema = this.__schema; // @ts-ignore this.__type = this.__type; + // @ts-ignore + this.__schema = this.__schema; } /** @@ -380,8 +394,7 @@ export class AggConfig { } fieldOwnFormatter(contentType?: FieldFormatsContentType, defaultFormat?: any) { - const fieldFormatsService = getFieldFormats(); - + const fieldFormatsService = npStart.plugins.data.fieldFormats; const field = this.getField(); let format = field && field.format; if (!format) format = defaultFormat; @@ -443,8 +456,8 @@ export class AggConfig { }); } - public setType(type: IAggType) { - this.type = type; + public setType(type: string | IAggType) { + this.type = typeof type === 'string' ? getTypeFromRegistry(type) : type; } public get schema() { diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts deleted file mode 100644 index 29f16b1e4f0bf..0000000000000 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts +++ /dev/null @@ -1,503 +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 { indexBy } from 'lodash'; -import { AggConfig } from './agg_config'; -import { AggConfigs } from './agg_configs'; -import { AggTypesRegistryStart } from './agg_types_registry'; -import { Schemas } from './schemas'; -import { AggGroupNames } from './agg_groups'; -import { mockDataServices, mockAggTypesRegistry } from './test_helpers'; -import { IndexPatternField, IndexPattern } from '../../../../../../plugins/data/public'; -import { - stubIndexPattern, - stubIndexPatternWithFields, - // eslint-disable-next-line @kbn/eslint/no-restricted-paths -} from '../../../../../../plugins/data/public/stubs'; - -describe('AggConfigs', () => { - let indexPattern: IndexPattern; - let typesRegistry: AggTypesRegistryStart; - - beforeEach(() => { - indexPattern = stubIndexPatternWithFields as IndexPattern; - typesRegistry = mockAggTypesRegistry(); - }); - - describe('constructor', () => { - it('handles passing just a type', () => { - const configStates = [ - { - enabled: true, - type: 'histogram', - params: {}, - }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - expect(ac.aggs).toHaveLength(1); - }); - - it('attempts to ensure that all states have an id', () => { - const configStates = [ - { - enabled: true, - type: 'histogram', - params: {}, - }, - { - enabled: true, - type: 'date_histogram', - params: {}, - }, - { - enabled: true, - type: 'terms', - params: {}, - schema: 'split', - }, - ]; - - const spy = jest.spyOn(AggConfig, 'ensureIds'); - new AggConfigs(indexPattern, configStates, { typesRegistry }); - expect(spy).toHaveBeenCalledTimes(1); - expect(spy.mock.calls[0]).toEqual([configStates]); - spy.mockRestore(); - }); - - describe('defaults', () => { - const schemas = new Schemas([ - { - group: AggGroupNames.Metrics, - name: 'metric', - title: 'Simple', - min: 1, - max: 2, - defaults: [ - { schema: 'metric', type: 'count' }, - { schema: 'metric', type: 'avg' }, - { schema: 'metric', type: 'sum' }, - ], - }, - { - group: AggGroupNames.Buckets, - name: 'segment', - title: 'Example', - min: 0, - max: 1, - defaults: [ - { schema: 'segment', type: 'terms' }, - { schema: 'segment', type: 'filters' }, - ], - }, - ]); - - it('should only set the number of defaults defined by the max', () => { - const ac = new AggConfigs(indexPattern, [], { - schemas: schemas.all, - typesRegistry, - }); - expect(ac.bySchemaName('metric')).toHaveLength(2); - }); - - it('should set the defaults defined in the schema when none exist', () => { - const ac = new AggConfigs(indexPattern, [], { - schemas: schemas.all, - typesRegistry, - }); - expect(ac.aggs).toHaveLength(3); - }); - - it('should NOT set the defaults defined in the schema when some exist', () => { - const configStates = [ - { - enabled: true, - type: 'date_histogram', - params: {}, - schema: 'segment', - }, - ]; - const ac = new AggConfigs(indexPattern, configStates, { - schemas: schemas.all, - typesRegistry, - }); - expect(ac.aggs).toHaveLength(3); - expect(ac.bySchemaName('segment')[0].type.name).toEqual('date_histogram'); - }); - }); - }); - - describe('#createAggConfig', () => { - it('accepts a configState which is provided as an AggConfig object', () => { - const configStates = [ - { - enabled: true, - type: 'histogram', - params: {}, - }, - { - enabled: true, - type: 'date_histogram', - params: {}, - }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - expect(ac.aggs).toHaveLength(2); - - ac.createAggConfig( - new AggConfig(ac, { - enabled: true, - type: typesRegistry.get('terms'), - params: {}, - schema: 'split', - }) - ); - expect(ac.aggs).toHaveLength(3); - }); - - it('adds new AggConfig entries to AggConfigs by default', () => { - const configStates = [ - { - enabled: true, - type: 'histogram', - params: {}, - }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - expect(ac.aggs).toHaveLength(1); - - ac.createAggConfig({ - enabled: true, - type: 'terms', - params: {}, - schema: 'split', - }); - expect(ac.aggs).toHaveLength(2); - }); - - it('does not add an agg to AggConfigs if addToAggConfigs: false', () => { - const configStates = [ - { - enabled: true, - type: 'histogram', - params: {}, - }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - expect(ac.aggs).toHaveLength(1); - - ac.createAggConfig( - { - enabled: true, - type: 'terms', - params: {}, - schema: 'split', - }, - { addToAggConfigs: false } - ); - expect(ac.aggs).toHaveLength(1); - }); - }); - - describe('#getRequestAggs', () => { - it('performs a stable sort, but moves metrics to the bottom', () => { - const configStates = [ - { type: 'avg', enabled: true, params: {}, schema: 'metric' }, - { type: 'terms', enabled: true, params: {}, schema: 'split' }, - { type: 'histogram', enabled: true, params: {}, schema: 'split' }, - { type: 'sum', enabled: true, params: {}, schema: 'metric' }, - { type: 'date_histogram', enabled: true, params: {}, schema: 'segment' }, - { type: 'filters', enabled: true, params: {}, schema: 'split' }, - { type: 'percentiles', enabled: true, params: {}, schema: 'metric' }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - const sorted = ac.getRequestAggs(); - const aggs = indexBy(ac.aggs, agg => agg.type.name); - - expect(sorted.shift()).toBe(aggs.terms); - expect(sorted.shift()).toBe(aggs.histogram); - expect(sorted.shift()).toBe(aggs.date_histogram); - expect(sorted.shift()).toBe(aggs.filters); - expect(sorted.shift()).toBe(aggs.avg); - expect(sorted.shift()).toBe(aggs.sum); - expect(sorted.shift()).toBe(aggs.percentiles); - expect(sorted).toHaveLength(0); - }); - }); - - describe('#getResponseAggs', () => { - it('returns all request aggs for basic aggs', () => { - const configStates = [ - { type: 'terms', enabled: true, params: {}, schema: 'split' }, - { type: 'date_histogram', enabled: true, params: {}, schema: 'segment' }, - { type: 'count', enabled: true, params: {}, schema: 'metric' }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - const sorted = ac.getResponseAggs(); - const aggs = indexBy(ac.aggs, agg => agg.type.name); - - expect(sorted.shift()).toBe(aggs.terms); - expect(sorted.shift()).toBe(aggs.date_histogram); - expect(sorted.shift()).toBe(aggs.count); - expect(sorted).toHaveLength(0); - }); - - it('expands aggs that have multiple responses', () => { - const configStates = [ - { type: 'terms', enabled: true, params: {}, schema: 'split' }, - { type: 'date_histogram', enabled: true, params: {}, schema: 'segment' }, - { type: 'percentiles', enabled: true, params: { percents: [1, 2, 3] }, schema: 'metric' }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - const sorted = ac.getResponseAggs(); - const aggs = indexBy(ac.aggs, agg => agg.type.name); - - expect(sorted.shift()).toBe(aggs.terms); - expect(sorted.shift()).toBe(aggs.date_histogram); - expect(sorted.shift()!.id!).toBe(aggs.percentiles.id + '.' + 1); - expect(sorted.shift()!.id!).toBe(aggs.percentiles.id + '.' + 2); - expect(sorted.shift()!.id!).toBe(aggs.percentiles.id + '.' + 3); - expect(sorted).toHaveLength(0); - }); - }); - - describe('#toDsl', () => { - const schemas = new Schemas([ - { - group: AggGroupNames.Buckets, - name: 'segment', - }, - { - group: AggGroupNames.Buckets, - name: 'split', - }, - ]); - - beforeEach(() => { - mockDataServices(); - indexPattern = stubIndexPattern as IndexPattern; - indexPattern.fields.getByName = name => (name as unknown) as IndexPatternField; - }); - - it('uses the sorted aggs', () => { - const configStates = [{ enabled: true, type: 'avg', params: { field: 'bytes' } }]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - const spy = jest.spyOn(AggConfigs.prototype, 'getRequestAggs'); - ac.toDsl(); - expect(spy).toHaveBeenCalledTimes(1); - spy.mockRestore(); - }); - - it('calls aggConfig#toDsl() on each aggConfig and compiles the nested output', () => { - const configStates = [ - { enabled: true, type: 'date_histogram', params: {}, schema: 'segment' }, - { enabled: true, type: 'terms', params: {}, schema: 'split' }, - { enabled: true, type: 'count', params: {} }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { - typesRegistry, - schemas: schemas.all, - }); - - const aggInfos = ac.aggs.map(aggConfig => { - const football = {}; - aggConfig.toDsl = jest.fn().mockImplementation(() => football); - - return { - id: aggConfig.id, - football, - }; - }); - - (function recurse(lvl: Record): void { - const info = aggInfos.shift(); - if (!info) return; - - expect(lvl).toHaveProperty(info.id); - expect(lvl[info.id]).toBe(info.football); - - if (lvl[info.id].aggs) { - return recurse(lvl[info.id].aggs); - } - })(ac.toDsl()); - - expect(aggInfos).toHaveLength(1); - }); - - it("skips aggs that don't have a dsl representation", () => { - const configStates = [ - { - enabled: true, - type: 'date_histogram', - params: { field: '@timestamp', interval: '10s' }, - schema: 'segment', - }, - { - enabled: true, - type: 'count', - params: {}, - schema: 'metric', - }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - const dsl = ac.toDsl(); - const histo = ac.byName('date_histogram')[0]; - const count = ac.byName('count')[0]; - - expect(dsl).toHaveProperty(histo.id); - expect(typeof dsl[histo.id]).toBe('object'); - expect(dsl[histo.id]).not.toHaveProperty('aggs'); - expect(dsl).not.toHaveProperty(count.id); - }); - - it('writes multiple metric aggregations at the same level', () => { - const configStates = [ - { - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: { field: '@timestamp', interval: '10s' }, - }, - { enabled: true, type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { enabled: true, type: 'sum', schema: 'metric', params: { field: 'bytes' } }, - { enabled: true, type: 'min', schema: 'metric', params: { field: 'bytes' } }, - { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { - typesRegistry, - schemas: schemas.all, - }); - const dsl = ac.toDsl(); - const histo = ac.byName('date_histogram')[0]; - const metrics = ac.bySchemaGroup('metrics'); - - expect(dsl).toHaveProperty(histo.id); - expect(typeof dsl[histo.id]).toBe('object'); - expect(dsl[histo.id]).toHaveProperty('aggs'); - - metrics.forEach(metric => { - expect(dsl[histo.id].aggs).toHaveProperty(metric.id); - expect(dsl[histo.id].aggs[metric.id]).not.toHaveProperty('aggs'); - }); - }); - - it('writes multiple metric aggregations at every level if the vis is hierarchical', () => { - const configStates = [ - { enabled: true, type: 'terms', schema: 'segment', params: { field: 'bytes', orderBy: 1 } }, - { enabled: true, type: 'terms', schema: 'segment', params: { field: 'bytes', orderBy: 1 } }, - { enabled: true, id: '1', type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { enabled: true, type: 'sum', schema: 'metric', params: { field: 'bytes' } }, - { enabled: true, type: 'min', schema: 'metric', params: { field: 'bytes' } }, - { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - const topLevelDsl = ac.toDsl(true); - const buckets = ac.bySchemaGroup('buckets'); - const metrics = ac.bySchemaGroup('metrics'); - - (function checkLevel(dsl) { - const bucket = buckets.shift(); - if (!bucket) return; - - expect(dsl).toHaveProperty(bucket.id); - - expect(typeof dsl[bucket.id]).toBe('object'); - expect(dsl[bucket.id]).toHaveProperty('aggs'); - - metrics.forEach((metric: AggConfig) => { - expect(dsl[bucket.id].aggs).toHaveProperty(metric.id); - expect(dsl[bucket.id].aggs[metric.id]).not.toHaveProperty('aggs'); - }); - - if (buckets.length) { - checkLevel(dsl[bucket.id].aggs); - } - })(topLevelDsl); - }); - - it('adds the parent aggs of nested metrics at every level if the vis is hierarchical', () => { - const configStates = [ - { - enabled: true, - id: '1', - type: 'avg_bucket', - schema: 'metric', - params: { - customBucket: { - id: '1-bucket', - type: 'date_histogram', - schema: 'bucketAgg', - params: { - field: '@timestamp', - interval: '10s', - }, - }, - customMetric: { - id: '1-metric', - type: 'count', - schema: 'metricAgg', - params: {}, - }, - }, - }, - { - enabled: true, - id: '2', - type: 'terms', - schema: 'bucket', - params: { - field: 'clientip', - }, - }, - { - enabled: true, - id: '3', - type: 'terms', - schema: 'bucket', - params: { - field: 'machine.os.raw', - }, - }, - ]; - - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); - const topLevelDsl = ac.toDsl(true)['2']; - - expect(Object.keys(topLevelDsl.aggs)).toContain('1'); - expect(Object.keys(topLevelDsl.aggs)).toContain('1-bucket'); - expect(topLevelDsl.aggs['1'].avg_bucket).toHaveProperty('buckets_path', '1-bucket>_count'); - expect(Object.keys(topLevelDsl.aggs['3'].aggs)).toContain('1'); - expect(Object.keys(topLevelDsl.aggs['3'].aggs)).toContain('1-bucket'); - expect(topLevelDsl.aggs['3'].aggs['1'].avg_bucket).toHaveProperty( - 'buckets_path', - '1-bucket>_count' - ); - }); - }); -}); diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts index ab70e66b1e138..8e091ed5f21ae 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts @@ -17,12 +17,17 @@ * under the License. */ -import _ from 'lodash'; -import { Assign } from '@kbn/utility-types'; +/** + * @name AggConfig + * + * @extends IndexedArray + * + * @description A "data structure"-like class with methods for indexing and + * accessing instances of AggConfig. + */ +import _ from 'lodash'; import { AggConfig, AggConfigOptions, IAggConfig } from './agg_config'; -import { IAggType } from './agg_type'; -import { AggTypesRegistryStart } from './agg_types_registry'; import { Schema } from './schemas'; import { AggGroupNames } from './agg_groups'; import { @@ -50,24 +55,6 @@ function parseParentAggs(dslLvlCursor: any, dsl: any) { } } -export interface AggConfigsOptions { - schemas?: Schemas; - typesRegistry: AggTypesRegistryStart; -} - -export type CreateAggConfigParams = Assign; - -/** - * @name AggConfigs - * - * @description A "data structure"-like class with methods for indexing and - * accessing instances of AggConfig. This should never be instantiated directly - * outside of this plugin. Rather, downstream plugins should do this via - * `createAggConfigs()` - * - * @internal - */ - // TODO need to make a more explicit interface for this export type IAggConfigs = AggConfigs; @@ -75,31 +62,23 @@ export class AggConfigs { public indexPattern: IndexPattern; public schemas: any; public timeRange?: TimeRange; - private readonly typesRegistry: AggTypesRegistryStart; aggs: IAggConfig[]; - constructor( - indexPattern: IndexPattern, - configStates: CreateAggConfigParams[] = [], - opts: AggConfigsOptions - ) { - this.typesRegistry = opts.typesRegistry; - + constructor(indexPattern: IndexPattern, configStates = [] as any, schemas?: any) { configStates = AggConfig.ensureIds(configStates); this.aggs = []; this.indexPattern = indexPattern; - this.schemas = opts.schemas; + this.schemas = schemas; configStates.forEach((params: any) => this.createAggConfig(params)); - if (this.schemas) { - this.initializeDefaultsFromSchemas(this.schemas); + if (schemas) { + this.initializeDefaultsFromSchemas(schemas); } } - // do this wherever the schemas were passed in, & pass in state defaults instead initializeDefaultsFromSchemas(schemas: Schemas) { // Set the defaults for any schema which has them. If the defaults // for some reason has more then the max only set the max number @@ -112,11 +91,10 @@ export class AggConfigs { }) .each((schema: any) => { if (!this.aggs.find((agg: AggConfig) => agg.schema && agg.schema.name === schema.name)) { - // the result here should be passable as a configState const defaults = schema.defaults.slice(0, schema.max); _.each(defaults, defaultState => { const state = _.defaults({ id: AggConfig.nextId(this.aggs) }, defaultState); - this.createAggConfig(state as AggConfigOptions); + this.aggs.push(new AggConfig(this, state as AggConfigOptions)); }); } }) @@ -146,36 +124,28 @@ export class AggConfigs { if (!enabledOnly) return true; return agg.enabled; }; - - const aggConfigs = new AggConfigs(this.indexPattern, this.aggs.filter(filterAggs), { - schemas: this.schemas, - typesRegistry: this.typesRegistry, - }); - + const aggConfigs = new AggConfigs( + this.indexPattern, + this.aggs.filter(filterAggs), + this.schemas + ); return aggConfigs; } createAggConfig = ( - params: CreateAggConfigParams, + params: AggConfig | AggConfigOptions, { addToAggConfigs = true } = {} ) => { - const { type } = params; let aggConfig; - if (params instanceof AggConfig) { aggConfig = params; params.parent = this; } else { - aggConfig = new AggConfig(this, { - ...params, - type: typeof type === 'string' ? this.typesRegistry.get(type) : type, - }); + aggConfig = new AggConfig(this, params); } - if (addToAggConfigs) { this.aggs.push(aggConfig); } - return aggConfig as T; }; @@ -196,10 +166,10 @@ export class AggConfigs { return true; } - toDsl(hierarchical: boolean = false): Record { + toDsl(hierarchical: boolean = false) { const dslTopLvl = {}; let dslLvlCursor: Record; - let nestedMetrics: Array<{ config: AggConfig; dsl: Record }> | []; + let nestedMetrics: Array<{ config: AggConfig; dsl: any }> | []; if (hierarchical) { // collect all metrics, and filter out the ones that we won't be copying diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts index b08fcf309e9ed..30ab272537dad 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts @@ -23,6 +23,8 @@ import { FieldParamType } from './param_types/field'; import { OptionedParamType } from './param_types/optioned'; import { AggParamType } from '../aggs/param_types/agg'; +jest.mock('ui/new_platform'); + describe('AggParams class', () => { describe('constructor args', () => { it('accepts an array of param defs', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts index c78e56dd25887..6d4c2d1317f50 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts @@ -19,16 +19,11 @@ import { AggType, AggTypeConfig } from './agg_type'; import { IAggConfig } from './agg_config'; -import { mockDataServices } from './test_helpers'; -import { dataPluginMock } from '../../../../../../plugins/data/public/mocks'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { setFieldFormats } from '../../../../../../plugins/data/public/services'; +import { npStart } from 'ui/new_platform'; -describe('AggType Class', () => { - beforeEach(() => { - mockDataServices(); - }); +jest.mock('ui/new_platform'); +describe('AggType Class', () => { describe('constructor', () => { it("requires a valid config object as it's first param", () => { expect(() => { @@ -158,10 +153,7 @@ describe('AggType Class', () => { }); it('returns default formatter', () => { - setFieldFormats({ - ...dataPluginMock.createStartContract().fieldFormats, - getDefaultInstance: jest.fn(() => 'default') as any, - }); + npStart.plugins.data.fieldFormats.getDefaultInstance = jest.fn(() => 'default') as any; const aggType = new AggType({ name: 'name', diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts index 3cd9496d3f23d..5ccf0f65c0e92 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts @@ -19,6 +19,7 @@ import { constant, noop, identity } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { initParams } from './agg_params'; import { AggConfig } from './agg_config'; @@ -31,8 +32,6 @@ import { IFieldFormat, ISearchSource, } from '../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getFieldFormats } from '../../../../../../plugins/data/public/services'; export interface AggTypeConfig< TAggConfig extends AggConfig = AggConfig, @@ -66,7 +65,7 @@ export interface AggTypeConfig< const getFormat = (agg: AggConfig) => { const field = agg.getField(); - const fieldFormatsService = getFieldFormats(); + const fieldFormatsService = npStart.plugins.data.fieldFormats; return field ? field.format : fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.STRING); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts deleted file mode 100644 index 405f83e237de8..0000000000000 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts +++ /dev/null @@ -1,91 +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 { - AggTypesRegistry, - AggTypesRegistrySetup, - AggTypesRegistryStart, -} from './agg_types_registry'; -import { BucketAggType } from './buckets/_bucket_agg_type'; -import { MetricAggType } from './metrics/metric_agg_type'; - -const bucketType = { name: 'terms', type: 'bucket' } as BucketAggType; -const metricType = { name: 'count', type: 'metric' } as MetricAggType; - -describe('AggTypesRegistry', () => { - let registry: AggTypesRegistry; - let setup: AggTypesRegistrySetup; - let start: AggTypesRegistryStart; - - beforeEach(() => { - registry = new AggTypesRegistry(); - setup = registry.setup(); - start = registry.start(); - }); - - it('registerBucket adds new buckets', () => { - setup.registerBucket(bucketType); - expect(start.getBuckets()).toEqual([bucketType]); - }); - - it('registerBucket throws error when registering duplicate bucket', () => { - expect(() => { - setup.registerBucket(bucketType); - setup.registerBucket(bucketType); - }).toThrow(/already been registered with name: terms/); - }); - - it('registerMetric adds new metrics', () => { - setup.registerMetric(metricType); - expect(start.getMetrics()).toEqual([metricType]); - }); - - it('registerMetric throws error when registering duplicate metric', () => { - expect(() => { - setup.registerMetric(metricType); - setup.registerMetric(metricType); - }).toThrow(/already been registered with name: count/); - }); - - it('gets either buckets or metrics by id', () => { - setup.registerBucket(bucketType); - setup.registerMetric(metricType); - expect(start.get('terms')).toEqual(bucketType); - expect(start.get('count')).toEqual(metricType); - }); - - it('getBuckets retrieves only buckets', () => { - setup.registerBucket(bucketType); - expect(start.getBuckets()).toEqual([bucketType]); - }); - - it('getMetrics retrieves only metrics', () => { - setup.registerMetric(metricType); - expect(start.getMetrics()).toEqual([metricType]); - }); - - it('getAll returns all buckets and metrics', () => { - setup.registerBucket(bucketType); - setup.registerMetric(metricType); - expect(start.getAll()).toEqual({ - buckets: [bucketType], - metrics: [metricType], - }); - }); -}); diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts deleted file mode 100644 index 8a8746106ae58..0000000000000 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts +++ /dev/null @@ -1,68 +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 { BucketAggType } from './buckets/_bucket_agg_type'; -import { MetricAggType } from './metrics/metric_agg_type'; - -export type AggTypesRegistrySetup = ReturnType; -export type AggTypesRegistryStart = ReturnType; - -export class AggTypesRegistry { - private readonly bucketAggs = new Map(); - private readonly metricAggs = new Map(); - - setup = () => { - return { - registerBucket: >(type: T): void => { - const { name } = type; - if (this.bucketAggs.get(name)) { - throw new Error(`Bucket agg has already been registered with name: ${name}`); - } - this.bucketAggs.set(name, type); - }, - registerMetric: >(type: T): void => { - const { name } = type; - if (this.metricAggs.get(name)) { - throw new Error(`Metric agg has already been registered with name: ${name}`); - } - this.metricAggs.set(name, type); - }, - }; - }; - - start = () => { - return { - get: (name: string) => { - return this.bucketAggs.get(name) || this.metricAggs.get(name); - }, - getBuckets: () => { - return Array.from(this.bucketAggs.values()); - }, - getMetrics: () => { - return Array.from(this.metricAggs.values()); - }, - getAll: () => { - return { - buckets: Array.from(this.bucketAggs.values()), - metrics: Array.from(this.metricAggs.values()), - }; - }, - }; - }; -} diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts index d6ab58d5250a8..546d054c5af97 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts @@ -17,16 +17,16 @@ * under the License. */ -import { IAggConfig } from '../agg_config'; +import { AggConfig } from '../agg_config'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; import { AggType, AggTypeConfig } from '../agg_type'; import { AggParamType } from '../param_types/agg'; -export interface IBucketAggConfig extends IAggConfig { +export interface IBucketAggConfig extends AggConfig { type: InstanceType; } -export interface BucketAggParam +export interface BucketAggParam extends AggParamType { scriptable?: boolean; filterFieldTypes?: KBN_FIELD_TYPES | KBN_FIELD_TYPES[] | '*'; @@ -34,12 +34,12 @@ export interface BucketAggParam const bucketType = 'buckets'; -interface BucketAggTypeConfig +interface BucketAggTypeConfig extends AggTypeConfig> { - getKey?: (bucket: any, key: any, agg: IAggConfig) => any; + getKey?: (bucket: any, key: any, agg: AggConfig) => any; } -export class BucketAggType extends AggType< +export class BucketAggType extends AggType< TBucketAggConfig, BucketAggParam > { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts index 393d3b745250f..e196687607d19 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { i18n } from '@kbn/i18n'; import { IBucketAggConfig } from './_bucket_agg_type'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts index 2b47dc384bca2..0d3f58c50a42e 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts @@ -21,22 +21,14 @@ import moment from 'moment'; import { createFilterDateHistogram } from './date_histogram'; import { intervalOptions } from '../_interval_options'; import { AggConfigs } from '../../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; -import { dateHistogramBucketAgg, IBucketDateHistogramAggConfig } from '../date_histogram'; +import { IBucketDateHistogramAggConfig } from '../date_histogram'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { RangeFilter } from '../../../../../../../../plugins/data/public'; -// TODO: remove this once time buckets is migrated jest.mock('ui/new_platform'); describe('AggConfig Filters', () => { describe('date_histogram', () => { - beforeEach(() => { - mockDataServices(); - }); - - const typesRegistry = mockAggTypesRegistry([dateHistogramBucketAgg]); - let agg: IBucketDateHistogramAggConfig; let filter: RangeFilter; let bucketStart: any; @@ -64,7 +56,7 @@ describe('AggConfig Filters', () => { params: { field: field.name, interval, customInterval: '5d' }, }, ], - { typesRegistry } + null ); const bucketKey = 1422579600000; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts index c594c7718e58b..41e806668337e 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts @@ -18,17 +18,16 @@ */ import moment from 'moment'; -import { dateRangeBucketAgg } from '../date_range'; import { createFilterDateRange } from './date_range'; import { fieldFormats, FieldFormatsGetConfigFn } from '../../../../../../../../plugins/data/public'; import { AggConfigs } from '../../agg_configs'; -import { mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; +jest.mock('ui/new_platform'); + describe('AggConfig Filters', () => { describe('Date range', () => { - const typesRegistry = mockAggTypesRegistry([dateRangeBucketAgg]); const getConfig = (() => {}) as FieldFormatsGetConfigFn; const getAggConfigs = () => { const field = { @@ -56,7 +55,7 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry } + null ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts index 3b9c771e0f15f..34cf996826865 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts @@ -16,21 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - -import { filtersBucketAgg } from '../filters'; import { createFilterFilters } from './filters'; import { AggConfigs } from '../../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; import { IBucketAggConfig } from '../_bucket_agg_type'; +jest.mock('ui/new_platform'); + describe('AggConfig Filters', () => { describe('filters', () => { - beforeEach(() => { - mockDataServices(); - }); - - const typesRegistry = mockAggTypesRegistry([filtersBucketAgg]); - const getAggConfigs = () => { const field = { name: 'bytes', @@ -59,7 +52,7 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry } + null ); }; it('should return a filters filter', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts index b046c802c58c1..9f845847df5d9 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts @@ -16,22 +16,16 @@ * specific language governing permissions and limitations * under the License. */ - import { createFilterHistogram } from './histogram'; import { AggConfigs } from '../../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; import { fieldFormats, FieldFormatsGetConfigFn } from '../../../../../../../../plugins/data/public'; +jest.mock('ui/new_platform'); + describe('AggConfig Filters', () => { describe('histogram', () => { - beforeEach(() => { - mockDataServices(); - }); - - const typesRegistry = mockAggTypesRegistry(); - const getConfig = (() => {}) as FieldFormatsGetConfigFn; const getAggConfigs = () => { const field = { @@ -61,7 +55,7 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry } + null ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts index 7572c48390dc2..e92ba5cb2852a 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts @@ -17,18 +17,17 @@ * under the License. */ -import { ipRangeBucketAgg } from '../ip_range'; import { createFilterIpRange } from './ip_range'; -import { AggConfigs, CreateAggConfigParams } from '../../agg_configs'; -import { mockAggTypesRegistry } from '../../test_helpers'; +import { AggConfigs } from '../../agg_configs'; import { fieldFormats } from '../../../../../../../../plugins/data/public'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; +jest.mock('ui/new_platform'); + describe('AggConfig Filters', () => { describe('IP range', () => { - const typesRegistry = mockAggTypesRegistry([ipRangeBucketAgg]); - const getAggConfigs = (aggs: CreateAggConfigParams[]) => { + const getAggConfigs = (aggs: Array>) => { const field = { name: 'ip', format: fieldFormats.IpFormat, @@ -43,7 +42,7 @@ describe('AggConfig Filters', () => { }, } as any; - return new AggConfigs(indexPattern, aggs, { typesRegistry }); + return new AggConfigs(indexPattern, aggs, null); }; it('should return a range filter for ip_range agg', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts index 324d425290832..33344ca0a3484 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts @@ -17,22 +17,16 @@ * under the License. */ -import { rangeBucketAgg } from '../range'; import { createFilterRange } from './range'; import { fieldFormats, FieldFormatsGetConfigFn } from '../../../../../../../../plugins/data/public'; import { AggConfigs } from '../../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; +jest.mock('ui/new_platform'); + describe('AggConfig Filters', () => { describe('range', () => { - beforeEach(() => { - mockDataServices(); - }); - - const typesRegistry = mockAggTypesRegistry([rangeBucketAgg]); - const getConfig = (() => {}) as FieldFormatsGetConfigFn; const getAggConfigs = () => { const field = { @@ -62,7 +56,7 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry } + null ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts index 6db6eb11a5f52..7c6e769437ca1 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts @@ -17,18 +17,17 @@ * under the License. */ -import { termsBucketAgg } from '../terms'; import { createFilterTerms } from './terms'; -import { AggConfigs, CreateAggConfigParams } from '../../agg_configs'; -import { mockAggTypesRegistry } from '../../test_helpers'; +import { AggConfigs } from '../../agg_configs'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; import { Filter, ExistsFilter } from '../../../../../../../../plugins/data/public'; +jest.mock('ui/new_platform'); + describe('AggConfig Filters', () => { describe('terms', () => { - const typesRegistry = mockAggTypesRegistry([termsBucketAgg]); - const getAggConfigs = (aggs: CreateAggConfigParams[]) => { + const getAggConfigs = (aggs: Array>) => { const indexPattern = { id: '1234', title: 'logstash-*', @@ -43,7 +42,7 @@ describe('AggConfig Filters', () => { indexPattern, }; - return new AggConfigs(indexPattern, aggs, { typesRegistry }); + return new AggConfigs(indexPattern, aggs, null); }; it('should return a match_phrase filter for terms', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts index a5368135728d4..dc0f9baa6d0cc 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts @@ -21,7 +21,8 @@ import _ from 'lodash'; import moment from 'moment-timezone'; import { i18n } from '@kbn/i18n'; -// TODO need to move TimeBuckets +import { npStart } from 'ui/new_platform'; +import { timefilter } from 'ui/timefilter'; import { TimeBuckets } from 'ui/time_buckets'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; @@ -32,8 +33,6 @@ import { writeParams } from '../agg_params'; import { isMetricAggType } from '../metrics/metric_agg_type'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getQueryService, getUiSettings } from '../../../../../../../plugins/data/public/services'; const detectedTimezone = moment.tz.guess(); const tzOffset = moment().format('Z'); @@ -41,7 +40,6 @@ const tzOffset = moment().format('Z'); const getInterval = (agg: IBucketAggConfig): string => _.get(agg, ['params', 'interval']); export const setBounds = (agg: IBucketDateHistogramAggConfig, force?: boolean) => { - const { timefilter } = getQueryService().timefilter; if (agg.buckets._alreadySet && !force) return; agg.buckets._alreadySet = true; const bounds = agg.params.timeRange ? timefilter.calculateBounds(agg.params.timeRange) : null; @@ -223,7 +221,7 @@ export const dateHistogramBucketAgg = new BucketAggType { - beforeEach(() => { - mockDataServices(); - }); +import { npStart } from 'ui/new_platform'; - const typesRegistry = mockAggTypesRegistry([dateRangeBucketAgg]); +jest.mock('ui/new_platform'); +describe('date_range params', () => { const getAggConfigs = (params: Record = {}, hasIncludeTypeMeta: boolean = true) => { const field = { name: 'bytes', @@ -67,7 +58,7 @@ describe('date_range params', () => { params, }, ], - { typesRegistry } + null ); }; @@ -104,11 +95,7 @@ describe('date_range params', () => { }); it('should use the Kibana time_zone if no parameter specified', () => { - const core = coreMock.createStart(); - setUiSettings({ - ...core.uiSettings, - get: () => 'kibanaTimeZone' as any, - }); + npStart.core.uiSettings.get = jest.fn(() => 'kibanaTimeZone' as any); const aggConfigs = getAggConfigs( { @@ -119,8 +106,6 @@ describe('date_range params', () => { const dateRange = aggConfigs.aggs[0]; const params = dateRange.toDsl()[BUCKET_TYPES.DATE_RANGE]; - setUiSettings(core.uiSettings); // clean up - expect(params.time_zone).toBe('kibanaTimeZone'); }); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts index 933cdd0577f8d..1dc24ca80035c 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts @@ -16,20 +16,18 @@ * specific language governing permissions and limitations * under the License. */ - import { get } from 'lodash'; import moment from 'moment-timezone'; import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; +import { convertDateRangeToString, DateRangeKey } from './lib/date_range'; import { BUCKET_TYPES } from './bucket_agg_types'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { createFilterDateRange } from './create_filter/date_range'; import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getFieldFormats, getUiSettings } from '../../../../../../../plugins/data/public/services'; -import { convertDateRangeToString, DateRangeKey } from './lib/date_range'; -export { convertDateRangeToString, DateRangeKey }; // for BWC +export { convertDateRangeToString, DateRangeKey }; const dateRangeTitle = i18n.translate('data.search.aggs.buckets.dateRangeTitle', { defaultMessage: 'Date Range', @@ -43,7 +41,7 @@ export const dateRangeBucketAgg = new BucketAggType({ return { from, to }; }, getFormat(agg) { - const fieldFormatsService = getFieldFormats(); + const fieldFormatsService = npStart.plugins.data.fieldFormats; const formatter = agg.fieldOwnFormatter( fieldFormats.TEXT_CONTEXT_TYPE, @@ -94,7 +92,7 @@ export const dateRangeBucketAgg = new BucketAggType({ ]); } if (!tz) { - const config = getUiSettings(); + const config = npStart.core.uiSettings; const detectedTimezone = moment.tz.guess(); const tzOffset = moment().format('Z'); const isDefaultTimezone = config.isDefault('dateFormat:tz'); diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts index 80efc0cf92071..b52e2d6cfd4df 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { i18n } from '@kbn/i18n'; import { BucketAggType } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts index 2852f3e4bdf46..6eaf788b83c04 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts @@ -18,21 +18,19 @@ */ import _ from 'lodash'; +import angular from 'angular'; + import { i18n } from '@kbn/i18n'; import chrome from 'ui/chrome'; - import { createFilterFilters } from './create_filter/filters'; -import { toAngularJSON } from '../utils'; import { BucketAggType } from './_bucket_agg_type'; -import { BUCKET_TYPES } from './bucket_agg_types'; import { Storage } from '../../../../../../../plugins/kibana_utils/public'; - import { getQueryLog, esQuery, Query } from '../../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getUiSettings } from '../../../../../../../plugins/data/public/services'; +import { BUCKET_TYPES } from './bucket_agg_types'; const config = chrome.getUiSettingsClient(); +const storage = new Storage(window.localStorage); const filtersTitle = i18n.translate('data.search.aggs.buckets.filtersTitle', { defaultMessage: 'Filters', @@ -54,17 +52,15 @@ export const filtersBucketAgg = new BucketAggType({ params: [ { name: 'filters', - // TODO need to get rid of reference to `config` below default: [{ input: { query: '', language: config.get('search:queryLanguage') }, label: '' }], write(aggConfig, output) { - const uiSettings = getUiSettings(); const inFilters: FilterValue[] = aggConfig.params.filters; if (!_.size(inFilters)) return; inFilters.forEach(filter => { const persistedLog = getQueryLog( - uiSettings, - new Storage(window.localStorage), + config, + storage, 'vis_default_editor', filter.input.language ); @@ -81,13 +77,7 @@ export const filtersBucketAgg = new BucketAggType({ return; } - const esQueryConfigs = esQuery.getEsQueryConfig(uiSettings); - const query = esQuery.buildEsQuery( - aggConfig.getIndexPattern(), - [input], - [], - esQueryConfigs - ); + const query = esQuery.buildEsQuery(aggConfig.getIndexPattern(), [input], [], config); if (!query) { console.log('malformed filter agg params, missing "query" on input'); // eslint-disable-line no-console @@ -100,7 +90,7 @@ export const filtersBucketAgg = new BucketAggType({ matchAllLabel || (typeof filter.input.query === 'string' ? filter.input.query - : toAngularJSON(filter.input.query)); + : angular.toJson(filter.input.query)); filters[label] = { query }; }, {} diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts index 09dd03c759155..f0ad595476486 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts @@ -19,13 +19,12 @@ import { geoHashBucketAgg } from './geo_hash'; import { AggConfigs, IAggConfigs } from '../agg_configs'; -import { mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; import { IBucketAggConfig } from './_bucket_agg_type'; +jest.mock('ui/new_platform'); + describe('Geohash Agg', () => { - // const typesRegistry = mockAggTypesRegistry([geoHashBucketAgg]); - const typesRegistry = mockAggTypesRegistry(); const getAggConfigs = (params?: Record) => { const indexPattern = { id: '1234', @@ -63,7 +62,7 @@ describe('Geohash Agg', () => { }, }, ], - { typesRegistry } + null ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts index 9142a30338163..57e8f6e8c5ded 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts @@ -19,6 +19,7 @@ import { i18n } from '@kbn/i18n'; import { noop } from 'lodash'; +import { AggConfigOptions } from '../agg_config'; import { BucketAggType } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; @@ -56,7 +57,7 @@ export const geoTileBucketAgg = new BucketAggType({ aggs.push(agg); if (useGeocentroid) { - const aggConfig = { + const aggConfig: AggConfigOptions = { type: METRIC_TYPES.GEO_CENTROID, enabled: true, params: { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts index 11dc8e42fd653..4e89d7db1ff64 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts @@ -17,23 +17,16 @@ * under the License. */ -import { AggConfigs } from '../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; +import { npStart } from 'ui/new_platform'; +import { AggConfigs } from '../index'; import { BUCKET_TYPES } from './bucket_agg_types'; import { IBucketHistogramAggConfig, histogramBucketAgg, AutoBounds } from './histogram'; import { BucketAggType } from './_bucket_agg_type'; -import { coreMock } from '../../../../../../../../src/core/public/mocks'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { setUiSettings } from '../../../../../../../plugins/data/public/services'; -describe('Histogram Agg', () => { - beforeEach(() => { - mockDataServices(); - }); +jest.mock('ui/new_platform'); - const typesRegistry = mockAggTypesRegistry([histogramBucketAgg]); - - const getAggConfigs = (params: Record) => { +describe('Histogram Agg', () => { + const getAggConfigs = (params: Record = {}) => { const indexPattern = { id: '1234', title: 'logstash-*', @@ -52,13 +45,16 @@ describe('Histogram Agg', () => { indexPattern, [ { + field: { + name: 'field', + }, id: 'test', type: BUCKET_TYPES.HISTOGRAM, schema: 'segment', params, }, ], - { typesRegistry } + null ); }; @@ -162,15 +158,10 @@ describe('Histogram Agg', () => { aggConfig.setAutoBounds(autoBounds); } - const core = coreMock.createStart(); - setUiSettings({ - ...core.uiSettings, - get: () => maxBars as any, - }); + // mock histogram:maxBars value; + npStart.core.uiSettings.get = jest.fn(() => maxBars as any); - const interval = aggConfig.write(aggConfigs).params; - setUiSettings(core.uiSettings); // clean up - return interval; + return aggConfig.write(aggConfigs).params; }; it('will respect the histogram:maxBars setting', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts index 70df2f230db09..f7e9ef45961e0 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts @@ -19,13 +19,13 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; +import { toastNotifications } from 'ui/notify'; +import { npStart } from 'ui/new_platform'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { createFilterHistogram } from './create_filter/histogram'; -import { BUCKET_TYPES } from './bucket_agg_types'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getNotifications, getUiSettings } from '../../../../../../../plugins/data/public/services'; +import { BUCKET_TYPES } from './bucket_agg_types'; export interface AutoBounds { min: number; @@ -37,6 +37,8 @@ export interface IBucketHistogramAggConfig extends IBucketAggConfig { getAutoBounds: () => AutoBounds; } +const getUIConfig = () => npStart.core.uiSettings; + export const histogramBucketAgg = new BucketAggType({ name: BUCKET_TYPES.HISTOGRAM, title: i18n.translate('data.search.aggs.buckets.histogramTitle', { @@ -114,7 +116,7 @@ export const histogramBucketAgg = new BucketAggType({ }) .catch((e: Error) => { if (e.name === 'AbortError') return; - getNotifications().toasts.addWarning( + toastNotifications.addWarning( i18n.translate('data.search.aggs.histogram.missingMaxMinValuesWarning', { defaultMessage: 'Unable to retrieve max and min values to auto-scale histogram buckets. This may lead to poor visualization performance.', @@ -134,7 +136,7 @@ export const histogramBucketAgg = new BucketAggType({ const range = autoBounds.max - autoBounds.min; const bars = range / interval; - const config = getUiSettings(); + const config = getUIConfig(); if (bars > config.get('histogram:maxBars')) { const minInterval = range / config.get('histogram:maxBars'); diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts index 3fb464d8fa7a8..91bdf53e7f809 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts @@ -19,17 +19,15 @@ import { noop, map, omit, isNull } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; +import { IpRangeKey, convertIPRangeToString } from './lib/ip_range'; import { BucketAggType } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; +// @ts-ignore import { createFilterIpRange } from './create_filter/ip_range'; import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../../../plugins/data/public'; - -import { IpRangeKey, convertIPRangeToString } from './lib/ip_range'; -export { IpRangeKey, convertIPRangeToString }; // for BWC - -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getFieldFormats } from '../../../../../../../plugins/data/public/services'; +export { IpRangeKey, convertIPRangeToString }; const ipRangeTitle = i18n.translate('data.search.aggs.buckets.ipRangeTitle', { defaultMessage: 'IPv4 Range', @@ -46,7 +44,7 @@ export const ipRangeBucketAgg = new BucketAggType({ return { type: 'range', from: bucket.from, to: bucket.to }; }, getFormat(agg) { - const fieldFormatsService = getFieldFormats(); + const fieldFormatsService = npStart.plugins.data.fieldFormats; const formatter = agg.fieldOwnFormatter( fieldFormats.TEXT_CONTEXT_TYPE, fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.IP) diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts index d94477b588f8d..77e84e044de55 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts @@ -19,10 +19,10 @@ import { isString, isObject } from 'lodash'; import { IBucketAggConfig, BucketAggType, BucketAggParam } from './_bucket_agg_type'; -import { IAggConfig } from '../agg_config'; +import { AggConfig } from '../agg_config'; export const isType = (type: string) => { - return (agg: IAggConfig): boolean => { + return (agg: AggConfig): boolean => { const field = agg.params.field; return field && field.type === type; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts index 096b19fe7de66..b1b0c4bc30a58 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts @@ -17,12 +17,12 @@ * under the License. */ -import { rangeBucketAgg } from './range'; import { AggConfigs } from '../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; import { FieldFormatsGetConfigFn, fieldFormats } from '../../../../../../../plugins/data/public'; +jest.mock('ui/new_platform'); + const buckets = [ { to: 1024, @@ -44,12 +44,6 @@ const buckets = [ ]; describe('Range Agg', () => { - beforeEach(() => { - mockDataServices(); - }); - - const typesRegistry = mockAggTypesRegistry([rangeBucketAgg]); - const getConfig = (() => {}) as FieldFormatsGetConfigFn; const getAggConfigs = () => { const field = { @@ -86,7 +80,7 @@ describe('Range Agg', () => { }, }, ], - { typesRegistry } + null ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts index cee3ed506c29c..37b829bfc20fb 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts @@ -17,16 +17,17 @@ * under the License. */ -import { AggConfigs, IAggConfigs } from '../agg_configs'; -import { mockAggTypesRegistry } from '../test_helpers'; +import { AggConfigs } from '../index'; +import { IAggConfigs } from '../types'; import { BUCKET_TYPES } from './bucket_agg_types'; import { significantTermsBucketAgg } from './significant_terms'; import { IBucketAggConfig } from './_bucket_agg_type'; +jest.mock('ui/new_platform'); + describe('Significant Terms Agg', () => { describe('order agg editor UI', () => { describe('convert include/exclude from old format', () => { - const typesRegistry = mockAggTypesRegistry([significantTermsBucketAgg]); const getAggConfigs = (params: Record = {}) => { const indexPattern = { id: '1234', @@ -52,7 +53,7 @@ describe('Significant Terms Agg', () => { params, }, ], - { typesRegistry } + null ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts index 9a4f28afd3edf..24ac332ae4d55 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts @@ -17,13 +17,13 @@ * under the License. */ -import { AggConfigs } from '../agg_configs'; -import { mockAggTypesRegistry } from '../test_helpers'; +import { AggConfigs } from '../index'; import { BUCKET_TYPES } from './bucket_agg_types'; +jest.mock('ui/new_platform'); + describe('Terms Agg', () => { describe('order agg editor UI', () => { - const typesRegistry = mockAggTypesRegistry(); const getAggConfigs = (params: Record = {}) => { const indexPattern = { id: '1234', @@ -48,7 +48,7 @@ describe('Terms Agg', () => { type: BUCKET_TYPES.TERMS, }, ], - { typesRegistry } + null ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts index 0de1c31d02f96..cc1288d339692 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts @@ -19,12 +19,13 @@ import { IndexPattern } from '../../../../../../../plugins/data/public'; import { AggTypeFilters } from './agg_type_filters'; -import { IAggConfig, IAggType } from '../types'; +import { AggConfig } from '..'; +import { IAggType } from '../types'; describe('AggTypeFilters', () => { let registry: AggTypeFilters; const indexPattern = ({ id: '1234', fields: [], title: 'foo' } as unknown) as IndexPattern; - const aggConfig = {} as IAggConfig; + const aggConfig = {} as AggConfig; beforeEach(() => { registry = new AggTypeFilters(); diff --git a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts index 13a4cc0856b09..d3b38ce041d7e 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { IndexPattern } from 'src/plugins/data/public'; import { IAggConfig, IAggType } from '../types'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts b/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts index 32cda7b950e93..431e1161e0dbd 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts @@ -17,6 +17,7 @@ * under the License. */ +import expect from '@kbn/expect'; import { propFilter } from './prop_filter'; describe('prop filter', () => { @@ -46,48 +47,48 @@ describe('prop filter', () => { it('returns list when no filters are provided', () => { const objects = getObjects('table', 'table', 'pie'); - expect(nameFilter(objects)).toEqual(objects); + expect(nameFilter(objects)).to.eql(objects); }); it('returns list when empty list of filters is provided', () => { const objects = getObjects('table', 'table', 'pie'); - expect(nameFilter(objects, [])).toEqual(objects); + expect(nameFilter(objects, [])).to.eql(objects); }); it('should keep only the tables', () => { const objects = getObjects('table', 'table', 'pie'); - expect(nameFilter(objects, 'table')).toEqual(getObjects('table', 'table')); + expect(nameFilter(objects, 'table')).to.eql(getObjects('table', 'table')); }); it('should support comma-separated values', () => { const objects = getObjects('table', 'line', 'pie'); - expect(nameFilter(objects, 'table,line')).toEqual(getObjects('table', 'line')); + expect(nameFilter(objects, 'table,line')).to.eql(getObjects('table', 'line')); }); it('should support an array of values', () => { const objects = getObjects('table', 'line', 'pie'); - expect(nameFilter(objects, ['table', 'line'])).toEqual(getObjects('table', 'line')); + expect(nameFilter(objects, ['table', 'line'])).to.eql(getObjects('table', 'line')); }); it('should return all objects', () => { const objects = getObjects('table', 'line', 'pie'); - expect(nameFilter(objects, '*')).toEqual(objects); + expect(nameFilter(objects, '*')).to.eql(objects); }); it('should allow negation', () => { const objects = getObjects('table', 'line', 'pie'); - expect(nameFilter(objects, ['!line'])).toEqual(getObjects('table', 'pie')); + expect(nameFilter(objects, ['!line'])).to.eql(getObjects('table', 'pie')); }); it('should support a function for specifying what should be kept', () => { const objects = getObjects('table', 'line', 'pie'); const line = (value: string) => value === 'line'; - expect(nameFilter(objects, line)).toEqual(getObjects('line')); + expect(nameFilter(objects, line)).to.eql(getObjects('line')); }); it('gracefully handles a filter function with zero arity', () => { const objects = getObjects('table', 'line', 'pie'); const rejectEverything = () => false; - expect(nameFilter(objects, rejectEverything)).toEqual([]); + expect(nameFilter(objects, rejectEverything)).to.eql([]); }); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/index.test.ts b/src/legacy/core_plugins/data/public/search/aggs/index.test.ts index 4d0cd55b09d53..a867769a77fc1 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/index.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/index.test.ts @@ -25,6 +25,8 @@ import { isMetricAggType } from './metrics/metric_agg_type'; const bucketAggs = aggTypes.buckets; const metricAggs = aggTypes.metrics; +jest.mock('ui/new_platform'); + describe('AggTypesComponent', () => { describe('bucket aggs', () => { it('all extend BucketAggType', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/index.ts b/src/legacy/core_plugins/data/public/search/aggs/index.ts index f6914c36f6c05..0bdb92b8de65e 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/index.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/index.ts @@ -17,13 +17,8 @@ * under the License. */ -export { - AggTypesRegistry, - AggTypesRegistrySetup, - AggTypesRegistryStart, -} from './agg_types_registry'; -export { AggType } from './agg_type'; export { aggTypes } from './agg_types'; +export { AggType } from './agg_type'; export { AggConfig } from './agg_config'; export { AggConfigs } from './agg_configs'; export { FieldParamType } from './param_types'; @@ -57,4 +52,4 @@ export { METRIC_TYPES } from './metrics/metric_agg_types'; export { ISchemas, Schema, Schemas } from './schemas'; // types -export { CreateAggConfigParams, IAggConfig, IAggConfigs } from './types'; +export { IAggConfig, IAggConfigs } from './types'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts index 11bb559274729..9fb28f8631bc6 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts @@ -19,6 +19,7 @@ import { i18n } from '@kbn/i18n'; import { get } from 'lodash'; + import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts index 0668a9bcf57a8..83837f0de5114 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts @@ -18,6 +18,7 @@ */ import { i18n } from '@kbn/i18n'; + import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts index 8f728cb5e7e42..d96197693dc2e 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { i18n } from '@kbn/i18n'; import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts index 4f7b6e555ca33..147e925521088 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts @@ -18,11 +18,10 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getFieldFormats } from '../../../../../../../plugins/data/public/services'; const uniqueCountTitle = i18n.translate('data.search.aggs.metrics.uniqueCountTitle', { defaultMessage: 'Unique Count', @@ -38,7 +37,7 @@ export const cardinalityMetricAgg = new MetricAggType({ }); }, getFormat() { - const fieldFormatsService = getFieldFormats(); + const fieldFormatsService = npStart.plugins.data.fieldFormats; return fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }, diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts index 8b3e0a488c68a..14a9bd073ff2b 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts @@ -18,11 +18,10 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; +import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; -import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getFieldFormats } from '../../../../../../../plugins/data/public/services'; export const countMetricAgg = new MetricAggType({ name: METRIC_TYPES.COUNT, @@ -36,7 +35,7 @@ export const countMetricAgg = new MetricAggType({ }); }, getFormat() { - const fieldFormatsService = getFieldFormats(); + const fieldFormatsService = npStart.plugins.data.fieldFormats; return fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }, diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts index 00d866e6f2b3e..054543de3dd06 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { assign } from 'lodash'; import { IMetricAggConfig } from '../metric_agg_type'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts index 88549ee3019ee..e24aca08271c7 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts @@ -23,6 +23,7 @@ import { noop, identity } from 'lodash'; import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers'; import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type'; import { parentPipelineAggWriter } from './parent_pipeline_agg_writer'; + import { Schemas } from '../../schemas'; import { fieldFormats } from '../../../../../../../../plugins/data/public'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts index 05e009cc9da30..e7c98e575fdb4 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts @@ -21,6 +21,7 @@ import { identity } from 'lodash'; import { i18n } from '@kbn/i18n'; import { siblingPipelineAggWriter } from './sibling_pipeline_agg_writer'; import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers'; + import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type'; import { Schemas } from '../../schemas'; import { fieldFormats } from '../../../../../../../../plugins/data/public'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts index ad55837ec9a30..4755a873e6977 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts @@ -17,16 +17,15 @@ * under the License. */ -import { medianMetricAgg } from './median'; import { AggConfigs, IAggConfigs } from '../agg_configs'; -import { mockAggTypesRegistry } from '../test_helpers'; import { METRIC_TYPES } from './metric_agg_types'; +jest.mock('ui/new_platform'); + describe('AggTypeMetricMedianProvider class', () => { let aggConfigs: IAggConfigs; beforeEach(() => { - const typesRegistry = mockAggTypesRegistry([medianMetricAgg]); const field = { name: 'bytes', }; @@ -51,7 +50,7 @@ describe('AggTypeMetricMedianProvider class', () => { }, }, ], - { typesRegistry } + null ); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts index 68fc98261118c..53a5ffff418f1 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts @@ -16,10 +16,12 @@ * specific language governing permissions and limitations * under the License. */ - import { i18n } from '@kbn/i18n'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; + +// @ts-ignore +import { percentilesMetricAgg } from './percentiles'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; const medianTitle = i18n.translate('data.search.aggs.metrics.medianTitle', { diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts index 952dcc96de833..3bae7b92618dc 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts @@ -18,14 +18,13 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { AggType, AggTypeConfig } from '../agg_type'; import { AggParamType } from '../param_types/agg'; import { AggConfig } from '../agg_config'; -import { FilterFieldTypes } from '../param_types/field'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getFieldFormats } from '../../../../../../../plugins/data/public/services'; +import { FilterFieldTypes } from '../param_types/field'; export interface IMetricAggConfig extends AggConfig { type: InstanceType; @@ -79,7 +78,7 @@ export class MetricAggType { - const fieldFormatsService = getFieldFormats(); + const fieldFormatsService = npStart.plugins.data.fieldFormats; const field = agg.getField(); return field ? field.format diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts index 1806c6d9d7710..4885105163435 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { i18n } from '@kbn/i18n'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts index 58b4ee530a8c2..11fc39c20bdc4 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts @@ -17,12 +17,12 @@ * 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 '../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; jest.mock('../schemas', () => { @@ -34,13 +34,9 @@ jest.mock('../schemas', () => { }; }); -describe('parent pipeline aggs', function() { - beforeEach(() => { - mockDataServices(); - }); - - const typesRegistry = mockAggTypesRegistry(); +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 }, @@ -98,7 +94,7 @@ describe('parent pipeline aggs', function() { schema: 'metric', }, ], - { typesRegistry } + null ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) @@ -224,16 +220,16 @@ describe('parent pipeline aggs', function() { }); const searchSource: any = {}; - const customMetricSpy = jest.fn(); + 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, {}); + param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource); }); - expect(customMetricSpy.mock.calls[0]).toEqual([customMetric, searchSource, {}]); + expect(customMetricSpy.calledWith(customMetric, searchSource)).toBe(true); }); }); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts index 628f1cd204ee5..655e918ce07de 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts @@ -19,16 +19,14 @@ import { IPercentileRanksAggConfig, percentileRanksMetricAgg } from './percentile_ranks'; import { AggConfigs, IAggConfigs } from '../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; import { METRIC_TYPES } from './metric_agg_types'; +jest.mock('ui/new_platform'); + describe('AggTypesMetricsPercentileRanksProvider class', function() { let aggConfigs: IAggConfigs; beforeEach(() => { - mockDataServices(); - - const typesRegistry = mockAggTypesRegistry([percentileRanksMetricAgg]); const field = { name: 'bytes', }; @@ -60,7 +58,7 @@ describe('AggTypesMetricsPercentileRanksProvider class', function() { }, }, ], - { typesRegistry } + null ); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts index 1d640a9c1fa42..38b47a7e97d2f 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts @@ -18,17 +18,20 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { MetricAggType } from './metric_agg_type'; import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; + import { getPercentileValue } from './percentiles_get_value'; import { METRIC_TYPES } from './metric_agg_types'; import { fieldFormats, KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getFieldFormats } from '../../../../../../../plugins/data/public/services'; // required by the values editor + export type IPercentileRanksAggConfig = IResponseAggConfig; +const getFieldFormats = () => npStart.plugins.data.fieldFormats; + const valueProps = { makeLabel(this: IPercentileRanksAggConfig) { const fieldFormatsService = getFieldFormats(); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts index e077bc0f8c773..dd1aaca973e47 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts @@ -19,14 +19,14 @@ import { IPercentileAggConfig, percentilesMetricAgg } from './percentiles'; import { AggConfigs, IAggConfigs } from '../agg_configs'; -import { mockAggTypesRegistry } from '../test_helpers'; import { METRIC_TYPES } from './metric_agg_types'; +jest.mock('ui/new_platform'); + describe('AggTypesMetricsPercentilesProvider class', () => { let aggConfigs: IAggConfigs; beforeEach(() => { - const typesRegistry = mockAggTypesRegistry([percentilesMetricAgg]); const field = { name: 'bytes', }; @@ -58,7 +58,7 @@ describe('AggTypesMetricsPercentilesProvider class', () => { }, }, ], - { typesRegistry } + null ); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts index 49e927d07d8dd..39dc0d0f181e9 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts @@ -18,11 +18,15 @@ */ import { i18n } from '@kbn/i18n'; + import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; + import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; import { getPercentileValue } from './percentiles_get_value'; + +// @ts-ignore import { ordinalSuffix } from './lib/ordinal_suffix'; export type IPercentileAggConfig = IResponseAggConfig; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts index d3456bacceb6a..d643cf0d2a478 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts @@ -17,6 +17,7 @@ * under the License. */ +import { spy } from 'sinon'; import { bucketSumMetricAgg } from './bucket_sum'; import { bucketAvgMetricAgg } from './bucket_avg'; import { bucketMinMetricAgg } from './bucket_min'; @@ -24,7 +25,6 @@ import { bucketMaxMetricAgg } from './bucket_max'; import { AggConfigs } from '../agg_configs'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; -import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; jest.mock('../schemas', () => { class MockedSchemas { @@ -35,13 +35,9 @@ jest.mock('../schemas', () => { }; }); -describe('sibling pipeline aggs', () => { - beforeEach(() => { - mockDataServices(); - }); - - const typesRegistry = mockAggTypesRegistry(); +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 }, @@ -100,7 +96,7 @@ describe('sibling pipeline aggs', () => { }, }, ], - { typesRegistry } + null ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) @@ -166,8 +162,8 @@ describe('sibling pipeline aggs', () => { init(); const searchSource: any = {}; - const customMetricSpy = jest.fn(); - const customBucketSpy = jest.fn(); + const customMetricSpy = spy(); + const customBucketSpy = spy(); const { customMetric, customBucket } = aggConfig.params; // Attach a modifyAggConfigOnSearchRequestStart with a spy to the first parameter @@ -175,11 +171,11 @@ describe('sibling pipeline aggs', () => { customBucket.type.params[0].modifyAggConfigOnSearchRequestStart = customBucketSpy; aggConfig.type.params.forEach(param => { - param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource, {}); + param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource); }); - expect(customMetricSpy.mock.calls[0]).toEqual([customMetric, searchSource, {}]); - expect(customBucketSpy.mock.calls[0]).toEqual([customBucket, searchSource, {}]); + expect(customMetricSpy.calledWith(customMetric, searchSource)).toBe(true); + expect(customBucketSpy.calledWith(customBucket, searchSource)).toBe(true); }); }); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts index 0679831b1e6ac..3125026a52185 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts @@ -19,11 +19,11 @@ import { IStdDevAggConfig, stdDeviationMetricAgg } from './std_deviation'; import { AggConfigs } from '../agg_configs'; -import { mockAggTypesRegistry } from '../test_helpers'; import { METRIC_TYPES } from './metric_agg_types'; +jest.mock('ui/new_platform'); + describe('AggTypeMetricStandardDeviationProvider class', () => { - const typesRegistry = mockAggTypesRegistry([stdDeviationMetricAgg]); const getAggConfigs = (customLabel?: string) => { const field = { name: 'memory', @@ -52,7 +52,7 @@ describe('AggTypeMetricStandardDeviationProvider class', () => { }, }, ], - { typesRegistry } + null ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts index ad1f42f5c563e..a973de4fe8659 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts @@ -20,10 +20,11 @@ import { dropRight, last } from 'lodash'; import { topHitMetricAgg } from './top_hit'; import { AggConfigs } from '../agg_configs'; -import { mockAggTypesRegistry } from '../test_helpers'; import { IMetricAggConfig } from './metric_agg_type'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; +jest.mock('ui/new_platform'); + describe('Top hit metric', () => { let aggDsl: Record; let aggConfig: IMetricAggConfig; @@ -36,7 +37,6 @@ describe('Top hit metric', () => { fieldType = KBN_FIELD_TYPES.NUMBER, size = 1, }: any) => { - const typesRegistry = mockAggTypesRegistry([topHitMetricAgg]); const field = { name: fieldName, displayName: fieldName, @@ -81,7 +81,7 @@ describe('Top hit metric', () => { params, }, ], - { typesRegistry } + null ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts index d31abe64491d0..2e7c11004b472 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts @@ -17,10 +17,10 @@ * under the License. */ -import { AggConfig, IAggConfig } from '../agg_config'; +import { AggConfig } from '../agg_config'; import { BaseParamType } from './base'; -export class AggParamType extends BaseParamType< +export class AggParamType extends BaseParamType< TAggConfig > { makeAgg: (agg: TAggConfig, state?: any) => TAggConfig; diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts index 95ad71a616ab2..1523cb03eb966 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts @@ -18,10 +18,10 @@ */ import { IAggConfigs } from '../agg_configs'; -import { IAggConfig } from '../agg_config'; +import { AggConfig } from '../agg_config'; import { FetchOptions, ISearchSource } from '../../../../../../../plugins/data/public'; -export class BaseParamType { +export class BaseParamType { name: string; type: string; displayName: string; diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts index 7338c41f920d7..fa88754ac60b9 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts @@ -25,6 +25,8 @@ import { IAggConfig } from '../agg_config'; import { IMetricAggConfig } from '../metrics/metric_agg_type'; import { Schema } from '../schemas'; +jest.mock('ui/new_platform'); + describe('Field', () => { const indexPattern = { id: '1234', diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts index bb5707cbb482e..40c30f6210a83 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts @@ -19,6 +19,7 @@ import { i18n } from '@kbn/i18n'; import { isFunction } from 'lodash'; +import { npStart } from 'ui/new_platform'; import { IAggConfig } from '../agg_config'; import { SavedObjectNotFound } from '../../../../../../../plugins/kibana_utils/public'; import { BaseParamType } from './base'; @@ -29,8 +30,6 @@ import { indexPatterns, KBN_FIELD_TYPES, } from '../../../../../../../plugins/data/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getNotifications } from '../../../../../../../plugins/data/public/services'; const filterByType = propFilter('type'); @@ -94,7 +93,7 @@ export class FieldParamType extends BaseParamType { // @ts-ignore const validField = this.getAvailableFields(aggConfig).find((f: any) => f.name === fieldName); if (!validField) { - getNotifications().toasts.addDanger( + npStart.core.notifications.toasts.addDanger( i18n.translate( 'data.search.aggs.paramTypes.field.invalidSavedFieldParameterErrorMessage', { diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts index 1a453a225797d..bc36bb46d3d16 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts @@ -17,26 +17,27 @@ * under the License. */ +import { IndexedArray } from 'ui/indexed_array'; import { AggTypeFieldFilters } from './field_filters'; -import { IAggConfig } from '../../agg_config'; +import { AggConfig } from '../../agg_config'; import { IndexPatternField } from '../../../../../../../../plugins/data/public'; describe('AggTypeFieldFilters', () => { let registry: AggTypeFieldFilters; - const aggConfig = {} as IAggConfig; + const aggConfig = {} as AggConfig; beforeEach(() => { registry = new AggTypeFieldFilters(); }); it('should filter nothing without registered filters', async () => { - const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexPatternField[]; + const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexedArray; const filtered = registry.filter(fields, aggConfig); expect(filtered).toEqual(fields); }); it('should pass all fields to the registered filter', async () => { - const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexPatternField[]; + const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexedArray; const filter = jest.fn(); registry.addFilter(filter); registry.filter(fields, aggConfig); @@ -45,7 +46,7 @@ describe('AggTypeFieldFilters', () => { }); it('should allow registered filters to filter out fields', async () => { - const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexPatternField[]; + const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexedArray; let filtered = registry.filter(fields, aggConfig); expect(filtered).toEqual(fields); diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts index 1cbf0c9ae3624..7d1348ab5423b 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts @@ -17,9 +17,9 @@ * under the License. */ import { IndexPatternField } from 'src/plugins/data/public'; -import { IAggConfig } from '../../agg_config'; +import { AggConfig } from '../../agg_config'; -type AggTypeFieldFilter = (field: IndexPatternField, aggConfig: IAggConfig) => boolean; +type AggTypeFieldFilter = (field: IndexPatternField, aggConfig: AggConfig) => boolean; /** * A registry to store {@link AggTypeFieldFilter} which are used to filter down @@ -41,11 +41,11 @@ class AggTypeFieldFilters { /** * Returns the {@link any|fields} filtered by all registered filters. * - * @param fields An array of fields that will be filtered down by this registry. + * @param fields An IndexedArray of fields that will be filtered down by this registry. * @param aggConfig The aggConfig for which the returning list will be used. * @return A filtered list of the passed fields. */ - public filter(fields: IndexPatternField[], aggConfig: IAggConfig) { + public filter(fields: IndexPatternField[], aggConfig: AggConfig) { const allFilters = Array.from(this.filters); const allowedAggTypeFields = fields.filter(field => { const isAggTypeFieldAllowed = allFilters.every(filter => filter(field, aggConfig)); diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts index 12fd29b3a1452..827299814c62a 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts @@ -19,11 +19,13 @@ import { BaseParamType } from './base'; import { JsonParamType } from './json'; -import { IAggConfig } from '../agg_config'; +import { AggConfig } from '../agg_config'; + +jest.mock('ui/new_platform'); describe('JSON', function() { const paramName = 'json_test'; - let aggConfig: IAggConfig; + let aggConfig: AggConfig; let output: Record; const initAggParam = (config: Record = {}) => @@ -34,7 +36,7 @@ describe('JSON', function() { }); beforeEach(function() { - aggConfig = { params: {} } as IAggConfig; + aggConfig = { params: {} } as AggConfig; output = { params: {} }; }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts index bf85b3b890c35..771919b0bb56b 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts @@ -19,7 +19,7 @@ import _ from 'lodash'; -import { IAggConfig } from '../agg_config'; +import { AggConfig } from '../agg_config'; import { BaseParamType } from './base'; export class JsonParamType extends BaseParamType { @@ -29,7 +29,7 @@ export class JsonParamType extends BaseParamType { this.name = config.name || 'json'; if (!config.write) { - this.write = (aggConfig: IAggConfig, output: Record) => { + this.write = (aggConfig: AggConfig, output: Record) => { let paramJson; const param = aggConfig.params[this.name]; diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts index c03d6cdfa1c70..6b58d81914097 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts @@ -20,6 +20,8 @@ import { BaseParamType } from './base'; import { OptionedParamType } from './optioned'; +jest.mock('ui/new_platform'); + describe('Optioned', () => { describe('constructor', () => { it('it is an instance of BaseParamType', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts index 9eb7ceda60711..5ffda3740af49 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts @@ -17,14 +17,14 @@ * under the License. */ -import { IAggConfig } from '../agg_config'; +import { AggConfig } from '../agg_config'; import { BaseParamType } from './base'; export interface OptionedValueProp { value: string; text: string; disabled?: boolean; - isCompatible: (agg: IAggConfig) => boolean; + isCompatible: (agg: AggConfig) => boolean; } export interface OptionedParamEditorProps { @@ -40,7 +40,7 @@ export class OptionedParamType extends BaseParamType { super(config); if (!config.write) { - this.write = (aggConfig: IAggConfig, output: Record) => { + this.write = (aggConfig: AggConfig, output: Record) => { output.params[this.name] = aggConfig.params[this.name].value; }; } diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts index 29ec9741611a3..fd5ccebde993e 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts @@ -19,11 +19,13 @@ import { BaseParamType } from './base'; import { StringParamType } from './string'; -import { IAggConfig } from '../agg_config'; +import { AggConfig } from '../agg_config'; + +jest.mock('ui/new_platform'); describe('String', function() { let paramName = 'json_test'; - let aggConfig: IAggConfig; + let aggConfig: AggConfig; let output: Record; const initAggParam = (config: Record = {}) => @@ -34,7 +36,7 @@ describe('String', function() { }); beforeEach(() => { - aggConfig = { params: {} } as IAggConfig; + aggConfig = { params: {} } as AggConfig; output = { params: {} }; }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts index 750606eb8433b..58ba99f8a6d63 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IAggConfig } from '../agg_config'; +import { AggConfig } from '../agg_config'; import { BaseParamType } from './base'; export class StringParamType extends BaseParamType { @@ -25,7 +25,7 @@ export class StringParamType extends BaseParamType { super(config); if (!config.write) { - this.write = (aggConfig: IAggConfig, output: Record) => { + this.write = (aggConfig: AggConfig, output: Record) => { if (aggConfig.params[this.name] && aggConfig.params[this.name].length) { output.params[this.name] = aggConfig.params[this.name]; } diff --git a/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts deleted file mode 100644 index d6bb793866493..0000000000000 --- a/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts +++ /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 { AggTypesRegistry, AggTypesRegistryStart } from '../agg_types_registry'; -import { aggTypes } from '../agg_types'; -import { BucketAggType } from '../buckets/_bucket_agg_type'; -import { MetricAggType } from '../metrics/metric_agg_type'; - -/** - * Testing utility which creates a new instance of AggTypesRegistry, - * registers the provided agg types, and returns AggTypesRegistry.start() - * - * This is useful if your test depends on a certain agg type to be present - * in the registry. - * - * @param [types] - Optional array of AggTypes to register. - * If no value is provided, all default types will be registered. - * - * @internal - */ -export function mockAggTypesRegistry | MetricAggType>( - types?: T[] -): AggTypesRegistryStart { - const registry = new AggTypesRegistry(); - const registrySetup = registry.setup(); - - if (types) { - types.forEach(type => { - if (type instanceof BucketAggType) { - registrySetup.registerBucket(type); - } else if (type instanceof MetricAggType) { - registrySetup.registerMetric(type); - } - }); - } else { - aggTypes.buckets.forEach(type => registrySetup.registerBucket(type)); - aggTypes.metrics.forEach(type => registrySetup.registerMetric(type)); - } - - return registry.start(); -} diff --git a/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.ts b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.ts deleted file mode 100644 index c4e78ab8f6422..0000000000000 --- a/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.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 { coreMock } from '../../../../../../../../src/core/public/mocks'; -import { dataPluginMock } from '../../../../../../../plugins/data/public/mocks'; -import { searchStartMock } from '../../mocks'; -import { setSearchServiceShim } from '../../../services'; -import { - setFieldFormats, - setIndexPatterns, - setNotifications, - setOverlays, - setQueryService, - setSearchService, - setUiSettings, - // eslint-disable-next-line @kbn/eslint/no-restricted-paths -} from '../../../../../../../plugins/data/public/services'; - -/** - * Testing helper which calls all of the service setters used in the - * data plugin. Services are added using their provided mocks. - * - * @internal - */ -export function mockDataServices() { - const core = coreMock.createStart(); - const data = dataPluginMock.createStartContract(); - const searchShim = searchStartMock(); - - setSearchServiceShim(searchShim); - setFieldFormats(data.fieldFormats); - setIndexPatterns(data.indexPatterns); - setNotifications(core.notifications); - setOverlays(core.overlays); - setQueryService(data.query); - setSearchService(data.search); - setUiSettings(core.uiSettings); -} diff --git a/src/legacy/core_plugins/data/public/search/aggs/types.ts b/src/legacy/core_plugins/data/public/search/aggs/types.ts index 5d02f426b5896..2c918abf99fca 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/types.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/types.ts @@ -18,7 +18,7 @@ */ export { IAggConfig } from './agg_config'; -export { CreateAggConfigParams, IAggConfigs } from './agg_configs'; +export { IAggConfigs } from './agg_configs'; export { IAggType } from './agg_type'; export { AggParam, AggParamOption } from './agg_params'; export { IFieldParamType } from './param_types'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx b/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx index c0662c98755a3..a3c7f24f3927d 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx +++ b/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx @@ -19,6 +19,8 @@ import { isValidJson } from './utils'; +jest.mock('ui/new_platform'); + const input = { valid: '{ "test": "json input" }', invalid: 'strings are not json', diff --git a/src/legacy/core_plugins/data/public/search/aggs/utils.ts b/src/legacy/core_plugins/data/public/search/aggs/utils.ts index 67ea373f438fb..62f07ce44ab46 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/utils.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/utils.ts @@ -26,7 +26,7 @@ import { isValidEsInterval } from '../../../common'; * @param {string} value a string that should be validated * @returns {boolean} true if value is a valid JSON or if value is an empty string, or a string with whitespaces, otherwise false */ -export function isValidJson(value: string): boolean { +function isValidJson(value: string): boolean { if (!value || value.length === 0) { return true; } @@ -49,7 +49,7 @@ export function isValidJson(value: string): boolean { } } -export function isValidInterval(value: string, baseInterval?: string) { +function isValidInterval(value: string, baseInterval?: string) { if (baseInterval) { return _parseWithBase(value, baseInterval); } else { @@ -69,37 +69,4 @@ function _parseWithBase(value: string, baseInterval: string) { } } -// An inlined version of angular.toJSON() -// source: https://github.com/angular/angular.js/blob/master/src/Angular.js#L1312 -// @internal -export function toAngularJSON(obj: any, pretty?: any): string { - if (obj === undefined) return ''; - if (typeof pretty === 'number') { - pretty = pretty ? 2 : null; - } - return JSON.stringify(obj, toJsonReplacer, pretty); -} - -function isWindow(obj: any) { - return obj && obj.window === obj; -} - -function isScope(obj: any) { - return obj && obj.$evalAsync && obj.$watch; -} - -function toJsonReplacer(key: any, value: any) { - let val = value; - - if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { - val = undefined; - } else if (isWindow(value)) { - val = '$WINDOW'; - } else if (value && window.document === value) { - val = '$DOCUMENT'; - } else if (isScope(value)) { - val = '$SCOPE'; - } - - return val; -} +export { isValidJson, isValidInterval }; diff --git a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts index 24dd1c4944bfb..7a5d927d0f219 100644 --- a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts +++ b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts @@ -19,7 +19,7 @@ import { get, has } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { createAggConfigs, IAggConfigs } from 'ui/agg_types'; +import { AggConfigs, IAggConfigs } from 'ui/agg_types'; import { createFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; import { KibanaContext, @@ -258,7 +258,7 @@ export const esaggs = (): ExpressionFunctionDefinition { - const { aggs } = getSearchServiceShim(); - const aggConfigs = aggs.createAggConfigs(indexPattern); + const aggConfigs = new AggConfigs(indexPattern); const aggConfig = aggConfigs.createAggConfig({ enabled: true, type, diff --git a/src/legacy/core_plugins/data/public/search/mocks.ts b/src/legacy/core_plugins/data/public/search/mocks.ts deleted file mode 100644 index 86b6a928dc5b4..0000000000000 --- a/src/legacy/core_plugins/data/public/search/mocks.ts +++ /dev/null @@ -1,85 +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 { SearchSetup, SearchStart } from './search_service'; -import { AggTypesRegistrySetup, AggTypesRegistryStart } from './aggs/agg_types_registry'; -import { AggConfigs } from './aggs/agg_configs'; -import { mockAggTypesRegistry } from './aggs/test_helpers'; - -const aggTypeBaseParamMock = () => ({ - name: 'some_param', - type: 'some_param_type', - displayName: 'some_agg_type_param', - required: false, - advanced: false, - default: {}, - write: jest.fn(), - serialize: jest.fn().mockImplementation(() => {}), - deserialize: jest.fn().mockImplementation(() => {}), - options: [], -}); - -const aggTypeConfigMock = () => ({ - name: 'some_name', - title: 'some_title', - params: [aggTypeBaseParamMock()], -}); - -export const aggTypesRegistrySetupMock = (): MockedKeys => ({ - registerBucket: jest.fn(), - registerMetric: jest.fn(), -}); - -export const aggTypesRegistryStartMock = (): MockedKeys => ({ - get: jest.fn().mockImplementation(aggTypeConfigMock), - getBuckets: jest.fn().mockImplementation(() => [aggTypeConfigMock()]), - getMetrics: jest.fn().mockImplementation(() => [aggTypeConfigMock()]), - getAll: jest.fn().mockImplementation(() => ({ - buckets: [aggTypeConfigMock()], - metrics: [aggTypeConfigMock()], - })), -}); - -export const searchSetupMock = (): MockedKeys => ({ - aggs: { - types: aggTypesRegistrySetupMock(), - }, -}); - -export const searchStartMock = (): MockedKeys => ({ - aggs: { - createAggConfigs: jest.fn().mockImplementation((indexPattern, configStates = [], schemas) => { - return new AggConfigs(indexPattern, configStates, { - schemas, - typesRegistry: mockAggTypesRegistry(), - }); - }), - types: mockAggTypesRegistry(), - __LEGACY: { - AggConfig: jest.fn() as any, - AggType: jest.fn(), - aggTypeFieldFilters: jest.fn() as any, - FieldParamType: jest.fn(), - MetricAggType: jest.fn(), - parentPipelineAggHelper: jest.fn() as any, - setBounds: jest.fn(), - siblingPipelineAggHelper: jest.fn() as any, - }, - }, -}); diff --git a/src/legacy/core_plugins/data/public/search/search_service.ts b/src/legacy/core_plugins/data/public/search/search_service.ts index 6754c0e3551af..45f9ff17328ad 100644 --- a/src/legacy/core_plugins/data/public/search/search_service.ts +++ b/src/legacy/core_plugins/data/public/search/search_service.ts @@ -18,16 +18,11 @@ */ import { CoreSetup, CoreStart } from '../../../../../core/public'; -import { IndexPattern } from '../../../../../plugins/data/public'; import { aggTypes, AggType, - AggTypesRegistry, - AggTypesRegistrySetup, - AggTypesRegistryStart, AggConfig, AggConfigs, - CreateAggConfigParams, FieldParamType, MetricAggType, aggTypeFieldFilters, @@ -37,28 +32,20 @@ import { } from './aggs'; interface AggsSetup { - types: AggTypesRegistrySetup; + types: typeof aggTypes; } -interface AggsStartLegacy { +interface AggsStart { + types: typeof aggTypes; AggConfig: typeof AggConfig; + AggConfigs: typeof AggConfigs; AggType: typeof AggType; aggTypeFieldFilters: typeof aggTypeFieldFilters; FieldParamType: typeof FieldParamType; MetricAggType: typeof MetricAggType; parentPipelineAggHelper: typeof parentPipelineAggHelper; - setBounds: typeof setBounds; siblingPipelineAggHelper: typeof siblingPipelineAggHelper; -} - -interface AggsStart { - createAggConfigs: ( - indexPattern: IndexPattern, - configStates?: CreateAggConfigParams[], - schemas?: Record - ) => InstanceType; - types: AggTypesRegistryStart; - __LEGACY: AggsStartLegacy; + setBounds: typeof setBounds; } export interface SearchSetup { @@ -76,41 +63,28 @@ export interface SearchStart { * it will move into the existing search service in src/plugins/data/public/search */ export class SearchService { - private readonly aggTypesRegistry = new AggTypesRegistry(); - public setup(core: CoreSetup): SearchSetup { - const aggTypesSetup = this.aggTypesRegistry.setup(); - aggTypes.buckets.forEach(b => aggTypesSetup.registerBucket(b)); - aggTypes.metrics.forEach(m => aggTypesSetup.registerMetric(m)); - return { aggs: { - types: aggTypesSetup, + types: aggTypes, // TODO convert to registry + // TODO add other items as needed }, }; } public start(core: CoreStart): SearchStart { - const aggTypesStart = this.aggTypesRegistry.start(); return { aggs: { - createAggConfigs: (indexPattern, configStates = [], schemas) => { - return new AggConfigs(indexPattern, configStates, { - schemas, - typesRegistry: aggTypesStart, - }); - }, - types: aggTypesStart, - __LEGACY: { - AggConfig, // TODO make static - AggType, - aggTypeFieldFilters, - FieldParamType, - MetricAggType, - parentPipelineAggHelper, // TODO make static - setBounds, // TODO make static - siblingPipelineAggHelper, // TODO make static - }, + types: aggTypes, // TODO convert to registry + AggConfig, // TODO make static + AggConfigs, + AggType, + aggTypeFieldFilters, + FieldParamType, + MetricAggType, + parentPipelineAggHelper, // TODO make static + siblingPipelineAggHelper, // TODO make static + setBounds, // TODO make static }, }; } diff --git a/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts b/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts index 98048cb25db2f..ef2748102623a 100644 --- a/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts +++ b/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts @@ -20,6 +20,8 @@ import { TabifyBuckets } from './buckets'; import { AggGroupNames } from '../aggs'; +jest.mock('ui/new_platform'); + describe('Buckets wrapper', () => { const check = (aggResp: any, count: number, keys: string[]) => { test('reads the length', () => { diff --git a/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts b/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts index 6c5dc790ef976..cfd4cd7de640b 100644 --- a/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts +++ b/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts @@ -18,17 +18,12 @@ */ import { tabifyGetColumns } from './get_columns'; -import { TabbedAggColumn } from './types'; import { AggConfigs, AggGroupNames, Schemas } from '../aggs'; -import { mockAggTypesRegistry, mockDataServices } from '../aggs/test_helpers'; - -describe('get columns', () => { - beforeEach(() => { - mockDataServices(); - }); +import { TabbedAggColumn } from './types'; - const typesRegistry = mockAggTypesRegistry(); +jest.mock('ui/new_platform'); +describe('get columns', () => { const createAggConfigs = (aggs: any[] = []) => { const field = { name: '@timestamp', @@ -43,17 +38,18 @@ describe('get columns', () => { }, } as any; - return new AggConfigs(indexPattern, aggs, { - typesRegistry, - schemas: new Schemas([ + return new AggConfigs( + indexPattern, + aggs, + new Schemas([ { group: AggGroupNames.Metrics, name: 'metric', min: 1, defaults: [{ schema: 'metric', type: 'count' }], }, - ]).all, - }); + ]).all + ); }; test('should inject a count metric if no aggs exist', () => { diff --git a/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts b/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts index 94301eedac74a..f5df0a683ca00 100644 --- a/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts +++ b/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts @@ -19,19 +19,14 @@ import { TabbedAggResponseWriter } from './response_writer'; import { AggConfigs, AggGroupNames, Schemas, BUCKET_TYPES } from '../aggs'; -import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers'; import { TabbedResponseWriterOptions } from './types'; -describe('TabbedAggResponseWriter class', () => { - beforeEach(() => { - mockDataServices(); - }); +jest.mock('ui/new_platform'); +describe('TabbedAggResponseWriter class', () => { let responseWriter: TabbedAggResponseWriter; - const typesRegistry = mockAggTypesRegistry(); - const splitAggConfig = [ { type: BUCKET_TYPES.TERMS, @@ -71,17 +66,18 @@ describe('TabbedAggResponseWriter class', () => { } as any; return new TabbedAggResponseWriter( - new AggConfigs(indexPattern, aggs, { - typesRegistry, - schemas: new Schemas([ + new AggConfigs( + indexPattern, + aggs, + new Schemas([ { group: AggGroupNames.Metrics, name: 'metric', min: 1, defaults: [{ schema: 'metric', type: 'count' }], }, - ]).all, - }), + ]).all + ), { metricsAtAllLevels: false, partialRows: false, diff --git a/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts b/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts index db4ad3bdea96b..13fe7719b0a85 100644 --- a/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts +++ b/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts @@ -20,12 +20,11 @@ import { IndexPattern } from '../../../../../../plugins/data/public'; import { tabifyAggResponse } from './tabify'; import { IAggConfig, IAggConfigs, AggGroupNames, Schemas, AggConfigs } from '../aggs'; -import { mockAggTypesRegistry } from '../aggs/test_helpers'; import { metricOnly, threeTermBuckets } from 'fixtures/fake_hierarchical_data'; -describe('tabifyAggResponse Integration', () => { - const typesRegistry = mockAggTypesRegistry(); +jest.mock('ui/new_platform'); +describe('tabifyAggResponse Integration', () => { const createAggConfigs = (aggs: IAggConfig[] = []) => { const field = { name: '@timestamp', @@ -40,17 +39,18 @@ describe('tabifyAggResponse Integration', () => { }, } as unknown) as IndexPattern; - return new AggConfigs(indexPattern, aggs, { - typesRegistry, - schemas: new Schemas([ + return new AggConfigs( + indexPattern, + aggs, + new Schemas([ { group: AggGroupNames.Metrics, name: 'metric', min: 1, defaults: [{ schema: 'metric', type: 'count' }], }, - ]).all, - }); + ]).all + ); }; const mockAggConfig = (agg: any): IAggConfig => (agg as unknown) as IAggConfig; diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts b/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts index 6ae4e415f8caa..6591aa5fb53d5 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts +++ b/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts @@ -20,8 +20,7 @@ import { cloneDeep } from 'lodash'; import { Vis, VisState } from 'src/legacy/core_plugins/visualizations/public'; - -import { createAggConfigs, IAggConfig, AggGroupNames } from '../../../legacy_imports'; +import { AggConfigs, IAggConfig, AggGroupNames } from '../../../legacy_imports'; import { EditorStateActionTypes } from './constants'; import { getEnabledMetricAggsCount } from '../../agg_group_helper'; import { EditorAction } from './actions'; @@ -33,8 +32,7 @@ function initEditorState(vis: Vis) { function editorStateReducer(state: VisState, action: EditorAction): VisState { switch (action.type) { case EditorStateActionTypes.ADD_NEW_AGG: { - const payloadAggConfig = action.payload as IAggConfig; - const aggConfig = state.aggs.createAggConfig(payloadAggConfig, { + const aggConfig = state.aggs.createAggConfig(action.payload as IAggConfig, { addToAggConfigs: false, }); aggConfig.brandNew = true; @@ -42,7 +40,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } @@ -65,7 +63,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } @@ -90,7 +88,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } @@ -131,7 +129,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } @@ -143,7 +141,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } @@ -165,7 +163,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } diff --git a/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts b/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts index 8aed263c4e4d1..832f73752a99b 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts @@ -22,12 +22,12 @@ export { AggType, IAggType, IAggConfig, + AggConfigs, IAggConfigs, AggParam, AggGroupNames, aggGroupNamesMap, aggTypes, - createAggConfigs, FieldParamType, IFieldParamType, BUCKET_TYPES, diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts index 736152c7014dc..0e1e48d00a1b2 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts @@ -34,7 +34,7 @@ import { stubFields } from '../../../../plugins/data/public/stubs'; import { tableVisResponseHandler } from './table_vis_response_handler'; import { coreMock } from '../../../../core/public/mocks'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { createAggConfigs } from 'ui/agg_types'; +import { AggConfigs } from 'ui/agg_types'; import { tabifyAggResponse, IAggConfig } from './legacy_imports'; jest.mock('ui/new_platform'); @@ -113,7 +113,7 @@ describe('Table Vis - Controller', () => { return ({ type: tableVisTypeDefinition, params: Object.assign({}, tableVisTypeDefinition.visConfig.defaults, params), - aggs: createAggConfigs( + aggs: new AggConfigs( stubIndexPattern, [ { type: 'count', schema: 'metric' }, diff --git a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts index 0a3b1938436c0..fb7a157b53a9a 100644 --- a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts +++ b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts @@ -18,10 +18,10 @@ */ export { + AggConfigs, IAggConfig, IAggConfigs, isDateHistogramBucketAggConfig, setBounds, } from '../../data/public'; -export { createAggConfigs } from 'ui/agg_types'; export { createSavedSearchesLoader } from '../../../../plugins/discover/public'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js index 15a826cc6ddbe..2f36322c67256 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js @@ -30,7 +30,7 @@ import { EventEmitter } from 'events'; import _ from 'lodash'; import { PersistedState } from '../../../../../../../src/plugins/visualizations/public'; -import { createAggConfigs } from '../../legacy_imports'; +import { AggConfigs } from '../../legacy_imports'; import { updateVisualizationConfig } from './legacy/vis_update'; import { getTypes } from './services'; @@ -83,7 +83,7 @@ class VisImpl extends EventEmitter { updateVisualizationConfig(state.params, this.params); if (state.aggs || !this.aggs) { - this.aggs = createAggConfigs( + this.aggs = new AggConfigs( this.indexPattern, state.aggs ? state.aggs.aggs || state.aggs : [], this.type.schemas.all @@ -125,7 +125,7 @@ class VisImpl extends EventEmitter { copyCurrentState(includeDisabled = false) { const state = this.getCurrentState(includeDisabled); - state.aggs = createAggConfigs( + state.aggs = new AggConfigs( this.indexPattern, state.aggs.aggs || state.aggs, this.type.schemas.all diff --git a/src/legacy/ui/public/agg_types/index.ts b/src/legacy/ui/public/agg_types/index.ts index ffc300251c4bb..ac5d0bed7ef15 100644 --- a/src/legacy/ui/public/agg_types/index.ts +++ b/src/legacy/ui/public/agg_types/index.ts @@ -27,19 +27,18 @@ import { start as dataStart } from '../../../core_plugins/data/public/legacy'; // runtime contracts -const { types } = dataStart.search.aggs; -export const aggTypes = types.getAll(); -export const { createAggConfigs } = dataStart.search.aggs; export const { + types: aggTypes, AggConfig, + AggConfigs, AggType, aggTypeFieldFilters, FieldParamType, MetricAggType, parentPipelineAggHelper, - setBounds, siblingPipelineAggHelper, -} = dataStart.search.aggs.__LEGACY; + setBounds, +} = dataStart.search.aggs; // types export { diff --git a/src/legacy/ui/public/vis/__tests__/_agg_config.js b/src/legacy/ui/public/vis/__tests__/_agg_config.js new file mode 100644 index 0000000000000..9e53044f681ba --- /dev/null +++ b/src/legacy/ui/public/vis/__tests__/_agg_config.js @@ -0,0 +1,485 @@ +/* + * 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 expect from '@kbn/expect'; +import ngMock from 'ng_mock'; +import { AggType, AggConfig } from '../../agg_types'; +import { start as visualizationsStart } from '../../../../core_plugins/visualizations/public/np_ready/public/legacy'; + +import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; + +describe('AggConfig', function() { + let indexPattern; + + beforeEach(ngMock.module('kibana')); + beforeEach( + ngMock.inject(function(Private) { + indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); + }) + ); + + describe('#toDsl', function() { + it('calls #write()', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }); + + const aggConfig = vis.aggs.byName('date_histogram')[0]; + const stub = sinon.stub(aggConfig, 'write').returns({ params: {} }); + + aggConfig.toDsl(); + expect(stub.callCount).to.be(1); + }); + + it('uses the type name as the agg name', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }); + + const aggConfig = vis.aggs.byName('date_histogram')[0]; + sinon.stub(aggConfig, 'write').returns({ params: {} }); + + const dsl = aggConfig.toDsl(); + expect(dsl).to.have.property('date_histogram'); + }); + + it('uses the params from #write() output as the agg params', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }); + + const aggConfig = vis.aggs.byName('date_histogram')[0]; + const football = {}; + + sinon.stub(aggConfig, 'write').returns({ params: football }); + + const dsl = aggConfig.toDsl(); + expect(dsl.date_histogram).to.be(football); + }); + + it('includes subAggs from #write() output', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { + type: 'avg', + schema: 'metric', + }, + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }); + + const histoConfig = vis.aggs.byName('date_histogram')[0]; + const avgConfig = vis.aggs.byName('avg')[0]; + const football = {}; + + sinon.stub(histoConfig, 'write').returns({ params: {}, subAggs: [avgConfig] }); + sinon.stub(avgConfig, 'write').returns({ params: football }); + + const dsl = histoConfig.toDsl(); + + // didn't use .eql() because of variable key names, and final check is strict + expect(dsl).to.have.property('aggs'); + expect(dsl.aggs).to.have.property(avgConfig.id); + expect(dsl.aggs[avgConfig.id]).to.have.property('avg'); + expect(dsl.aggs[avgConfig.id].avg).to.be(football); + }); + }); + + describe('::ensureIds', function() { + it('accepts an array of objects and assigns ids to them', function() { + const objs = [{}, {}, {}, {}]; + AggConfig.ensureIds(objs); + expect(objs[0]).to.have.property('id', '1'); + expect(objs[1]).to.have.property('id', '2'); + expect(objs[2]).to.have.property('id', '3'); + expect(objs[3]).to.have.property('id', '4'); + }); + + it('assigns ids relative to the other only item in the list', function() { + const objs = [{ id: '100' }, {}]; + AggConfig.ensureIds(objs); + expect(objs[0]).to.have.property('id', '100'); + expect(objs[1]).to.have.property('id', '101'); + }); + + it('assigns ids relative to the other items in the list', function() { + const objs = [{ id: '100' }, { id: '200' }, { id: '500' }, { id: '350' }, {}]; + AggConfig.ensureIds(objs); + expect(objs[0]).to.have.property('id', '100'); + expect(objs[1]).to.have.property('id', '200'); + expect(objs[2]).to.have.property('id', '500'); + expect(objs[3]).to.have.property('id', '350'); + expect(objs[4]).to.have.property('id', '501'); + }); + + it('uses ::nextId to get the starting value', function() { + sinon.stub(AggConfig, 'nextId').returns(534); + const objs = AggConfig.ensureIds([{}]); + AggConfig.nextId.restore(); + expect(objs[0]).to.have.property('id', '534'); + }); + + it('only calls ::nextId once', function() { + const start = 420; + sinon.stub(AggConfig, 'nextId').returns(start); + const objs = AggConfig.ensureIds([{}, {}, {}, {}, {}, {}, {}]); + + expect(AggConfig.nextId).to.have.property('callCount', 1); + + AggConfig.nextId.restore(); + objs.forEach(function(obj, i) { + expect(obj).to.have.property('id', String(start + i)); + }); + }); + }); + + describe('::nextId', function() { + it('accepts a list of objects and picks the next id', function() { + const next = AggConfig.nextId([{ id: 100 }, { id: 500 }]); + expect(next).to.be(501); + }); + + it('handles an empty list', function() { + const next = AggConfig.nextId([]); + expect(next).to.be(1); + }); + + it('fails when the list is not defined', function() { + expect(function() { + AggConfig.nextId(); + }).to.throwError(); + }); + }); + + describe('#toJsonDataEquals', function() { + const testsIdentical = [ + { + type: 'metric', + aggs: [ + { + type: 'count', + schema: 'metric', + params: { field: '@timestamp' }, + }, + ], + }, + { + type: 'histogram', + aggs: [ + { + type: 'avg', + schema: 'metric', + }, + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }, + ]; + + testsIdentical.forEach((visConfig, index) => { + it(`identical aggregations (${index})`, function() { + const vis1 = new visualizationsStart.Vis(indexPattern, visConfig); + const vis2 = new visualizationsStart.Vis(indexPattern, visConfig); + expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(true); + }); + }); + + const testsIdenticalDifferentOrder = [ + { + config1: { + type: 'histogram', + aggs: [ + { + type: 'avg', + schema: 'metric', + }, + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }, + config2: { + type: 'histogram', + aggs: [ + { + schema: 'metric', + type: 'avg', + }, + { + schema: 'segment', + type: 'date_histogram', + }, + ], + }, + }, + ]; + + testsIdenticalDifferentOrder.forEach((test, index) => { + it(`identical aggregations (${index}) - init json is in different order`, function() { + const vis1 = new visualizationsStart.Vis(indexPattern, test.config1); + const vis2 = new visualizationsStart.Vis(indexPattern, test.config2); + expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(true); + }); + }); + + const testsDifferent = [ + { + config1: { + type: 'histogram', + aggs: [ + { + type: 'avg', + schema: 'metric', + }, + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }, + config2: { + type: 'histogram', + aggs: [ + { + type: 'max', + schema: 'metric', + }, + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }, + }, + { + config1: { + type: 'metric', + aggs: [ + { + type: 'count', + schema: 'metric', + params: { field: '@timestamp' }, + }, + ], + }, + config2: { + type: 'metric', + aggs: [ + { + type: 'count', + schema: 'metric', + params: { field: '@timestamp' }, + }, + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }, + }, + ]; + + testsDifferent.forEach((test, index) => { + it(`different aggregations (${index})`, function() { + const vis1 = new visualizationsStart.Vis(indexPattern, test.config1); + const vis2 = new visualizationsStart.Vis(indexPattern, test.config2); + expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(false); + }); + }); + }); + + describe('#toJSON', function() { + it('includes the aggs id, params, type and schema', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }); + + const aggConfig = vis.aggs.byName('date_histogram')[0]; + expect(aggConfig.id).to.be('1'); + expect(aggConfig.params).to.be.an('object'); + expect(aggConfig.type) + .to.be.an(AggType) + .and.have.property('name', 'date_histogram'); + expect(aggConfig.schema) + .to.be.an('object') + .and.have.property('name', 'segment'); + + const state = aggConfig.toJSON(); + expect(state).to.have.property('id', '1'); + expect(state.params).to.be.an('object'); + expect(state).to.have.property('type', 'date_histogram'); + expect(state).to.have.property('schema', 'segment'); + }); + + it('test serialization order is identical (for visual consistency)', function() { + const vis1 = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { + type: 'date_histogram', + schema: 'segment', + }, + ], + }); + const vis2 = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { + schema: 'segment', + type: 'date_histogram', + }, + ], + }); + + //this relies on the assumption that js-engines consistently loop over properties in insertion order. + //most likely the case, but strictly speaking not guaranteed by the JS and JSON specifications. + expect(JSON.stringify(vis1.aggs.aggs) === JSON.stringify(vis2.aggs.aggs)).to.be(true); + }); + }); + + describe('#makeLabel', function() { + it('uses the custom label if it is defined', function() { + const vis = new visualizationsStart.Vis(indexPattern, {}); + const aggConfig = vis.aggs.aggs[0]; + aggConfig.params.customLabel = 'Custom label'; + const label = aggConfig.makeLabel(); + expect(label).to.be(aggConfig.params.customLabel); + }); + it('default label should be "Count"', function() { + const vis = new visualizationsStart.Vis(indexPattern, {}); + const aggConfig = vis.aggs.aggs[0]; + const label = aggConfig.makeLabel(); + expect(label).to.be('Count'); + }); + it('default label should be "Percentage of Count" when percentageMode is set to true', function() { + const vis = new visualizationsStart.Vis(indexPattern, {}); + const aggConfig = vis.aggs.aggs[0]; + const label = aggConfig.makeLabel(true); + expect(label).to.be('Percentage of Count'); + }); + it('empty label if the visualizationsStart.Vis type is not defined', function() { + const vis = new visualizationsStart.Vis(indexPattern, {}); + const aggConfig = vis.aggs.aggs[0]; + aggConfig.type = undefined; + const label = aggConfig.makeLabel(); + expect(label).to.be(''); + }); + }); + + describe('#fieldFormatter - custom getFormat handler', function() { + it('returns formatter from getFormat handler', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'metric', + aggs: [ + { + type: 'count', + schema: 'metric', + params: { field: '@timestamp' }, + }, + ], + }); + + const fieldFormatter = vis.aggs.aggs[0].fieldFormatter(); + + expect(fieldFormatter).to.be.defined; + expect(fieldFormatter('text')).to.be('text'); + }); + }); + + describe('#fieldFormatter - no custom getFormat handler', function() { + const visStateAggWithoutCustomGetFormat = { + aggs: [ + { + type: 'histogram', + schema: 'bucket', + params: { field: 'bytes' }, + }, + ], + }; + let vis; + + beforeEach(function() { + vis = new visualizationsStart.Vis(indexPattern, visStateAggWithoutCustomGetFormat); + }); + + it("returns the field's formatter", function() { + expect(vis.aggs.aggs[0].fieldFormatter().toString()).to.be( + vis.aggs.aggs[0] + .getField() + .format.getConverterFor() + .toString() + ); + }); + + it('returns the string format if the field does not have a format', function() { + const agg = vis.aggs.aggs[0]; + agg.params.field = { type: 'number', format: null }; + const fieldFormatter = agg.fieldFormatter(); + expect(fieldFormatter).to.be.defined; + expect(fieldFormatter('text')).to.be('text'); + }); + + it('returns the string format if their is no field', function() { + const agg = vis.aggs.aggs[0]; + delete agg.params.field; + const fieldFormatter = agg.fieldFormatter(); + expect(fieldFormatter).to.be.defined; + expect(fieldFormatter('text')).to.be('text'); + }); + + it('returns the html converter if "html" is passed in', function() { + const field = indexPattern.fields.getByName('bytes'); + expect(vis.aggs.aggs[0].fieldFormatter('html').toString()).to.be( + field.format.getConverterFor('html').toString() + ); + }); + }); +}); diff --git a/src/legacy/ui/public/vis/__tests__/_agg_configs.js b/src/legacy/ui/public/vis/__tests__/_agg_configs.js new file mode 100644 index 0000000000000..172523ec50c8b --- /dev/null +++ b/src/legacy/ui/public/vis/__tests__/_agg_configs.js @@ -0,0 +1,420 @@ +/* + * 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 sinon from 'sinon'; +import expect from '@kbn/expect'; +import ngMock from 'ng_mock'; +import { AggConfig, AggConfigs, AggGroupNames, Schemas } from '../../agg_types'; +import { start as visualizationsStart } from '../../../../core_plugins/visualizations/public/np_ready/public/legacy'; +import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; + +describe('AggConfigs', function() { + let indexPattern; + + beforeEach(ngMock.module('kibana')); + beforeEach( + ngMock.inject(function(Private) { + // load main deps + indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); + }) + ); + + describe('constructor', function() { + it('handles passing just a vis', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [], + }); + + const ac = new AggConfigs(vis.indexPattern, [], vis.type.schemas.all); + expect(ac.aggs).to.have.length(1); + }); + + it('converts configStates into AggConfig objects if they are not already', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [], + }); + + const ac = new AggConfigs( + vis.indexPattern, + [ + { + type: 'date_histogram', + schema: 'segment', + }, + new AggConfig(vis.aggs, { + type: 'terms', + schema: 'split', + }), + ], + vis.type.schemas.all + ); + + expect(ac.aggs).to.have.length(3); + }); + + it('attempts to ensure that all states have an id', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [], + }); + + const states = [ + { + type: 'date_histogram', + schema: 'segment', + }, + { + type: 'terms', + schema: 'split', + }, + ]; + + const spy = sinon.spy(AggConfig, 'ensureIds'); + new AggConfigs(vis.indexPattern, states, vis.type.schemas.all); + expect(spy.callCount).to.be(1); + expect(spy.firstCall.args[0]).to.be(states); + AggConfig.ensureIds.restore(); + }); + + describe('defaults', function() { + let vis; + beforeEach(function() { + vis = { + indexPattern: indexPattern, + type: { + schemas: new Schemas([ + { + group: AggGroupNames.Metrics, + name: 'metric', + title: 'Simple', + min: 1, + max: 2, + defaults: [ + { schema: 'metric', type: 'count' }, + { schema: 'metric', type: 'avg' }, + { schema: 'metric', type: 'sum' }, + ], + }, + { + group: AggGroupNames.Buckets, + name: 'segment', + title: 'Example', + min: 0, + max: 1, + defaults: [ + { schema: 'segment', type: 'terms' }, + { schema: 'segment', type: 'filters' }, + ], + }, + ]), + }, + }; + }); + + it('should only set the number of defaults defined by the max', function() { + const ac = new AggConfigs(vis.indexPattern, [], vis.type.schemas.all); + expect(ac.bySchemaName('metric')).to.have.length(2); + }); + + it('should set the defaults defined in the schema when none exist', function() { + const ac = new AggConfigs(vis.indexPattern, [], vis.type.schemas.all); + expect(ac.aggs).to.have.length(3); + }); + + it('should NOT set the defaults defined in the schema when some exist', function() { + const ac = new AggConfigs( + vis.indexPattern, + [{ schema: 'segment', type: 'date_histogram' }], + vis.type.schemas.all + ); + expect(ac.aggs).to.have.length(3); + expect(ac.bySchemaName('segment')[0].type.name).to.equal('date_histogram'); + }); + }); + }); + + describe('#getRequestAggs', function() { + it('performs a stable sort, but moves metrics to the bottom', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { type: 'avg', schema: 'metric' }, + { type: 'terms', schema: 'split' }, + { type: 'histogram', schema: 'split' }, + { type: 'sum', schema: 'metric' }, + { type: 'date_histogram', schema: 'segment' }, + { type: 'filters', schema: 'split' }, + { type: 'percentiles', schema: 'metric' }, + ], + }); + + const sorted = vis.aggs.getRequestAggs(); + const aggs = _.indexBy(vis.aggs.aggs, function(agg) { + return agg.type.name; + }); + + expect(sorted.shift()).to.be(aggs.terms); + expect(sorted.shift()).to.be(aggs.histogram); + expect(sorted.shift()).to.be(aggs.date_histogram); + expect(sorted.shift()).to.be(aggs.filters); + expect(sorted.shift()).to.be(aggs.avg); + expect(sorted.shift()).to.be(aggs.sum); + expect(sorted.shift()).to.be(aggs.percentiles); + expect(sorted).to.have.length(0); + }); + }); + + describe('#getResponseAggs', function() { + it('returns all request aggs for basic aggs', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { type: 'terms', schema: 'split' }, + { type: 'date_histogram', schema: 'segment' }, + { type: 'count', schema: 'metric' }, + ], + }); + + const sorted = vis.aggs.getResponseAggs(); + const aggs = _.indexBy(vis.aggs.aggs, function(agg) { + return agg.type.name; + }); + + expect(sorted.shift()).to.be(aggs.terms); + expect(sorted.shift()).to.be(aggs.date_histogram); + expect(sorted.shift()).to.be(aggs.count); + expect(sorted).to.have.length(0); + }); + + it('expands aggs that have multiple responses', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { type: 'terms', schema: 'split' }, + { type: 'date_histogram', schema: 'segment' }, + { type: 'percentiles', schema: 'metric', params: { percents: [1, 2, 3] } }, + ], + }); + + const sorted = vis.aggs.getResponseAggs(); + const aggs = _.indexBy(vis.aggs.aggs, function(agg) { + return agg.type.name; + }); + + expect(sorted.shift()).to.be(aggs.terms); + expect(sorted.shift()).to.be(aggs.date_histogram); + expect(sorted.shift().id).to.be(aggs.percentiles.id + '.' + 1); + expect(sorted.shift().id).to.be(aggs.percentiles.id + '.' + 2); + expect(sorted.shift().id).to.be(aggs.percentiles.id + '.' + 3); + expect(sorted).to.have.length(0); + }); + }); + + describe('#toDsl', function() { + it('uses the sorted aggs', function() { + const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram' }); + sinon.spy(vis.aggs, 'getRequestAggs'); + vis.aggs.toDsl(); + expect(vis.aggs.getRequestAggs).to.have.property('callCount', 1); + }); + + it('calls aggConfig#toDsl() on each aggConfig and compiles the nested output', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { type: 'date_histogram', schema: 'segment' }, + { type: 'filters', schema: 'split' }, + ], + }); + + const aggInfos = vis.aggs.aggs.map(function(aggConfig) { + const football = {}; + + sinon.stub(aggConfig, 'toDsl').returns(football); + + return { + id: aggConfig.id, + football: football, + }; + }); + + (function recurse(lvl) { + const info = aggInfos.shift(); + + expect(lvl).to.have.property(info.id); + expect(lvl[info.id]).to.be(info.football); + + if (lvl[info.id].aggs) { + return recurse(lvl[info.id].aggs); + } + })(vis.aggs.toDsl()); + + expect(aggInfos).to.have.length(1); + }); + + it("skips aggs that don't have a dsl representation", function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { + type: 'date_histogram', + schema: 'segment', + params: { field: '@timestamp', interval: '10s' }, + }, + { type: 'count', schema: 'metric' }, + ], + }); + + const dsl = vis.aggs.toDsl(); + const histo = vis.aggs.byName('date_histogram')[0]; + const count = vis.aggs.byName('count')[0]; + + expect(dsl).to.have.property(histo.id); + expect(dsl[histo.id]).to.be.an('object'); + expect(dsl[histo.id]).to.not.have.property('aggs'); + expect(dsl).to.not.have.property(count.id); + }); + + it('writes multiple metric aggregations at the same level', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { + type: 'date_histogram', + schema: 'segment', + params: { field: '@timestamp', interval: '10s' }, + }, + { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, + { type: 'sum', schema: 'metric', params: { field: 'bytes' } }, + { type: 'min', schema: 'metric', params: { field: 'bytes' } }, + { type: 'max', schema: 'metric', params: { field: 'bytes' } }, + ], + }); + + const dsl = vis.aggs.toDsl(); + + const histo = vis.aggs.byName('date_histogram')[0]; + const metrics = vis.aggs.bySchemaGroup('metrics'); + + expect(dsl).to.have.property(histo.id); + expect(dsl[histo.id]).to.be.an('object'); + expect(dsl[histo.id]).to.have.property('aggs'); + + metrics.forEach(function(metric) { + expect(dsl[histo.id].aggs).to.have.property(metric.id); + expect(dsl[histo.id].aggs[metric.id]).to.not.have.property('aggs'); + }); + }); + + it('writes multiple metric aggregations at every level if the vis is hierarchical', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { type: 'terms', schema: 'segment', params: { field: 'ip', orderBy: 1 } }, + { type: 'terms', schema: 'segment', params: { field: 'extension', orderBy: 1 } }, + { id: 1, type: 'avg', schema: 'metric', params: { field: 'bytes' } }, + { type: 'sum', schema: 'metric', params: { field: 'bytes' } }, + { type: 'min', schema: 'metric', params: { field: 'bytes' } }, + { type: 'max', schema: 'metric', params: { field: 'bytes' } }, + ], + }); + vis.isHierarchical = _.constant(true); + + const topLevelDsl = vis.aggs.toDsl(vis.isHierarchical()); + const buckets = vis.aggs.bySchemaGroup('buckets'); + const metrics = vis.aggs.bySchemaGroup('metrics'); + + (function checkLevel(dsl) { + const bucket = buckets.shift(); + expect(dsl).to.have.property(bucket.id); + + expect(dsl[bucket.id]).to.be.an('object'); + expect(dsl[bucket.id]).to.have.property('aggs'); + + metrics.forEach(function(metric) { + expect(dsl[bucket.id].aggs).to.have.property(metric.id); + expect(dsl[bucket.id].aggs[metric.id]).to.not.have.property('aggs'); + }); + + if (buckets.length) { + checkLevel(dsl[bucket.id].aggs); + } + })(topLevelDsl); + }); + + it('adds the parent aggs of nested metrics at every level if the vis is hierarchical', function() { + const vis = new visualizationsStart.Vis(indexPattern, { + type: 'histogram', + aggs: [ + { + id: '1', + type: 'avg_bucket', + schema: 'metric', + params: { + customBucket: { + id: '1-bucket', + type: 'date_histogram', + schema: 'bucketAgg', + params: { + field: '@timestamp', + interval: '10s', + }, + }, + customMetric: { + id: '1-metric', + type: 'count', + schema: 'metricAgg', + params: {}, + }, + }, + }, + { + id: '2', + type: 'terms', + schema: 'bucket', + params: { + field: 'geo.src', + }, + }, + { + id: '3', + type: 'terms', + schema: 'bucket', + params: { + field: 'machine.os', + }, + }, + ], + }); + vis.isHierarchical = _.constant(true); + + const topLevelDsl = vis.aggs.toDsl(vis.isHierarchical())['2']; + expect(topLevelDsl.aggs).to.have.keys(['1', '1-bucket']); + expect(topLevelDsl.aggs['1'].avg_bucket).to.have.property('buckets_path', '1-bucket>_count'); + expect(topLevelDsl.aggs['3'].aggs).to.have.keys(['1', '1-bucket']); + expect(topLevelDsl.aggs['3'].aggs['1'].avg_bucket).to.have.property( + 'buckets_path', + '1-bucket>_count' + ); + }); + }); +}); diff --git a/src/legacy/core_plugins/data/public/search/aggs/test_helpers/index.ts b/src/legacy/ui/public/vis/__tests__/index.js similarity index 86% rename from src/legacy/core_plugins/data/public/search/aggs/test_helpers/index.ts rename to src/legacy/ui/public/vis/__tests__/index.js index 131f921586144..46074f2c5197b 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/test_helpers/index.ts +++ b/src/legacy/ui/public/vis/__tests__/index.js @@ -17,5 +17,5 @@ * under the License. */ -export { mockAggTypesRegistry } from './mock_agg_types_registry'; -export { mockDataServices } from './mock_data_services'; +import './_agg_config'; +import './_agg_configs'; diff --git a/src/plugins/data/common/field_formats/mocks.ts b/src/plugins/data/common/field_formats/mocks.ts deleted file mode 100644 index bc38374e147cf..0000000000000 --- a/src/plugins/data/common/field_formats/mocks.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { FieldFormat, IFieldFormatsRegistry } from '.'; - -const fieldFormatMock = ({ - convert: jest.fn(), - getConverterFor: jest.fn(), - getParamDefaults: jest.fn(), - param: jest.fn(), - params: jest.fn(), - toJSON: jest.fn(), - type: jest.fn(), - setupContentType: jest.fn(), -} as unknown) as FieldFormat; - -export const fieldFormatsMock: IFieldFormatsRegistry = { - getByFieldType: jest.fn(), - getDefaultConfig: jest.fn(), - getDefaultInstance: jest.fn().mockImplementation(() => fieldFormatMock) as any, - getDefaultInstanceCacheResolver: jest.fn(), - getDefaultInstancePlain: jest.fn(), - getDefaultType: jest.fn(), - getDefaultTypeName: jest.fn(), - getInstance: jest.fn() as any, - getType: jest.fn(), - getTypeNameByEsTypes: jest.fn(), - init: jest.fn(), - register: jest.fn(), - parseDefaultTypeMap: jest.fn(), - deserialize: jest.fn(), - getTypeWithoutMetaParams: jest.fn(), -}; diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 27de3b5a29bfd..6a0a33096eaac 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -16,9 +16,13 @@ * specific language governing permissions and limitations * under the License. */ - -import { Plugin, DataPublicPluginSetup, DataPublicPluginStart, IndexPatternsContract } from '.'; -import { fieldFormatsMock } from '../common/field_formats/mocks'; +import { + Plugin, + DataPublicPluginSetup, + DataPublicPluginStart, + IndexPatternsContract, + IFieldFormatsRegistry, +} from '.'; import { searchSetupMock } from './search/mocks'; import { queryServiceMock } from './query/mocks'; @@ -31,6 +35,24 @@ const autocompleteMock: any = { hasQuerySuggestions: jest.fn(), }; +const fieldFormatsMock: IFieldFormatsRegistry = { + getByFieldType: jest.fn(), + getDefaultConfig: jest.fn(), + getDefaultInstance: jest.fn() as any, + getDefaultInstanceCacheResolver: jest.fn(), + getDefaultInstancePlain: jest.fn(), + getDefaultType: jest.fn(), + getDefaultTypeName: jest.fn(), + getInstance: jest.fn() as any, + getType: jest.fn(), + getTypeNameByEsTypes: jest.fn(), + init: jest.fn(), + register: jest.fn(), + parseDefaultTypeMap: jest.fn(), + deserialize: jest.fn(), + getTypeWithoutMetaParams: jest.fn(), +}; + const createSetupContract = (): Setup => { const querySetupMock = queryServiceMock.createSetupContract(); const setupContract = { diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index 700bea741bd6a..fd72158012de6 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -17,6 +17,25 @@ * under the License. */ +/* + * 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 { ISearchSource } from './search_source'; export const searchSourceMock: MockedKeys = { diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx index 2e1645c816140..ef4b5f6d7b834 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx @@ -17,6 +17,10 @@ jest.mock('ui/new_platform'); // mock away actual dependencies to prevent all of it being loaded jest.mock('../../../../../../src/legacy/core_plugins/interpreter/public/registries', () => {}); +jest.mock('../../../../../../src/legacy/core_plugins/data/public/legacy', () => ({ + start: {}, + setup: {}, +})); jest.mock('./embeddable/embeddable_factory', () => ({ EmbeddableFactory: class Mock {}, })); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap index da04b970a494b..c883983f8cf01 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap @@ -2803,7 +2803,7 @@ tr:hover .c3:focus::before {
- - -
- - -
- - - - - - + -
- - - - - - - - + } + > + - Cu0n232QMyvNtzb75j - - - - + + - - + > + + + + - - - - - - - - -
-
-
-
-
-
-
- -
-
-
-
-
-
+ + + + + + + +
+ + + + + + + + + + + + + + @@ -3087,7 +3105,7 @@ tr:hover .c3:focus::before {
- - -
- - -
- - - - - - + -
- - - - - - - - + } + > + - files - - - - + + - - + > + + + + - - - - - - - - -
-
-
-
-
-
-
- -
-
-
-
-
-
+ + + + + + + +
+ + + + + + + + + + + + + + @@ -3371,7 +3407,7 @@ tr:hover .c3:focus::before {
- - -
- - -
- - - - - - + -
- - - - - - - - + } + > + - sha1: fa5195a... - - - - + + - - + > + + + + - - - - - - - - -
-
-
-
-
-
-
- -
-
-
-
-
-
+ + + + + + + +
+ + + + + + + + + + + + + + @@ -3655,7 +3709,7 @@ tr:hover .c3:focus::before {
- - -
- - -
- - - - - - + -
- - - - - - - - + } + > + - md5: f7653f1... - - - - + + - - + > + + + + - - - - - - - - -
-
-
-
-
-
-
- -
-
-
-
-
-
+ + + + + + + +
+ + + + + + + + + + + + + + From 8a8af5a57c5fa33e02da8e8d3db652f5b716375e Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 27 Feb 2020 23:37:39 -0700 Subject: [PATCH 61/64] skip flaky suite (#58662) --- .../bfetch/common/buffer/tests/timed_item_buffer.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts b/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts index c1c6a8f187a44..e1640927c4ead 100644 --- a/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts +++ b/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts @@ -20,7 +20,8 @@ import { TimedItemBuffer } from '../timed_item_buffer'; import { runItemBufferTests } from './run_item_buffer_tests'; -describe('TimedItemBuffer', () => { +// FLAKY: https://github.com/elastic/kibana/issues/58662 +describe.skip('TimedItemBuffer', () => { runItemBufferTests(TimedItemBuffer); test('does not do unnecessary flushes', async () => { From 913afb3bada2bd75f045ac7d8ec7483c774e2c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Fri, 28 Feb 2020 08:54:50 +0100 Subject: [PATCH 62/64] Update APM readme --- x-pack/legacy/plugins/apm/readme.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/apm/readme.md b/x-pack/legacy/plugins/apm/readme.md index a513249c296db..0edcdc279815c 100644 --- a/x-pack/legacy/plugins/apm/readme.md +++ b/x-pack/legacy/plugins/apm/readme.md @@ -74,10 +74,14 @@ node scripts/jest.js plugins/apm --updateSnapshot ### Functional tests **Start server** -`node scripts/functional_tests_server --config x-pack/test/functional/config.js` +``` +node scripts/functional_tests_server --config x-pack/test/functional/config.js +``` **Run tests** -`node scripts/functional_test_runner --config x-pack/test/functional/config.js --grep='APM specs'` +``` +node scripts/functional_test_runner --config x-pack/test/functional/config.js --grep='APM specs' +``` APM tests are located in `x-pack/test/functional/apps/apm`. For debugging access Elasticsearch on http://localhost:9220` (elastic/changeme) @@ -85,10 +89,14 @@ For debugging access Elasticsearch on http://localhost:9220` (elastic/changeme) ### API integration tests **Start server** -`node scripts/functional_tests_server --config x-pack/test/api_integration/config.js` +``` +node scripts/functional_tests_server --config x-pack/test/api_integration/config.js +``` **Run tests** -`node scripts/functional_test_runner --config x-pack/test/api_integration/config.js --grep='APM specs'` +``` +node scripts/functional_test_runner --config x-pack/test/api_integration/config.js --grep='APM specs' +``` APM tests are located in `x-pack/test/api_integration/apis/apm`. For debugging access Elasticsearch on http://localhost:9220` (elastic/changeme) From ce45647ea2212f5cc42147e9b5bb82cb962e81ca Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Fri, 28 Feb 2020 09:20:51 +0100 Subject: [PATCH 63/64] block SO setup API calls after startup (#58718) --- ...-plugin-server.savedobjectsservicesetup.md | 2 ++ src/core/MIGRATION_EXAMPLES.md | 8 ++++- .../saved_objects_service.test.ts | 30 +++++++++++++++++++ .../saved_objects/saved_objects_service.ts | 15 ++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md index b6f2e7320c48a..963c4bbeb5515 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md @@ -16,6 +16,8 @@ export interface SavedObjectsServiceSetup When plugins access the Saved Objects client, a new client is created using the factory provided to `setClientFactory` and wrapped by all wrappers registered through `addClientWrapper`. +All the setup APIs will throw if called after the service has started, and therefor cannot be used from legacy plugin code. Legacy plugins should use the legacy savedObject service until migrated. + ## Example 1 diff --git a/src/core/MIGRATION_EXAMPLES.md b/src/core/MIGRATION_EXAMPLES.md index def83ba177fc9..2953edb535f47 100644 --- a/src/core/MIGRATION_EXAMPLES.md +++ b/src/core/MIGRATION_EXAMPLES.md @@ -917,4 +917,10 @@ Would be converted to: ```typescript const migration: SavedObjectMigrationFn = (doc, { log }) => {...} -``` \ No newline at end of file +``` + +### Remarks + +The `registerType` API will throw if called after the service has started, and therefor cannot be used from +legacy plugin code. Legacy plugins should use the legacy savedObjects service and the legacy way to register +saved object types until migrated. \ No newline at end of file diff --git a/src/core/server/saved_objects/saved_objects_service.test.ts b/src/core/server/saved_objects/saved_objects_service.test.ts index a1e2c1e8dbf26..554acf8d43dcb 100644 --- a/src/core/server/saved_objects/saved_objects_service.test.ts +++ b/src/core/server/saved_objects/saved_objects_service.test.ts @@ -232,6 +232,36 @@ describe('SavedObjectsService', () => { expect(migratorInstanceMock.runMigrations).toHaveBeenCalledTimes(1); }); + it('throws when calling setup APIs once started', async () => { + const coreContext = createCoreContext({ skipMigration: false }); + const soService = new SavedObjectsService(coreContext); + const setup = await soService.setup(createSetupDeps()); + await soService.start({}); + + expect(() => { + setup.setClientFactoryProvider(jest.fn()); + }).toThrowErrorMatchingInlineSnapshot( + `"cannot call \`setClientFactoryProvider\` after service startup."` + ); + + expect(() => { + setup.addClientWrapper(0, 'dummy', jest.fn()); + }).toThrowErrorMatchingInlineSnapshot( + `"cannot call \`addClientWrapper\` after service startup."` + ); + + expect(() => { + setup.registerType({ + name: 'someType', + hidden: false, + namespaceAgnostic: false, + mappings: { properties: {} }, + }); + }).toThrowErrorMatchingInlineSnapshot( + `"cannot call \`registerType\` after service startup."` + ); + }); + describe('#getTypeRegistry', () => { it('returns the internal type registry of the service', async () => { const coreContext = createCoreContext({ skipMigration: false }); diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index da8f7ab96d689..d5a9f47420971 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -61,6 +61,9 @@ import { registerRoutes } from './routes'; * the factory provided to `setClientFactory` and wrapped by all wrappers * registered through `addClientWrapper`. * + * All the setup APIs will throw if called after the service has started, and therefor cannot be used + * from legacy plugin code. Legacy plugins should use the legacy savedObject service until migrated. + * * @example * ```ts * import { SavedObjectsClient, CoreSetup } from 'src/core/server'; @@ -275,6 +278,7 @@ export class SavedObjectsService private migrator$ = new Subject(); private typeRegistry = new SavedObjectTypeRegistry(); private validations: PropertyValidators = {}; + private started = false; constructor(private readonly coreContext: CoreContext) { this.logger = coreContext.logger.get('savedobjects-service'); @@ -316,12 +320,18 @@ export class SavedObjectsService return { setClientFactoryProvider: provider => { + if (this.started) { + throw new Error('cannot call `setClientFactoryProvider` after service startup.'); + } if (this.clientFactoryProvider) { throw new Error('custom client factory is already set, and can only be set once'); } this.clientFactoryProvider = provider; }, addClientWrapper: (priority, id, factory) => { + if (this.started) { + throw new Error('cannot call `addClientWrapper` after service startup.'); + } this.clientFactoryWrappers.push({ priority, id, @@ -329,6 +339,9 @@ export class SavedObjectsService }); }, registerType: type => { + if (this.started) { + throw new Error('cannot call `registerType` after service startup.'); + } this.typeRegistry.registerType(type); }, }; @@ -415,6 +428,8 @@ export class SavedObjectsService clientProvider.addClientWrapperFactory(priority, id, factory); }); + this.started = true; + return { migrator, clientProvider, From bd92b7d56f85bd7c788a3d256a9740890ac5f317 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Fri, 28 Feb 2020 10:09:41 +0100 Subject: [PATCH 64/64] Implement HTTP Authentication provider and allow `ApiKey` authentication by default. (#58126) --- .../routes/api/__fixtures__/authc_mock.ts | 41 +- x-pack/plugins/case/server/services/index.ts | 10 +- .../authentication/authenticator.test.ts | 329 +++-- .../server/authentication/authenticator.ts | 50 + .../get_http_authentication_scheme.test.ts | 58 + .../get_http_authentication_scheme.ts | 21 + .../server/authentication/index.mock.ts | 3 +- .../server/authentication/index.test.ts | 2 +- .../security/server/authentication/index.ts | 1 + .../authentication/providers/base.mock.ts | 30 - .../server/authentication/providers/base.ts | 7 + .../authentication/providers/basic.test.ts | 227 ++-- .../server/authentication/providers/basic.ts | 67 +- .../authentication/providers/http.test.ts | 198 +++ .../server/authentication/providers/http.ts | 99 ++ .../server/authentication/providers/index.ts | 1 + .../authentication/providers/kerberos.test.ts | 612 ++++----- .../authentication/providers/kerberos.ts | 63 +- .../authentication/providers/oidc.test.ts | 603 +++++---- .../server/authentication/providers/oidc.ts | 62 +- .../authentication/providers/pki.test.ts | 352 ++--- .../server/authentication/providers/pki.ts | 48 +- .../authentication/providers/saml.test.ts | 1163 ++++++++--------- .../server/authentication/providers/saml.ts | 51 +- .../authentication/providers/token.test.ts | 541 ++++---- .../server/authentication/providers/token.ts | 59 +- x-pack/plugins/security/server/config.test.ts | 198 +-- x-pack/plugins/security/server/config.ts | 5 + x-pack/plugins/security/server/index.ts | 11 + x-pack/plugins/security/server/plugin.test.ts | 2 + .../routes/authentication/basic.test.ts | 18 + .../server/routes/authentication/basic.ts | 13 +- .../server/routes/authentication/index.ts | 9 +- .../api_integration/apis/security/session.ts | 8 +- 34 files changed, 2579 insertions(+), 2383 deletions(-) create mode 100644 x-pack/plugins/security/server/authentication/get_http_authentication_scheme.test.ts create mode 100644 x-pack/plugins/security/server/authentication/get_http_authentication_scheme.ts create mode 100644 x-pack/plugins/security/server/authentication/providers/http.test.ts create mode 100644 x-pack/plugins/security/server/authentication/providers/http.ts diff --git a/x-pack/plugins/case/server/routes/api/__fixtures__/authc_mock.ts b/x-pack/plugins/case/server/routes/api/__fixtures__/authc_mock.ts index 94ce9627b9ac6..17a2518482637 100644 --- a/x-pack/plugins/case/server/routes/api/__fixtures__/authc_mock.ts +++ b/x-pack/plugins/case/server/routes/api/__fixtures__/authc_mock.ts @@ -3,33 +3,22 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { Authentication } from '../../../../../security/server'; +import { AuthenticatedUser } from '../../../../../security/server'; +import { securityMock } from '../../../../../security/server/mocks'; -const getCurrentUser = jest.fn().mockReturnValue({ - username: 'awesome', - full_name: 'Awesome D00d', -}); -const getCurrentUserThrow = jest.fn().mockImplementation(() => { - throw new Error('Bad User - the user is not authenticated'); -}); +function createAuthenticationMock({ + currentUser, +}: { currentUser?: AuthenticatedUser | null } = {}) { + const { authc } = securityMock.createSetup(); + authc.getCurrentUser.mockReturnValue( + currentUser !== undefined + ? currentUser + : ({ username: 'awesome', full_name: 'Awesome D00d' } as AuthenticatedUser) + ); + return authc; +} export const authenticationMock = { - create: (): jest.Mocked => ({ - login: jest.fn(), - createAPIKey: jest.fn(), - getCurrentUser, - invalidateAPIKey: jest.fn(), - isAuthenticated: jest.fn(), - logout: jest.fn(), - getSessionInfo: jest.fn(), - }), - createInvalid: (): jest.Mocked => ({ - login: jest.fn(), - createAPIKey: jest.fn(), - getCurrentUser: getCurrentUserThrow, - invalidateAPIKey: jest.fn(), - isAuthenticated: jest.fn(), - logout: jest.fn(), - getSessionInfo: jest.fn(), - }), + create: () => createAuthenticationMock(), + createInvalid: () => createAuthenticationMock({ currentUser: null }), }; diff --git a/x-pack/plugins/case/server/services/index.ts b/x-pack/plugins/case/server/services/index.ts index d6d4bd606676c..e6416e268e30b 100644 --- a/x-pack/plugins/case/server/services/index.ts +++ b/x-pack/plugins/case/server/services/index.ts @@ -149,14 +149,8 @@ export class CaseService { } }, getUser: async ({ request, response }: GetUserArgs) => { - let user; - try { - this.log.debug(`Attempting to authenticate a user`); - user = await authentication!.getCurrentUser(request); - } catch (error) { - this.log.debug(`Error on GET user: ${error}`); - throw error; - } + this.log.debug(`Attempting to authenticate a user`); + const user = authentication!.getCurrentUser(request); if (!user) { this.log.debug(`Error on GET user: Bad User`); throw new Error('Bad User - the user is not authenticated'); diff --git a/x-pack/plugins/security/server/authentication/authenticator.test.ts b/x-pack/plugins/security/server/authentication/authenticator.test.ts index 65874ba3a461e..af019ff10dedc 100644 --- a/x-pack/plugins/security/server/authentication/authenticator.test.ts +++ b/x-pack/plugins/security/server/authentication/authenticator.test.ts @@ -5,6 +5,8 @@ */ jest.mock('./providers/basic'); +jest.mock('./providers/saml'); +jest.mock('./providers/http'); import Boom from 'boom'; import { duration, Duration } from 'moment'; @@ -23,15 +25,27 @@ import { Authenticator, AuthenticatorOptions, ProviderSession } from './authenti import { DeauthenticationResult } from './deauthentication_result'; import { BasicAuthenticationProvider } from './providers'; -function getMockOptions(config: Partial = {}) { +function getMockOptions({ + session, + providers, + http = {}, +}: { + session?: AuthenticatorOptions['config']['session']; + providers?: string[]; + http?: Partial; +} = {}) { return { clusterClient: elasticsearchServiceMock.createClusterClient(), basePath: httpServiceMock.createSetupContract().basePath, loggers: loggingServiceMock.create(), config: { - session: { idleTimeout: null, lifespan: null }, - authc: { providers: [], oidc: {}, saml: {} }, - ...config, + session: { idleTimeout: null, lifespan: null, ...(session || {}) }, + authc: { + providers: providers || [], + oidc: {}, + saml: {}, + http: { enabled: true, autoSchemesEnabled: true, schemes: ['apikey'], ...http }, + }, }, sessionStorageFactory: sessionStorageMock.createFactory(), }; @@ -44,8 +58,13 @@ describe('Authenticator', () => { login: jest.fn(), authenticate: jest.fn(), logout: jest.fn(), + getHTTPAuthenticationScheme: jest.fn(), }; + jest.requireMock('./providers/http').HTTPAuthenticationProvider.mockImplementation(() => ({ + authenticate: jest.fn().mockResolvedValue(AuthenticationResult.notHandled()), + })); + jest .requireMock('./providers/basic') .BasicAuthenticationProvider.mockImplementation(() => mockBasicAuthenticationProvider); @@ -55,23 +74,80 @@ describe('Authenticator', () => { describe('initialization', () => { it('fails if authentication providers are not configured.', () => { - const mockOptions = getMockOptions({ - authc: { providers: [], oidc: {}, saml: {} }, - }); - expect(() => new Authenticator(mockOptions)).toThrowError( + expect(() => new Authenticator(getMockOptions())).toThrowError( 'No authentication provider is configured. Verify `xpack.security.authc.providers` config value.' ); }); it('fails if configured authentication provider is not known.', () => { - const mockOptions = getMockOptions({ - authc: { providers: ['super-basic'], oidc: {}, saml: {} }, - }); - - expect(() => new Authenticator(mockOptions)).toThrowError( + expect(() => new Authenticator(getMockOptions({ providers: ['super-basic'] }))).toThrowError( 'Unsupported authentication provider name: super-basic.' ); }); + + describe('HTTP authentication provider', () => { + beforeEach(() => { + jest + .requireMock('./providers/basic') + .BasicAuthenticationProvider.mockImplementation(() => ({ + getHTTPAuthenticationScheme: jest.fn().mockReturnValue('basic'), + })); + }); + + afterEach(() => jest.resetAllMocks()); + + it('enabled by default', () => { + const authenticator = new Authenticator(getMockOptions({ providers: ['basic'] })); + expect(authenticator.isProviderEnabled('basic')).toBe(true); + expect(authenticator.isProviderEnabled('http')).toBe(true); + + expect( + jest.requireMock('./providers/http').HTTPAuthenticationProvider + ).toHaveBeenCalledWith(expect.anything(), { + supportedSchemes: new Set(['apikey', 'basic']), + }); + }); + + it('includes all required schemes if `autoSchemesEnabled` is enabled', () => { + const authenticator = new Authenticator( + getMockOptions({ providers: ['basic', 'kerberos'] }) + ); + expect(authenticator.isProviderEnabled('basic')).toBe(true); + expect(authenticator.isProviderEnabled('kerberos')).toBe(true); + expect(authenticator.isProviderEnabled('http')).toBe(true); + + expect( + jest.requireMock('./providers/http').HTTPAuthenticationProvider + ).toHaveBeenCalledWith(expect.anything(), { + supportedSchemes: new Set(['apikey', 'basic', 'bearer']), + }); + }); + + it('does not include additional schemes if `autoSchemesEnabled` is disabled', () => { + const authenticator = new Authenticator( + getMockOptions({ providers: ['basic', 'kerberos'], http: { autoSchemesEnabled: false } }) + ); + expect(authenticator.isProviderEnabled('basic')).toBe(true); + expect(authenticator.isProviderEnabled('kerberos')).toBe(true); + expect(authenticator.isProviderEnabled('http')).toBe(true); + + expect( + jest.requireMock('./providers/http').HTTPAuthenticationProvider + ).toHaveBeenCalledWith(expect.anything(), { supportedSchemes: new Set(['apikey']) }); + }); + + it('disabled if explicitly disabled', () => { + const authenticator = new Authenticator( + getMockOptions({ providers: ['basic'], http: { enabled: false } }) + ); + expect(authenticator.isProviderEnabled('basic')).toBe(true); + expect(authenticator.isProviderEnabled('http')).toBe(false); + + expect( + jest.requireMock('./providers/http').HTTPAuthenticationProvider + ).not.toHaveBeenCalled(); + }); + }); }); describe('`login` method', () => { @@ -80,9 +156,7 @@ describe('Authenticator', () => { let mockSessionStorage: jest.Mocked>; let mockSessVal: any; beforeEach(() => { - mockOptions = getMockOptions({ - authc: { providers: ['basic'], oidc: {}, saml: {} }, - }); + mockOptions = getMockOptions({ providers: ['basic'] }); mockSessionStorage = sessionStorageMock.create(); mockOptions.sessionStorageFactory.asScoped.mockReturnValue(mockSessionStorage); mockSessVal = { @@ -124,12 +198,9 @@ describe('Authenticator', () => { AuthenticationResult.failed(failureReason) ); - const authenticationResult = await authenticator.login(request, { - provider: 'basic', - value: {}, - }); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); + await expect(authenticator.login(request, { provider: 'basic', value: {} })).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); }); it('returns user that authentication provider returns.', async () => { @@ -140,13 +211,9 @@ describe('Authenticator', () => { AuthenticationResult.succeeded(user, { authHeaders: { authorization: 'Basic .....' } }) ); - const authenticationResult = await authenticator.login(request, { - provider: 'basic', - value: {}, - }); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); - expect(authenticationResult.authHeaders).toEqual({ authorization: 'Basic .....' }); + await expect(authenticator.login(request, { provider: 'basic', value: {} })).resolves.toEqual( + AuthenticationResult.succeeded(user, { authHeaders: { authorization: 'Basic .....' } }) + ); }); it('creates session whenever authentication provider returns state', async () => { @@ -158,12 +225,9 @@ describe('Authenticator', () => { AuthenticationResult.succeeded(user, { state: { authorization } }) ); - const authenticationResult = await authenticator.login(request, { - provider: 'basic', - value: {}, - }); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); + await expect(authenticator.login(request, { provider: 'basic', value: {} })).resolves.toEqual( + AuthenticationResult.succeeded(user, { state: { authorization } }) + ); expect(mockSessionStorage.set).toHaveBeenCalledTimes(1); expect(mockSessionStorage.set).toHaveBeenCalledWith({ @@ -174,11 +238,9 @@ describe('Authenticator', () => { it('returns `notHandled` if login attempt is targeted to not configured provider.', async () => { const request = httpServerMock.createKibanaRequest(); - const authenticationResult = await authenticator.login(request, { - provider: 'token', - value: {}, - }); - expect(authenticationResult.notHandled()).toBe(true); + await expect(authenticator.login(request, { provider: 'token', value: {} })).resolves.toEqual( + AuthenticationResult.notHandled() + ); }); it('clears session if it belongs to a different provider.', async () => { @@ -189,12 +251,9 @@ describe('Authenticator', () => { mockBasicAuthenticationProvider.login.mockResolvedValue(AuthenticationResult.succeeded(user)); mockSessionStorage.get.mockResolvedValue({ ...mockSessVal, provider: 'token' }); - const authenticationResult = await authenticator.login(request, { - provider: 'basic', - value: credentials, - }); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toBe(user); + await expect( + authenticator.login(request, { provider: 'basic', value: credentials }) + ).resolves.toEqual(AuthenticationResult.succeeded(user)); expect(mockBasicAuthenticationProvider.login).toHaveBeenCalledWith( request, @@ -214,12 +273,9 @@ describe('Authenticator', () => { AuthenticationResult.succeeded(user, { state: null }) ); - const authenticationResult = await authenticator.login(request, { - provider: 'basic', - value: {}, - }); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); + await expect(authenticator.login(request, { provider: 'basic', value: {} })).resolves.toEqual( + AuthenticationResult.succeeded(user, { state: null }) + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).toHaveBeenCalled(); @@ -232,9 +288,7 @@ describe('Authenticator', () => { let mockSessionStorage: jest.Mocked>; let mockSessVal: any; beforeEach(() => { - mockOptions = getMockOptions({ - authc: { providers: ['basic'], oidc: {}, saml: {} }, - }); + mockOptions = getMockOptions({ providers: ['basic'] }); mockSessionStorage = sessionStorageMock.create(); mockOptions.sessionStorageFactory.asScoped.mockReturnValue(mockSessionStorage); mockSessVal = { @@ -277,10 +331,9 @@ describe('Authenticator', () => { AuthenticationResult.succeeded(user, { authHeaders: { authorization: 'Basic .....' } }) ); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); - expect(authenticationResult.authHeaders).toEqual({ authorization: 'Basic .....' }); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded(user, { authHeaders: { authorization: 'Basic .....' } }) + ); }); it('creates session whenever authentication provider returns state for system API requests', async () => { @@ -294,9 +347,9 @@ describe('Authenticator', () => { AuthenticationResult.succeeded(user, { state: { authorization } }) ); - const systemAPIAuthenticationResult = await authenticator.authenticate(request); - expect(systemAPIAuthenticationResult.succeeded()).toBe(true); - expect(systemAPIAuthenticationResult.user).toEqual(user); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded(user, { state: { authorization } }) + ); expect(mockSessionStorage.set).toHaveBeenCalledTimes(1); expect(mockSessionStorage.set).toHaveBeenCalledWith({ @@ -316,9 +369,9 @@ describe('Authenticator', () => { AuthenticationResult.succeeded(user, { state: { authorization } }) ); - const systemAPIAuthenticationResult = await authenticator.authenticate(request); - expect(systemAPIAuthenticationResult.succeeded()).toBe(true); - expect(systemAPIAuthenticationResult.user).toEqual(user); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded(user, { state: { authorization } }) + ); expect(mockSessionStorage.set).toHaveBeenCalledTimes(1); expect(mockSessionStorage.set).toHaveBeenCalledWith({ @@ -338,9 +391,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded(user) + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).not.toHaveBeenCalled(); @@ -357,9 +410,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded(user) + ); expect(mockSessionStorage.set).toHaveBeenCalledTimes(1); expect(mockSessionStorage.set).toHaveBeenCalledWith(mockSessVal); @@ -377,7 +430,7 @@ describe('Authenticator', () => { idleTimeout: duration(3600 * 24), lifespan: null, }, - authc: { providers: ['basic'], oidc: {}, saml: {} }, + providers: ['basic'], }); mockSessionStorage = sessionStorageMock.create(); @@ -392,9 +445,9 @@ describe('Authenticator', () => { jest.spyOn(Date, 'now').mockImplementation(() => currentDate); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded(user) + ); expect(mockSessionStorage.set).toHaveBeenCalledTimes(1); expect(mockSessionStorage.set).toHaveBeenCalledWith({ @@ -416,7 +469,7 @@ describe('Authenticator', () => { idleTimeout: duration(hr * 2), lifespan: duration(hr * 8), }, - authc: { providers: ['basic'], oidc: {}, saml: {} }, + providers: ['basic'], }); mockSessionStorage = sessionStorageMock.create(); @@ -437,9 +490,9 @@ describe('Authenticator', () => { jest.spyOn(Date, 'now').mockImplementation(() => currentDate); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded(user) + ); expect(mockSessionStorage.set).toHaveBeenCalledTimes(1); expect(mockSessionStorage.set).toHaveBeenCalledWith({ @@ -468,7 +521,7 @@ describe('Authenticator', () => { idleTimeout: null, lifespan, }, - authc: { providers: ['basic'], oidc: {}, saml: {} }, + providers: ['basic'], }); mockSessionStorage = sessionStorageMock.create(); @@ -485,9 +538,9 @@ describe('Authenticator', () => { AuthenticationResult.succeeded(user) ); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded(user) + ); expect(mockSessionStorage.set).toHaveBeenCalledTimes(1); expect(mockSessionStorage.set).toHaveBeenCalledWith({ @@ -517,13 +570,15 @@ describe('Authenticator', () => { headers: { 'kbn-system-request': 'true' }, }); + const failureReason = new Error('some error'); mockBasicAuthenticationProvider.authenticate.mockResolvedValue( - AuthenticationResult.failed(new Error('some error')) + AuthenticationResult.failed(failureReason) ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.failed()).toBe(true); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).not.toHaveBeenCalled(); @@ -534,13 +589,15 @@ describe('Authenticator', () => { headers: { 'kbn-system-request': 'false' }, }); + const failureReason = new Error('some error'); mockBasicAuthenticationProvider.authenticate.mockResolvedValue( - AuthenticationResult.failed(new Error('some error')) + AuthenticationResult.failed(failureReason) ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.failed()).toBe(true); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).not.toHaveBeenCalled(); @@ -558,9 +615,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded(user, { state: newState }) + ); expect(mockSessionStorage.set).toHaveBeenCalledTimes(1); expect(mockSessionStorage.set).toHaveBeenCalledWith({ @@ -582,9 +639,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded(user, { state: newState }) + ); expect(mockSessionStorage.set).toHaveBeenCalledTimes(1); expect(mockSessionStorage.set).toHaveBeenCalledWith({ @@ -604,8 +661,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.failed()).toBe(true); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(Boom.unauthorized()) + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).toHaveBeenCalled(); @@ -621,8 +679,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.failed()).toBe(true); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(Boom.unauthorized()) + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).toHaveBeenCalled(); @@ -636,8 +695,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.redirected()).toBe(true); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.redirectTo('some-url', { state: null }) + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).toHaveBeenCalled(); @@ -653,8 +713,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.notHandled()).toBe(true); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).not.toHaveBeenCalled(); @@ -670,8 +731,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.notHandled()).toBe(true); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).not.toHaveBeenCalled(); @@ -687,8 +749,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue({ ...mockSessVal, provider: 'token' }); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.notHandled()).toBe(true); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).toHaveBeenCalled(); @@ -704,8 +767,9 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue({ ...mockSessVal, provider: 'token' }); - const authenticationResult = await authenticator.authenticate(request); - expect(authenticationResult.notHandled()).toBe(true); + await expect(authenticator.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); expect(mockSessionStorage.set).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).toHaveBeenCalled(); @@ -718,9 +782,7 @@ describe('Authenticator', () => { let mockSessionStorage: jest.Mocked>; let mockSessVal: any; beforeEach(() => { - mockOptions = getMockOptions({ - authc: { providers: ['basic'], oidc: {}, saml: {} }, - }); + mockOptions = getMockOptions({ providers: ['basic'] }); mockSessionStorage = sessionStorageMock.create(); mockOptions.sessionStorageFactory.asScoped.mockReturnValue(mockSessionStorage); mockSessVal = { @@ -744,9 +806,10 @@ describe('Authenticator', () => { const request = httpServerMock.createKibanaRequest(); mockSessionStorage.get.mockResolvedValue(null); - const deauthenticationResult = await authenticator.logout(request); + await expect(authenticator.logout(request)).resolves.toEqual( + DeauthenticationResult.notHandled() + ); - expect(deauthenticationResult.notHandled()).toBe(true); expect(mockSessionStorage.clear).not.toHaveBeenCalled(); }); @@ -757,12 +820,12 @@ describe('Authenticator', () => { ); mockSessionStorage.get.mockResolvedValue(mockSessVal); - const deauthenticationResult = await authenticator.logout(request); + await expect(authenticator.logout(request)).resolves.toEqual( + DeauthenticationResult.redirectTo('some-url') + ); expect(mockBasicAuthenticationProvider.logout).toHaveBeenCalledTimes(1); expect(mockSessionStorage.clear).toHaveBeenCalled(); - expect(deauthenticationResult.redirected()).toBe(true); - expect(deauthenticationResult.redirectURL).toBe('some-url'); }); it('if session does not exist but provider name is valid, returns whatever authentication provider returns.', async () => { @@ -773,21 +836,22 @@ describe('Authenticator', () => { DeauthenticationResult.redirectTo('some-url') ); - const deauthenticationResult = await authenticator.logout(request); + await expect(authenticator.logout(request)).resolves.toEqual( + DeauthenticationResult.redirectTo('some-url') + ); expect(mockBasicAuthenticationProvider.logout).toHaveBeenCalledTimes(1); expect(mockSessionStorage.clear).not.toHaveBeenCalled(); - expect(deauthenticationResult.redirected()).toBe(true); - expect(deauthenticationResult.redirectURL).toBe('some-url'); }); it('returns `notHandled` if session does not exist and provider name is invalid', async () => { const request = httpServerMock.createKibanaRequest({ query: { provider: 'foo' } }); mockSessionStorage.get.mockResolvedValue(null); - const deauthenticationResult = await authenticator.logout(request); + await expect(authenticator.logout(request)).resolves.toEqual( + DeauthenticationResult.notHandled() + ); - expect(deauthenticationResult.notHandled()).toBe(true); expect(mockSessionStorage.clear).not.toHaveBeenCalled(); }); @@ -796,11 +860,12 @@ describe('Authenticator', () => { const state = { authorization: 'Bearer xxx' }; mockSessionStorage.get.mockResolvedValue({ ...mockSessVal, state, provider: 'token' }); - const deauthenticationResult = await authenticator.logout(request); + await expect(authenticator.logout(request)).resolves.toEqual( + DeauthenticationResult.notHandled() + ); expect(mockBasicAuthenticationProvider.logout).not.toHaveBeenCalled(); expect(mockSessionStorage.clear).toHaveBeenCalled(); - expect(deauthenticationResult.notHandled()).toBe(true); }); }); @@ -809,9 +874,7 @@ describe('Authenticator', () => { let mockOptions: ReturnType; let mockSessionStorage: jest.Mocked>; beforeEach(() => { - mockOptions = getMockOptions({ - authc: { providers: ['basic'], oidc: {}, saml: {} }, - }); + mockOptions = getMockOptions({ providers: ['basic'] }); mockSessionStorage = sessionStorageMock.create(); mockOptions.sessionStorageFactory.asScoped.mockReturnValue(mockSessionStorage); @@ -851,4 +914,16 @@ describe('Authenticator', () => { expect(sessionInfo).toBe(null); }); }); + + describe('`isProviderEnabled` method', () => { + it('returns `true` only if specified provider is enabled', () => { + let authenticator = new Authenticator(getMockOptions({ providers: ['basic'] })); + expect(authenticator.isProviderEnabled('basic')).toBe(true); + expect(authenticator.isProviderEnabled('saml')).toBe(false); + + authenticator = new Authenticator(getMockOptions({ providers: ['basic', 'saml'] })); + expect(authenticator.isProviderEnabled('basic')).toBe(true); + expect(authenticator.isProviderEnabled('saml')).toBe(true); + }); + }); }); diff --git a/x-pack/plugins/security/server/authentication/authenticator.ts b/x-pack/plugins/security/server/authentication/authenticator.ts index 3ab49d3c5b124..4954e1b24216c 100644 --- a/x-pack/plugins/security/server/authentication/authenticator.ts +++ b/x-pack/plugins/security/server/authentication/authenticator.ts @@ -27,6 +27,7 @@ import { TokenAuthenticationProvider, OIDCAuthenticationProvider, PKIAuthenticationProvider, + HTTPAuthenticationProvider, isSAMLRequestQuery, } from './providers'; import { AuthenticationResult } from './authentication_result'; @@ -191,6 +192,7 @@ export class Authenticator { client: this.options.clusterClient, logger: this.options.loggers.get('tokens'), }), + isProviderEnabled: this.isProviderEnabled.bind(this), }; const authProviders = this.options.config.authc.providers; @@ -206,6 +208,8 @@ export class Authenticator { ? (this.options.config.authc as Record)[providerType] : undefined; + this.logger.debug(`Enabling "${providerType}" authentication provider.`); + return [ providerType, instantiateProvider( @@ -216,6 +220,17 @@ export class Authenticator { ] as [string, BaseAuthenticationProvider]; }) ); + + // For the BWC reasons we always include HTTP authentication provider unless it's explicitly disabled. + if (this.options.config.authc.http.enabled) { + this.setupHTTPAuthenticationProvider( + Object.freeze({ + ...providerCommonOptions, + logger: options.loggers.get(HTTPAuthenticationProvider.type), + }) + ); + } + this.serverBasePath = this.options.basePath.serverBasePath || '/'; this.idleTimeout = this.options.config.session.idleTimeout; @@ -385,6 +400,41 @@ export class Authenticator { return null; } + /** + * Checks whether specified provider type is currently enabled. + * @param providerType Type of the provider (`basic`, `saml`, `pki` etc.). + */ + isProviderEnabled(providerType: string) { + return this.providers.has(providerType); + } + + /** + * Initializes HTTP Authentication provider and appends it to the end of the list of enabled + * authentication providers. + * @param options Common provider options. + */ + private setupHTTPAuthenticationProvider(options: AuthenticationProviderOptions) { + const supportedSchemes = new Set( + this.options.config.authc.http.schemes.map(scheme => scheme.toLowerCase()) + ); + + // If `autoSchemesEnabled` is set we should allow schemes that other providers use to + // authenticate requests with Elasticsearch. + if (this.options.config.authc.http.autoSchemesEnabled) { + for (const provider of this.providers.values()) { + const supportedScheme = provider.getHTTPAuthenticationScheme(); + if (supportedScheme) { + supportedSchemes.add(supportedScheme.toLowerCase()); + } + } + } + + this.providers.set( + HTTPAuthenticationProvider.type, + new HTTPAuthenticationProvider(options, { supportedSchemes }) + ); + } + /** * Returns provider iterator where providers are sorted in the order of priority (based on the session ownership). * @param sessionValue Current session value. diff --git a/x-pack/plugins/security/server/authentication/get_http_authentication_scheme.test.ts b/x-pack/plugins/security/server/authentication/get_http_authentication_scheme.test.ts new file mode 100644 index 0000000000000..6a63634394ec0 --- /dev/null +++ b/x-pack/plugins/security/server/authentication/get_http_authentication_scheme.test.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { httpServerMock } from '../../../../../src/core/server/http/http_server.mocks'; + +import { getHTTPAuthenticationScheme } from './get_http_authentication_scheme'; + +describe('getHTTPAuthenticationScheme', () => { + it('returns `null` if request does not have authorization header', () => { + expect(getHTTPAuthenticationScheme(httpServerMock.createKibanaRequest())).toBeNull(); + }); + + it('returns `null` if authorization header value isn not a string', () => { + expect( + getHTTPAuthenticationScheme( + httpServerMock.createKibanaRequest({ + headers: { authorization: ['Basic xxx', 'Bearer xxx'] as any }, + }) + ) + ).toBeNull(); + }); + + it('returns `null` if authorization header value is an empty string', () => { + expect( + getHTTPAuthenticationScheme( + httpServerMock.createKibanaRequest({ headers: { authorization: '' } }) + ) + ).toBeNull(); + }); + + it('returns only scheme portion of the authorization header value in lower case', () => { + const headerValueAndSchemeMap = [ + ['Basic xxx', 'basic'], + ['Basic xxx yyy', 'basic'], + ['basic xxx', 'basic'], + ['basic', 'basic'], + // We don't trim leading whitespaces in scheme. + [' Basic xxx', ''], + ['Negotiate xxx', 'negotiate'], + ['negotiate xxx', 'negotiate'], + ['negotiate', 'negotiate'], + ['ApiKey xxx', 'apikey'], + ['apikey xxx', 'apikey'], + ['Api Key xxx', 'api'], + ]; + + for (const [authorization, scheme] of headerValueAndSchemeMap) { + expect( + getHTTPAuthenticationScheme( + httpServerMock.createKibanaRequest({ headers: { authorization } }) + ) + ).toBe(scheme); + } + }); +}); diff --git a/x-pack/plugins/security/server/authentication/get_http_authentication_scheme.ts b/x-pack/plugins/security/server/authentication/get_http_authentication_scheme.ts new file mode 100644 index 0000000000000..b9c53f34dbcab --- /dev/null +++ b/x-pack/plugins/security/server/authentication/get_http_authentication_scheme.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { KibanaRequest } from '../../../../../src/core/server'; + +/** + * Parses request's `Authorization` HTTP header if present and extracts authentication scheme. + * https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml#authschemes + * @param request Request instance to extract authentication scheme for. + */ +export function getHTTPAuthenticationScheme(request: KibanaRequest) { + const authorizationHeaderValue = request.headers.authorization; + if (!authorizationHeaderValue || typeof authorizationHeaderValue !== 'string') { + return null; + } + + return authorizationHeaderValue.split(/\s+/)[0].toLowerCase(); +} diff --git a/x-pack/plugins/security/server/authentication/index.mock.ts b/x-pack/plugins/security/server/authentication/index.mock.ts index 77f1f9e45aea7..c634e2c80c299 100644 --- a/x-pack/plugins/security/server/authentication/index.mock.ts +++ b/x-pack/plugins/security/server/authentication/index.mock.ts @@ -9,11 +9,12 @@ import { Authentication } from '.'; export const authenticationMock = { create: (): jest.Mocked => ({ login: jest.fn(), + logout: jest.fn(), + isProviderEnabled: jest.fn(), createAPIKey: jest.fn(), getCurrentUser: jest.fn(), invalidateAPIKey: jest.fn(), isAuthenticated: jest.fn(), - logout: jest.fn(), getSessionInfo: jest.fn(), }), }; diff --git a/x-pack/plugins/security/server/authentication/index.test.ts b/x-pack/plugins/security/server/authentication/index.test.ts index 3727b1fc13dac..aaf3fc357352e 100644 --- a/x-pack/plugins/security/server/authentication/index.test.ts +++ b/x-pack/plugins/security/server/authentication/index.test.ts @@ -61,7 +61,7 @@ describe('setupAuthentication()', () => { lifespan: null, }, cookieName: 'my-sid-cookie', - authc: { providers: ['basic'] }, + authc: { providers: ['basic'], http: { enabled: true } }, }), true ); diff --git a/x-pack/plugins/security/server/authentication/index.ts b/x-pack/plugins/security/server/authentication/index.ts index 467afe0034025..189babbc6bfe6 100644 --- a/x-pack/plugins/security/server/authentication/index.ts +++ b/x-pack/plugins/security/server/authentication/index.ts @@ -169,6 +169,7 @@ export async function setupAuthentication({ login: authenticator.login.bind(authenticator), logout: authenticator.logout.bind(authenticator), getSessionInfo: authenticator.getSessionInfo.bind(authenticator), + isProviderEnabled: authenticator.isProviderEnabled.bind(authenticator), getCurrentUser, createAPIKey: (request: KibanaRequest, params: CreateAPIKeyParams) => apiKeys.create(request, params), diff --git a/x-pack/plugins/security/server/authentication/providers/base.mock.ts b/x-pack/plugins/security/server/authentication/providers/base.mock.ts index a659786f4aeff..0781608f8bc4c 100644 --- a/x-pack/plugins/security/server/authentication/providers/base.mock.ts +++ b/x-pack/plugins/security/server/authentication/providers/base.mock.ts @@ -4,9 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import sinon from 'sinon'; -import { ScopedClusterClient } from '../../../../../../src/core/server'; -import { Tokens } from '../tokens'; import { loggingServiceMock, httpServiceMock, @@ -17,34 +14,7 @@ export type MockAuthenticationProviderOptions = ReturnType< typeof mockAuthenticationProviderOptions >; -export type MockAuthenticationProviderOptionsWithJest = ReturnType< - typeof mockAuthenticationProviderOptionsWithJest ->; - -export function mockScopedClusterClient( - client: MockAuthenticationProviderOptions['client'], - requestMatcher: sinon.SinonMatcher = sinon.match.any -) { - const scopedClusterClient = sinon.createStubInstance(ScopedClusterClient); - client.asScoped.withArgs(requestMatcher).returns(scopedClusterClient); - return scopedClusterClient; -} - export function mockAuthenticationProviderOptions() { - const logger = loggingServiceMock.create().get(); - const basePath = httpServiceMock.createSetupContract().basePath; - basePath.get.mockReturnValue('/base-path'); - - return { - client: { callAsInternalUser: sinon.stub(), asScoped: sinon.stub(), close: sinon.stub() }, - logger, - basePath, - tokens: sinon.createStubInstance(Tokens), - }; -} - -// Will be renamed to mockAuthenticationProviderOptions as soon as we migrate all providers tests to Jest. -export function mockAuthenticationProviderOptionsWithJest() { const basePath = httpServiceMock.createSetupContract().basePath; basePath.get.mockReturnValue('/base-path'); diff --git a/x-pack/plugins/security/server/authentication/providers/base.ts b/x-pack/plugins/security/server/authentication/providers/base.ts index a40732768810d..300e59d9ea3da 100644 --- a/x-pack/plugins/security/server/authentication/providers/base.ts +++ b/x-pack/plugins/security/server/authentication/providers/base.ts @@ -84,6 +84,13 @@ export abstract class BaseAuthenticationProvider { */ abstract logout(request: KibanaRequest, state?: unknown): Promise; + /** + * Returns HTTP authentication scheme that provider uses within `Authorization` HTTP header that + * it attaches to all successfully authenticated requests to Elasticsearch or `null` in case + * provider doesn't attach any additional `Authorization` HTTP headers. + */ + abstract getHTTPAuthenticationScheme(): string | null; + /** * Queries Elasticsearch `_authenticate` endpoint to authenticate request and retrieve the user * information of authenticated user. diff --git a/x-pack/plugins/security/server/authentication/providers/basic.test.ts b/x-pack/plugins/security/server/authentication/providers/basic.test.ts index f9c665d6cea48..b7bdff0531fc2 100644 --- a/x-pack/plugins/security/server/authentication/providers/basic.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/basic.test.ts @@ -4,18 +4,31 @@ * you may not use this file except in compliance with the Elastic License. */ -import sinon from 'sinon'; - -import { httpServerMock } from '../../../../../../src/core/server/mocks'; +import { elasticsearchServiceMock, httpServerMock } from '../../../../../../src/core/server/mocks'; import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock'; -import { mockAuthenticationProviderOptions, mockScopedClusterClient } from './base.mock'; +import { mockAuthenticationProviderOptions } from './base.mock'; +import { IClusterClient, ScopeableRequest } from '../../../../../../src/core/server'; +import { AuthenticationResult } from '../authentication_result'; +import { DeauthenticationResult } from '../deauthentication_result'; import { BasicAuthenticationProvider } from './basic'; function generateAuthorizationHeader(username: string, password: string) { return `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`; } +function expectAuthenticateCall( + mockClusterClient: jest.Mocked, + scopeableRequest: ScopeableRequest +) { + expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); + expect(mockClusterClient.asScoped).toHaveBeenCalledWith(scopeableRequest); + + const mockScopedClusterClient = mockClusterClient.asScoped.mock.results[0].value; + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); +} + describe('BasicAuthenticationProvider', () => { let provider: BasicAuthenticationProvider; let mockOptions: ReturnType; @@ -30,38 +43,39 @@ describe('BasicAuthenticationProvider', () => { const credentials = { username: 'user', password: 'password' }; const authorization = generateAuthorizationHeader(credentials.username, credentials.password); - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - const authenticationResult = await provider.login( - httpServerMock.createKibanaRequest(), - credentials + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect( + provider.login(httpServerMock.createKibanaRequest({ headers: {} }), credentials) + ).resolves.toEqual( + AuthenticationResult.succeeded(user, { + authHeaders: { authorization }, + state: { authorization }, + }) ); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); - expect(authenticationResult.state).toEqual({ authorization }); - expect(authenticationResult.authHeaders).toEqual({ authorization }); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); }); it('fails if user cannot be retrieved during login attempt', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const credentials = { username: 'user', password: 'password' }; const authorization = generateAuthorizationHeader(credentials.username, credentials.password); const authenticationError = new Error('Some error'); - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(authenticationError); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(authenticationError); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - const authenticationResult = await provider.login(request, credentials); + await expect(provider.login(request, credentials)).resolves.toEqual( + AuthenticationResult.failed(authenticationError) + ); + + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.user).toBeUndefined(); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.error).toEqual(authenticationError); }); }); @@ -69,142 +83,113 @@ describe('BasicAuthenticationProvider', () => { it('does not redirect AJAX requests that can not be authenticated to the login page.', async () => { // Add `kbn-xsrf` header to make `can_redirect_request` think that it's AJAX request and // avoid triggering of redirect logic. - const authenticationResult = await provider.authenticate( - httpServerMock.createKibanaRequest({ headers: { 'kbn-xsrf': 'xsrf' } }), - null - ); - - expect(authenticationResult.notHandled()).toBe(true); + await expect( + provider.authenticate( + httpServerMock.createKibanaRequest({ headers: { 'kbn-xsrf': 'xsrf' } }), + null + ) + ).resolves.toEqual(AuthenticationResult.notHandled()); }); it('redirects non-AJAX requests that can not be authenticated to the login page.', async () => { - const authenticationResult = await provider.authenticate( - httpServerMock.createKibanaRequest({ path: '/s/foo/some-path # that needs to be encoded' }), - null - ); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - '/base-path/login?next=%2Fbase-path%2Fs%2Ffoo%2Fsome-path%20%23%20that%20needs%20to%20be%20encoded' + await expect( + provider.authenticate( + httpServerMock.createKibanaRequest({ + path: '/s/foo/some-path # that needs to be encoded', + }), + null + ) + ).resolves.toEqual( + AuthenticationResult.redirectTo( + '/base-path/login?next=%2Fbase-path%2Fs%2Ffoo%2Fsome-path%20%23%20that%20needs%20to%20be%20encoded' + ) ); }); it('does not handle authentication if state exists, but authorization property is missing.', async () => { - const authenticationResult = await provider.authenticate( - httpServerMock.createKibanaRequest(), - {} - ); - expect(authenticationResult.notHandled()).toBe(true); + await expect( + provider.authenticate(httpServerMock.createKibanaRequest(), {}) + ).resolves.toEqual(AuthenticationResult.notHandled()); }); - it('succeeds if only `authorization` header is available.', async () => { - const request = httpServerMock.createKibanaRequest({ - headers: { authorization: generateAuthorizationHeader('user', 'password') }, - }); - const user = mockAuthenticatedUser(); - - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: request.headers })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - const authenticationResult = await provider.authenticate(request); + it('does not handle authentication via `authorization` header.', async () => { + const authorization = generateAuthorizationHeader('user', 'password'); + const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); - // Session state and authHeaders aren't returned for header-based auth. - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.authHeaders).toBeUndefined(); + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe(authorization); }); - it('succeeds if only state is available.', async () => { - const request = httpServerMock.createKibanaRequest(); - const user = mockAuthenticatedUser(); + it('does not handle authentication via `authorization` header even if state contains valid credentials.', async () => { const authorization = generateAuthorizationHeader('user', 'password'); + const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - const authenticationResult = await provider.authenticate(request, { authorization }); + await expect(provider.authenticate(request, { authorization })).resolves.toEqual( + AuthenticationResult.notHandled() + ); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.authHeaders).toEqual({ authorization }); + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe(authorization); }); - it('does not handle `authorization` header with unsupported schema even if state contains valid credentials.', async () => { - const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Bearer ***' }, - }); + it('succeeds if only state is available.', async () => { + const request = httpServerMock.createKibanaRequest({ headers: {} }); + const user = mockAuthenticatedUser(); const authorization = generateAuthorizationHeader('user', 'password'); - const authenticationResult = await provider.authenticate(request, { authorization }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - sinon.assert.notCalled(mockOptions.client.asScoped); - expect(request.headers.authorization).toBe('Bearer ***'); - expect(authenticationResult.notHandled()).toBe(true); + await expect(provider.authenticate(request, { authorization })).resolves.toEqual( + AuthenticationResult.succeeded(user, { authHeaders: { authorization } }) + ); + + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); }); it('fails if state contains invalid credentials.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const authorization = generateAuthorizationHeader('user', 'password'); const authenticationError = new Error('Forbidden'); - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(authenticationError); - - const authenticationResult = await provider.authenticate(request, { authorization }); - - expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.user).toBeUndefined(); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.authHeaders).toBeUndefined(); - expect(authenticationResult.error).toBe(authenticationError); - }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(authenticationError); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - it('authenticates only via `authorization` header even if state is available.', async () => { - const request = httpServerMock.createKibanaRequest({ - headers: { authorization: generateAuthorizationHeader('user', 'password') }, - }); - const user = mockAuthenticatedUser(); - - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: request.headers })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + await expect(provider.authenticate(request, { authorization })).resolves.toEqual( + AuthenticationResult.failed(authenticationError) + ); - const authorizationInState = generateAuthorizationHeader('user1', 'password2'); - const authenticationResult = await provider.authenticate(request, { - authorization: authorizationInState, - }); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual(user); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.authHeaders).toBeUndefined(); + expect(request.headers).not.toHaveProperty('authorization'); }); }); describe('`logout` method', () => { it('always redirects to the login page.', async () => { - const request = httpServerMock.createKibanaRequest(); - const deauthenticateResult = await provider.logout(request); - expect(deauthenticateResult.redirected()).toBe(true); - expect(deauthenticateResult.redirectURL).toBe('/base-path/login?msg=LOGGED_OUT'); + await expect(provider.logout(httpServerMock.createKibanaRequest())).resolves.toEqual( + DeauthenticationResult.redirectTo('/base-path/login?msg=LOGGED_OUT') + ); }); it('passes query string parameters to the login page.', async () => { - const request = httpServerMock.createKibanaRequest({ - query: { next: '/app/ml', msg: 'SESSION_EXPIRED' }, - }); - const deauthenticateResult = await provider.logout(request); - expect(deauthenticateResult.redirected()).toBe(true); - expect(deauthenticateResult.redirectURL).toBe( - '/base-path/login?next=%2Fapp%2Fml&msg=SESSION_EXPIRED' + await expect( + provider.logout( + httpServerMock.createKibanaRequest({ query: { next: '/app/ml', msg: 'SESSION_EXPIRED' } }) + ) + ).resolves.toEqual( + DeauthenticationResult.redirectTo('/base-path/login?next=%2Fapp%2Fml&msg=SESSION_EXPIRED') ); }); }); + + it('`getHTTPAuthenticationScheme` method', () => { + expect(provider.getHTTPAuthenticationScheme()).toBe('basic'); + }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/basic.ts b/x-pack/plugins/security/server/authentication/providers/basic.ts index a8e4e8705a7a8..ad46aff8afa51 100644 --- a/x-pack/plugins/security/server/authentication/providers/basic.ts +++ b/x-pack/plugins/security/server/authentication/providers/basic.ts @@ -8,6 +8,7 @@ import { KibanaRequest } from '../../../../../../src/core/server'; import { canRedirectRequest } from '../can_redirect_request'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; +import { getHTTPAuthenticationScheme } from '../get_http_authentication_scheme'; import { BaseAuthenticationProvider } from './base'; /** @@ -75,29 +76,25 @@ export class BasicAuthenticationProvider extends BaseAuthenticationProvider { public async authenticate(request: KibanaRequest, state?: ProviderState | null) { this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); - // try header-based auth - const { - authenticationResult: headerAuthResult, - headerNotRecognized, - } = await this.authenticateViaHeader(request); - if (headerNotRecognized) { - return headerAuthResult; + if (getHTTPAuthenticationScheme(request) != null) { + this.logger.debug('Cannot authenticate requests with `Authorization` header.'); + return AuthenticationResult.notHandled(); } - let authenticationResult = headerAuthResult; - if (authenticationResult.notHandled() && state) { - authenticationResult = await this.authenticateViaState(request, state); - } else if (authenticationResult.notHandled() && canRedirectRequest(request)) { - // If we couldn't handle authentication let's redirect user to the login page. - const nextURL = encodeURIComponent( - `${this.options.basePath.get(request)}${request.url.path}` - ); - authenticationResult = AuthenticationResult.redirectTo( - `${this.options.basePath.get(request)}/login?next=${nextURL}` + if (state) { + return await this.authenticateViaState(request, state); + } + + // If state isn't present let's redirect user to the login page. + if (canRedirectRequest(request)) { + this.logger.debug('Redirecting request to Login page.'); + const basePath = this.options.basePath.get(request); + return AuthenticationResult.redirectTo( + `${basePath}/login?next=${encodeURIComponent(`${basePath}${request.url.path}`)}` ); } - return authenticationResult; + return AuthenticationResult.notHandled(); } /** @@ -114,37 +111,11 @@ export class BasicAuthenticationProvider extends BaseAuthenticationProvider { } /** - * Validates whether request contains `Basic ***` Authorization header and just passes it - * forward to Elasticsearch backend. - * @param request Request instance. + * Returns HTTP authentication scheme (`Bearer`) that's used within `Authorization` HTTP header + * that provider attaches to all successfully authenticated requests to Elasticsearch. */ - private async authenticateViaHeader(request: KibanaRequest) { - this.logger.debug('Trying to authenticate via header.'); - - const authorization = request.headers.authorization; - if (!authorization || typeof authorization !== 'string') { - this.logger.debug('Authorization header is not presented.'); - return { authenticationResult: AuthenticationResult.notHandled() }; - } - - const authenticationSchema = authorization.split(/\s+/)[0]; - if (authenticationSchema.toLowerCase() !== 'basic') { - this.logger.debug(`Unsupported authentication schema: ${authenticationSchema}`); - return { - authenticationResult: AuthenticationResult.notHandled(), - headerNotRecognized: true, - }; - } - - try { - const user = await this.getUser(request); - - this.logger.debug('Request has been authenticated via header.'); - return { authenticationResult: AuthenticationResult.succeeded(user) }; - } catch (err) { - this.logger.debug(`Failed to authenticate request via header: ${err.message}`); - return { authenticationResult: AuthenticationResult.failed(err) }; - } + public getHTTPAuthenticationScheme() { + return 'basic'; } /** diff --git a/x-pack/plugins/security/server/authentication/providers/http.test.ts b/x-pack/plugins/security/server/authentication/providers/http.test.ts new file mode 100644 index 0000000000000..65fbd7cd9f4ad --- /dev/null +++ b/x-pack/plugins/security/server/authentication/providers/http.test.ts @@ -0,0 +1,198 @@ +/* + * 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 { elasticsearchServiceMock, httpServerMock } from '../../../../../../src/core/server/mocks'; +import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock'; +import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; + +import { + ElasticsearchErrorHelpers, + IClusterClient, + ScopeableRequest, +} from '../../../../../../src/core/server'; +import { AuthenticationResult } from '../authentication_result'; +import { DeauthenticationResult } from '../deauthentication_result'; +import { HTTPAuthenticationProvider } from './http'; + +function expectAuthenticateCall( + mockClusterClient: jest.Mocked, + scopeableRequest: ScopeableRequest +) { + expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); + expect(mockClusterClient.asScoped).toHaveBeenCalledWith(scopeableRequest); + + const mockScopedClusterClient = mockClusterClient.asScoped.mock.results[0].value; + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); +} + +describe('HTTPAuthenticationProvider', () => { + let mockOptions: MockAuthenticationProviderOptions; + beforeEach(() => { + mockOptions = mockAuthenticationProviderOptions(); + }); + + it('throws if `schemes` are not specified', () => { + const providerOptions = mockAuthenticationProviderOptions(); + + expect(() => new HTTPAuthenticationProvider(providerOptions, undefined as any)).toThrowError( + 'Supported schemes should be specified' + ); + expect(() => new HTTPAuthenticationProvider(providerOptions, {} as any)).toThrowError( + 'Supported schemes should be specified' + ); + expect( + () => new HTTPAuthenticationProvider(providerOptions, { supportedSchemes: new Set() }) + ).toThrowError('Supported schemes should be specified'); + }); + + describe('`login` method', () => { + it('does not handle login', async () => { + const provider = new HTTPAuthenticationProvider(mockOptions, { + supportedSchemes: new Set(['apikey']), + }); + + await expect(provider.login()).resolves.toEqual(AuthenticationResult.notHandled()); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); + }); + }); + + describe('`authenticate` method', () => { + it('does not handle authentication for requests without `authorization` header.', async () => { + const provider = new HTTPAuthenticationProvider(mockOptions, { + supportedSchemes: new Set(['apikey']), + }); + + await expect(provider.authenticate(httpServerMock.createKibanaRequest())).resolves.toEqual( + AuthenticationResult.notHandled() + ); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); + }); + + it('does not handle authentication for requests with empty scheme in `authorization` header.', async () => { + const provider = new HTTPAuthenticationProvider(mockOptions, { + supportedSchemes: new Set(['apikey']), + }); + + await expect( + provider.authenticate( + httpServerMock.createKibanaRequest({ headers: { authorization: '' } }) + ) + ).resolves.toEqual(AuthenticationResult.notHandled()); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); + }); + + it('does not handle authentication via `authorization` header if scheme is not supported.', async () => { + for (const { schemes, header } of [ + { schemes: ['basic'], header: 'Bearer xxx' }, + { schemes: ['bearer'], header: 'Basic xxx' }, + { schemes: ['basic', 'apikey'], header: 'Bearer xxx' }, + { schemes: ['basic', 'bearer'], header: 'ApiKey xxx' }, + ]) { + const request = httpServerMock.createKibanaRequest({ headers: { authorization: header } }); + + const provider = new HTTPAuthenticationProvider(mockOptions, { + supportedSchemes: new Set(schemes), + }); + + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); + + expect(request.headers.authorization).toBe(header); + } + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); + }); + + it('succeeds if authentication via `authorization` header with supported scheme succeeds.', async () => { + const user = mockAuthenticatedUser(); + for (const { schemes, header } of [ + { schemes: ['basic'], header: 'Basic xxx' }, + { schemes: ['bearer'], header: 'Bearer xxx' }, + { schemes: ['basic', 'apikey'], header: 'ApiKey xxx' }, + { schemes: ['some-weird-scheme'], header: 'some-weird-scheme xxx' }, + { schemes: ['apikey', 'bearer'], header: 'Bearer xxx' }, + ]) { + const request = httpServerMock.createKibanaRequest({ headers: { authorization: header } }); + + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + mockOptions.client.asScoped.mockClear(); + + const provider = new HTTPAuthenticationProvider(mockOptions, { + supportedSchemes: new Set(schemes), + }); + + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded({ ...user, authentication_provider: 'http' }) + ); + + expectAuthenticateCall(mockOptions.client, { headers: { authorization: header } }); + + expect(request.headers.authorization).toBe(header); + } + }); + + it('fails if authentication via `authorization` header with supported scheme fails.', async () => { + const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + for (const { schemes, header } of [ + { schemes: ['basic'], header: 'Basic xxx' }, + { schemes: ['bearer'], header: 'Bearer xxx' }, + { schemes: ['basic', 'apikey'], header: 'ApiKey xxx' }, + { schemes: ['some-weird-scheme'], header: 'some-weird-scheme xxx' }, + { schemes: ['apikey', 'bearer'], header: 'Bearer xxx' }, + ]) { + const request = httpServerMock.createKibanaRequest({ headers: { authorization: header } }); + + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + mockOptions.client.asScoped.mockClear(); + + const provider = new HTTPAuthenticationProvider(mockOptions, { + supportedSchemes: new Set(schemes), + }); + + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); + + expectAuthenticateCall(mockOptions.client, { headers: { authorization: header } }); + + expect(request.headers.authorization).toBe(header); + } + }); + }); + + describe('`logout` method', () => { + it('does not handle logout', async () => { + const provider = new HTTPAuthenticationProvider(mockOptions, { + supportedSchemes: new Set(['apikey']), + }); + + await expect(provider.logout()).resolves.toEqual(DeauthenticationResult.notHandled()); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); + }); + }); + + it('`getHTTPAuthenticationScheme` method', () => { + const provider = new HTTPAuthenticationProvider(mockOptions, { + supportedSchemes: new Set(['apikey']), + }); + expect(provider.getHTTPAuthenticationScheme()).toBeNull(); + }); +}); diff --git a/x-pack/plugins/security/server/authentication/providers/http.ts b/x-pack/plugins/security/server/authentication/providers/http.ts new file mode 100644 index 0000000000000..57163bf8145b8 --- /dev/null +++ b/x-pack/plugins/security/server/authentication/providers/http.ts @@ -0,0 +1,99 @@ +/* + * 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 { KibanaRequest } from '../../../../../../src/core/server'; +import { AuthenticationResult } from '../authentication_result'; +import { DeauthenticationResult } from '../deauthentication_result'; +import { getHTTPAuthenticationScheme } from '../get_http_authentication_scheme'; +import { AuthenticationProviderOptions, BaseAuthenticationProvider } from './base'; + +interface HTTPAuthenticationProviderOptions { + supportedSchemes: Set; +} + +/** + * Provider that supports request authentication via forwarding `Authorization` HTTP header to Elasticsearch. + */ +export class HTTPAuthenticationProvider extends BaseAuthenticationProvider { + /** + * Type of the provider. + */ + static readonly type = 'http'; + + /** + * Set of the schemes (`Basic`, `Bearer` etc.) that provider expects to see within `Authorization` + * HTTP header while authenticating request. + */ + private readonly supportedSchemes: Set; + + constructor( + protected readonly options: Readonly, + httpOptions: Readonly + ) { + super(options); + + if ((httpOptions?.supportedSchemes?.size ?? 0) === 0) { + throw new Error('Supported schemes should be specified'); + } + this.supportedSchemes = httpOptions.supportedSchemes; + } + + /** + * NOT SUPPORTED. + */ + public async login() { + this.logger.debug('Login is not supported.'); + return AuthenticationResult.notHandled(); + } + + /** + * Performs request authentication using provided `Authorization` HTTP headers. + * @param request Request instance. + */ + public async authenticate(request: KibanaRequest) { + this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); + + const authenticationScheme = getHTTPAuthenticationScheme(request); + if (authenticationScheme == null) { + this.logger.debug('Authorization header is not presented.'); + return AuthenticationResult.notHandled(); + } + + if (!this.supportedSchemes.has(authenticationScheme)) { + this.logger.debug(`Unsupported authentication scheme: ${authenticationScheme}`); + return AuthenticationResult.notHandled(); + } + + try { + const user = await this.getUser(request); + this.logger.debug( + `Request to ${request.url.path} has been authenticated via authorization header with "${authenticationScheme}" scheme.` + ); + return AuthenticationResult.succeeded(user); + } catch (err) { + this.logger.debug( + `Failed to authenticate request to ${request.url.path} via authorization header with "${authenticationScheme}" scheme: ${err.message}` + ); + return AuthenticationResult.failed(err); + } + } + + /** + * NOT SUPPORTED. + */ + public async logout() { + this.logger.debug('Logout is not supported.'); + return DeauthenticationResult.notHandled(); + } + + /** + * Returns `null` since provider doesn't attach any additional `Authorization` HTTP headers to + * successfully authenticated requests to Elasticsearch. + */ + public getHTTPAuthenticationScheme() { + return null; + } +} diff --git a/x-pack/plugins/security/server/authentication/providers/index.ts b/x-pack/plugins/security/server/authentication/providers/index.ts index 1ec6dfb67a81d..cd8f5a70c64e3 100644 --- a/x-pack/plugins/security/server/authentication/providers/index.ts +++ b/x-pack/plugins/security/server/authentication/providers/index.ts @@ -15,3 +15,4 @@ export { SAMLAuthenticationProvider, isSAMLRequestQuery, SAMLLoginStep } from '. export { TokenAuthenticationProvider } from './token'; export { OIDCAuthenticationProvider, OIDCAuthenticationFlow } from './oidc'; export { PKIAuthenticationProvider } from './pki'; +export { HTTPAuthenticationProvider } from './http'; diff --git a/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts b/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts index e4b4df3feeae2..51fb961482e83 100644 --- a/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts @@ -6,18 +6,31 @@ import Boom from 'boom'; import { errors } from 'elasticsearch'; -import sinon from 'sinon'; -import { httpServerMock } from '../../../../../../src/core/server/mocks'; +import { elasticsearchServiceMock, httpServerMock } from '../../../../../../src/core/server/mocks'; import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock'; -import { - MockAuthenticationProviderOptions, - mockAuthenticationProviderOptions, - mockScopedClusterClient, -} from './base.mock'; +import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; +import { + ElasticsearchErrorHelpers, + IClusterClient, + ScopeableRequest, +} from '../../../../../../src/core/server'; +import { AuthenticationResult } from '../authentication_result'; +import { DeauthenticationResult } from '../deauthentication_result'; import { KerberosAuthenticationProvider } from './kerberos'; -import { ElasticsearchErrorHelpers } from '../../../../../../src/core/server/elasticsearch'; + +function expectAuthenticateCall( + mockClusterClient: jest.Mocked, + scopeableRequest: ScopeableRequest +) { + expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); + expect(mockClusterClient.asScoped).toHaveBeenCalledWith(scopeableRequest); + + const mockScopedClusterClient = mockClusterClient.asScoped.mock.results[0].value; + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); +} describe('KerberosAuthenticationProvider', () => { let provider: KerberosAuthenticationProvider; @@ -28,104 +41,128 @@ describe('KerberosAuthenticationProvider', () => { }); describe('`authenticate` method', () => { - it('does not handle `authorization` header with unsupported schema even if state contains a valid token.', async () => { + it('does not handle authentication via `authorization` header with non-negotiate scheme.', async () => { + const request = httpServerMock.createKibanaRequest({ + headers: { authorization: 'Bearer some-token' }, + }); + + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe('Bearer some-token'); + }); + + it('does not handle authentication via `authorization` header with non-negotiate scheme even if state contains a valid token.', async () => { const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Basic some:credentials' }, + headers: { authorization: 'Bearer some-token' }, }); const tokenPair = { accessToken: 'some-valid-token', refreshToken: 'some-valid-refresh-token', }; - const authenticationResult = await provider.authenticate(request, tokenPair); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.notHandled() + ); - sinon.assert.notCalled(mockOptions.client.asScoped); - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); - expect(request.headers.authorization).toBe('Basic some:credentials'); - expect(authenticationResult.notHandled()).toBe(true); + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe('Bearer some-token'); }); it('does not handle requests that can be authenticated without `Negotiate` header.', async () => { - const request = httpServerMock.createKibanaRequest(); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ - headers: { authorization: `Negotiate ${Buffer.from('__fake__').toString('base64')}` }, - }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves({}); + const request = httpServerMock.createKibanaRequest({ headers: {} }); - const authenticationResult = await provider.authenticate(request, null); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue({}); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.notHandled() + ); - expect(authenticationResult.notHandled()).toBe(true); + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: `Negotiate ${Buffer.from('__fake__').toString('base64')}` }, + }); }); it('does not handle requests if backend does not support Kerberos.', async () => { - const request = httpServerMock.createKibanaRequest(); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ - headers: { authorization: `Negotiate ${Buffer.from('__fake__').toString('base64')}` }, - }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error())); + const request = httpServerMock.createKibanaRequest({ headers: {} }); + + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.notHandled() + ); - const authenticationResult = await provider.authenticate(request, null); - expect(authenticationResult.notHandled()).toBe(true); + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: `Negotiate ${Buffer.from('__fake__').toString('base64')}` }, + }); }); it('fails if state is present, but backend does not support Kerberos.', async () => { const request = httpServerMock.createKibanaRequest(); const tokenPair = { accessToken: 'token', refreshToken: 'refresh-token' }; - mockScopedClusterClient(mockOptions.client) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error())); - mockOptions.tokens.refresh.withArgs(tokenPair.refreshToken).resolves(null); + const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + mockOptions.tokens.refresh.mockResolvedValue(null); + + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); - const authenticationResult = await provider.authenticate(request, tokenPair); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toHaveProperty('output.statusCode', 401); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); }); it('fails with `Negotiate` challenge if backend supports Kerberos.', async () => { - const request = httpServerMock.createKibanaRequest(); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ - headers: { authorization: `Negotiate ${Buffer.from('__fake__').toString('base64')}` }, + const request = httpServerMock.createKibanaRequest({ headers: {} }); + + const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError( + new (errors.AuthenticationException as any)('Unauthorized', { + body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects( - ElasticsearchErrorHelpers.decorateNotAuthorizedError( - new (errors.AuthenticationException as any)('Unauthorized', { - body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, - }) - ) - ); - - const authenticationResult = await provider.authenticate(request, null); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toHaveProperty('output.statusCode', 401); - expect(authenticationResult.authResponseHeaders).toEqual({ 'WWW-Authenticate': 'Negotiate' }); + ); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.failed(failureReason, { + authResponseHeaders: { 'WWW-Authenticate': 'Negotiate' }, + }) + ); + + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: `Negotiate ${Buffer.from('__fake__').toString('base64')}` }, + }); }); it('fails if request authentication is failed with non-401 error.', async () => { - const request = httpServerMock.createKibanaRequest(); - mockScopedClusterClient(mockOptions.client) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(new errors.ServiceUnavailable()); + const request = httpServerMock.createKibanaRequest({ headers: {} }); + + const failureReason = new errors.ServiceUnavailable(); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - const authenticationResult = await provider.authenticate(request, null); + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toHaveProperty('status', 503); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: `Negotiate ${Buffer.from('__fake__').toString('base64')}` }, + }); }); it('gets a token pair in exchange to SPNEGO one and stores it in the state.', async () => { @@ -134,34 +171,33 @@ describe('KerberosAuthenticationProvider', () => { headers: { authorization: 'negotiate spnego' }, }); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer some-token' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + mockOptions.client.callAsInternalUser.mockResolvedValue({ + access_token: 'some-token', + refresh_token: 'some-refresh-token', + }); - mockOptions.client.callAsInternalUser - .withArgs('shield.getAccessToken') - .resolves({ access_token: 'some-token', refresh_token: 'some-refresh-token' }); + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'kerberos' }, + { + authHeaders: { authorization: 'Bearer some-token' }, + state: { accessToken: 'some-token', refreshToken: 'some-refresh-token' }, + } + ) + ); - const authenticationResult = await provider.authenticate(request); + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: 'Bearer some-token' }, + }); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.getAccessToken', - { body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' } } - ); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.getAccessToken', { + body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' }, + }); expect(request.headers.authorization).toBe('negotiate spnego'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'kerberos' }); - expect(authenticationResult.authHeaders).toEqual({ authorization: 'Bearer some-token' }); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); - expect(authenticationResult.state).toEqual({ - accessToken: 'some-token', - refreshToken: 'some-refresh-token', - }); }); it('requests auth response header if token pair is complemented with Kerberos response token.', async () => { @@ -170,38 +206,35 @@ describe('KerberosAuthenticationProvider', () => { headers: { authorization: 'negotiate spnego' }, }); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer some-token' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - mockOptions.client.callAsInternalUser.withArgs('shield.getAccessToken').resolves({ + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + mockOptions.client.callAsInternalUser.mockResolvedValue({ access_token: 'some-token', refresh_token: 'some-refresh-token', kerberos_authentication_response_token: 'response-token', }); - const authenticationResult = await provider.authenticate(request); - - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.getAccessToken', - { body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' } } + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'kerberos' }, + { + authHeaders: { authorization: 'Bearer some-token' }, + authResponseHeaders: { 'WWW-Authenticate': 'Negotiate response-token' }, + state: { accessToken: 'some-token', refreshToken: 'some-refresh-token' }, + } + ) ); - expect(request.headers.authorization).toBe('negotiate spnego'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'kerberos' }); - expect(authenticationResult.authHeaders).toEqual({ authorization: 'Bearer some-token' }); - expect(authenticationResult.authResponseHeaders).toEqual({ - 'WWW-Authenticate': 'Negotiate response-token', + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: 'Bearer some-token' }, }); - expect(authenticationResult.state).toEqual({ - accessToken: 'some-token', - refreshToken: 'some-refresh-token', + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.getAccessToken', { + body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' }, }); + + expect(request.headers.authorization).toBe('negotiate spnego'); }); it('fails with `Negotiate response-token` if cannot complete context with a response token.', async () => { @@ -214,24 +247,19 @@ describe('KerberosAuthenticationProvider', () => { body: { error: { header: { 'WWW-Authenticate': 'Negotiate response-token' } } }, }) ); - mockOptions.client.callAsInternalUser - .withArgs('shield.getAccessToken') - .rejects(failureReason); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); - const authenticationResult = await provider.authenticate(request); - - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.getAccessToken', - { body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' } } + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(Boom.unauthorized(), { + authResponseHeaders: { 'WWW-Authenticate': 'Negotiate response-token' }, + }) ); - expect(request.headers.authorization).toBe('negotiate spnego'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toEqual(Boom.unauthorized()); - expect(authenticationResult.authResponseHeaders).toEqual({ - 'WWW-Authenticate': 'Negotiate response-token', + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.getAccessToken', { + body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' }, }); + + expect(request.headers.authorization).toBe('negotiate spnego'); }); it('fails with `Negotiate` if cannot create context using provided SPNEGO token.', async () => { @@ -244,24 +272,19 @@ describe('KerberosAuthenticationProvider', () => { body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, }) ); - mockOptions.client.callAsInternalUser - .withArgs('shield.getAccessToken') - .rejects(failureReason); - - const authenticationResult = await provider.authenticate(request); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.getAccessToken', - { body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' } } + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(Boom.unauthorized(), { + authResponseHeaders: { 'WWW-Authenticate': 'Negotiate' }, + }) ); - expect(request.headers.authorization).toBe('negotiate spnego'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toEqual(Boom.unauthorized()); - expect(authenticationResult.authResponseHeaders).toEqual({ - 'WWW-Authenticate': 'Negotiate', + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.getAccessToken', { + body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' }, }); + + expect(request.headers.authorization).toBe('negotiate spnego'); }); it('fails if could not retrieve an access token in exchange to SPNEGO one.', async () => { @@ -270,22 +293,17 @@ describe('KerberosAuthenticationProvider', () => { }); const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); - mockOptions.client.callAsInternalUser - .withArgs('shield.getAccessToken') - .rejects(failureReason); - - const authenticationResult = await provider.authenticate(request); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.getAccessToken', - { body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' } } + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(failureReason) ); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.getAccessToken', { + body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' }, + }); + expect(request.headers.authorization).toBe('negotiate spnego'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); }); it('fails if could not retrieve user using the new access token.', async () => { @@ -294,51 +312,52 @@ describe('KerberosAuthenticationProvider', () => { }); const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer some-token' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(failureReason); - - mockOptions.client.callAsInternalUser - .withArgs('shield.getAccessToken') - .resolves({ access_token: 'some-token', refresh_token: 'some-refresh-token' }); - - const authenticationResult = await provider.authenticate(request); - - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.getAccessToken', - { body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' } } + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + mockOptions.client.callAsInternalUser.mockResolvedValue({ + access_token: 'some-token', + refresh_token: 'some-refresh-token', + }); + + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(failureReason) ); + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: 'Bearer some-token' }, + }); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.getAccessToken', { + body: { grant_type: '_kerberos', kerberos_ticket: 'spnego' }, + }); + expect(request.headers.authorization).toBe('negotiate spnego'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); }); it('succeeds if state contains a valid token.', async () => { const user = mockAuthenticatedUser(); - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const tokenPair = { accessToken: 'some-valid-token', refreshToken: 'some-valid-refresh-token', }; const authorization = `Bearer ${tokenPair.accessToken}`; - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'kerberos' }, + { authHeaders: { authorization } } + ) + ); - const authenticationResult = await provider.authenticate(request, tokenPair); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toEqual({ authorization }); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'kerberos' }); - expect(authenticationResult.state).toBeUndefined(); }); it('succeeds with valid session even if requiring a token refresh', async () => { @@ -346,149 +365,94 @@ describe('KerberosAuthenticationProvider', () => { const request = httpServerMock.createKibanaRequest(); const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error())); - - mockOptions.tokens.refresh - .withArgs(tokenPair.refreshToken) - .resolves({ accessToken: 'newfoo', refreshToken: 'newbar' }); + mockOptions.client.asScoped.mockImplementation(scopeableRequest => { + if (scopeableRequest?.headers.authorization === `Bearer ${tokenPair.accessToken}`) { + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + return mockScopedClusterClient; + } + + if (scopeableRequest?.headers.authorization === 'Bearer newfoo') { + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + return mockScopedClusterClient; + } + + throw new Error('Unexpected call'); + }); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer newfoo' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + mockOptions.tokens.refresh.mockResolvedValue({ + accessToken: 'newfoo', + refreshToken: 'newbar', + }); - const authenticationResult = await provider.authenticate(request, tokenPair); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'kerberos' }, + { + authHeaders: { authorization: 'Bearer newfoo' }, + state: { accessToken: 'newfoo', refreshToken: 'newbar' }, + } + ) + ); - sinon.assert.calledOnce(mockOptions.tokens.refresh); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toEqual({ authorization: 'Bearer newfoo' }); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'kerberos' }); - expect(authenticationResult.state).toEqual({ accessToken: 'newfoo', refreshToken: 'newbar' }); expect(request.headers).not.toHaveProperty('authorization'); }); it('fails if token from the state is rejected because of unknown reason.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const tokenPair = { accessToken: 'some-valid-token', refreshToken: 'some-valid-refresh-token', }; const failureReason = new errors.InternalServerError('Token is not valid!'); - const scopedClusterClient = mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.failed(failureReason) ); - scopedClusterClient.callAsCurrentUser.withArgs('shield.authenticate').rejects(failureReason); - const authenticationResult = await provider.authenticate(request, tokenPair); + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: `Bearer ${tokenPair.accessToken}` }, + }); + + expect(mockScopedClusterClient.callAsInternalUser).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); - sinon.assert.neverCalledWith(scopedClusterClient.callAsCurrentUser, 'shield.getAccessToken'); }); it('fails with `Negotiate` challenge if both access and refresh tokens from the state are expired and backend supports Kerberos.', async () => { const request = httpServerMock.createKibanaRequest(); const tokenPair = { accessToken: 'expired-token', refreshToken: 'some-valid-refresh-token' }; - mockScopedClusterClient(mockOptions.client) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects( - ElasticsearchErrorHelpers.decorateNotAuthorizedError( - new (errors.AuthenticationException as any)('Unauthorized', { - body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, - }) - ) - ); - mockOptions.tokens.refresh.withArgs(tokenPair.refreshToken).resolves(null); - - const authenticationResult = await provider.authenticate(request, tokenPair); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toHaveProperty('output.statusCode', 401); - expect(authenticationResult.authResponseHeaders).toEqual({ 'WWW-Authenticate': 'Negotiate' }); - }); - - it('succeeds if `authorization` contains a valid token.', async () => { - const user = mockAuthenticatedUser(); - const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Bearer some-valid-token' }, - }); - - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer some-valid-token' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - const authenticationResult = await provider.authenticate(request); - - expect(request.headers.authorization).toBe('Bearer some-valid-token'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toBeUndefined(); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'kerberos' }); - expect(authenticationResult.state).toBeUndefined(); - }); - - it('fails if token from `authorization` header is rejected.', async () => { - const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Bearer some-invalid-token' }, - }); - - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer some-invalid-token' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(failureReason); - - const authenticationResult = await provider.authenticate(request); + const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError( + new (errors.AuthenticationException as any)('Unauthorized', { + body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, + }) + ); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); - }); + mockOptions.tokens.refresh.mockResolvedValue(null); - it('fails if token from `authorization` header is rejected even if state contains a valid one.', async () => { - const user = mockAuthenticatedUser(); - const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Bearer some-invalid-token' }, - }); - const tokenPair = { - accessToken: 'some-valid-token', - refreshToken: 'some-valid-refresh-token', - }; + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.failed(failureReason, { + authResponseHeaders: { 'WWW-Authenticate': 'Negotiate' }, + }) + ); - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer some-invalid-token' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(failureReason); - - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - const authenticationResult = await provider.authenticate(request, tokenPair); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); }); }); @@ -496,13 +460,13 @@ describe('KerberosAuthenticationProvider', () => { it('returns `notHandled` if state is not presented.', async () => { const request = httpServerMock.createKibanaRequest(); - let deauthenticateResult = await provider.logout(request); - expect(deauthenticateResult.notHandled()).toBe(true); + await expect(provider.logout(request)).resolves.toEqual(DeauthenticationResult.notHandled()); - deauthenticateResult = await provider.logout(request, null); - expect(deauthenticateResult.notHandled()).toBe(true); + await expect(provider.logout(request, null)).resolves.toEqual( + DeauthenticationResult.notHandled() + ); - sinon.assert.notCalled(mockOptions.tokens.invalidate); + expect(mockOptions.tokens.invalidate).not.toHaveBeenCalled(); }); it('fails if `tokens.invalidate` fails', async () => { @@ -510,15 +474,14 @@ describe('KerberosAuthenticationProvider', () => { const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; const failureReason = new Error('failed to delete token'); - mockOptions.tokens.invalidate.withArgs(tokenPair).rejects(failureReason); - - const authenticationResult = await provider.logout(request, tokenPair); + mockOptions.tokens.invalidate.mockRejectedValue(failureReason); - sinon.assert.calledOnce(mockOptions.tokens.invalidate); - sinon.assert.calledWithExactly(mockOptions.tokens.invalidate, tokenPair); + await expect(provider.logout(request, tokenPair)).resolves.toEqual( + DeauthenticationResult.failed(failureReason) + ); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith(tokenPair); }); it('redirects to `/logged_out` page if tokens are invalidated successfully.', async () => { @@ -528,15 +491,18 @@ describe('KerberosAuthenticationProvider', () => { refreshToken: 'some-valid-refresh-token', }; - mockOptions.tokens.invalidate.withArgs(tokenPair).resolves(); - - const authenticationResult = await provider.logout(request, tokenPair); + mockOptions.tokens.invalidate.mockResolvedValue(undefined); - sinon.assert.calledOnce(mockOptions.tokens.invalidate); - sinon.assert.calledWithExactly(mockOptions.tokens.invalidate, tokenPair); + await expect(provider.logout(request, tokenPair)).resolves.toEqual( + DeauthenticationResult.redirectTo('/mock-server-basepath/logged_out') + ); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith(tokenPair); }); }); + + it('`getHTTPAuthenticationScheme` method', () => { + expect(provider.getHTTPAuthenticationScheme()).toBe('bearer'); + }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/kerberos.ts b/x-pack/plugins/security/server/authentication/providers/kerberos.ts index b8e3b7bc23790..b6474a5e1d471 100644 --- a/x-pack/plugins/security/server/authentication/providers/kerberos.ts +++ b/x-pack/plugins/security/server/authentication/providers/kerberos.ts @@ -12,27 +12,15 @@ import { } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; -import { BaseAuthenticationProvider } from './base'; +import { getHTTPAuthenticationScheme } from '../get_http_authentication_scheme'; import { Tokens, TokenPair } from '../tokens'; +import { BaseAuthenticationProvider } from './base'; /** * The state supported by the provider. */ type ProviderState = TokenPair; -/** - * Parses request's `Authorization` HTTP header if present and extracts authentication scheme. - * @param request Request instance to extract authentication scheme for. - */ -function getRequestAuthenticationScheme(request: KibanaRequest) { - const authorization = request.headers.authorization; - if (!authorization || typeof authorization !== 'string') { - return ''; - } - - return authorization.split(/\s+/)[0].toLowerCase(); -} - /** * Name of the `WWW-Authenticate` we parse out of Elasticsearch responses or/and return to the * client to initiate or continue negotiation. @@ -56,24 +44,15 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { public async authenticate(request: KibanaRequest, state?: ProviderState | null) { this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); - const authenticationScheme = getRequestAuthenticationScheme(request); - if ( - authenticationScheme && - authenticationScheme !== 'negotiate' && - authenticationScheme !== 'bearer' - ) { + const authenticationScheme = getHTTPAuthenticationScheme(request); + if (authenticationScheme && authenticationScheme !== 'negotiate') { this.logger.debug(`Unsupported authentication scheme: ${authenticationScheme}`); return AuthenticationResult.notHandled(); } - let authenticationResult = AuthenticationResult.notHandled(); - if (authenticationScheme) { - // We should get rid of `Bearer` scheme support as soon as Reporting doesn't need it anymore. - authenticationResult = - authenticationScheme === 'bearer' - ? await this.authenticateWithBearerScheme(request) - : await this.authenticateWithNegotiateScheme(request); - } + let authenticationResult = authenticationScheme + ? await this.authenticateWithNegotiateScheme(request) + : AuthenticationResult.notHandled(); if (state && authenticationResult.notHandled()) { authenticationResult = await this.authenticateViaState(request, state); @@ -115,6 +94,14 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { return DeauthenticationResult.redirectTo(`${this.options.basePath.serverBasePath}/logged_out`); } + /** + * Returns HTTP authentication scheme (`Bearer`) that's used within `Authorization` HTTP header + * that provider attaches to all successfully authenticated requests to Elasticsearch. + */ + public getHTTPAuthenticationScheme() { + return 'bearer'; + } + /** * Tries to authenticate request with `Negotiate ***` Authorization header by passing it to the Elasticsearch backend to * get an access token in exchange. @@ -201,26 +188,6 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { } } - /** - * Tries to authenticate request with `Bearer ***` Authorization header by passing it to the Elasticsearch backend. - * @param request Request instance. - */ - private async authenticateWithBearerScheme(request: KibanaRequest) { - this.logger.debug('Trying to authenticate request using "Bearer" authentication scheme.'); - - try { - const user = await this.getUser(request); - - this.logger.debug('Request has been authenticated using "Bearer" authentication scheme.'); - return AuthenticationResult.succeeded(user); - } catch (err) { - this.logger.debug( - `Failed to authenticate request using "Bearer" authentication scheme: ${err.message}` - ); - return AuthenticationResult.failed(err); - } - } - /** * Tries to extract access token from state and adds it to the request before it's * forwarded to Elasticsearch backend. diff --git a/x-pack/plugins/security/server/authentication/providers/oidc.test.ts b/x-pack/plugins/security/server/authentication/providers/oidc.test.ts index dae3774955859..51a25825bf985 100644 --- a/x-pack/plugins/security/server/authentication/providers/oidc.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/oidc.test.ts @@ -4,20 +4,34 @@ * you may not use this file except in compliance with the Elastic License. */ -import sinon from 'sinon'; import Boom from 'boom'; -import { httpServerMock } from '../../../../../../src/core/server/mocks'; +import { elasticsearchServiceMock, httpServerMock } from '../../../../../../src/core/server/mocks'; import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock'; -import { - MockAuthenticationProviderOptions, - mockAuthenticationProviderOptions, - mockScopedClusterClient, -} from './base.mock'; +import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; -import { KibanaRequest } from '../../../../../../src/core/server'; +import { + ElasticsearchErrorHelpers, + IClusterClient, + KibanaRequest, + ScopeableRequest, +} from '../../../../../../src/core/server'; +import { AuthenticationResult } from '../authentication_result'; +import { DeauthenticationResult } from '../deauthentication_result'; import { OIDCAuthenticationProvider, OIDCAuthenticationFlow, ProviderLoginAttempt } from './oidc'; +function expectAuthenticateCall( + mockClusterClient: jest.Mocked, + scopeableRequest: ScopeableRequest +) { + expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); + expect(mockClusterClient.asScoped).toHaveBeenCalledWith(scopeableRequest); + + const mockScopedClusterClient = mockClusterClient.asScoped.mock.results[0].value; + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); +} + describe('OIDCAuthenticationProvider', () => { let provider: OIDCAuthenticationProvider; let mockOptions: MockAuthenticationProviderOptions; @@ -44,7 +58,7 @@ describe('OIDCAuthenticationProvider', () => { it('redirects third party initiated login attempts to the OpenId Connect Provider.', async () => { const request = httpServerMock.createKibanaRequest({ path: '/api/security/oidc/callback' }); - mockOptions.client.callAsInternalUser.withArgs('shield.oidcPrepare').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ state: 'statevalue', nonce: 'noncevalue', redirect: @@ -56,30 +70,27 @@ describe('OIDCAuthenticationProvider', () => { '&login_hint=loginhint', }); - const authenticationResult = await provider.login(request, { - flow: OIDCAuthenticationFlow.InitiatedBy3rdParty, - iss: 'theissuer', - loginHint: 'loginhint', - }); + await expect( + provider.login(request, { + flow: OIDCAuthenticationFlow.InitiatedBy3rdParty, + iss: 'theissuer', + loginHint: 'loginhint', + }) + ).resolves.toEqual( + AuthenticationResult.redirectTo( + 'https://op-host/path/login?response_type=code' + + '&scope=openid%20profile%20email' + + '&client_id=s6BhdRkqt3' + + '&state=statevalue' + + '&redirect_uri=https%3A%2F%2Ftest-hostname:1234%2Ftest-base-path%2Fapi%2Fsecurity%2Fv1%2F/oidc' + + '&login_hint=loginhint', + { state: { state: 'statevalue', nonce: 'noncevalue', nextURL: '/base-path/' } } + ) + ); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.oidcPrepare', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.oidcPrepare', { body: { iss: 'theissuer', login_hint: 'loginhint' }, }); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - 'https://op-host/path/login?response_type=code' + - '&scope=openid%20profile%20email' + - '&client_id=s6BhdRkqt3' + - '&state=statevalue' + - '&redirect_uri=https%3A%2F%2Ftest-hostname:1234%2Ftest-base-path%2Fapi%2Fsecurity%2Fv1%2F/oidc' + - '&login_hint=loginhint' - ); - expect(authenticationResult.state).toEqual({ - state: 'statevalue', - nonce: 'noncevalue', - nextURL: '/base-path/', - }); }); function defineAuthenticationFlowTests( @@ -92,18 +103,24 @@ describe('OIDCAuthenticationProvider', () => { it('gets token and redirects user to requested URL if OIDC authentication response is valid.', async () => { const { request, attempt, expectedRedirectURI } = getMocks(); - mockOptions.client.callAsInternalUser - .withArgs('shield.oidcAuthenticate') - .resolves({ access_token: 'some-token', refresh_token: 'some-refresh-token' }); - - const authenticationResult = await provider.login(request, attempt, { - state: 'statevalue', - nonce: 'noncevalue', - nextURL: '/base-path/some-path', + mockOptions.client.callAsInternalUser.mockResolvedValue({ + access_token: 'some-token', + refresh_token: 'some-refresh-token', }); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, + await expect( + provider.login(request, attempt, { + state: 'statevalue', + nonce: 'noncevalue', + nextURL: '/base-path/some-path', + }) + ).resolves.toEqual( + AuthenticationResult.redirectTo('/base-path/some-path', { + state: { accessToken: 'some-token', refreshToken: 'some-refresh-token' }, + }) + ); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith( 'shield.oidcAuthenticate', { body: { @@ -114,58 +131,52 @@ describe('OIDCAuthenticationProvider', () => { }, } ); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/base-path/some-path'); - expect(authenticationResult.state).toEqual({ - accessToken: 'some-token', - refreshToken: 'some-refresh-token', - }); }); it('fails if authentication response is presented but session state does not contain the state parameter.', async () => { const { request, attempt } = getMocks(); - const authenticationResult = await provider.login(request, attempt, { - nextURL: '/base-path/some-path', - }); - - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toEqual( - Boom.badRequest( - 'Response session state does not have corresponding state or nonce parameters or redirect URL.' + await expect( + provider.login(request, attempt, { nextURL: '/base-path/some-path' }) + ).resolves.toEqual( + AuthenticationResult.failed( + Boom.badRequest( + 'Response session state does not have corresponding state or nonce parameters or redirect URL.' + ) ) ); + + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); it('fails if authentication response is presented but session state does not contain redirect URL.', async () => { const { request, attempt } = getMocks(); - const authenticationResult = await provider.login(request, attempt, { - state: 'statevalue', - nonce: 'noncevalue', - }); - - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toEqual( - Boom.badRequest( - 'Response session state does not have corresponding state or nonce parameters or redirect URL.' + await expect( + provider.login(request, attempt, { state: 'statevalue', nonce: 'noncevalue' }) + ).resolves.toEqual( + AuthenticationResult.failed( + Boom.badRequest( + 'Response session state does not have corresponding state or nonce parameters or redirect URL.' + ) ) ); + + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); it('fails if session state is not presented.', async () => { const { request, attempt } = getMocks(); - const authenticationResult = await provider.login(request, attempt, {}); - - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); + await expect(provider.login(request, attempt, {})).resolves.toEqual( + AuthenticationResult.failed( + Boom.badRequest( + 'Response session state does not have corresponding state or nonce parameters or redirect URL.' + ) + ) + ); - expect(authenticationResult.failed()).toBe(true); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); it('fails if authentication response is not valid.', async () => { @@ -174,18 +185,17 @@ describe('OIDCAuthenticationProvider', () => { const failureReason = new Error( 'Failed to exchange code for Id Token using the Token Endpoint.' ); - mockOptions.client.callAsInternalUser - .withArgs('shield.oidcAuthenticate') - .returns(Promise.reject(failureReason)); - - const authenticationResult = await provider.login(request, attempt, { - state: 'statevalue', - nonce: 'noncevalue', - nextURL: '/base-path/some-path', - }); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, + await expect( + provider.login(request, attempt, { + state: 'statevalue', + nonce: 'noncevalue', + nextURL: '/base-path/some-path', + }) + ).resolves.toEqual(AuthenticationResult.failed(failureReason)); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith( 'shield.oidcAuthenticate', { body: { @@ -196,9 +206,6 @@ describe('OIDCAuthenticationProvider', () => { }, } ); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); } @@ -234,16 +241,15 @@ describe('OIDCAuthenticationProvider', () => { describe('`authenticate` method', () => { it('does not handle AJAX request that can not be authenticated.', async () => { const request = httpServerMock.createKibanaRequest({ headers: { 'kbn-xsrf': 'xsrf' } }); - - const authenticationResult = await provider.authenticate(request, null); - - expect(authenticationResult.notHandled()).toBe(true); + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.notHandled() + ); }); it('redirects non-AJAX request that can not be authenticated to the OpenId Connect Provider.', async () => { const request = httpServerMock.createKibanaRequest({ path: '/s/foo/some-path' }); - mockOptions.client.callAsInternalUser.withArgs('shield.oidcPrepare').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ state: 'statevalue', nonce: 'noncevalue', redirect: @@ -254,84 +260,99 @@ describe('OIDCAuthenticationProvider', () => { '&redirect_uri=https%3A%2F%2Ftest-hostname:1234%2Ftest-base-path%2Fapi%2Fsecurity%2Fv1%2F/oidc', }); - const authenticationResult = await provider.authenticate(request, null); + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.redirectTo( + 'https://op-host/path/login?response_type=code' + + '&scope=openid%20profile%20email' + + '&client_id=s6BhdRkqt3' + + '&state=statevalue' + + '&redirect_uri=https%3A%2F%2Ftest-hostname:1234%2Ftest-base-path%2Fapi%2Fsecurity%2Fv1%2F/oidc', + { + state: { + state: 'statevalue', + nonce: 'noncevalue', + nextURL: '/base-path/s/foo/some-path', + }, + } + ) + ); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.oidcPrepare', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.oidcPrepare', { body: { realm: `oidc1` }, }); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - 'https://op-host/path/login?response_type=code' + - '&scope=openid%20profile%20email' + - '&client_id=s6BhdRkqt3' + - '&state=statevalue' + - '&redirect_uri=https%3A%2F%2Ftest-hostname:1234%2Ftest-base-path%2Fapi%2Fsecurity%2Fv1%2F/oidc' - ); - expect(authenticationResult.state).toEqual({ - state: 'statevalue', - nonce: 'noncevalue', - nextURL: '/base-path/s/foo/some-path', - }); }); it('fails if OpenID Connect authentication request preparation fails.', async () => { const request = httpServerMock.createKibanaRequest({ path: '/some-path' }); const failureReason = new Error('Realm is misconfigured!'); - mockOptions.client.callAsInternalUser - .withArgs('shield.oidcPrepare') - .returns(Promise.reject(failureReason)); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); - const authenticationResult = await provider.authenticate(request, null); + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.oidcPrepare', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.oidcPrepare', { body: { realm: `oidc1` }, }); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); it('succeeds if state contains a valid token.', async () => { const user = mockAuthenticatedUser(); - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const tokenPair = { accessToken: 'some-valid-token', refreshToken: 'some-valid-refresh-token', }; const authorization = `Bearer ${tokenPair.accessToken}`; - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'oidc' }, + { authHeaders: { authorization } } + ) + ); - const authenticationResult = await provider.authenticate(request, tokenPair); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toEqual({ authorization }); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'oidc' }); - expect(authenticationResult.state).toBeUndefined(); }); - it('does not handle `authorization` header with unsupported schema even if state contains a valid token.', async () => { + it('does not handle authentication via `authorization` header.', async () => { const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Basic some:credentials' }, + headers: { authorization: 'Bearer some-token' }, }); - const authenticationResult = await provider.authenticate(request, { - accessToken: 'some-valid-token', - refreshToken: 'some-valid-refresh-token', + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe('Bearer some-token'); + }); + + it('does not handle authentication via `authorization` header even if state contains a valid token.', async () => { + const request = httpServerMock.createKibanaRequest({ + headers: { authorization: 'Bearer some-token' }, }); - sinon.assert.notCalled(mockOptions.client.asScoped); - expect(request.headers.authorization).toBe('Basic some:credentials'); - expect(authenticationResult.notHandled()).toBe(true); + await expect( + provider.authenticate(request, { + accessToken: 'some-valid-token', + refreshToken: 'some-valid-refresh-token', + }) + ).resolves.toEqual(AuthenticationResult.notHandled()); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe('Bearer some-token'); }); it('fails if token from the state is rejected because of unknown reason.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const tokenPair = { accessToken: 'some-invalid-token', refreshToken: 'some-invalid-refresh-token', @@ -339,15 +360,17 @@ describe('OIDCAuthenticationProvider', () => { const authorization = `Bearer ${tokenPair.accessToken}`; const failureReason = new Error('Token is not valid!'); - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(failureReason); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); - const authenticationResult = await provider.authenticate(request, tokenPair); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); it('succeeds if token from the state is expired, but has been successfully refreshed.', async () => { @@ -355,67 +378,80 @@ describe('OIDCAuthenticationProvider', () => { const request = httpServerMock.createKibanaRequest(); const tokenPair = { accessToken: 'expired-token', refreshToken: 'valid-refresh-token' }; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + mockOptions.client.asScoped.mockImplementation(scopeableRequest => { + if (scopeableRequest?.headers.authorization === `Bearer ${tokenPair.accessToken}`) { + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + return mockScopedClusterClient; + } + + if (scopeableRequest?.headers.authorization === 'Bearer new-access-token') { + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + return mockScopedClusterClient; + } + + throw new Error('Unexpected call'); + }); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer new-access-token' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + mockOptions.tokens.refresh.mockResolvedValue({ + accessToken: 'new-access-token', + refreshToken: 'new-refresh-token', + }); - mockOptions.tokens.refresh - .withArgs(tokenPair.refreshToken) - .resolves({ accessToken: 'new-access-token', refreshToken: 'new-refresh-token' }); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'oidc' }, + { + authHeaders: { authorization: 'Bearer new-access-token' }, + state: { accessToken: 'new-access-token', refreshToken: 'new-refresh-token' }, + } + ) + ); - const authenticationResult = await provider.authenticate(request, tokenPair); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toEqual({ - authorization: 'Bearer new-access-token', - }); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'oidc' }); - expect(authenticationResult.state).toEqual({ - accessToken: 'new-access-token', - refreshToken: 'new-refresh-token', - }); }); it('fails if token from the state is expired and refresh attempt failed too.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const tokenPair = { accessToken: 'expired-token', refreshToken: 'invalid-refresh-token' }; + const authorization = `Bearer ${tokenPair.accessToken}`; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); const refreshFailureReason = { statusCode: 500, message: 'Something is wrong with refresh token.', }; - mockOptions.tokens.refresh.withArgs(tokenPair.refreshToken).rejects(refreshFailureReason); + mockOptions.tokens.refresh.mockRejectedValue(refreshFailureReason); - const authenticationResult = await provider.authenticate(request, tokenPair); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.failed(refreshFailureReason as any) + ); + + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); + + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(refreshFailureReason); }); it('redirects to OpenID Connect Provider for non-AJAX requests if refresh token is expired or already refreshed.', async () => { - const request = httpServerMock.createKibanaRequest({ path: '/s/foo/some-path' }); + const request = httpServerMock.createKibanaRequest({ path: '/s/foo/some-path', headers: {} }); const tokenPair = { accessToken: 'expired-token', refreshToken: 'expired-refresh-token' }; + const authorization = `Bearer ${tokenPair.accessToken}`; - mockOptions.client.callAsInternalUser.withArgs('shield.oidcPrepare').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ state: 'statevalue', nonce: 'noncevalue', redirect: @@ -426,115 +462,71 @@ describe('OIDCAuthenticationProvider', () => { '&redirect_uri=https%3A%2F%2Ftest-hostname:1234%2Ftest-base-path%2Fapi%2Fsecurity%2Fv1%2F/oidc', }); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - mockOptions.tokens.refresh.withArgs(tokenPair.refreshToken).resolves(null); + mockOptions.tokens.refresh.mockResolvedValue(null); - const authenticationResult = await provider.authenticate(request, tokenPair); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.redirectTo( + 'https://op-host/path/login?response_type=code' + + '&scope=openid%20profile%20email' + + '&client_id=s6BhdRkqt3' + + '&state=statevalue' + + '&redirect_uri=https%3A%2F%2Ftest-hostname:1234%2Ftest-base-path%2Fapi%2Fsecurity%2Fv1%2F/oidc', + { + state: { + state: 'statevalue', + nonce: 'noncevalue', + nextURL: '/base-path/s/foo/some-path', + }, + } + ) + ); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.oidcPrepare', { - body: { realm: `oidc1` }, + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); + + expect(mockOptions.client.asScoped).toHaveBeenCalledTimes(1); + expect(mockOptions.client.asScoped).toHaveBeenCalledWith({ + headers: { authorization }, }); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - 'https://op-host/path/login?response_type=code' + - '&scope=openid%20profile%20email' + - '&client_id=s6BhdRkqt3' + - '&state=statevalue' + - '&redirect_uri=https%3A%2F%2Ftest-hostname:1234%2Ftest-base-path%2Fapi%2Fsecurity%2Fv1%2F/oidc' - ); - expect(authenticationResult.state).toEqual({ - state: 'statevalue', - nonce: 'noncevalue', - nextURL: '/base-path/s/foo/some-path', + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.oidcPrepare', { + body: { realm: `oidc1` }, }); }); it('fails for AJAX requests with user friendly message if refresh token is expired.', async () => { const request = httpServerMock.createKibanaRequest({ headers: { 'kbn-xsrf': 'xsrf' } }); const tokenPair = { accessToken: 'expired-token', refreshToken: 'expired-refresh-token' }; + const authorization = `Bearer ${tokenPair.accessToken}`; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); - - mockOptions.tokens.refresh.withArgs(tokenPair.refreshToken).resolves(null); - - const authenticationResult = await provider.authenticate(request, tokenPair); - - expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toEqual( - Boom.badRequest('Both access and refresh tokens are expired.') + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); - }); - - it('succeeds if `authorization` contains a valid token.', async () => { - const user = mockAuthenticatedUser(); - const authorization = 'Bearer some-valid-token'; - const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - const authenticationResult = await provider.authenticate(request); + mockOptions.tokens.refresh.mockResolvedValue(null); - expect(request.headers.authorization).toBe('Bearer some-valid-token'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toBeUndefined(); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'oidc' }); - expect(authenticationResult.state).toBeUndefined(); - }); - - it('fails if token from `authorization` header is rejected.', async () => { - const authorization = 'Bearer some-invalid-token'; - const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - - const failureReason = { statusCode: 401 }; - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(failureReason); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.failed(Boom.badRequest('Both access and refresh tokens are expired.')) + ); - const authenticationResult = await provider.authenticate(request); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); - }); - - it('fails if token from `authorization` header is rejected even if state contains a valid one.', async () => { - const user = mockAuthenticatedUser(); - const authorization = 'Bearer some-invalid-token'; - const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - - const failureReason = { statusCode: 401 }; - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(failureReason); - - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer some-valid-token' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - const authenticationResult = await provider.authenticate(request, { - accessToken: 'some-valid-token', - refreshToken: 'some-valid-refresh-token', + expectAuthenticateCall(mockOptions.client, { + headers: { 'kbn-xsrf': 'xsrf', authorization }, }); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); + expect(request.headers).not.toHaveProperty('authorization'); }); }); @@ -542,16 +534,19 @@ describe('OIDCAuthenticationProvider', () => { it('returns `notHandled` if state is not presented or does not include access token.', async () => { const request = httpServerMock.createKibanaRequest(); - let deauthenticateResult = await provider.logout(request, {}); - expect(deauthenticateResult.notHandled()).toBe(true); + await expect(provider.logout(request, undefined as any)).resolves.toEqual( + DeauthenticationResult.notHandled() + ); - deauthenticateResult = await provider.logout(request, {}); - expect(deauthenticateResult.notHandled()).toBe(true); + await expect(provider.logout(request, {})).resolves.toEqual( + DeauthenticationResult.notHandled() + ); - deauthenticateResult = await provider.logout(request, { nonce: 'x' }); - expect(deauthenticateResult.notHandled()).toBe(true); + await expect(provider.logout(request, { nonce: 'x' })).resolves.toEqual( + DeauthenticationResult.notHandled() + ); - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); it('fails if OpenID Connect logout call fails.', async () => { @@ -560,22 +555,16 @@ describe('OIDCAuthenticationProvider', () => { const refreshToken = 'x-oidc-refresh-token'; const failureReason = new Error('Realm is misconfigured!'); - mockOptions.client.callAsInternalUser - .withArgs('shield.oidcLogout') - .returns(Promise.reject(failureReason)); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); - const authenticationResult = await provider.logout(request, { - accessToken, - refreshToken, - }); + await expect(provider.logout(request, { accessToken, refreshToken })).resolves.toEqual( + DeauthenticationResult.failed(failureReason) + ); - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.oidcLogout', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.oidcLogout', { body: { token: accessToken, refresh_token: refreshToken }, }); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); it('redirects to /logged_out if `redirect` field in OpenID Connect logout response is null.', async () => { @@ -583,22 +572,16 @@ describe('OIDCAuthenticationProvider', () => { const accessToken = 'x-oidc-token'; const refreshToken = 'x-oidc-refresh-token'; - mockOptions.client.callAsInternalUser - .withArgs('shield.oidcLogout') - .resolves({ redirect: null }); + mockOptions.client.callAsInternalUser.mockResolvedValue({ redirect: null }); - const authenticationResult = await provider.logout(request, { - accessToken, - refreshToken, - }); + await expect(provider.logout(request, { accessToken, refreshToken })).resolves.toEqual( + DeauthenticationResult.redirectTo('/mock-server-basepath/logged_out') + ); - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.oidcLogout', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.oidcLogout', { body: { token: accessToken, refresh_token: refreshToken }, }); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects user to the OpenID Connect Provider if RP initiated SLO is supported.', async () => { @@ -606,18 +589,22 @@ describe('OIDCAuthenticationProvider', () => { const accessToken = 'x-oidc-token'; const refreshToken = 'x-oidc-refresh-token'; - mockOptions.client.callAsInternalUser - .withArgs('shield.oidcLogout') - .resolves({ redirect: 'http://fake-idp/logout&id_token_hint=thehint' }); - - const authenticationResult = await provider.logout(request, { - accessToken, - refreshToken, + mockOptions.client.callAsInternalUser.mockResolvedValue({ + redirect: 'http://fake-idp/logout&id_token_hint=thehint', }); - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('http://fake-idp/logout&id_token_hint=thehint'); + await expect(provider.logout(request, { accessToken, refreshToken })).resolves.toEqual( + DeauthenticationResult.redirectTo('http://fake-idp/logout&id_token_hint=thehint') + ); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.oidcLogout', { + body: { token: accessToken, refresh_token: refreshToken }, + }); }); }); + + it('`getHTTPAuthenticationScheme` method', () => { + expect(provider.getHTTPAuthenticationScheme()).toBe('bearer'); + }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/oidc.ts b/x-pack/plugins/security/server/authentication/providers/oidc.ts index f13a2ec05231a..c6b504e722adf 100644 --- a/x-pack/plugins/security/server/authentication/providers/oidc.ts +++ b/x-pack/plugins/security/server/authentication/providers/oidc.ts @@ -10,6 +10,7 @@ import { KibanaRequest } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; import { canRedirectRequest } from '../can_redirect_request'; import { DeauthenticationResult } from '../deauthentication_result'; +import { getHTTPAuthenticationScheme } from '../get_http_authentication_scheme'; import { Tokens, TokenPair } from '../tokens'; import { AuthenticationProviderOptions, @@ -130,16 +131,13 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider { public async authenticate(request: KibanaRequest, state?: ProviderState | null) { this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); - // We should get rid of `Bearer` scheme support as soon as Reporting doesn't need it anymore. - let { - authenticationResult, - headerNotRecognized, // eslint-disable-line prefer-const - } = await this.authenticateViaHeader(request); - if (headerNotRecognized) { - return authenticationResult; + if (getHTTPAuthenticationScheme(request) != null) { + this.logger.debug('Cannot authenticate requests with `Authorization` header.'); + return AuthenticationResult.notHandled(); } - if (state && authenticationResult.notHandled()) { + let authenticationResult = AuthenticationResult.notHandled(); + if (state) { authenticationResult = await this.authenticateViaState(request, state); if ( authenticationResult.failed() && @@ -276,46 +274,6 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider { } } - /** - * Validates whether request contains `Bearer ***` Authorization header and just passes it - * forward to Elasticsearch backend. - * @param request Request instance. - */ - private async authenticateViaHeader(request: KibanaRequest) { - this.logger.debug('Trying to authenticate via header.'); - - const authorization = request.headers.authorization; - if (!authorization || typeof authorization !== 'string') { - this.logger.debug('Authorization header is not presented.'); - return { - authenticationResult: AuthenticationResult.notHandled(), - }; - } - - const authenticationSchema = authorization.split(/\s+/)[0]; - if (authenticationSchema.toLowerCase() !== 'bearer') { - this.logger.debug(`Unsupported authentication schema: ${authenticationSchema}`); - return { - authenticationResult: AuthenticationResult.notHandled(), - headerNotRecognized: true, - }; - } - - try { - const user = await this.getUser(request); - - this.logger.debug('Request has been authenticated via header.'); - return { - authenticationResult: AuthenticationResult.succeeded(user), - }; - } catch (err) { - this.logger.debug(`Failed to authenticate request via header: ${err.message}`); - return { - authenticationResult: AuthenticationResult.failed(err), - }; - } - } - /** * Tries to extract an elasticsearch access token from state and adds it to the request before it's * forwarded to Elasticsearch backend. @@ -444,4 +402,12 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider { return DeauthenticationResult.failed(err); } } + + /** + * Returns HTTP authentication scheme (`Bearer`) that's used within `Authorization` HTTP header + * that provider attaches to all successfully authenticated requests to Elasticsearch. + */ + public getHTTPAuthenticationScheme() { + return 'bearer'; + } } diff --git a/x-pack/plugins/security/server/authentication/providers/pki.test.ts b/x-pack/plugins/security/server/authentication/providers/pki.test.ts index a2dda88c4680c..efc286c6c895f 100644 --- a/x-pack/plugins/security/server/authentication/providers/pki.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/pki.test.ts @@ -7,23 +7,23 @@ jest.mock('net'); jest.mock('tls'); +import { Socket } from 'net'; import { PeerCertificate, TLSSocket } from 'tls'; +import Boom from 'boom'; import { errors } from 'elasticsearch'; import { elasticsearchServiceMock, httpServerMock } from '../../../../../../src/core/server/mocks'; import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock'; -import { - MockAuthenticationProviderOptionsWithJest, - mockAuthenticationProviderOptionsWithJest, -} from './base.mock'; +import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; -import { PKIAuthenticationProvider } from './pki'; import { ElasticsearchErrorHelpers, - ScopedClusterClient, -} from '../../../../../../src/core/server/elasticsearch'; -import { Socket } from 'net'; -import { getErrorStatusCode } from '../../errors'; + IClusterClient, + ScopeableRequest, +} from '../../../../../../src/core/server'; +import { AuthenticationResult } from '../authentication_result'; +import { DeauthenticationResult } from '../deauthentication_result'; +import { PKIAuthenticationProvider } from './pki'; interface MockPeerCertificate extends Partial { issuerCertificate: MockPeerCertificate; @@ -62,32 +62,59 @@ function getMockSocket({ return socket; } +function expectAuthenticateCall( + mockClusterClient: jest.Mocked, + scopeableRequest: ScopeableRequest +) { + expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); + expect(mockClusterClient.asScoped).toHaveBeenCalledWith(scopeableRequest); + + const mockScopedClusterClient = mockClusterClient.asScoped.mock.results[0].value; + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); +} + describe('PKIAuthenticationProvider', () => { let provider: PKIAuthenticationProvider; - let mockOptions: MockAuthenticationProviderOptionsWithJest; + let mockOptions: MockAuthenticationProviderOptions; beforeEach(() => { - mockOptions = mockAuthenticationProviderOptionsWithJest(); + mockOptions = mockAuthenticationProviderOptions(); provider = new PKIAuthenticationProvider(mockOptions); }); afterEach(() => jest.clearAllMocks()); describe('`authenticate` method', () => { - it('does not handle `authorization` header with unsupported schema even if state contains a valid token.', async () => { + it('does not handle authentication via `authorization` header.', async () => { + const request = httpServerMock.createKibanaRequest({ + headers: { authorization: 'Bearer some-token' }, + }); + + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe('Bearer some-token'); + }); + + it('does not handle authentication via `authorization` header even if state contains a valid token.', async () => { const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Basic some:credentials' }, + headers: { authorization: 'Bearer some-token' }, }); const state = { accessToken: 'some-valid-token', peerCertificateFingerprint256: '2A:7A:C2:DD', }; - const authenticationResult = await provider.authenticate(request, state); + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.notHandled() + ); expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); - expect(request.headers.authorization).toBe('Basic some:credentials'); - expect(authenticationResult.notHandled()).toBe(true); + expect(request.headers.authorization).toBe('Bearer some-token'); }); it('does not handle requests without certificate.', async () => { @@ -95,9 +122,10 @@ describe('PKIAuthenticationProvider', () => { socket: getMockSocket({ authorized: true }), }); - const authenticationResult = await provider.authenticate(request, null); + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.notHandled() + ); - expect(authenticationResult.notHandled()).toBe(true); expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); @@ -107,9 +135,10 @@ describe('PKIAuthenticationProvider', () => { socket: getMockSocket({ peerCertificate: getMockPeerCertificate('2A:7A:C2:DD') }), }); - const authenticationResult = await provider.authenticate(request, null); + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.notHandled() + ); - expect(authenticationResult.notHandled()).toBe(true); expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); @@ -121,12 +150,10 @@ describe('PKIAuthenticationProvider', () => { const state = { accessToken: 'token', peerCertificateFingerprint256: '2A:7A:C2:DD' }; - const authenticationResult = await provider.authenticate(request, state); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toMatchInlineSnapshot( - `[Error: Peer certificate is not available]` + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.failed(new Error('Peer certificate is not available')) ); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); + expect(mockOptions.tokens.invalidate).not.toHaveBeenCalled(); }); @@ -134,10 +161,9 @@ describe('PKIAuthenticationProvider', () => { const request = httpServerMock.createKibanaRequest({ socket: getMockSocket() }); const state = { accessToken: 'token', peerCertificateFingerprint256: '2A:7A:C2:DD' }; - const authenticationResult = await provider.authenticate(request, state); - - expect(authenticationResult.failed()).toBe(true); - expect(getErrorStatusCode(authenticationResult.error)).toBe(401); + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.failed(Boom.unauthorized()) + ); expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith({ @@ -151,10 +177,9 @@ describe('PKIAuthenticationProvider', () => { }); const state = { accessToken: 'token', peerCertificateFingerprint256: '2A:7A:C2:DD' }; - const authenticationResult = await provider.authenticate(request, state); - - expect(authenticationResult.failed()).toBe(true); - expect(getErrorStatusCode(authenticationResult.error)).toBe(401); + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.failed(Boom.unauthorized()) + ); expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith({ @@ -174,12 +199,18 @@ describe('PKIAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked - ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); mockOptions.client.callAsInternalUser.mockResolvedValue({ access_token: 'access-token' }); - const authenticationResult = await provider.authenticate(request); + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'pki' }, + { + authHeaders: { authorization: 'Bearer access-token' }, + state: { accessToken: 'access-token', peerCertificateFingerprint256: '2A:7A:C2:DD' }, + } + ) + ); expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.delegatePKI', { @@ -191,22 +222,11 @@ describe('PKIAuthenticationProvider', () => { }, }); - expect(mockOptions.client.asScoped).toHaveBeenCalledTimes(1); - expect(mockOptions.client.asScoped).toHaveBeenCalledWith({ - headers: { authorization: `Bearer access-token` }, + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: 'Bearer access-token' }, }); - expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); - expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'pki' }); - expect(authenticationResult.authHeaders).toEqual({ authorization: 'Bearer access-token' }); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); - expect(authenticationResult.state).toEqual({ - accessToken: 'access-token', - peerCertificateFingerprint256: '2A:7A:C2:DD', - }); }); it('gets an access token in exchange to a self-signed certificate and stores it in the state.', async () => { @@ -221,34 +241,29 @@ describe('PKIAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked - ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); mockOptions.client.callAsInternalUser.mockResolvedValue({ access_token: 'access-token' }); - const authenticationResult = await provider.authenticate(request); + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'pki' }, + { + authHeaders: { authorization: 'Bearer access-token' }, + state: { accessToken: 'access-token', peerCertificateFingerprint256: '2A:7A:C2:DD' }, + } + ) + ); expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.delegatePKI', { body: { x509_certificate_chain: ['fingerprint:2A:7A:C2:DD:base64'] }, }); - expect(mockOptions.client.asScoped).toHaveBeenCalledTimes(1); - expect(mockOptions.client.asScoped).toHaveBeenCalledWith({ - headers: { authorization: `Bearer access-token` }, + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: 'Bearer access-token' }, }); - expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); - expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'pki' }); - expect(authenticationResult.authHeaders).toEqual({ authorization: 'Bearer access-token' }); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); - expect(authenticationResult.state).toEqual({ - accessToken: 'access-token', - peerCertificateFingerprint256: '2A:7A:C2:DD', - }); }); it('invalidates existing token and gets a new one if fingerprints do not match.', async () => { @@ -263,12 +278,18 @@ describe('PKIAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked - ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); mockOptions.client.callAsInternalUser.mockResolvedValue({ access_token: 'access-token' }); - const authenticationResult = await provider.authenticate(request, state); + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'pki' }, + { + authHeaders: { authorization: 'Bearer access-token' }, + state: { accessToken: 'access-token', peerCertificateFingerprint256: '2A:7A:C2:DD' }, + } + ) + ); expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith({ @@ -286,14 +307,6 @@ describe('PKIAuthenticationProvider', () => { }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'pki' }); - expect(authenticationResult.authHeaders).toEqual({ authorization: 'Bearer access-token' }); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); - expect(authenticationResult.state).toEqual({ - accessToken: 'access-token', - peerCertificateFingerprint256: '2A:7A:C2:DD', - }); }); it('gets a new access token even if existing token is expired.', async () => { @@ -312,12 +325,18 @@ describe('PKIAuthenticationProvider', () => { .mockRejectedValueOnce(ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error())) // In response to a call with a new token. .mockResolvedValueOnce(user); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked - ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); mockOptions.client.callAsInternalUser.mockResolvedValue({ access_token: 'access-token' }); - const authenticationResult = await provider.authenticate(request, state); + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'pki' }, + { + authHeaders: { authorization: 'Bearer access-token' }, + state: { accessToken: 'access-token', peerCertificateFingerprint256: '2A:7A:C2:DD' }, + } + ) + ); expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.delegatePKI', { @@ -330,14 +349,6 @@ describe('PKIAuthenticationProvider', () => { }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'pki' }); - expect(authenticationResult.authHeaders).toEqual({ authorization: 'Bearer access-token' }); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); - expect(authenticationResult.state).toEqual({ - accessToken: 'access-token', - peerCertificateFingerprint256: '2A:7A:C2:DD', - }); }); it('fails with 401 if existing token is expired, but certificate is not present.', async () => { @@ -348,18 +359,15 @@ describe('PKIAuthenticationProvider', () => { mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked - ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - const authenticationResult = await provider.authenticate(request, state); + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.failed(Boom.unauthorized()) + ); expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(getErrorStatusCode(authenticationResult.error)).toBe(401); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); }); it('fails if could not retrieve an access token in exchange to peer certificate chain.', async () => { @@ -373,7 +381,9 @@ describe('PKIAuthenticationProvider', () => { const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); - const authenticationResult = await provider.authenticate(request); + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.delegatePKI', { @@ -381,9 +391,6 @@ describe('PKIAuthenticationProvider', () => { }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); }); it('fails if could not retrieve user using the new access token.', async () => { @@ -398,35 +405,30 @@ describe('PKIAuthenticationProvider', () => { const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked - ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); mockOptions.client.callAsInternalUser.mockResolvedValue({ access_token: 'access-token' }); - const authenticationResult = await provider.authenticate(request); + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.delegatePKI', { body: { x509_certificate_chain: ['fingerprint:2A:7A:C2:DD:base64'] }, }); - expect(mockOptions.client.asScoped).toHaveBeenCalledTimes(1); - expect(mockOptions.client.asScoped).toHaveBeenCalledWith({ - headers: { authorization: `Bearer access-token` }, + expectAuthenticateCall(mockOptions.client, { + headers: { authorization: 'Bearer access-token' }, }); - expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); - expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); }); it('succeeds if state contains a valid token.', async () => { const user = mockAuthenticatedUser(); const state = { accessToken: 'token', peerCertificateFingerprint256: '2A:7A:C2:DD' }; const request = httpServerMock.createKibanaRequest({ + headers: {}, socket: getMockSocket({ authorized: true, peerCertificate: getMockPeerCertificate(state.peerCertificateFingerprint256), @@ -435,110 +437,42 @@ describe('PKIAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'pki' }, + { authHeaders: { authorization: `Bearer ${state.accessToken}` } } + ) ); - const authenticationResult = await provider.authenticate(request, state); + expectAuthenticateCall(mockOptions.client, { headers: { authorization: 'Bearer token' } }); expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toEqual({ - authorization: `Bearer ${state.accessToken}`, - }); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'pki' }); - expect(authenticationResult.state).toBeUndefined(); }); it('fails if token from the state is rejected because of unknown reason.', async () => { const state = { accessToken: 'token', peerCertificateFingerprint256: '2A:7A:C2:DD' }; const request = httpServerMock.createKibanaRequest({ + headers: {}, socket: getMockSocket({ authorized: true, peerCertificate: getMockPeerCertificate(state.peerCertificateFingerprint256), }), }); - const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); - mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(new errors.ServiceUnavailable()); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked - ); - - const authenticationResult = await provider.authenticate(request, state); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toHaveProperty('status', 503); - expect(authenticationResult.authResponseHeaders).toBeUndefined(); - }); - - it('succeeds if `authorization` contains a valid token.', async () => { - const user = mockAuthenticatedUser(); - const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Bearer some-valid-token' }, - }); - - const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); - mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked - ); - - const authenticationResult = await provider.authenticate(request); - - expect(request.headers.authorization).toBe('Bearer some-valid-token'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toBeUndefined(); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'pki' }); - expect(authenticationResult.state).toBeUndefined(); - }); - - it('fails if token from `authorization` header is rejected.', async () => { - const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Bearer some-invalid-token' }, - }); - - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + const failureReason = new errors.ServiceUnavailable(); const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked - ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - const authenticationResult = await provider.authenticate(request); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); - }); - - it('fails if token from `authorization` header is rejected even if state contains a valid one.', async () => { - const user = mockAuthenticatedUser(); - const state = { accessToken: 'token', peerCertificateFingerprint256: '2A:7A:C2:DD' }; - const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Bearer some-invalid-token' }, - socket: getMockSocket({ - authorized: true, - peerCertificate: getMockPeerCertificate(state.peerCertificateFingerprint256), - }), - }); - - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); - const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); - mockScopedClusterClient.callAsCurrentUser - // In response to call with a token from header. - .mockRejectedValueOnce(failureReason) - // In response to a call with a token from session (not expected to be called). - .mockResolvedValueOnce(user); - mockOptions.client.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.failed(failureReason) ); - const authenticationResult = await provider.authenticate(request, state); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); + expectAuthenticateCall(mockOptions.client, { headers: { authorization: 'Bearer token' } }); }); }); @@ -546,11 +480,11 @@ describe('PKIAuthenticationProvider', () => { it('returns `notHandled` if state is not presented.', async () => { const request = httpServerMock.createKibanaRequest(); - let deauthenticateResult = await provider.logout(request); - expect(deauthenticateResult.notHandled()).toBe(true); + await expect(provider.logout(request)).resolves.toEqual(DeauthenticationResult.notHandled()); - deauthenticateResult = await provider.logout(request, null); - expect(deauthenticateResult.notHandled()).toBe(true); + await expect(provider.logout(request, null)).resolves.toEqual( + DeauthenticationResult.notHandled() + ); expect(mockOptions.tokens.invalidate).not.toHaveBeenCalled(); }); @@ -562,13 +496,12 @@ describe('PKIAuthenticationProvider', () => { const failureReason = new Error('failed to delete token'); mockOptions.tokens.invalidate.mockRejectedValue(failureReason); - const authenticationResult = await provider.logout(request, state); + await expect(provider.logout(request, state)).resolves.toEqual( + DeauthenticationResult.failed(failureReason) + ); expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith({ accessToken: 'foo' }); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); it('redirects to `/logged_out` page if access token is invalidated successfully.', async () => { @@ -577,13 +510,16 @@ describe('PKIAuthenticationProvider', () => { mockOptions.tokens.invalidate.mockResolvedValue(undefined); - const authenticationResult = await provider.logout(request, state); + await expect(provider.logout(request, state)).resolves.toEqual( + DeauthenticationResult.redirectTo('/mock-server-basepath/logged_out') + ); expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith({ accessToken: 'foo' }); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); }); + + it('`getHTTPAuthenticationScheme` method', () => { + expect(provider.getHTTPAuthenticationScheme()).toBe('bearer'); + }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/pki.ts b/x-pack/plugins/security/server/authentication/providers/pki.ts index 6d5aa9f01f2ea..854f92a50fa9d 100644 --- a/x-pack/plugins/security/server/authentication/providers/pki.ts +++ b/x-pack/plugins/security/server/authentication/providers/pki.ts @@ -9,8 +9,9 @@ import { DetailedPeerCertificate } from 'tls'; import { KibanaRequest } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; -import { BaseAuthenticationProvider } from './base'; +import { getHTTPAuthenticationScheme } from '../get_http_authentication_scheme'; import { Tokens } from '../tokens'; +import { BaseAuthenticationProvider } from './base'; /** * The state supported by the provider. @@ -27,19 +28,6 @@ interface ProviderState { peerCertificateFingerprint256: string; } -/** - * Parses request's `Authorization` HTTP header if present and extracts authentication scheme. - * @param request Request instance to extract authentication scheme for. - */ -function getRequestAuthenticationScheme(request: KibanaRequest) { - const authorization = request.headers.authorization; - if (!authorization || typeof authorization !== 'string') { - return ''; - } - - return authorization.split(/\s+/)[0].toLowerCase(); -} - /** * Provider that supports PKI request authentication. */ @@ -57,19 +45,13 @@ export class PKIAuthenticationProvider extends BaseAuthenticationProvider { public async authenticate(request: KibanaRequest, state?: ProviderState | null) { this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); - const authenticationScheme = getRequestAuthenticationScheme(request); - if (authenticationScheme && authenticationScheme !== 'bearer') { - this.logger.debug(`Unsupported authentication scheme: ${authenticationScheme}`); + if (getHTTPAuthenticationScheme(request) != null) { + this.logger.debug('Cannot authenticate requests with `Authorization` header.'); return AuthenticationResult.notHandled(); } let authenticationResult = AuthenticationResult.notHandled(); - if (authenticationScheme) { - // We should get rid of `Bearer` scheme support as soon as Reporting doesn't need it anymore. - authenticationResult = await this.authenticateWithBearerScheme(request); - } - - if (state && authenticationResult.notHandled()) { + if (state) { authenticationResult = await this.authenticateViaState(request, state); // If access token expired or doesn't match to the certificate fingerprint we should try to get @@ -120,23 +102,11 @@ export class PKIAuthenticationProvider extends BaseAuthenticationProvider { } /** - * Tries to authenticate request with `Bearer ***` Authorization header by passing it to the Elasticsearch backend. - * @param request Request instance. + * Returns HTTP authentication scheme (`Bearer`) that's used within `Authorization` HTTP header + * that provider attaches to all successfully authenticated requests to Elasticsearch. */ - private async authenticateWithBearerScheme(request: KibanaRequest) { - this.logger.debug('Trying to authenticate request using "Bearer" authentication scheme.'); - - try { - const user = await this.getUser(request); - - this.logger.debug('Request has been authenticated using "Bearer" authentication scheme.'); - return AuthenticationResult.succeeded(user); - } catch (err) { - this.logger.debug( - `Failed to authenticate request using "Bearer" authentication scheme: ${err.message}` - ); - return AuthenticationResult.failed(err); - } + public getHTTPAuthenticationScheme() { + return 'bearer'; } /** diff --git a/x-pack/plugins/security/server/authentication/providers/saml.test.ts b/x-pack/plugins/security/server/authentication/providers/saml.test.ts index c4fdf0b25061b..d97a6c0838b86 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.test.ts @@ -5,19 +5,33 @@ */ import Boom from 'boom'; -import sinon from 'sinon'; import { ByteSizeValue } from '@kbn/config-schema'; -import { httpServerMock } from '../../../../../../src/core/server/mocks'; +import { elasticsearchServiceMock, httpServerMock } from '../../../../../../src/core/server/mocks'; import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock'; -import { - MockAuthenticationProviderOptions, - mockAuthenticationProviderOptions, - mockScopedClusterClient, -} from './base.mock'; +import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; +import { + ElasticsearchErrorHelpers, + IClusterClient, + ScopeableRequest, +} from '../../../../../../src/core/server'; +import { AuthenticationResult } from '../authentication_result'; +import { DeauthenticationResult } from '../deauthentication_result'; import { SAMLAuthenticationProvider, SAMLLoginStep } from './saml'; +function expectAuthenticateCall( + mockClusterClient: jest.Mocked, + scopeableRequest: ScopeableRequest +) { + expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); + expect(mockClusterClient.asScoped).toHaveBeenCalledWith(scopeableRequest); + + const mockScopedClusterClient = mockClusterClient.asScoped.mock.results[0].value; + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); +} + describe('SAMLAuthenticationProvider', () => { let provider: SAMLAuthenticationProvider; let mockOptions: MockAuthenticationProviderOptions; @@ -63,294 +77,317 @@ describe('SAMLAuthenticationProvider', () => { it('gets token and redirects user to requested URL if SAML Response is valid.', async () => { const request = httpServerMock.createKibanaRequest(); - mockOptions.client.callAsInternalUser.withArgs('shield.samlAuthenticate').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ username: 'user', access_token: 'some-token', refresh_token: 'some-refresh-token', }); - const authenticationResult = await provider.login( - request, - { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, - { requestId: 'some-request-id', redirectURL: '/test-base-path/some-path#some-app' } + await expect( + provider.login( + request, + { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, + { requestId: 'some-request-id', redirectURL: '/test-base-path/some-path#some-app' } + ) + ).resolves.toEqual( + AuthenticationResult.redirectTo('/test-base-path/some-path#some-app', { + state: { + username: 'user', + accessToken: 'some-token', + refreshToken: 'some-refresh-token', + }, + }) ); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith( 'shield.samlAuthenticate', { body: { ids: ['some-request-id'], content: 'saml-response-xml', realm: 'test-realm' } } ); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/test-base-path/some-path#some-app'); - expect(authenticationResult.state).toEqual({ - username: 'user', - accessToken: 'some-token', - refreshToken: 'some-refresh-token', - }); }); it('fails if SAML Response payload is presented but state does not contain SAML Request token.', async () => { const request = httpServerMock.createKibanaRequest(); - const authenticationResult = await provider.login( - request, - { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, - {} + await expect( + provider.login( + request, + { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, + {} + ) + ).resolves.toEqual( + AuthenticationResult.failed( + Boom.badRequest('SAML response state does not have corresponding request id.') + ) ); - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toEqual( - Boom.badRequest('SAML response state does not have corresponding request id.') - ); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); it('redirects to the default location if state contains empty redirect URL.', async () => { const request = httpServerMock.createKibanaRequest(); - mockOptions.client.callAsInternalUser.withArgs('shield.samlAuthenticate').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ access_token: 'user-initiated-login-token', refresh_token: 'user-initiated-login-refresh-token', }); - const authenticationResult = await provider.login( - request, - { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, - { requestId: 'some-request-id', redirectURL: '' } + await expect( + provider.login( + request, + { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, + { requestId: 'some-request-id', redirectURL: '' } + ) + ).resolves.toEqual( + AuthenticationResult.redirectTo('/base-path/', { + state: { + accessToken: 'user-initiated-login-token', + refreshToken: 'user-initiated-login-refresh-token', + }, + }) ); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith( 'shield.samlAuthenticate', { body: { ids: ['some-request-id'], content: 'saml-response-xml', realm: 'test-realm' } } ); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/base-path/'); - expect(authenticationResult.state).toEqual({ - accessToken: 'user-initiated-login-token', - refreshToken: 'user-initiated-login-refresh-token', - }); }); it('redirects to the default location if state is not presented.', async () => { const request = httpServerMock.createKibanaRequest(); - mockOptions.client.callAsInternalUser.withArgs('shield.samlAuthenticate').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ access_token: 'idp-initiated-login-token', refresh_token: 'idp-initiated-login-refresh-token', }); - const authenticationResult = await provider.login(request, { - step: SAMLLoginStep.SAMLResponseReceived, - samlResponse: 'saml-response-xml', - }); + await expect( + provider.login(request, { + step: SAMLLoginStep.SAMLResponseReceived, + samlResponse: 'saml-response-xml', + }) + ).resolves.toEqual( + AuthenticationResult.redirectTo('/base-path/', { + state: { + accessToken: 'idp-initiated-login-token', + refreshToken: 'idp-initiated-login-refresh-token', + }, + }) + ); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith( 'shield.samlAuthenticate', { body: { ids: [], content: 'saml-response-xml', realm: 'test-realm' } } ); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/base-path/'); - expect(authenticationResult.state).toEqual({ - accessToken: 'idp-initiated-login-token', - refreshToken: 'idp-initiated-login-refresh-token', - }); }); it('fails if SAML Response is rejected.', async () => { const request = httpServerMock.createKibanaRequest(); const failureReason = new Error('SAML response is stale!'); - mockOptions.client.callAsInternalUser - .withArgs('shield.samlAuthenticate') - .rejects(failureReason); - - const authenticationResult = await provider.login( - request, - { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, - { requestId: 'some-request-id', redirectURL: '/test-base-path/some-path' } - ); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); + + await expect( + provider.login( + request, + { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, + { requestId: 'some-request-id', redirectURL: '/test-base-path/some-path' } + ) + ).resolves.toEqual(AuthenticationResult.failed(failureReason)); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith( 'shield.samlAuthenticate', { body: { ids: ['some-request-id'], content: 'saml-response-xml', realm: 'test-realm' } } ); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); describe('IdP initiated login with existing session', () => { it('fails if new SAML Response is rejected.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); + const authorization = 'Bearer some-valid-token'; const user = mockAuthenticatedUser(); - mockScopedClusterClient(mockOptions.client) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); const failureReason = new Error('SAML response is invalid!'); - mockOptions.client.callAsInternalUser - .withArgs('shield.samlAuthenticate') - .rejects(failureReason); - - const authenticationResult = await provider.login( - request, - { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); + + await expect( + provider.login( + request, + { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, + { + username: 'user', + accessToken: 'some-valid-token', + refreshToken: 'some-valid-refresh-token', + } + ) + ).resolves.toEqual(AuthenticationResult.failed(failureReason)); + + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith( + 'shield.samlAuthenticate', { - username: 'user', - accessToken: 'some-valid-token', - refreshToken: 'some-valid-refresh-token', + body: { ids: [], content: 'saml-response-xml', realm: 'test-realm' }, } ); - - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.samlAuthenticate', - { body: { ids: [], content: 'saml-response-xml', realm: 'test-realm' } } - ); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); it('fails if fails to invalidate existing access/refresh tokens.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const state = { username: 'user', accessToken: 'existing-valid-token', refreshToken: 'existing-valid-refresh-token', }; + const authorization = `Bearer ${state.accessToken}`; const user = mockAuthenticatedUser(); - mockScopedClusterClient(mockOptions.client) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - mockOptions.client.callAsInternalUser.withArgs('shield.samlAuthenticate').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ username: 'user', access_token: 'new-valid-token', refresh_token: 'new-valid-refresh-token', }); const failureReason = new Error('Failed to invalidate token!'); - mockOptions.tokens.invalidate.rejects(failureReason); + mockOptions.tokens.invalidate.mockRejectedValue(failureReason); - const authenticationResult = await provider.login( - request, - { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, - state - ); + await expect( + provider.login( + request, + { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, + state + ) + ).resolves.toEqual(AuthenticationResult.failed(failureReason)); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith( 'shield.samlAuthenticate', - { body: { ids: [], content: 'saml-response-xml', realm: 'test-realm' } } + { + body: { ids: [], content: 'saml-response-xml', realm: 'test-realm' }, + } ); - sinon.assert.calledOnce(mockOptions.tokens.invalidate); - sinon.assert.calledWithExactly(mockOptions.tokens.invalidate, { + expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith({ accessToken: state.accessToken, refreshToken: state.refreshToken, }); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); it('redirects to the home page if new SAML Response is for the same user.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const state = { username: 'user', accessToken: 'existing-valid-token', refreshToken: 'existing-valid-refresh-token', }; + const authorization = `Bearer ${state.accessToken}`; const user = { username: 'user' }; - mockScopedClusterClient(mockOptions.client) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - mockOptions.client.callAsInternalUser.withArgs('shield.samlAuthenticate').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ username: 'user', access_token: 'new-valid-token', refresh_token: 'new-valid-refresh-token', }); - mockOptions.tokens.invalidate.resolves(); - - const authenticationResult = await provider.login( - request, - { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, - state + mockOptions.tokens.invalidate.mockResolvedValue(undefined); + + await expect( + provider.login( + request, + { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, + state + ) + ).resolves.toEqual( + AuthenticationResult.redirectTo('/base-path/', { + state: { + username: 'user', + accessToken: 'new-valid-token', + refreshToken: 'new-valid-refresh-token', + }, + }) ); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith( 'shield.samlAuthenticate', - { body: { ids: [], content: 'saml-response-xml', realm: 'test-realm' } } + { + body: { ids: [], content: 'saml-response-xml', realm: 'test-realm' }, + } ); - sinon.assert.calledOnce(mockOptions.tokens.invalidate); - sinon.assert.calledWithExactly(mockOptions.tokens.invalidate, { + expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith({ accessToken: state.accessToken, refreshToken: state.refreshToken, }); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/base-path/'); }); it('redirects to `overwritten_session` if new SAML Response is for the another user.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const state = { username: 'user', accessToken: 'existing-valid-token', refreshToken: 'existing-valid-refresh-token', }; + const authorization = `Bearer ${state.accessToken}`; const existingUser = { username: 'user' }; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${state.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(existingUser); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(existingUser); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - mockOptions.client.callAsInternalUser.withArgs('shield.samlAuthenticate').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ username: 'new-user', access_token: 'new-valid-token', refresh_token: 'new-valid-refresh-token', }); - mockOptions.tokens.invalidate.resolves(); - - const authenticationResult = await provider.login( - request, - { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, - state + mockOptions.tokens.invalidate.mockResolvedValue(undefined); + + await expect( + provider.login( + request, + { step: SAMLLoginStep.SAMLResponseReceived, samlResponse: 'saml-response-xml' }, + state + ) + ).resolves.toEqual( + AuthenticationResult.redirectTo('/base-path/overwritten_session', { + state: { + username: 'new-user', + accessToken: 'new-valid-token', + refreshToken: 'new-valid-refresh-token', + }, + }) ); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith( 'shield.samlAuthenticate', - { body: { ids: [], content: 'saml-response-xml', realm: 'test-realm' } } + { + body: { ids: [], content: 'saml-response-xml', realm: 'test-realm' }, + } ); - sinon.assert.calledOnce(mockOptions.tokens.invalidate); - sinon.assert.calledWithExactly(mockOptions.tokens.invalidate, { + expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith({ accessToken: state.accessToken, refreshToken: state.refreshToken, }); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/base-path/overwritten_session'); }); }); @@ -358,170 +395,171 @@ describe('SAMLAuthenticationProvider', () => { it('fails if state is not available', async () => { const request = httpServerMock.createKibanaRequest(); - const authenticationResult = await provider.login(request, { - step: SAMLLoginStep.RedirectURLFragmentCaptured, - redirectURLFragment: '#some-fragment', - }); - - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toEqual( - Boom.badRequest('State does not include URL path to redirect to.') + await expect( + provider.login(request, { + step: SAMLLoginStep.RedirectURLFragmentCaptured, + redirectURLFragment: '#some-fragment', + }) + ).resolves.toEqual( + AuthenticationResult.failed( + Boom.badRequest('State does not include URL path to redirect to.') + ) ); + + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); it('does not handle AJAX requests.', async () => { const request = httpServerMock.createKibanaRequest({ headers: { 'kbn-xsrf': 'xsrf' } }); - const authenticationResult = await provider.login( - request, - { - step: SAMLLoginStep.RedirectURLFragmentCaptured, - redirectURLFragment: '#some-fragment', - }, - { redirectURL: '/test-base-path/some-path' } - ); - - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); - - expect(authenticationResult.notHandled()).toBe(true); + await expect( + provider.login( + request, + { + step: SAMLLoginStep.RedirectURLFragmentCaptured, + redirectURLFragment: '#some-fragment', + }, + { redirectURL: '/test-base-path/some-path' } + ) + ).resolves.toEqual(AuthenticationResult.notHandled()); + + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); it('redirects non-AJAX requests to the IdP remembering combined redirect URL.', async () => { const request = httpServerMock.createKibanaRequest(); - mockOptions.client.callAsInternalUser.withArgs('shield.samlPrepare').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ id: 'some-request-id', redirect: 'https://idp-host/path/login?SAMLRequest=some%20request%20', }); - const authenticationResult = await provider.login( - request, - { - step: SAMLLoginStep.RedirectURLFragmentCaptured, - redirectURLFragment: '#some-fragment', - }, - { redirectURL: '/test-base-path/some-path' } + await expect( + provider.login( + request, + { + step: SAMLLoginStep.RedirectURLFragmentCaptured, + redirectURLFragment: '#some-fragment', + }, + { redirectURL: '/test-base-path/some-path' } + ) + ).resolves.toEqual( + AuthenticationResult.redirectTo( + 'https://idp-host/path/login?SAMLRequest=some%20request%20', + { + state: { + requestId: 'some-request-id', + redirectURL: '/test-base-path/some-path#some-fragment', + }, + } + ) ); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.samlPrepare', - { body: { realm: 'test-realm' } } - ); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlPrepare', { + body: { realm: 'test-realm' }, + }); expect(mockOptions.logger.warn).not.toHaveBeenCalled(); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - 'https://idp-host/path/login?SAMLRequest=some%20request%20' - ); - expect(authenticationResult.state).toEqual({ - requestId: 'some-request-id', - redirectURL: '/test-base-path/some-path#some-fragment', - }); }); it('prepends redirect URL fragment with `#` if it does not have one.', async () => { const request = httpServerMock.createKibanaRequest(); - mockOptions.client.callAsInternalUser.withArgs('shield.samlPrepare').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ id: 'some-request-id', redirect: 'https://idp-host/path/login?SAMLRequest=some%20request%20', }); - const authenticationResult = await provider.login( - request, - { - step: SAMLLoginStep.RedirectURLFragmentCaptured, - redirectURLFragment: '../some-fragment', - }, - { redirectURL: '/test-base-path/some-path' } + await expect( + provider.login( + request, + { + step: SAMLLoginStep.RedirectURLFragmentCaptured, + redirectURLFragment: '../some-fragment', + }, + { redirectURL: '/test-base-path/some-path' } + ) + ).resolves.toEqual( + AuthenticationResult.redirectTo( + 'https://idp-host/path/login?SAMLRequest=some%20request%20', + { + state: { + requestId: 'some-request-id', + redirectURL: '/test-base-path/some-path#../some-fragment', + }, + } + ) ); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.samlPrepare', - { body: { realm: 'test-realm' } } - ); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlPrepare', { + body: { realm: 'test-realm' }, + }); expect(mockOptions.logger.warn).toHaveBeenCalledTimes(1); expect(mockOptions.logger.warn).toHaveBeenCalledWith( 'Redirect URL fragment does not start with `#`.' ); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - 'https://idp-host/path/login?SAMLRequest=some%20request%20' - ); - expect(authenticationResult.state).toEqual({ - requestId: 'some-request-id', - redirectURL: '/test-base-path/some-path#../some-fragment', - }); }); it('redirects non-AJAX requests to the IdP remembering only redirect URL path if fragment is too large.', async () => { const request = httpServerMock.createKibanaRequest(); - mockOptions.client.callAsInternalUser.withArgs('shield.samlPrepare').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ id: 'some-request-id', redirect: 'https://idp-host/path/login?SAMLRequest=some%20request%20', }); - const authenticationResult = await provider.login( - request, - { - step: SAMLLoginStep.RedirectURLFragmentCaptured, - redirectURLFragment: '#some-fragment'.repeat(10), - }, - { redirectURL: '/test-base-path/some-path' } + await expect( + provider.login( + request, + { + step: SAMLLoginStep.RedirectURLFragmentCaptured, + redirectURLFragment: '#some-fragment'.repeat(10), + }, + { redirectURL: '/test-base-path/some-path' } + ) + ).resolves.toEqual( + AuthenticationResult.redirectTo( + 'https://idp-host/path/login?SAMLRequest=some%20request%20', + { + state: { + requestId: 'some-request-id', + redirectURL: '/test-base-path/some-path', + }, + } + ) ); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.samlPrepare', - { body: { realm: 'test-realm' } } - ); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlPrepare', { + body: { realm: 'test-realm' }, + }); expect(mockOptions.logger.warn).toHaveBeenCalledTimes(1); expect(mockOptions.logger.warn).toHaveBeenCalledWith( 'Max URL size should not exceed 100b but it was 165b. Only URL path is captured.' ); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - 'https://idp-host/path/login?SAMLRequest=some%20request%20' - ); - expect(authenticationResult.state).toEqual({ - requestId: 'some-request-id', - redirectURL: '/test-base-path/some-path', - }); }); it('fails if SAML request preparation fails.', async () => { const request = httpServerMock.createKibanaRequest(); const failureReason = new Error('Realm is misconfigured!'); - mockOptions.client.callAsInternalUser.withArgs('shield.samlPrepare').rejects(failureReason); - - const authenticationResult = await provider.login( - request, - { - step: SAMLLoginStep.RedirectURLFragmentCaptured, - redirectURLFragment: '#some-fragment', - }, - { redirectURL: '/test-base-path/some-path' } - ); - - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.samlPrepare', - { body: { realm: 'test-realm' } } - ); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); + + await expect( + provider.login( + request, + { + step: SAMLLoginStep.RedirectURLFragmentCaptured, + redirectURLFragment: '#some-fragment', + }, + { redirectURL: '/test-base-path/some-path' } + ) + ).resolves.toEqual(AuthenticationResult.failed(failureReason)); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlPrepare', { + body: { realm: 'test-realm' }, + }); }); }); }); @@ -530,44 +568,57 @@ describe('SAMLAuthenticationProvider', () => { it('does not handle AJAX request that can not be authenticated.', async () => { const request = httpServerMock.createKibanaRequest({ headers: { 'kbn-xsrf': 'xsrf' } }); - const authenticationResult = await provider.authenticate(request, null); - - expect(authenticationResult.notHandled()).toBe(true); + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.notHandled() + ); }); - it('does not handle `authorization` header with unsupported schema even if state contains a valid token.', async () => { + it('does not handle authentication via `authorization` header.', async () => { const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Basic some:credentials' }, + headers: { authorization: 'Bearer some-token' }, }); - const authenticationResult = await provider.authenticate(request, { - username: 'user', - accessToken: 'some-valid-token', - refreshToken: 'some-valid-refresh-token', + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe('Bearer some-token'); + }); + + it('does not handle authentication via `authorization` header even if state contains a valid token.', async () => { + const request = httpServerMock.createKibanaRequest({ + headers: { authorization: 'Bearer some-token' }, }); - sinon.assert.notCalled(mockOptions.client.asScoped); - expect(request.headers.authorization).toBe('Basic some:credentials'); - expect(authenticationResult.notHandled()).toBe(true); + await expect( + provider.authenticate(request, { + username: 'user', + accessToken: 'some-valid-token', + refreshToken: 'some-valid-refresh-token', + }) + ).resolves.toEqual(AuthenticationResult.notHandled()); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe('Bearer some-token'); }); it('redirects non-AJAX request that can not be authenticated to the "capture fragment" page.', async () => { const request = httpServerMock.createKibanaRequest({ path: '/s/foo/some-path' }); - mockOptions.client.callAsInternalUser.withArgs('shield.samlPrepare').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ id: 'some-request-id', redirect: 'https://idp-host/path/login?SAMLRequest=some%20request%20', }); - const authenticationResult = await provider.authenticate(request); - - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - '/mock-server-basepath/api/security/saml/capture-url-fragment' + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.redirectTo( + '/mock-server-basepath/api/security/saml/capture-url-fragment', + { state: { redirectURL: '/base-path/s/foo/some-path' } } + ) ); - expect(authenticationResult.state).toEqual({ redirectURL: '/base-path/s/foo/some-path' }); + + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); it('redirects non-AJAX request that can not be authenticated to the IdP if request path is too large.', async () => { @@ -575,14 +626,19 @@ describe('SAMLAuthenticationProvider', () => { path: `/s/foo/${'some-path'.repeat(10)}`, }); - mockOptions.client.callAsInternalUser.withArgs('shield.samlPrepare').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ id: 'some-request-id', redirect: 'https://idp-host/path/login?SAMLRequest=some%20request%20', }); - const authenticationResult = await provider.authenticate(request); + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.redirectTo( + 'https://idp-host/path/login?SAMLRequest=some%20request%20', + { state: { requestId: 'some-request-id', redirectURL: '' } } + ) + ); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.samlPrepare', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlPrepare', { body: { realm: 'test-realm' }, }); @@ -590,12 +646,6 @@ describe('SAMLAuthenticationProvider', () => { expect(mockOptions.logger.warn).toHaveBeenCalledWith( 'Max URL path size should not exceed 100b but it was 107b. URL is not captured.' ); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - 'https://idp-host/path/login?SAMLRequest=some%20request%20' - ); - expect(authenticationResult.state).toEqual({ requestId: 'some-request-id', redirectURL: '' }); }); it('fails if SAML request preparation fails.', async () => { @@ -604,21 +654,20 @@ describe('SAMLAuthenticationProvider', () => { }); const failureReason = new Error('Realm is misconfigured!'); - mockOptions.client.callAsInternalUser.withArgs('shield.samlPrepare').rejects(failureReason); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); - const authenticationResult = await provider.authenticate(request, null); + await expect(provider.authenticate(request, null)).resolves.toEqual( + AuthenticationResult.failed(failureReason) + ); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.samlPrepare', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlPrepare', { body: { realm: 'test-realm' }, }); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); it('succeeds if state contains a valid token.', async () => { const user = mockAuthenticatedUser(); - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const state = { username: 'user', accessToken: 'some-valid-token', @@ -626,40 +675,43 @@ describe('SAMLAuthenticationProvider', () => { }; const authorization = `Bearer ${state.accessToken}`; - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'saml' }, + { authHeaders: { authorization } } + ) + ); - const authenticationResult = await provider.authenticate(request, state); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toEqual({ authorization }); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'saml' }); - expect(authenticationResult.state).toBeUndefined(); }); it('fails if token from the state is rejected because of unknown reason.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const state = { username: 'user', accessToken: 'some-valid-token', refreshToken: 'some-valid-refresh-token', }; + const authorization = `Bearer ${state.accessToken}`; const failureReason = { statusCode: 500, message: 'Token is not valid!' }; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${state.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(failureReason); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.failed(failureReason as any) + ); - const authenticationResult = await provider.authenticate(request, state); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); it('succeeds if token from the state is expired, but has been successfully refreshed.', async () => { @@ -671,65 +723,80 @@ describe('SAMLAuthenticationProvider', () => { refreshToken: 'valid-refresh-token', }; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${state.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + mockOptions.client.asScoped.mockImplementation(scopeableRequest => { + if (scopeableRequest?.headers.authorization === `Bearer ${state.accessToken}`) { + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + return mockScopedClusterClient; + } + + if (scopeableRequest?.headers.authorization === 'Bearer new-access-token') { + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + return mockScopedClusterClient; + } + + throw new Error('Unexpected call'); + }); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer new-access-token' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + mockOptions.tokens.refresh.mockResolvedValue({ + accessToken: 'new-access-token', + refreshToken: 'new-refresh-token', + }); - mockOptions.tokens.refresh - .withArgs(state.refreshToken) - .resolves({ accessToken: 'new-access-token', refreshToken: 'new-refresh-token' }); + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'saml' }, + { + authHeaders: { authorization: 'Bearer new-access-token' }, + state: { + username: 'user', + accessToken: 'new-access-token', + refreshToken: 'new-refresh-token', + }, + } + ) + ); - const authenticationResult = await provider.authenticate(request, state); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(state.refreshToken); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toEqual({ - authorization: 'Bearer new-access-token', - }); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'saml' }); - expect(authenticationResult.state).toEqual({ - username: 'user', - accessToken: 'new-access-token', - refreshToken: 'new-refresh-token', - }); }); it('fails if token from the state is expired and refresh attempt failed with unknown reason too.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const state = { username: 'user', accessToken: 'expired-token', refreshToken: 'invalid-refresh-token', }; + const authorization = `Bearer ${state.accessToken}`; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${state.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); const refreshFailureReason = { statusCode: 500, message: 'Something is wrong with refresh token.', }; - mockOptions.tokens.refresh.withArgs(state.refreshToken).rejects(refreshFailureReason); + mockOptions.tokens.refresh.mockRejectedValue(refreshFailureReason); - const authenticationResult = await provider.authenticate(request, state); + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.failed(refreshFailureReason as any) + ); + + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(state.refreshToken); + + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(refreshFailureReason); }); it('fails for AJAX requests with user friendly message if refresh token is expired.', async () => { @@ -739,80 +806,100 @@ describe('SAMLAuthenticationProvider', () => { accessToken: 'expired-token', refreshToken: 'expired-refresh-token', }; + const authorization = `Bearer ${state.accessToken}`; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${state.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + mockOptions.tokens.refresh.mockResolvedValue(null); + + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.failed(Boom.badRequest('Both access and refresh tokens are expired.')) + ); - mockOptions.tokens.refresh.withArgs(state.refreshToken).resolves(null); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(state.refreshToken); - const authenticationResult = await provider.authenticate(request, state); + expectAuthenticateCall(mockOptions.client, { + headers: { 'kbn-xsrf': 'xsrf', authorization }, + }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toEqual( - Boom.badRequest('Both access and refresh tokens are expired.') - ); }); it('re-capture URL for non-AJAX requests if refresh token is expired.', async () => { - const request = httpServerMock.createKibanaRequest({ path: '/s/foo/some-path' }); + const request = httpServerMock.createKibanaRequest({ path: '/s/foo/some-path', headers: {} }); const state = { username: 'user', accessToken: 'expired-token', refreshToken: 'expired-refresh-token', }; + const authorization = `Bearer ${state.accessToken}`; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${state.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - mockOptions.tokens.refresh.withArgs(state.refreshToken).resolves(null); + mockOptions.tokens.refresh.mockResolvedValue(null); - const authenticationResult = await provider.authenticate(request, state); + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.redirectTo( + '/mock-server-basepath/api/security/saml/capture-url-fragment', + { state: { redirectURL: '/base-path/s/foo/some-path' } } + ) + ); - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(state.refreshToken); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - '/mock-server-basepath/api/security/saml/capture-url-fragment' - ); - expect(authenticationResult.state).toEqual({ redirectURL: '/base-path/s/foo/some-path' }); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); + + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); it('initiates SAML handshake for non-AJAX requests if refresh token is expired and request path is too large.', async () => { const request = httpServerMock.createKibanaRequest({ path: `/s/foo/${'some-path'.repeat(10)}`, + headers: {}, }); const state = { username: 'user', accessToken: 'expired-token', refreshToken: 'expired-refresh-token', }; + const authorization = `Bearer ${state.accessToken}`; - mockOptions.client.callAsInternalUser.withArgs('shield.samlPrepare').resolves({ + mockOptions.client.callAsInternalUser.mockResolvedValue({ id: 'some-request-id', redirect: 'https://idp-host/path/login?SAMLRequest=some%20request%20', }); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${state.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - mockOptions.tokens.refresh.withArgs(state.refreshToken).resolves(null); + mockOptions.tokens.refresh.mockResolvedValue(null); - const authenticationResult = await provider.authenticate(request, state); + await expect(provider.authenticate(request, state)).resolves.toEqual( + AuthenticationResult.redirectTo( + 'https://idp-host/path/login?SAMLRequest=some%20request%20', + { state: { requestId: 'some-request-id', redirectURL: '' } } + ) + ); + + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(state.refreshToken); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.samlPrepare', { + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlPrepare', { body: { realm: 'test-realm' }, }); @@ -820,71 +907,6 @@ describe('SAMLAuthenticationProvider', () => { expect(mockOptions.logger.warn).toHaveBeenCalledWith( 'Max URL path size should not exceed 100b but it was 107b. URL is not captured.' ); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - 'https://idp-host/path/login?SAMLRequest=some%20request%20' - ); - expect(authenticationResult.state).toEqual({ requestId: 'some-request-id', redirectURL: '' }); - }); - - it('succeeds if `authorization` contains a valid token.', async () => { - const user = mockAuthenticatedUser(); - const authorization = 'Bearer some-valid-token'; - const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - const authenticationResult = await provider.authenticate(request); - - expect(request.headers.authorization).toBe('Bearer some-valid-token'); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.authHeaders).toBeUndefined(); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'saml' }); - expect(authenticationResult.state).toBeUndefined(); - }); - - it('fails if token from `authorization` header is rejected.', async () => { - const authorization = 'Bearer some-invalid-token'; - const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - - const failureReason = { statusCode: 401 }; - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(failureReason); - - const authenticationResult = await provider.authenticate(request); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); - }); - - it('fails if token from `authorization` header is rejected even if state contains a valid one.', async () => { - const user = mockAuthenticatedUser(); - const authorization = 'Bearer some-invalid-token'; - const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - - const failureReason = { statusCode: 401 }; - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(failureReason); - - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer some-valid-token' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - const authenticationResult = await provider.authenticate(request, { - accessToken: 'some-valid-token', - refreshToken: 'some-valid-refresh-token', - }); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); }); @@ -892,16 +914,15 @@ describe('SAMLAuthenticationProvider', () => { it('returns `notHandled` if state is not presented or does not include access token.', async () => { const request = httpServerMock.createKibanaRequest(); - let deauthenticateResult = await provider.logout(request); - expect(deauthenticateResult.notHandled()).toBe(true); - - deauthenticateResult = await provider.logout(request, {} as any); - expect(deauthenticateResult.notHandled()).toBe(true); - - deauthenticateResult = await provider.logout(request, { somethingElse: 'x' } as any); - expect(deauthenticateResult.notHandled()).toBe(true); + await expect(provider.logout(request)).resolves.toEqual(DeauthenticationResult.notHandled()); + await expect(provider.logout(request, {} as any)).resolves.toEqual( + DeauthenticationResult.notHandled() + ); + await expect(provider.logout(request, { somethingElse: 'x' } as any)).resolves.toEqual( + DeauthenticationResult.notHandled() + ); - sinon.assert.notCalled(mockOptions.client.callAsInternalUser); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); it('fails if SAML logout call fails.', async () => { @@ -910,42 +931,32 @@ describe('SAMLAuthenticationProvider', () => { const refreshToken = 'x-saml-refresh-token'; const failureReason = new Error('Realm is misconfigured!'); - mockOptions.client.callAsInternalUser.withArgs('shield.samlLogout').rejects(failureReason); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); - const authenticationResult = await provider.logout(request, { - username: 'user', - accessToken, - refreshToken, - }); + await expect( + provider.logout(request, { username: 'user', accessToken, refreshToken }) + ).resolves.toEqual(DeauthenticationResult.failed(failureReason)); - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.samlLogout', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlLogout', { body: { token: accessToken, refresh_token: refreshToken }, }); - - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); }); it('fails if SAML invalidate call fails.', async () => { const request = httpServerMock.createKibanaRequest({ query: { SAMLRequest: 'xxx yyy' } }); const failureReason = new Error('Realm is misconfigured!'); - mockOptions.client.callAsInternalUser - .withArgs('shield.samlInvalidate') - .rejects(failureReason); + mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); - const authenticationResult = await provider.logout(request); - - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.samlInvalidate', - { body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' } } + await expect(provider.logout(request)).resolves.toEqual( + DeauthenticationResult.failed(failureReason) ); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlInvalidate', { + body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, + }); }); it('redirects to /logged_out if `redirect` field in SAML logout response is null.', async () => { @@ -953,23 +964,16 @@ describe('SAMLAuthenticationProvider', () => { const accessToken = 'x-saml-token'; const refreshToken = 'x-saml-refresh-token'; - mockOptions.client.callAsInternalUser - .withArgs('shield.samlLogout') - .resolves({ redirect: null }); + mockOptions.client.callAsInternalUser.mockResolvedValue({ redirect: null }); - const authenticationResult = await provider.logout(request, { - username: 'user', - accessToken, - refreshToken, - }); + await expect( + provider.logout(request, { username: 'user', accessToken, refreshToken }) + ).resolves.toEqual(DeauthenticationResult.redirectTo('/mock-server-basepath/logged_out')); - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.samlLogout', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlLogout', { body: { token: accessToken, refresh_token: refreshToken }, }); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects to /logged_out if `redirect` field in SAML logout response is not defined.', async () => { @@ -977,23 +981,16 @@ describe('SAMLAuthenticationProvider', () => { const accessToken = 'x-saml-token'; const refreshToken = 'x-saml-refresh-token'; - mockOptions.client.callAsInternalUser - .withArgs('shield.samlLogout') - .resolves({ redirect: undefined }); + mockOptions.client.callAsInternalUser.mockResolvedValue({ redirect: undefined }); - const authenticationResult = await provider.logout(request, { - username: 'user', - accessToken, - refreshToken, - }); + await expect( + provider.logout(request, { username: 'user', accessToken, refreshToken }) + ).resolves.toEqual(DeauthenticationResult.redirectTo('/mock-server-basepath/logged_out')); - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.samlLogout', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlLogout', { body: { token: accessToken, refresh_token: refreshToken }, }); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('relies on SAML logout if query string is not empty, but does not include SAMLRequest.', async () => { @@ -1003,87 +1000,65 @@ describe('SAMLAuthenticationProvider', () => { const accessToken = 'x-saml-token'; const refreshToken = 'x-saml-refresh-token'; - mockOptions.client.callAsInternalUser - .withArgs('shield.samlLogout') - .resolves({ redirect: null }); + mockOptions.client.callAsInternalUser.mockResolvedValue({ redirect: null }); - const authenticationResult = await provider.logout(request, { - username: 'user', - accessToken, - refreshToken, - }); + await expect( + provider.logout(request, { username: 'user', accessToken, refreshToken }) + ).resolves.toEqual(DeauthenticationResult.redirectTo('/mock-server-basepath/logged_out')); - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - sinon.assert.calledWithExactly(mockOptions.client.callAsInternalUser, 'shield.samlLogout', { + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlLogout', { body: { token: accessToken, refresh_token: refreshToken }, }); - - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('relies on SAML invalidate call even if access token is presented.', async () => { const request = httpServerMock.createKibanaRequest({ query: { SAMLRequest: 'xxx yyy' } }); - mockOptions.client.callAsInternalUser - .withArgs('shield.samlInvalidate') - .resolves({ redirect: null }); - - const authenticationResult = await provider.logout(request, { - username: 'user', - accessToken: 'x-saml-token', - refreshToken: 'x-saml-refresh-token', - }); + mockOptions.client.callAsInternalUser.mockResolvedValue({ redirect: null }); - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.samlInvalidate', - { body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' } } - ); + await expect( + provider.logout(request, { + username: 'user', + accessToken: 'x-saml-token', + refreshToken: 'x-saml-refresh-token', + }) + ).resolves.toEqual(DeauthenticationResult.redirectTo('/mock-server-basepath/logged_out')); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlInvalidate', { + body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, + }); }); it('redirects to /logged_out if `redirect` field in SAML invalidate response is null.', async () => { const request = httpServerMock.createKibanaRequest({ query: { SAMLRequest: 'xxx yyy' } }); - mockOptions.client.callAsInternalUser - .withArgs('shield.samlInvalidate') - .resolves({ redirect: null }); + mockOptions.client.callAsInternalUser.mockResolvedValue({ redirect: null }); - const authenticationResult = await provider.logout(request); - - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.samlInvalidate', - { body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' } } + await expect(provider.logout(request)).resolves.toEqual( + DeauthenticationResult.redirectTo('/mock-server-basepath/logged_out') ); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlInvalidate', { + body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, + }); }); it('redirects to /logged_out if `redirect` field in SAML invalidate response is not defined.', async () => { const request = httpServerMock.createKibanaRequest({ query: { SAMLRequest: 'xxx yyy' } }); - mockOptions.client.callAsInternalUser - .withArgs('shield.samlInvalidate') - .resolves({ redirect: undefined }); + mockOptions.client.callAsInternalUser.mockResolvedValue({ redirect: undefined }); - const authenticationResult = await provider.logout(request); - - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - sinon.assert.calledWithExactly( - mockOptions.client.callAsInternalUser, - 'shield.samlInvalidate', - { body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' } } + await expect(provider.logout(request)).resolves.toEqual( + DeauthenticationResult.redirectTo('/mock-server-basepath/logged_out') ); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.samlInvalidate', { + body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, + }); }); it('redirects user to the IdP if SLO is supported by IdP in case of SP initiated logout.', async () => { @@ -1091,37 +1066,41 @@ describe('SAMLAuthenticationProvider', () => { const accessToken = 'x-saml-token'; const refreshToken = 'x-saml-refresh-token'; - mockOptions.client.callAsInternalUser - .withArgs('shield.samlLogout') - .resolves({ redirect: 'http://fake-idp/SLO?SAMLRequest=7zlH37H' }); - - const authenticationResult = await provider.logout(request, { - username: 'user', - accessToken, - refreshToken, + mockOptions.client.callAsInternalUser.mockResolvedValue({ + redirect: 'http://fake-idp/SLO?SAMLRequest=7zlH37H', }); - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('http://fake-idp/SLO?SAMLRequest=7zlH37H'); + await expect( + provider.logout(request, { username: 'user', accessToken, refreshToken }) + ).resolves.toEqual( + DeauthenticationResult.redirectTo('http://fake-idp/SLO?SAMLRequest=7zlH37H') + ); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); }); it('redirects user to the IdP if SLO is supported by IdP in case of IdP initiated logout.', async () => { const request = httpServerMock.createKibanaRequest({ query: { SAMLRequest: 'xxx yyy' } }); - mockOptions.client.callAsInternalUser - .withArgs('shield.samlInvalidate') - .resolves({ redirect: 'http://fake-idp/SLO?SAMLRequest=7zlH37H' }); - - const authenticationResult = await provider.logout(request, { - username: 'user', - accessToken: 'x-saml-token', - refreshToken: 'x-saml-refresh-token', + mockOptions.client.callAsInternalUser.mockResolvedValue({ + redirect: 'http://fake-idp/SLO?SAMLRequest=7zlH37H', }); - sinon.assert.calledOnce(mockOptions.client.callAsInternalUser); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('http://fake-idp/SLO?SAMLRequest=7zlH37H'); + await expect( + provider.logout(request, { + username: 'user', + accessToken: 'x-saml-token', + refreshToken: 'x-saml-refresh-token', + }) + ).resolves.toEqual( + DeauthenticationResult.redirectTo('http://fake-idp/SLO?SAMLRequest=7zlH37H') + ); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); }); }); + + it('`getHTTPAuthenticationScheme` method', () => { + expect(provider.getHTTPAuthenticationScheme()).toBe('bearer'); + }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/saml.ts b/x-pack/plugins/security/server/authentication/providers/saml.ts index a817159fcd445..1ac59d66a2235 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.ts @@ -9,9 +9,10 @@ import { ByteSizeValue } from '@kbn/config-schema'; import { KibanaRequest } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; -import { AuthenticationProviderOptions, BaseAuthenticationProvider } from './base'; import { canRedirectRequest } from '../can_redirect_request'; +import { getHTTPAuthenticationScheme } from '../get_http_authentication_scheme'; import { Tokens, TokenPair } from '../tokens'; +import { AuthenticationProviderOptions, BaseAuthenticationProvider } from './base'; /** * The state supported by the provider (for the SAML handshake or established session). @@ -180,17 +181,13 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider { public async authenticate(request: KibanaRequest, state?: ProviderState | null) { this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); - // We should get rid of `Bearer` scheme support as soon as Reporting doesn't need it anymore. - let { - authenticationResult, - // eslint-disable-next-line prefer-const - headerNotRecognized, - } = await this.authenticateViaHeader(request); - if (headerNotRecognized) { - return authenticationResult; + if (getHTTPAuthenticationScheme(request) != null) { + this.logger.debug('Cannot authenticate requests with `Authorization` header.'); + return AuthenticationResult.notHandled(); } - if (state && authenticationResult.notHandled()) { + let authenticationResult = AuthenticationResult.notHandled(); + if (state) { authenticationResult = await this.authenticateViaState(request, state); if ( authenticationResult.failed() && @@ -243,37 +240,11 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider { } /** - * Validates whether request contains `Bearer ***` Authorization header and just passes it - * forward to Elasticsearch backend. - * @param request Request instance. + * Returns HTTP authentication scheme (`Bearer`) that's used within `Authorization` HTTP header + * that provider attaches to all successfully authenticated requests to Elasticsearch. */ - private async authenticateViaHeader(request: KibanaRequest) { - this.logger.debug('Trying to authenticate via header.'); - - const authorization = request.headers.authorization; - if (!authorization || typeof authorization !== 'string') { - this.logger.debug('Authorization header is not presented.'); - return { authenticationResult: AuthenticationResult.notHandled() }; - } - - const authenticationSchema = authorization.split(/\s+/)[0]; - if (authenticationSchema.toLowerCase() !== 'bearer') { - this.logger.debug(`Unsupported authentication schema: ${authenticationSchema}`); - return { - authenticationResult: AuthenticationResult.notHandled(), - headerNotRecognized: true, - }; - } - - try { - const user = await this.getUser(request); - - this.logger.debug('Request has been authenticated via header.'); - return { authenticationResult: AuthenticationResult.succeeded(user) }; - } catch (err) { - this.logger.debug(`Failed to authenticate request via header: ${err.message}`); - return { authenticationResult: AuthenticationResult.failed(err) }; - } + public getHTTPAuthenticationScheme() { + return 'bearer'; } /** diff --git a/x-pack/plugins/security/server/authentication/providers/token.test.ts b/x-pack/plugins/security/server/authentication/providers/token.test.ts index 0a55219e25d91..e81d14e8bf9f3 100644 --- a/x-pack/plugins/security/server/authentication/providers/token.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/token.test.ts @@ -6,18 +6,32 @@ import Boom from 'boom'; import { errors } from 'elasticsearch'; -import sinon from 'sinon'; -import { httpServerMock } from '../../../../../../src/core/server/mocks'; +import { elasticsearchServiceMock, httpServerMock } from '../../../../../../src/core/server/mocks'; import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock'; -import { - MockAuthenticationProviderOptions, - mockAuthenticationProviderOptions, - mockScopedClusterClient, -} from './base.mock'; +import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; +import { + ElasticsearchErrorHelpers, + IClusterClient, + ScopeableRequest, +} from '../../../../../../src/core/server'; +import { AuthenticationResult } from '../authentication_result'; +import { DeauthenticationResult } from '../deauthentication_result'; import { TokenAuthenticationProvider } from './token'; +function expectAuthenticateCall( + mockClusterClient: jest.Mocked, + scopeableRequest: ScopeableRequest +) { + expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); + expect(mockClusterClient.asScoped).toHaveBeenCalledWith(scopeableRequest); + + const mockScopedClusterClient = mockClusterClient.asScoped.mock.results[0].value; + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledTimes(1); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.authenticate'); +} + describe('TokenAuthenticationProvider', () => { let provider: TokenAuthenticationProvider; let mockOptions: MockAuthenticationProviderOptions; @@ -28,29 +42,35 @@ describe('TokenAuthenticationProvider', () => { describe('`login` method', () => { it('succeeds with valid login attempt, creates session and authHeaders', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const user = mockAuthenticatedUser(); const credentials = { username: 'user', password: 'password' }; const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; const authorization = `Bearer ${tokenPair.accessToken}`; - mockOptions.client.callAsInternalUser - .withArgs('shield.getAccessToken', { - body: { grant_type: 'password', ...credentials }, - }) - .resolves({ access_token: tokenPair.accessToken, refresh_token: tokenPair.refreshToken }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + mockOptions.client.callAsInternalUser.mockResolvedValue({ + access_token: tokenPair.accessToken, + refresh_token: tokenPair.refreshToken, + }); - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + await expect(provider.login(request, credentials)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'token' }, + { authHeaders: { authorization }, state: tokenPair } + ) + ); - const authenticationResult = await provider.login(request, credentials); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'token' }); - expect(authenticationResult.state).toEqual(tokenPair); - expect(authenticationResult.authHeaders).toEqual({ authorization }); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.getAccessToken', { + body: { grant_type: 'password', ...credentials }, + }); }); it('fails if token cannot be generated during login attempt', async () => { @@ -58,109 +78,125 @@ describe('TokenAuthenticationProvider', () => { const credentials = { username: 'user', password: 'password' }; const authenticationError = new Error('Invalid credentials'); - mockOptions.client.callAsInternalUser - .withArgs('shield.getAccessToken', { - body: { grant_type: 'password', ...credentials }, - }) - .rejects(authenticationError); + mockOptions.client.callAsInternalUser.mockRejectedValue(authenticationError); - const authenticationResult = await provider.login(request, credentials); + await expect(provider.login(request, credentials)).resolves.toEqual( + AuthenticationResult.failed(authenticationError) + ); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); - sinon.assert.notCalled(mockOptions.client.asScoped); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.getAccessToken', { + body: { grant_type: 'password', ...credentials }, + }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.user).toBeUndefined(); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.error).toEqual(authenticationError); }); it('fails if user cannot be retrieved during login attempt', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const credentials = { username: 'user', password: 'password' }; const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; + const authorization = `Bearer ${tokenPair.accessToken}`; - mockOptions.client.callAsInternalUser - .withArgs('shield.getAccessToken', { - body: { grant_type: 'password', ...credentials }, - }) - .resolves({ access_token: tokenPair.accessToken, refresh_token: tokenPair.refreshToken }); + mockOptions.client.callAsInternalUser.mockResolvedValue({ + access_token: tokenPair.accessToken, + refresh_token: tokenPair.refreshToken, + }); const authenticationError = new Error('Some error'); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(authenticationError); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(authenticationError); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - const authenticationResult = await provider.login(request, credentials); + await expect(provider.login(request, credentials)).resolves.toEqual( + AuthenticationResult.failed(authenticationError) + ); + + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); + + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.getAccessToken', { + body: { grant_type: 'password', ...credentials }, + }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.user).toBeUndefined(); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.error).toEqual(authenticationError); }); }); describe('`authenticate` method', () => { - it('does not redirect AJAX requests that can not be authenticated to the login page.', async () => { - // Add `kbn-xsrf` header to make `can_redirect_request` think that it's AJAX request and - // avoid triggering of redirect logic. - const authenticationResult = await provider.authenticate( - httpServerMock.createKibanaRequest({ headers: { 'kbn-xsrf': 'xsrf' } }), - null - ); - - expect(authenticationResult.notHandled()).toBe(true); - }); + it('does not handle authentication via `authorization` header.', async () => { + const request = httpServerMock.createKibanaRequest({ + headers: { authorization: 'Bearer some-token' }, + }); - it('redirects non-AJAX requests that can not be authenticated to the login page.', async () => { - const authenticationResult = await provider.authenticate( - httpServerMock.createKibanaRequest({ path: '/s/foo/some-path # that needs to be encoded' }), - null + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() ); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - '/base-path/login?next=%2Fbase-path%2Fs%2Ffoo%2Fsome-path%20%23%20that%20needs%20to%20be%20encoded' - ); + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe('Bearer some-token'); }); - it('succeeds if only `authorization` header is available and returns neither state nor authHeaders.', async () => { - const authorization = 'Bearer foo'; - const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - const user = mockAuthenticatedUser(); + it('does not handle authentication via `authorization` header even if state contains valid credentials.', async () => { + const request = httpServerMock.createKibanaRequest({ + headers: { authorization: 'Bearer some-token' }, + }); - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + await expect( + provider.authenticate(request, { accessToken: 'foo', refreshToken: 'bar' }) + ).resolves.toEqual(AuthenticationResult.notHandled()); - const authenticationResult = await provider.authenticate(request); + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(request.headers.authorization).toBe('Bearer some-token'); + }); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'token' }); - expect(authenticationResult.authHeaders).toBeUndefined(); - expect(authenticationResult.state).toBeUndefined(); + it('does not redirect AJAX requests that can not be authenticated to the login page.', async () => { + // Add `kbn-xsrf` header to make `can_redirect_request` think that it's AJAX request and + // avoid triggering of redirect logic. + await expect( + provider.authenticate( + httpServerMock.createKibanaRequest({ headers: { 'kbn-xsrf': 'xsrf' } }), + null + ) + ).resolves.toEqual(AuthenticationResult.notHandled()); + }); + + it('redirects non-AJAX requests that can not be authenticated to the login page.', async () => { + await expect( + provider.authenticate( + httpServerMock.createKibanaRequest({ + path: '/s/foo/some-path # that needs to be encoded', + }), + null + ) + ).resolves.toEqual( + AuthenticationResult.redirectTo( + '/base-path/login?next=%2Fbase-path%2Fs%2Ffoo%2Fsome-path%20%23%20that%20needs%20to%20be%20encoded' + ) + ); }); it('succeeds if only state is available.', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; const user = mockAuthenticatedUser(); const authorization = `Bearer ${tokenPair.accessToken}`; - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - const authenticationResult = await provider.authenticate(request, tokenPair); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'token' }, + { authHeaders: { authorization } } + ) + ); + + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'token' }); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.authHeaders).toEqual({ authorization }); expect(request.headers).not.toHaveProperty('authorization'); }); @@ -169,162 +205,115 @@ describe('TokenAuthenticationProvider', () => { const request = httpServerMock.createKibanaRequest(); const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); - - mockOptions.tokens.refresh - .withArgs(tokenPair.refreshToken) - .resolves({ accessToken: 'newfoo', refreshToken: 'newbar' }); + mockOptions.client.asScoped.mockImplementation(scopeableRequest => { + if (scopeableRequest?.headers.authorization === `Bearer ${tokenPair.accessToken}`) { + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + return mockScopedClusterClient; + } + + if (scopeableRequest?.headers.authorization === 'Bearer newfoo') { + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockResolvedValue(user); + return mockScopedClusterClient; + } + + throw new Error('Unexpected call'); + }); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer newfoo' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); + mockOptions.tokens.refresh.mockResolvedValue({ + accessToken: 'newfoo', + refreshToken: 'newbar', + }); - const authenticationResult = await provider.authenticate(request, tokenPair); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.succeeded( + { ...user, authentication_provider: 'token' }, + { + authHeaders: { authorization: 'Bearer newfoo' }, + state: { accessToken: 'newfoo', refreshToken: 'newbar' }, + } + ) + ); - sinon.assert.calledOnce(mockOptions.tokens.refresh); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'token' }); - expect(authenticationResult.state).toEqual({ accessToken: 'newfoo', refreshToken: 'newbar' }); - expect(authenticationResult.authHeaders).toEqual({ authorization: 'Bearer newfoo' }); expect(request.headers).not.toHaveProperty('authorization'); }); - it('does not handle `authorization` header with unsupported schema even if state contains valid credentials.', async () => { - const request = httpServerMock.createKibanaRequest({ - headers: { authorization: 'Basic ***' }, - }); + it('fails if authentication with token from state fails with unknown error.', async () => { const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; - const user = mockAuthenticatedUser(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const authorization = `Bearer ${tokenPair.accessToken}`; - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - const authenticationResult = await provider.authenticate(request, tokenPair); - - sinon.assert.notCalled(mockOptions.client.asScoped); - expect(request.headers.authorization).toBe('Basic ***'); - expect(authenticationResult.notHandled()).toBe(true); - }); - - it('authenticates only via `authorization` header even if state is available.', async () => { - const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; - const authorization = `Bearer foo-from-header`; - const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - const user = mockAuthenticatedUser(); - - // GetUser will be called with request's `authorization` header. - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .resolves(user); - - const authenticationResult = await provider.authenticate(request, tokenPair); - - expect(authenticationResult.succeeded()).toBe(true); - expect(authenticationResult.user).toEqual({ ...user, authentication_provider: 'token' }); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.authHeaders).toBeUndefined(); - expect(request.headers.authorization).toEqual('Bearer foo-from-header'); - }); - - it('fails if authentication with token from header fails with unknown error', async () => { - const authorization = `Bearer foo`; - const request = httpServerMock.createKibanaRequest({ headers: { authorization } }); - const authenticationError = new errors.InternalServerError('something went wrong'); - mockScopedClusterClient(mockOptions.client, sinon.match({ headers: { authorization } })) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(authenticationError); - - const authenticationResult = await provider.authenticate(request); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(authenticationError); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.user).toBeUndefined(); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.error).toEqual(authenticationError); - }); - - it('fails if authentication with token from state fails with unknown error.', async () => { - const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; - const request = httpServerMock.createKibanaRequest(); - - const authenticationError = new errors.InternalServerError('something went wrong'); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(authenticationError); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.failed(authenticationError) + ); - const authenticationResult = await provider.authenticate(request, tokenPair); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.user).toBeUndefined(); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.error).toEqual(authenticationError); }); it('fails if token refresh is rejected with unknown error', async () => { - const request = httpServerMock.createKibanaRequest(); + const request = httpServerMock.createKibanaRequest({ headers: {} }); const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; + const authorization = `Bearer ${tokenPair.accessToken}`; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); const refreshError = new errors.InternalServerError('failed to refresh token'); - mockOptions.tokens.refresh.withArgs(tokenPair.refreshToken).rejects(refreshError); + mockOptions.tokens.refresh.mockRejectedValue(refreshError); - const authenticationResult = await provider.authenticate(request, tokenPair); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.failed(refreshError) + ); + + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); - sinon.assert.calledOnce(mockOptions.tokens.refresh); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.user).toBeUndefined(); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.error).toEqual(refreshError); }); it('redirects non-AJAX requests to /login and clears session if token cannot be refreshed', async () => { - const request = httpServerMock.createKibanaRequest({ path: '/some-path' }); + const request = httpServerMock.createKibanaRequest({ path: '/some-path', headers: {} }); const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; + const authorization = `Bearer ${tokenPair.accessToken}`; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); + + mockOptions.tokens.refresh.mockResolvedValue(null); - mockOptions.tokens.refresh.withArgs(tokenPair.refreshToken).resolves(null); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.redirectTo('/base-path/login?next=%2Fbase-path%2Fsome-path', { + state: null, + }) + ); - const authenticationResult = await provider.authenticate(request, tokenPair); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); - sinon.assert.calledOnce(mockOptions.tokens.refresh); + expectAuthenticateCall(mockOptions.client, { headers: { authorization } }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe( - '/base-path/login?next=%2Fbase-path%2Fsome-path' - ); - expect(authenticationResult.user).toBeUndefined(); - expect(authenticationResult.state).toEqual(null); - expect(authenticationResult.error).toBeUndefined(); }); it('does not redirect AJAX requests if token token cannot be refreshed', async () => { @@ -333,61 +322,66 @@ describe('TokenAuthenticationProvider', () => { path: '/some-path', }); const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; + const authorization = `Bearer ${tokenPair.accessToken}`; + + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); + mockOptions.tokens.refresh.mockResolvedValue(null); - mockOptions.tokens.refresh.withArgs(tokenPair.refreshToken).resolves(null); + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.failed(Boom.badRequest('Both access and refresh tokens are expired.')) + ); - const authenticationResult = await provider.authenticate(request, tokenPair); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); - sinon.assert.calledOnce(mockOptions.tokens.refresh); + expectAuthenticateCall(mockOptions.client, { + headers: { 'kbn-xsrf': 'xsrf', authorization }, + }); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toEqual( - Boom.badRequest('Both access and refresh tokens are expired.') - ); - expect(authenticationResult.user).toBeUndefined(); - expect(authenticationResult.state).toBeUndefined(); }); it('fails if new access token is rejected after successful refresh', async () => { const request = httpServerMock.createKibanaRequest(); const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: `Bearer ${tokenPair.accessToken}` } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects({ statusCode: 401 }); - - mockOptions.tokens.refresh - .withArgs(tokenPair.refreshToken) - .resolves({ accessToken: 'newfoo', refreshToken: 'newbar' }); - const authenticationError = new errors.AuthenticationException('Some error'); - mockScopedClusterClient( - mockOptions.client, - sinon.match({ headers: { authorization: 'Bearer newfoo' } }) - ) - .callAsCurrentUser.withArgs('shield.authenticate') - .rejects(authenticationError); + mockOptions.client.asScoped.mockImplementation(scopeableRequest => { + if (scopeableRequest?.headers.authorization === `Bearer ${tokenPair.accessToken}`) { + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( + ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ); + return mockScopedClusterClient; + } + + if (scopeableRequest?.headers.authorization === 'Bearer newfoo') { + const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(authenticationError); + return mockScopedClusterClient; + } + + throw new Error('Unexpected call'); + }); - const authenticationResult = await provider.authenticate(request, tokenPair); + mockOptions.tokens.refresh.mockResolvedValue({ + accessToken: 'newfoo', + refreshToken: 'newbar', + }); + + await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + AuthenticationResult.failed(authenticationError) + ); - sinon.assert.calledOnce(mockOptions.tokens.refresh); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.user).toBeUndefined(); - expect(authenticationResult.state).toBeUndefined(); - expect(authenticationResult.error).toEqual(authenticationError); }); }); @@ -395,13 +389,15 @@ describe('TokenAuthenticationProvider', () => { it('returns `redirected` if state is not presented.', async () => { const request = httpServerMock.createKibanaRequest(); - let deauthenticateResult = await provider.logout(request); - expect(deauthenticateResult.redirected()).toBe(true); + await expect(provider.logout(request)).resolves.toEqual( + DeauthenticationResult.redirectTo('/base-path/login?msg=LOGGED_OUT') + ); - deauthenticateResult = await provider.logout(request, null); - expect(deauthenticateResult.redirected()).toBe(true); + await expect(provider.logout(request, null)).resolves.toEqual( + DeauthenticationResult.redirectTo('/base-path/login?msg=LOGGED_OUT') + ); - sinon.assert.notCalled(mockOptions.tokens.invalidate); + expect(mockOptions.tokens.invalidate).not.toHaveBeenCalled(); }); it('fails if `tokens.invalidate` fails', async () => { @@ -409,45 +405,46 @@ describe('TokenAuthenticationProvider', () => { const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; const failureReason = new Error('failed to delete token'); - mockOptions.tokens.invalidate.withArgs(tokenPair).rejects(failureReason); - - const authenticationResult = await provider.logout(request, tokenPair); + mockOptions.tokens.invalidate.mockRejectedValue(failureReason); - sinon.assert.calledOnce(mockOptions.tokens.invalidate); - sinon.assert.calledWithExactly(mockOptions.tokens.invalidate, tokenPair); + await expect(provider.logout(request, tokenPair)).resolves.toEqual( + DeauthenticationResult.failed(failureReason) + ); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toBe(failureReason); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith(tokenPair); }); it('redirects to /login if tokens are invalidated successfully', async () => { const request = httpServerMock.createKibanaRequest(); const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; - mockOptions.tokens.invalidate.withArgs(tokenPair).resolves(); + mockOptions.tokens.invalidate.mockResolvedValue(undefined); - const authenticationResult = await provider.logout(request, tokenPair); - - sinon.assert.calledOnce(mockOptions.tokens.invalidate); - sinon.assert.calledWithExactly(mockOptions.tokens.invalidate, tokenPair); + await expect(provider.logout(request, tokenPair)).resolves.toEqual( + DeauthenticationResult.redirectTo('/base-path/login?msg=LOGGED_OUT') + ); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/base-path/login?msg=LOGGED_OUT'); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith(tokenPair); }); it('redirects to /login with optional search parameters if tokens are invalidated successfully', async () => { const request = httpServerMock.createKibanaRequest({ query: { yep: 'nope' } }); const tokenPair = { accessToken: 'foo', refreshToken: 'bar' }; - mockOptions.tokens.invalidate.withArgs(tokenPair).resolves(); - - const authenticationResult = await provider.logout(request, tokenPair); + mockOptions.tokens.invalidate.mockResolvedValue(undefined); - sinon.assert.calledOnce(mockOptions.tokens.invalidate); - sinon.assert.calledWithExactly(mockOptions.tokens.invalidate, tokenPair); + await expect(provider.logout(request, tokenPair)).resolves.toEqual( + DeauthenticationResult.redirectTo('/base-path/login?yep=nope') + ); - expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/base-path/login?yep=nope'); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledTimes(1); + expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith(tokenPair); }); }); + + it('`getHTTPAuthenticationScheme` method', () => { + expect(provider.getHTTPAuthenticationScheme()).toBe('bearer'); + }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/token.ts b/x-pack/plugins/security/server/authentication/providers/token.ts index 03fd003e2cbde..fffac254ed30a 100644 --- a/x-pack/plugins/security/server/authentication/providers/token.ts +++ b/x-pack/plugins/security/server/authentication/providers/token.ts @@ -8,9 +8,10 @@ import Boom from 'boom'; import { KibanaRequest } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; -import { BaseAuthenticationProvider } from './base'; import { canRedirectRequest } from '../can_redirect_request'; +import { getHTTPAuthenticationScheme } from '../get_http_authentication_scheme'; import { Tokens, TokenPair } from '../tokens'; +import { BaseAuthenticationProvider } from './base'; /** * Describes the parameters that are required by the provider to process the initial login request. @@ -34,12 +35,6 @@ export class TokenAuthenticationProvider extends BaseAuthenticationProvider { */ static readonly type = 'token'; - /** - * Performs initial login request using username and password. - * @param request Request instance. - * @param loginAttempt Login attempt description. - * @param [state] Optional state object associated with the provider. - */ /** * Performs initial login request using username and password. * @param request Request instance. @@ -87,18 +82,13 @@ export class TokenAuthenticationProvider extends BaseAuthenticationProvider { public async authenticate(request: KibanaRequest, state?: ProviderState | null) { this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); - // if there isn't a payload, try header-based token auth - const { - authenticationResult: headerAuthResult, - headerNotRecognized, - } = await this.authenticateViaHeader(request); - if (headerNotRecognized) { - return headerAuthResult; + if (getHTTPAuthenticationScheme(request) != null) { + this.logger.debug('Cannot authenticate requests with `Authorization` header.'); + return AuthenticationResult.notHandled(); } - let authenticationResult = headerAuthResult; - // if we still can't attempt auth, try authenticating via state (session token) - if (authenticationResult.notHandled() && state) { + let authenticationResult = AuthenticationResult.notHandled(); + if (state) { authenticationResult = await this.authenticateViaState(request, state); if ( authenticationResult.failed() && @@ -111,6 +101,7 @@ export class TokenAuthenticationProvider extends BaseAuthenticationProvider { // finally, if authentication still can not be handled for this // request/state combination, redirect to the login page if appropriate if (authenticationResult.notHandled() && canRedirectRequest(request)) { + this.logger.debug('Redirecting request to Login page.'); authenticationResult = AuthenticationResult.redirectTo(this.getLoginPageURL(request)); } @@ -144,37 +135,11 @@ export class TokenAuthenticationProvider extends BaseAuthenticationProvider { } /** - * Validates whether request contains `Bearer ***` Authorization header and just passes it - * forward to Elasticsearch backend. - * @param request Request instance. + * Returns HTTP authentication scheme (`Bearer`) that's used within `Authorization` HTTP header + * that provider attaches to all successfully authenticated requests to Elasticsearch. */ - private async authenticateViaHeader(request: KibanaRequest) { - this.logger.debug('Trying to authenticate via header.'); - - const authorization = request.headers.authorization; - if (!authorization || typeof authorization !== 'string') { - this.logger.debug('Authorization header is not presented.'); - return { authenticationResult: AuthenticationResult.notHandled() }; - } - - const authenticationSchema = authorization.split(/\s+/)[0]; - if (authenticationSchema.toLowerCase() !== 'bearer') { - this.logger.debug(`Unsupported authentication schema: ${authenticationSchema}`); - return { authenticationResult: AuthenticationResult.notHandled(), headerNotRecognized: true }; - } - - try { - const user = await this.getUser(request); - - this.logger.debug('Request has been authenticated via header.'); - - // We intentionally do not store anything in session state because token - // header auth can only be used on a request by request basis. - return { authenticationResult: AuthenticationResult.succeeded(user) }; - } catch (err) { - this.logger.debug(`Failed to authenticate request via header: ${err.message}`); - return { authenticationResult: AuthenticationResult.failed(err) }; - } + public getHTTPAuthenticationScheme() { + return 'bearer'; } /** diff --git a/x-pack/plugins/security/server/config.test.ts b/x-pack/plugins/security/server/config.test.ts index f7374eedb5520..64c695670fa19 100644 --- a/x-pack/plugins/security/server/config.test.ts +++ b/x-pack/plugins/security/server/config.test.ts @@ -13,57 +13,78 @@ import { createConfig$, ConfigSchema } from './config'; describe('config schema', () => { it('generates proper defaults', () => { expect(ConfigSchema.validate({})).toMatchInlineSnapshot(` - Object { - "authc": Object { - "providers": Array [ - "basic", - ], - }, - "cookieName": "sid", - "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "loginAssistanceMessage": "", - "secureCookies": false, - "session": Object { - "idleTimeout": null, - "lifespan": null, - }, - } - `); + Object { + "authc": Object { + "http": Object { + "autoSchemesEnabled": true, + "enabled": true, + "schemes": Array [ + "apikey", + ], + }, + "providers": Array [ + "basic", + ], + }, + "cookieName": "sid", + "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "loginAssistanceMessage": "", + "secureCookies": false, + "session": Object { + "idleTimeout": null, + "lifespan": null, + }, + } + `); expect(ConfigSchema.validate({}, { dist: false })).toMatchInlineSnapshot(` - Object { - "authc": Object { - "providers": Array [ - "basic", - ], - }, - "cookieName": "sid", - "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "loginAssistanceMessage": "", - "secureCookies": false, - "session": Object { - "idleTimeout": null, - "lifespan": null, - }, - } - `); + Object { + "authc": Object { + "http": Object { + "autoSchemesEnabled": true, + "enabled": true, + "schemes": Array [ + "apikey", + ], + }, + "providers": Array [ + "basic", + ], + }, + "cookieName": "sid", + "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "loginAssistanceMessage": "", + "secureCookies": false, + "session": Object { + "idleTimeout": null, + "lifespan": null, + }, + } + `); expect(ConfigSchema.validate({}, { dist: true })).toMatchInlineSnapshot(` - Object { - "authc": Object { - "providers": Array [ - "basic", - ], - }, - "cookieName": "sid", - "loginAssistanceMessage": "", - "secureCookies": false, - "session": Object { - "idleTimeout": null, - "lifespan": null, - }, - } - `); + Object { + "authc": Object { + "http": Object { + "autoSchemesEnabled": true, + "enabled": true, + "schemes": Array [ + "apikey", + ], + }, + "providers": Array [ + "basic", + ], + }, + "cookieName": "sid", + "loginAssistanceMessage": "", + "secureCookies": false, + "session": Object { + "idleTimeout": null, + "lifespan": null, + }, + } + `); }); it('should throw error if xpack.security.encryptionKey is less than 32 characters', () => { @@ -101,15 +122,22 @@ describe('config schema', () => { authc: { providers: ['oidc'], oidc: { realm: 'realm-1' } }, }).authc ).toMatchInlineSnapshot(` - Object { - "oidc": Object { - "realm": "realm-1", - }, - "providers": Array [ - "oidc", - ], - } - `); + Object { + "http": Object { + "autoSchemesEnabled": true, + "enabled": true, + "schemes": Array [ + "apikey", + ], + }, + "oidc": Object { + "realm": "realm-1", + }, + "providers": Array [ + "oidc", + ], + } + `); }); it(`returns a validation error when authc.providers is "['oidc', 'basic']" and realm is unspecified`, async () => { @@ -126,16 +154,23 @@ describe('config schema', () => { authc: { providers: ['oidc', 'basic'], oidc: { realm: 'realm-1' } }, }).authc ).toMatchInlineSnapshot(` - Object { - "oidc": Object { - "realm": "realm-1", - }, - "providers": Array [ - "oidc", - "basic", - ], - } - `); + Object { + "http": Object { + "autoSchemesEnabled": true, + "enabled": true, + "schemes": Array [ + "apikey", + ], + }, + "oidc": Object { + "realm": "realm-1", + }, + "providers": Array [ + "oidc", + "basic", + ], + } + `); }); it(`realm is not allowed when authc.providers is "['basic']"`, async () => { @@ -164,18 +199,25 @@ describe('config schema', () => { authc: { providers: ['saml'], saml: { realm: 'realm-1' } }, }).authc ).toMatchInlineSnapshot(` - Object { - "providers": Array [ - "saml", - ], - "saml": Object { - "maxRedirectURLSize": ByteSizeValue { - "valueInBytes": 2048, - }, - "realm": "realm-1", - }, - } - `); + Object { + "http": Object { + "autoSchemesEnabled": true, + "enabled": true, + "schemes": Array [ + "apikey", + ], + }, + "providers": Array [ + "saml", + ], + "saml": Object { + "maxRedirectURLSize": ByteSizeValue { + "valueInBytes": 2048, + }, + "realm": "realm-1", + }, + } + `); }); it('`realm` is not allowed if saml provider is not enabled', async () => { diff --git a/x-pack/plugins/security/server/config.ts b/x-pack/plugins/security/server/config.ts index db8c48f314d7c..8663a6e61c203 100644 --- a/x-pack/plugins/security/server/config.ts +++ b/x-pack/plugins/security/server/config.ts @@ -49,6 +49,11 @@ export const ConfigSchema = schema.object( maxRedirectURLSize: schema.byteSize({ defaultValue: '2kb' }), }) ), + http: schema.object({ + enabled: schema.boolean({ defaultValue: true }), + autoSchemesEnabled: schema.boolean({ defaultValue: true }), + schemes: schema.arrayOf(schema.string(), { defaultValue: ['apikey'] }), + }), }), }, // This option should be removed as soon as we entirely migrate config from legacy Security plugin. diff --git a/x-pack/plugins/security/server/index.ts b/x-pack/plugins/security/server/index.ts index c0e86b289fe54..e1167af0be7f0 100644 --- a/x-pack/plugins/security/server/index.ts +++ b/x-pack/plugins/security/server/index.ts @@ -32,6 +32,17 @@ export const config: PluginConfigDescriptor> = { deprecations: ({ rename, unused }) => [ rename('sessionTimeout', 'session.idleTimeout'), unused('authorization.legacyFallback.enabled'), + (settings, fromPath, log) => { + const hasProvider = (provider: string) => + settings?.xpack?.security?.authc?.providers?.includes(provider) ?? false; + + if (hasProvider('basic') && hasProvider('token')) { + log( + 'Enabling both `basic` and `token` authentication providers in `xpack.security.authc.providers` is deprecated. Login page will only use `token` provider.' + ); + } + return settings; + }, ], }; export const plugin: PluginInitializer< diff --git a/x-pack/plugins/security/server/plugin.test.ts b/x-pack/plugins/security/server/plugin.test.ts index 56aad4ece3e95..6f5c79e873e86 100644 --- a/x-pack/plugins/security/server/plugin.test.ts +++ b/x-pack/plugins/security/server/plugin.test.ts @@ -28,6 +28,7 @@ describe('Security Plugin', () => { authc: { providers: ['saml', 'token'], saml: { realm: 'saml1', maxRedirectURLSize: new ByteSizeValue(2048) }, + http: { enabled: true, autoSchemesEnabled: true, schemes: ['apikey'] }, }, }) ); @@ -77,6 +78,7 @@ describe('Security Plugin', () => { "getSessionInfo": [Function], "invalidateAPIKey": [Function], "isAuthenticated": [Function], + "isProviderEnabled": [Function], "login": [Function], "logout": [Function], }, diff --git a/x-pack/plugins/security/server/routes/authentication/basic.test.ts b/x-pack/plugins/security/server/routes/authentication/basic.test.ts index be17b3e29f854..cc1c94d799be6 100644 --- a/x-pack/plugins/security/server/routes/authentication/basic.test.ts +++ b/x-pack/plugins/security/server/routes/authentication/basic.test.ts @@ -33,7 +33,9 @@ describe('Basic authentication routes', () => { let mockContext: RequestHandlerContext; beforeEach(() => { router = httpServiceMock.createRouter(); + authc = authenticationMock.create(); + authc.isProviderEnabled.mockImplementation(provider => provider === 'basic'); mockContext = ({ licensing: { @@ -166,6 +168,22 @@ describe('Basic authentication routes', () => { value: { username: 'user', password: 'password' }, }); }); + + it('prefers `token` authentication provider if it is enabled', async () => { + authc.login.mockResolvedValue(AuthenticationResult.succeeded(mockAuthenticatedUser())); + authc.isProviderEnabled.mockImplementation( + provider => provider === 'token' || provider === 'basic' + ); + + const response = await routeHandler(mockContext, mockRequest, kibanaResponseFactory); + + expect(response.status).toBe(204); + expect(response.payload).toBeUndefined(); + expect(authc.login).toHaveBeenCalledWith(mockRequest, { + provider: 'token', + value: { username: 'user', password: 'password' }, + }); + }); }); }); }); diff --git a/x-pack/plugins/security/server/routes/authentication/basic.ts b/x-pack/plugins/security/server/routes/authentication/basic.ts index 453dc1c4ea3b5..db36e45fc07e8 100644 --- a/x-pack/plugins/security/server/routes/authentication/basic.ts +++ b/x-pack/plugins/security/server/routes/authentication/basic.ts @@ -25,16 +25,13 @@ export function defineBasicRoutes({ router, authc, config }: RouteDefinitionPara options: { authRequired: false }, }, createLicensedRouteHandler(async (context, request, response) => { - const { username, password } = request.body; + // We should prefer `token` over `basic` if possible. + const loginAttempt = authc.isProviderEnabled('token') + ? { provider: 'token', value: request.body } + : { provider: 'basic', value: request.body }; try { - // We should prefer `token` over `basic` if possible. - const providerToLoginWith = config.authc.providers.includes('token') ? 'token' : 'basic'; - const authenticationResult = await authc.login(request, { - provider: providerToLoginWith, - value: { username, password }, - }); - + const authenticationResult = await authc.login(request, loginAttempt); if (!authenticationResult.succeeded()) { return response.unauthorized({ body: authenticationResult.error }); } diff --git a/x-pack/plugins/security/server/routes/authentication/index.ts b/x-pack/plugins/security/server/routes/authentication/index.ts index 6035025564cbf..a774edfb4ab2c 100644 --- a/x-pack/plugins/security/server/routes/authentication/index.ts +++ b/x-pack/plugins/security/server/routes/authentication/index.ts @@ -27,18 +27,15 @@ export function defineAuthenticationRoutes(params: RouteDefinitionParams) { defineSessionRoutes(params); defineCommonRoutes(params); - if ( - params.config.authc.providers.includes('basic') || - params.config.authc.providers.includes('token') - ) { + if (params.authc.isProviderEnabled('basic') || params.authc.isProviderEnabled('token')) { defineBasicRoutes(params); } - if (params.config.authc.providers.includes('saml')) { + if (params.authc.isProviderEnabled('saml')) { defineSAMLRoutes(params); } - if (params.config.authc.providers.includes('oidc')) { + if (params.authc.isProviderEnabled('oidc')) { defineOIDCRoutes(params); } } diff --git a/x-pack/test/api_integration/apis/security/session.ts b/x-pack/test/api_integration/apis/security/session.ts index d819dd38dddb1..ef7e48388ff66 100644 --- a/x-pack/test/api_integration/apis/security/session.ts +++ b/x-pack/test/api_integration/apis/security/session.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect/expect.js'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); const config = getService('config'); const kibanaServerConfig = config.get('servers.kibana'); @@ -25,7 +25,7 @@ export default function({ getService }: FtrProviderContext) { return response; }; const getSessionInfo = async () => - supertest + supertestWithoutAuth .get('/internal/security/session') .set('kbn-xsrf', 'xxx') .set('kbn-system-request', 'true') @@ -33,7 +33,7 @@ export default function({ getService }: FtrProviderContext) { .send() .expect(200); const extendSession = async () => - supertest + supertestWithoutAuth .post('/internal/security/session') .set('kbn-xsrf', 'xxx') .set('Cookie', sessionCookie.cookieString()) @@ -42,7 +42,7 @@ export default function({ getService }: FtrProviderContext) { .then(saveCookie); beforeEach(async () => { - await supertest + await supertestWithoutAuth .post('/internal/security/login') .set('kbn-xsrf', 'xxx') .send({ username: validUsername, password: validPassword })
+ + ); + + expect(props.registerProvider.mock.calls.length).toEqual(0); + }); + + it('calls registerProvider when isDragging', () => { + mount( + +
+ + ); + + expect(props.registerProvider.mock.calls.length).toEqual(1); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx index 7d84403b87f8d..4b80b9fff2740 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { createContext, useContext, useEffect } from 'react'; +import React, { createContext, useCallback, useContext, useEffect, useState } from 'react'; import { Draggable, DraggableProvided, DraggableStateSnapshot, Droppable, } from 'react-beautiful-dnd'; -import { connect, ConnectedProps } from 'react-redux'; +import { useDispatch } from 'react-redux'; import styled from 'styled-components'; import deepEqual from 'fast-deep-equal'; @@ -47,34 +47,50 @@ const ProviderContentWrapper = styled.span` } `; +type RenderFunctionProp = ( + props: DataProvider, + provided: DraggableProvided, + state: DraggableStateSnapshot +) => React.ReactNode; + interface OwnProps { dataProvider: DataProvider; inline?: boolean; - render: ( - props: DataProvider, - provided: DraggableProvided, - state: DraggableStateSnapshot - ) => React.ReactNode; + render: RenderFunctionProp; truncate?: boolean; } -type Props = OwnProps & PropsFromRedux; +type Props = OwnProps; /** * Wraps a draggable component to handle registration / unregistration of the * data provider associated with the item being dropped */ -const DraggableWrapperComponent = React.memo( - ({ dataProvider, registerProvider, render, truncate, unRegisterProvider }) => { +export const DraggableWrapper = React.memo( + ({ dataProvider, render, truncate }) => { + const [providerRegistered, setProviderRegistered] = useState(false); + const dispatch = useDispatch(); const usePortal = useDraggablePortalContext(); - useEffect(() => { - registerProvider!({ provider: dataProvider }); - return () => { - unRegisterProvider!({ id: dataProvider.id }); - }; - }, []); + const registerProvider = useCallback(() => { + if (!providerRegistered) { + dispatch(dragAndDropActions.registerProvider({ provider: dataProvider })); + setProviderRegistered(true); + } + }, [dispatch, providerRegistered, dataProvider]); + + const unRegisterProvider = useCallback( + () => dispatch(dragAndDropActions.unRegisterProvider({ id: dataProvider.id })), + [dispatch, dataProvider] + ); + + useEffect( + () => () => { + unRegisterProvider(); + }, + [] + ); return ( @@ -87,13 +103,18 @@ const DraggableWrapperComponent = React.memo( key={getDraggableId(dataProvider.id)} > {(provided, snapshot) => ( - + ( ); }, - (prevProps, nextProps) => { - return ( - deepEqual(prevProps.dataProvider, nextProps.dataProvider) && - prevProps.render !== nextProps.render && - prevProps.truncate === nextProps.truncate - ); - } + (prevProps, nextProps) => + deepEqual(prevProps.dataProvider, nextProps.dataProvider) && + prevProps.render !== nextProps.render && + prevProps.truncate === nextProps.truncate ); -DraggableWrapperComponent.displayName = 'DraggableWrapperComponent'; - -const mapDispatchToProps = { - registerProvider: dragAndDropActions.registerProvider, - unRegisterProvider: dragAndDropActions.unRegisterProvider, -}; - -const connector = connect(null, mapDispatchToProps); - -type PropsFromRedux = ConnectedProps; - -export const DraggableWrapper = connector(DraggableWrapperComponent); - DraggableWrapper.displayName = 'DraggableWrapper'; /** @@ -150,8 +155,24 @@ DraggableWrapper.displayName = 'DraggableWrapper'; * * See: https://github.com/atlassian/react-beautiful-dnd/issues/499 */ -const ConditionalPortal = React.memo<{ children: React.ReactNode; usePortal: boolean }>( - ({ children, usePortal }) => (usePortal ? {children} : <>{children}) + +interface ConditionalPortalProps { + children: React.ReactNode; + usePortal: boolean; + isDragging: boolean; + registerProvider: () => void; +} + +export const ConditionalPortal = React.memo( + ({ children, usePortal, registerProvider, isDragging }) => { + useEffect(() => { + if (isDragging) { + registerProvider(); + } + }, [isDragging, registerProvider]); + + return usePortal ? {children} : <>{children}; + } ); ConditionalPortal.displayName = 'ConditionalPortal'; From d474ccf244d22b8abf7df1be3e96b36b715281f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Thu, 27 Feb 2020 22:55:02 +0100 Subject: [PATCH 51/64] [APM] Fix timeout in APM setup (#58727) * [APM] Fix timeout in APM setup * Update plugin.ts --- src/plugins/apm_oss/server/index.ts | 2 +- src/plugins/apm_oss/server/plugin.ts | 6 ++- .../get_dynamic_index_pattern.ts | 3 +- .../create_agent_config_index.ts | 9 ++-- x-pack/plugins/apm/server/plugin.ts | 43 ++++++++----------- 5 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/plugins/apm_oss/server/index.ts b/src/plugins/apm_oss/server/index.ts index 801140694c139..95a4ae4519bc9 100644 --- a/src/plugins/apm_oss/server/index.ts +++ b/src/plugins/apm_oss/server/index.ts @@ -38,4 +38,4 @@ export function plugin(initializerContext: PluginInitializerContext) { export type APMOSSConfig = TypeOf; -export { APMOSSPlugin as Plugin }; +export { APMOSSPluginSetup } from './plugin'; diff --git a/src/plugins/apm_oss/server/plugin.ts b/src/plugins/apm_oss/server/plugin.ts index 2708f7729482b..9b14d19da90c2 100644 --- a/src/plugins/apm_oss/server/plugin.ts +++ b/src/plugins/apm_oss/server/plugin.ts @@ -20,7 +20,7 @@ import { Plugin, CoreSetup, PluginInitializerContext } from 'src/core/server'; import { Observable } from 'rxjs'; import { APMOSSConfig } from './'; -export class APMOSSPlugin implements Plugin<{ config$: Observable }> { +export class APMOSSPlugin implements Plugin { constructor(private readonly initContext: PluginInitializerContext) { this.initContext = initContext; } @@ -36,3 +36,7 @@ export class APMOSSPlugin implements Plugin<{ config$: Observable start() {} stop() {} } + +export interface APMOSSPluginSetup { + config$: Observable; +} diff --git a/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts b/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts index b1e4906317f81..a7476bf564a16 100644 --- a/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts +++ b/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts @@ -62,8 +62,7 @@ export const getDynamicIndexPattern = async ({ cache.set(CACHE_KEY, undefined); const notExists = e.output?.statusCode === 404; if (notExists) { - // eslint-disable-next-line no-console - console.error( + context.logger.error( `Could not get dynamic index pattern because indices "${indexPatternTitle}" don't exist` ); return; diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts index af2d2a13eaa2f..8cfb7e7edb4c6 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts @@ -4,17 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IClusterClient } from 'src/core/server'; +import { IClusterClient, Logger } from 'src/core/server'; import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; import { APMConfig } from '../../..'; import { getApmIndicesConfig } from '../apm_indices/get_apm_indices'; export async function createApmAgentConfigurationIndex({ esClient, - config + config, + logger }: { esClient: IClusterClient; config: APMConfig; + logger: Logger; }) { try { const index = getApmIndicesConfig(config).apmAgentConfigurationIndex; @@ -32,8 +34,7 @@ export async function createApmAgentConfigurationIndex({ ); } } catch (e) { - // eslint-disable-next-line no-console - console.error('Could not create APM Agent configuration:', e.message); + logger.error(`Could not create APM Agent configuration: ${e.message}`); } } diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index adc80cb43620b..773f0d4e6fac5 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -5,12 +5,12 @@ */ import { PluginInitializerContext, Plugin, CoreSetup } from 'src/core/server'; import { Observable, combineLatest, AsyncSubject } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { map, take } from 'rxjs/operators'; import { Server } from 'hapi'; import { once } from 'lodash'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { APMOSSPluginSetup } from '../../../../src/plugins/apm_oss/server'; import { makeApmUsageCollector } from './lib/apm_telemetry'; -import { Plugin as APMOSSPlugin } from '../../../../src/plugins/apm_oss/server'; import { createApmAgentConfigurationIndex } from './lib/settings/agent_configuration/create_agent_config_index'; import { createApmApi } from './routes/create_apm_api'; import { getApmIndices } from './lib/settings/apm_indices/get_apm_indices'; @@ -33,26 +33,23 @@ export interface APMPluginContract { export class APMPlugin implements Plugin { legacySetup$: AsyncSubject; - currentConfig: APMConfig; constructor(private readonly initContext: PluginInitializerContext) { this.initContext = initContext; this.legacySetup$ = new AsyncSubject(); - this.currentConfig = {} as APMConfig; } public async setup( core: CoreSetup, plugins: { - apm_oss: APMOSSPlugin extends Plugin ? TSetup : never; + apm_oss: APMOSSPluginSetup; home: HomeServerPluginSetup; licensing: LicensingPluginSetup; cloud?: CloudSetup; usageCollection?: UsageCollectionSetup; } ) { - const config$ = this.initContext.config.create(); const logger = this.initContext.logger.get('apm'); - + const config$ = this.initContext.config.create(); const mergedConfig$ = combineLatest(plugins.apm_oss.config$, config$).pipe( map(([apmOssConfig, apmConfig]) => mergeConfigs(apmOssConfig, apmConfig)) ); @@ -61,28 +58,26 @@ export class APMPlugin implements Plugin { createApmApi().init(core, { config$: mergedConfig$, logger, __LEGACY }); }); - await new Promise(resolve => { - mergedConfig$.subscribe(async config => { - this.currentConfig = config; - await createApmAgentConfigurationIndex({ - esClient: core.elasticsearch.dataClient, - config - }); - resolve(); - }); + const currentConfig = await mergedConfig$.pipe(take(1)).toPromise(); + + // create agent configuration index without blocking setup lifecycle + createApmAgentConfigurationIndex({ + esClient: core.elasticsearch.dataClient, + config: currentConfig, + logger }); plugins.home.tutorials.registerTutorial( tutorialProvider({ - isEnabled: this.currentConfig['xpack.apm.ui.enabled'], - indexPatternTitle: this.currentConfig['apm_oss.indexPattern'], + isEnabled: currentConfig['xpack.apm.ui.enabled'], + indexPatternTitle: currentConfig['apm_oss.indexPattern'], cloud: plugins.cloud, indices: { - errorIndices: this.currentConfig['apm_oss.errorIndices'], - metricsIndices: this.currentConfig['apm_oss.metricsIndices'], - onboardingIndices: this.currentConfig['apm_oss.onboardingIndices'], - sourcemapIndices: this.currentConfig['apm_oss.sourcemapIndices'], - transactionIndices: this.currentConfig['apm_oss.transactionIndices'] + errorIndices: currentConfig['apm_oss.errorIndices'], + metricsIndices: currentConfig['apm_oss.metricsIndices'], + onboardingIndices: currentConfig['apm_oss.onboardingIndices'], + sourcemapIndices: currentConfig['apm_oss.sourcemapIndices'], + transactionIndices: currentConfig['apm_oss.transactionIndices'] } }) ); @@ -108,7 +103,7 @@ export class APMPlugin implements Plugin { getApmIndices: async () => getApmIndices({ savedObjectsClient: await getInternalSavedObjectsClient(core), - config: this.currentConfig + config: currentConfig }) }; } From 07c22f13b73ee29ade817d8abb8f73823df76899 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 27 Feb 2020 15:23:54 -0700 Subject: [PATCH 52/64] skip flaky suite (#58785) --- x-pack/test/api_integration/apis/security/privileges.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/security/privileges.ts b/x-pack/test/api_integration/apis/security/privileges.ts index 7b1984222404b..81cffaac07285 100644 --- a/x-pack/test/api_integration/apis/security/privileges.ts +++ b/x-pack/test/api_integration/apis/security/privileges.ts @@ -9,7 +9,8 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - describe('Privileges', () => { + // FLAKY: https://github.com/elastic/kibana/issues/58785 + describe.skip('Privileges', () => { describe('GET /api/security/privileges', () => { it('should return a privilege map with all known privileges, without actions', async () => { await supertest From 467280232abf822d258aef5459e91e0375124485 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 27 Feb 2020 17:19:35 -0700 Subject: [PATCH 53/64] Revert "[SIEM] Fix Timeline registerProvider to be called only when it's needed (#58051)" This reverts commit 2a03dffdad6c1dbeaf9a541c4ea0fb84183a8ca8. --- .../drag_and_drop/draggable_wrapper.test.tsx | 31 +----- .../drag_and_drop/draggable_wrapper.tsx | 99 ++++++++----------- 2 files changed, 40 insertions(+), 90 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx index d34f4cce9fea4..92adc1a9adb7a 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx @@ -12,7 +12,7 @@ import { mockBrowserFields, mocksSource } from '../../containers/source/mock'; import { TestProviders } from '../../mock'; import { mockDataProviders } from '../timeline/data_providers/mock/mock_data_providers'; import { DragDropContextWrapper } from './drag_drop_context_wrapper'; -import { DraggableWrapper, ConditionalPortal } from './draggable_wrapper'; +import { DraggableWrapper } from './draggable_wrapper'; import { useMountAppended } from '../../utils/use_mount_appended'; describe('DraggableWrapper', () => { @@ -84,32 +84,3 @@ describe('DraggableWrapper', () => { }); }); }); - -describe('ConditionalPortal', () => { - const mount = useMountAppended(); - const props = { - usePortal: false, - registerProvider: jest.fn(), - isDragging: true, - }; - - it(`doesn't call registerProvider is NOT isDragging`, () => { - mount( - -
- - ); - - expect(props.registerProvider.mock.calls.length).toEqual(0); - }); - - it('calls registerProvider when isDragging', () => { - mount( - -
- - ); - - expect(props.registerProvider.mock.calls.length).toEqual(1); - }); -}); diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx index 4b80b9fff2740..7d84403b87f8d 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { createContext, useCallback, useContext, useEffect, useState } from 'react'; +import React, { createContext, useContext, useEffect } from 'react'; import { Draggable, DraggableProvided, DraggableStateSnapshot, Droppable, } from 'react-beautiful-dnd'; -import { useDispatch } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; import deepEqual from 'fast-deep-equal'; @@ -47,50 +47,34 @@ const ProviderContentWrapper = styled.span` } `; -type RenderFunctionProp = ( - props: DataProvider, - provided: DraggableProvided, - state: DraggableStateSnapshot -) => React.ReactNode; - interface OwnProps { dataProvider: DataProvider; inline?: boolean; - render: RenderFunctionProp; + render: ( + props: DataProvider, + provided: DraggableProvided, + state: DraggableStateSnapshot + ) => React.ReactNode; truncate?: boolean; } -type Props = OwnProps; +type Props = OwnProps & PropsFromRedux; /** * Wraps a draggable component to handle registration / unregistration of the * data provider associated with the item being dropped */ -export const DraggableWrapper = React.memo( - ({ dataProvider, render, truncate }) => { - const [providerRegistered, setProviderRegistered] = useState(false); - const dispatch = useDispatch(); +const DraggableWrapperComponent = React.memo( + ({ dataProvider, registerProvider, render, truncate, unRegisterProvider }) => { const usePortal = useDraggablePortalContext(); - const registerProvider = useCallback(() => { - if (!providerRegistered) { - dispatch(dragAndDropActions.registerProvider({ provider: dataProvider })); - setProviderRegistered(true); - } - }, [dispatch, providerRegistered, dataProvider]); - - const unRegisterProvider = useCallback( - () => dispatch(dragAndDropActions.unRegisterProvider({ id: dataProvider.id })), - [dispatch, dataProvider] - ); - - useEffect( - () => () => { - unRegisterProvider(); - }, - [] - ); + useEffect(() => { + registerProvider!({ provider: dataProvider }); + return () => { + unRegisterProvider!({ id: dataProvider.id }); + }; + }, []); return ( @@ -103,18 +87,13 @@ export const DraggableWrapper = React.memo( key={getDraggableId(dataProvider.id)} > {(provided, snapshot) => ( - + ( ); }, - (prevProps, nextProps) => - deepEqual(prevProps.dataProvider, nextProps.dataProvider) && - prevProps.render !== nextProps.render && - prevProps.truncate === nextProps.truncate + (prevProps, nextProps) => { + return ( + deepEqual(prevProps.dataProvider, nextProps.dataProvider) && + prevProps.render !== nextProps.render && + prevProps.truncate === nextProps.truncate + ); + } ); +DraggableWrapperComponent.displayName = 'DraggableWrapperComponent'; + +const mapDispatchToProps = { + registerProvider: dragAndDropActions.registerProvider, + unRegisterProvider: dragAndDropActions.unRegisterProvider, +}; + +const connector = connect(null, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const DraggableWrapper = connector(DraggableWrapperComponent); + DraggableWrapper.displayName = 'DraggableWrapper'; /** @@ -155,24 +150,8 @@ DraggableWrapper.displayName = 'DraggableWrapper'; * * See: https://github.com/atlassian/react-beautiful-dnd/issues/499 */ - -interface ConditionalPortalProps { - children: React.ReactNode; - usePortal: boolean; - isDragging: boolean; - registerProvider: () => void; -} - -export const ConditionalPortal = React.memo( - ({ children, usePortal, registerProvider, isDragging }) => { - useEffect(() => { - if (isDragging) { - registerProvider(); - } - }, [isDragging, registerProvider]); - - return usePortal ? {children} : <>{children}; - } +const ConditionalPortal = React.memo<{ children: React.ReactNode; usePortal: boolean }>( + ({ children, usePortal }) => (usePortal ? {children} : <>{children}) ); ConditionalPortal.displayName = 'ConditionalPortal'; From facae44f5b17481cf450e5b310b33a16239feff0 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 27 Feb 2020 18:03:04 -0700 Subject: [PATCH 54/64] skip flaky suite (#53888) --- test/functional/apps/context/_size.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/context/_size.js b/test/functional/apps/context/_size.js index 5f3d1ebe40974..ea9b2c8cf1819 100644 --- a/test/functional/apps/context/_size.js +++ b/test/functional/apps/context/_size.js @@ -30,7 +30,8 @@ export default function({ getService, getPageObjects }) { const docTable = getService('docTable'); const PageObjects = getPageObjects(['context']); - describe('context size', function contextSize() { + // FLAKY: https://github.com/elastic/kibana/issues/53888 + describe.skip('context size', function contextSize() { before(async function() { await kibanaServer.uiSettings.update({ 'context:defaultSize': `${TEST_DEFAULT_CONTEXT_SIZE}`, From 8c3d71b370fadf5872185decedc34886ae151263 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Thu, 27 Feb 2020 21:15:08 -0500 Subject: [PATCH 55/64] [ML] NP: migrate server (#58680) * remove obsolete legacy server deps * licensePreRoutingFactory uses licensing plugin rather than legacy xpack * move schemas to dir in routes * use NP license check method for license check * store license data in plugin for passing to check * create server plugin files in NP plugin dir * remove dependency on legacy xpack plugin * add sample data links first step * move all server dirs from legacy to np dir * fix requiredPlugin spaces name and update import routes * delete unnecessary files and add sample data links * update license and privilege check tests * add routeInit types --- x-pack/.i18nrc.json | 2 +- .../legacy/plugins/ml/common/constants/app.ts | 2 +- .../plugins/ml/common/constants/license.ts | 2 + x-pack/legacy/plugins/ml/index.ts | 55 +--- x-pack/legacy/plugins/ml/kibana.json | 8 - .../application/license/check_license.tsx | 11 +- .../call_with_internal_user_factory.d.ts | 9 - .../client/call_with_internal_user_factory.js | 18 -- .../call_with_internal_user_factory.test.ts | 28 --- .../client/call_with_request_factory.js | 21 -- .../ml/server/lib/__tests__/security_utils.js | 35 --- .../plugins/ml/server/lib/security_utils.d.ts | 9 - .../plugins/ml/server/lib/security_utils.js | 19 -- .../plugins/ml/server/new_platform/plugin.ts | 238 ------------------ x-pack/plugins/ml/kibana.json | 9 + .../client/__tests__/elasticsearch_ml.js | 0 .../ml/server/client/elasticsearch_ml.js | 0 .../plugins/ml/server/client/error_wrapper.ts | 0 .../plugins/ml/server/client/errors.js | 0 .../plugins/ml/server/client/log.ts | 2 +- .../ml/server}/index.ts | 7 +- .../ml/server/lib/__tests__/query_utils.js | 0 .../server/lib/check_annotations/index.d.ts | 0 .../ml/server/lib/check_annotations/index.js | 2 +- .../lib/check_license/check_license.test.ts | 46 ++-- .../server/lib/check_license/check_license.ts | 22 +- .../ml/server/lib/check_license/index.ts | 0 .../__mocks__/call_with_request.ts | 0 .../check_privileges/check_privileges.test.ts | 120 +++------ .../lib/check_privileges/check_privileges.ts | 16 +- .../ml/server/lib/check_privileges/index.ts | 0 .../server/lib/check_privileges/privileges.ts | 0 .../ml/server/lib/check_privileges/upgrade.ts | 0 .../ml/server/lib/ml_telemetry/index.ts | 0 .../ml_telemetry/make_ml_usage_collector.ts | 0 .../lib/ml_telemetry/ml_telemetry.test.ts | 30 +-- .../server/lib/ml_telemetry/ml_telemetry.ts | 19 +- .../plugins/ml/server/lib/query_utils.ts | 0 .../ml/server/lib/sample_data_sets/index.ts | 0 .../lib/sample_data_sets/sample_data_sets.ts | 0 .../plugins/ml/server/lib/spaces_utils.ts | 7 +- .../__mocks__/get_annotations_request.json | 0 .../__mocks__/get_annotations_response.json | 0 .../annotation_service/annotation.test.ts | 9 +- .../models/annotation_service/annotation.ts | 6 +- .../server/models/annotation_service/index.ts | 0 .../__tests__/bucket_span_estimator.js | 0 .../bucket_span_estimator.d.ts | 4 +- .../bucket_span_estimator.js | 10 +- .../models/bucket_span_estimator/index.ts | 0 .../models/bucket_span_estimator/intervals.js | 0 .../polled_data_checker.js | 0 .../single_series_checker.js | 0 .../calculate_model_memory_limit.d.ts | 0 .../calculate_model_memory_limit.js | 0 .../calculate_model_memory_limit/index.ts | 0 .../models/calendar/calendar_manager.ts | 0 .../server/models/calendar/event_manager.ts | 2 +- .../ml/server/models/calendar/index.ts | 0 .../analytics_audit_messages.ts | 6 +- .../models/data_frame_analytics/index.js | 0 .../data_recognizer/data_recognizer.test.ts | 2 +- .../models/data_recognizer/data_recognizer.ts | 9 +- .../ml/server/models/data_recognizer/index.ts | 0 .../ml_http_access_explorer_ecs.json | 0 .../search/ml_http_access_filebeat_ecs.json | 0 .../ml_http_access_events_timechart_ecs.json | 0 .../visualization/ml_http_access_map_ecs.json | 0 ...l_http_access_source_ip_timechart_ecs.json | 0 ...http_access_status_code_timechart_ecs.json | 0 ..._http_access_top_source_ips_table_ecs.json | 0 .../ml_http_access_top_urls_table_ecs.json | 0 ...access_unique_count_url_timechart_ecs.json | 0 .../modules/apache_ecs/logo.json | 0 .../modules/apache_ecs/manifest.json | 0 .../ml/datafeed_low_request_rate_ecs.json | 0 .../datafeed_source_ip_request_rate_ecs.json | 0 .../ml/datafeed_source_ip_url_count_ecs.json | 0 .../ml/datafeed_status_code_rate_ecs.json | 0 .../ml/datafeed_visitor_rate_ecs.json | 0 .../apache_ecs/ml/low_request_rate_ecs.json | 0 .../ml/source_ip_request_rate_ecs.json | 0 .../ml/source_ip_url_count_ecs.json | 0 .../apache_ecs/ml/status_code_rate_ecs.json | 0 .../apache_ecs/ml/visitor_rate_ecs.json | 0 .../modules/apm_jsbase/logo.json | 0 .../modules/apm_jsbase/manifest.json | 0 .../ml/abnormal_span_durations_jsbase.json | 0 ...ous_error_rate_for_user_agents_jsbase.json | 0 ...tafeed_abnormal_span_durations_jsbase.json | 0 ...ous_error_rate_for_user_agents_jsbase.json | 0 .../datafeed_decreased_throughput_jsbase.json | 0 ...afeed_high_count_by_user_agent_jsbase.json | 0 .../ml/decreased_throughput_jsbase.json | 0 .../ml/high_count_by_user_agent_jsbase.json | 0 .../modules/apm_nodejs/logo.json | 0 .../modules/apm_nodejs/manifest.json | 0 .../ml/abnormal_span_durations_nodejs.json | 0 .../ml/abnormal_trace_durations_nodejs.json | 0 ...tafeed_abnormal_span_durations_nodejs.json | 0 ...afeed_abnormal_trace_durations_nodejs.json | 0 .../datafeed_decreased_throughput_nodejs.json | 0 .../ml/decreased_throughput_nodejs.json | 0 .../modules/apm_transaction/logo.json | 0 .../modules/apm_transaction/manifest.json | 0 .../ml/datafeed_high_mean_response_time.json | 0 .../ml/high_mean_response_time.json | 0 ...ditbeat_docker_process_event_rate_ecs.json | 0 ...auditbeat_docker_process_explorer_ecs.json | 0 ...l_auditbeat_docker_process_events_ecs.json | 0 ...ker_process_event_rate_by_process_ecs.json | 0 ...eat_docker_process_event_rate_vis_ecs.json | 0 ...ditbeat_docker_process_occurrence_ecs.json | 0 .../auditbeat_process_docker_ecs/logo.json | 0 .../manifest.json | 0 ..._docker_high_count_process_events_ecs.json | 0 ...feed_docker_rare_process_activity_ecs.json | 0 .../docker_high_count_process_events_ecs.json | 0 .../ml/docker_rare_process_activity_ecs.json | 0 ...uditbeat_hosts_process_event_rate_ecs.json | 0 ..._auditbeat_hosts_process_explorer_ecs.json | 0 ...ml_auditbeat_hosts_process_events_ecs.json | 0 ...sts_process_event_rate_by_process_ecs.json | 0 ...beat_hosts_process_event_rate_vis_ecs.json | 0 ...uditbeat_hosts_process_occurrence_ecs.json | 0 .../auditbeat_process_hosts_ecs/logo.json | 0 .../auditbeat_process_hosts_ecs/manifest.json | 0 ...d_hosts_high_count_process_events_ecs.json | 0 ...afeed_hosts_rare_process_activity_ecs.json | 0 .../hosts_high_count_process_events_ecs.json | 0 .../ml/hosts_rare_process_activity_ecs.json | 0 .../modules/logs_ui_analysis/logo.json | 0 .../modules/logs_ui_analysis/manifest.json | 0 .../ml/datafeed_log_entry_rate.json | 0 .../logs_ui_analysis/ml/log_entry_rate.json | 0 .../modules/logs_ui_categories/logo.json | 0 .../modules/logs_ui_categories/manifest.json | 0 .../datafeed_log_entry_categories_count.json | 0 .../ml/log_entry_categories_count.json | 0 .../modules/metricbeat_system_ecs/logo.json | 0 .../metricbeat_system_ecs/manifest.json | 0 .../ml/datafeed_high_mean_cpu_iowait_ecs.json | 0 .../ml/datafeed_max_disk_utilization_ecs.json | 0 .../ml/datafeed_metricbeat_outages_ecs.json | 0 .../ml/high_mean_cpu_iowait_ecs.json | 0 .../ml/max_disk_utilization_ecs.json | 0 .../ml/metricbeat_outages_ecs.json | 0 .../ml_http_access_explorer_ecs.json | 0 .../search/ml_http_access_filebeat_ecs.json | 0 .../ml_http_access_events_timechart_ecs.json | 0 .../visualization/ml_http_access_map_ecs.json | 0 ...l_http_access_source_ip_timechart_ecs.json | 0 ...http_access_status_code_timechart_ecs.json | 0 ..._http_access_top_source_ips_table_ecs.json | 0 .../ml_http_access_top_urls_table_ecs.json | 0 ...access_unique_count_url_timechart_ecs.json | 0 .../modules/nginx_ecs/logo.json | 0 .../modules/nginx_ecs/manifest.json | 0 .../ml/datafeed_low_request_rate_ecs.json | 0 .../datafeed_source_ip_request_rate_ecs.json | 0 .../ml/datafeed_source_ip_url_count_ecs.json | 0 .../ml/datafeed_status_code_rate_ecs.json | 0 .../ml/datafeed_visitor_rate_ecs.json | 0 .../nginx_ecs/ml/low_request_rate_ecs.json | 0 .../ml/source_ip_request_rate_ecs.json | 0 .../nginx_ecs/ml/source_ip_url_count_ecs.json | 0 .../nginx_ecs/ml/status_code_rate_ecs.json | 0 .../nginx_ecs/ml/visitor_rate_ecs.json | 0 .../modules/sample_data_ecommerce/logo.json | 0 .../sample_data_ecommerce/manifest.json | 0 .../ml/datafeed_high_sum_total_sales.json | 0 .../ml/high_sum_total_sales.json | 0 .../modules/sample_data_weblogs/logo.json | 0 .../modules/sample_data_weblogs/manifest.json | 0 .../ml/datafeed_low_request_rate.json | 0 .../ml/datafeed_response_code_rates.json | 0 .../ml/datafeed_url_scanning.json | 0 .../ml/low_request_rate.json | 0 .../ml/response_code_rates.json | 0 .../sample_data_weblogs/ml/url_scanning.json | 0 .../modules/siem_auditbeat/logo.json | 0 .../modules/siem_auditbeat/manifest.json | 0 ..._linux_anomalous_network_activity_ecs.json | 0 ...x_anomalous_network_port_activity_ecs.json | 0 ...afeed_linux_anomalous_network_service.json | 0 ...ux_anomalous_network_url_activity_ecs.json | 0 ...linux_anomalous_process_all_hosts_ecs.json | 0 ...atafeed_linux_anomalous_user_name_ecs.json | 0 ...tafeed_rare_process_by_host_linux_ecs.json | 0 .../linux_anomalous_network_activity_ecs.json | 0 ...x_anomalous_network_port_activity_ecs.json | 0 .../ml/linux_anomalous_network_service.json | 0 ...ux_anomalous_network_url_activity_ecs.json | 0 ...linux_anomalous_process_all_hosts_ecs.json | 0 .../ml/linux_anomalous_user_name_ecs.json | 0 .../ml/rare_process_by_host_linux_ecs.json | 0 .../modules/siem_auditbeat_auth/logo.json | 0 .../modules/siem_auditbeat_auth/manifest.json | 0 ...atafeed_suspicious_login_activity_ecs.json | 0 .../ml/suspicious_login_activity_ecs.json | 0 .../modules/siem_packetbeat/logo.json | 0 .../modules/siem_packetbeat/manifest.json | 0 .../ml/datafeed_packetbeat_dns_tunneling.json | 0 ...datafeed_packetbeat_rare_dns_question.json | 0 ...atafeed_packetbeat_rare_server_domain.json | 0 .../ml/datafeed_packetbeat_rare_urls.json | 0 .../datafeed_packetbeat_rare_user_agent.json | 0 .../ml/packetbeat_dns_tunneling.json | 0 .../ml/packetbeat_rare_dns_question.json | 0 .../ml/packetbeat_rare_server_domain.json | 0 .../ml/packetbeat_rare_urls.json | 0 .../ml/packetbeat_rare_user_agent.json | 0 .../modules/siem_winlogbeat/logo.json | 0 .../modules/siem_winlogbeat/manifest.json | 0 ...feed_rare_process_by_host_windows_ecs.json | 0 ...indows_anomalous_network_activity_ecs.json | 0 ...d_windows_anomalous_path_activity_ecs.json | 0 ...ndows_anomalous_process_all_hosts_ecs.json | 0 ...ed_windows_anomalous_process_creation.json | 0 .../ml/datafeed_windows_anomalous_script.json | 0 .../datafeed_windows_anomalous_service.json | 0 ...afeed_windows_anomalous_user_name_ecs.json | 0 ...atafeed_windows_rare_user_runas_event.json | 0 .../ml/rare_process_by_host_windows_ecs.json | 0 ...indows_anomalous_network_activity_ecs.json | 0 .../windows_anomalous_path_activity_ecs.json | 0 ...ndows_anomalous_process_all_hosts_ecs.json | 0 .../windows_anomalous_process_creation.json | 0 .../ml/windows_anomalous_script.json | 0 .../ml/windows_anomalous_service.json | 0 .../ml/windows_anomalous_user_name_ecs.json | 0 .../ml/windows_rare_user_runas_event.json | 0 .../modules/siem_winlogbeat_auth/logo.json | 0 .../siem_winlogbeat_auth/manifest.json | 0 ...windows_rare_user_type10_remote_login.json | 0 ...windows_rare_user_type10_remote_login.json | 0 .../models/data_visualizer/data_visualizer.ts | 4 +- .../ml/server/models/data_visualizer/index.ts | 0 .../models/fields_service/fields_service.d.ts | 0 .../models/fields_service/fields_service.js | 0 .../ml/server/models/fields_service/index.ts | 0 .../file_data_visualizer.ts | 2 +- .../file_data_visualizer/import_data.ts | 2 +- .../models/file_data_visualizer/index.ts | 0 .../ml/server/models/filter/filter_manager.ts | 5 +- .../plugins/ml/server/models/filter/index.js | 0 .../plugins/ml/server/models/filter/index.ts | 0 .../server/models/job_audit_messages/index.ts | 0 .../job_audit_messages.d.ts | 0 .../job_audit_messages/job_audit_messages.js | 2 +- .../ml/server/models/job_service/datafeeds.js | 5 +- .../server/models/job_service/error_utils.js | 5 +- .../ml/server/models/job_service/groups.js | 2 +- .../ml/server/models/job_service/index.js | 0 .../ml/server/models/job_service/jobs.js | 7 +- .../new_job/categorization/examples.ts | 6 +- .../new_job/categorization/index.ts | 0 .../new_job/categorization/top_categories.ts | 9 +- .../categorization/validation_results.ts | 6 +- .../models/job_service/new_job/charts.ts | 2 +- .../models/job_service/new_job/index.ts | 0 .../models/job_service/new_job/line_chart.ts | 9 +- .../job_service/new_job/population_chart.ts | 9 +- .../responses/cloudwatch_field_caps.json | 0 .../responses/farequote_field_caps.json | 0 .../responses/kibana_saved_objects.json | 0 .../__mocks__/responses/rollup_caps.json | 0 .../results/cloudwatch_rollup_job_caps.json | 0 .../__mocks__/results/farequote_job_caps.json | 0 .../results/farequote_job_caps_empty.json | 0 .../job_service/new_job_caps/aggregations.ts | 7 +- .../job_service/new_job_caps/field_service.ts | 6 +- .../models/job_service/new_job_caps/index.ts | 0 .../new_job_caps/new_job_caps.test.ts | 0 .../job_service/new_job_caps/new_job_caps.ts | 6 +- .../models/job_service/new_job_caps/rollup.ts | 4 +- .../__tests__/job_validation.js | 0 .../__tests__/mock_farequote_cardinality.json | 0 .../mock_farequote_search_response.json | 0 .../__tests__/mock_field_caps.json | 0 .../__tests__/mock_it_search_response.json | 0 .../__tests__/mock_time_field.json | 0 .../__tests__/mock_time_field_nested.json | 0 .../__tests__/mock_time_range.json | 0 .../__tests__/validate_bucket_span.js | 2 +- .../__tests__/validate_cardinality.js | 0 .../__tests__/validate_influencers.js | 0 .../__tests__/validate_model_memory_limit.js | 0 .../__tests__/validate_time_range.js | 0 .../ml/server/models/job_validation/index.ts | 0 .../models/job_validation/job_validation.d.ts | 4 +- .../models/job_validation/job_validation.js | 13 +- .../server/models/job_validation/messages.js | 2 +- .../job_validation/validate_bucket_span.js | 10 +- .../job_validation/validate_cardinality.d.ts | 5 +- .../job_validation/validate_cardinality.js | 0 .../job_validation/validate_influencers.js | 0 .../job_validation/validate_job_object.js | 0 .../validate_model_memory_limit.js | 2 +- .../job_validation/validate_time_range.js | 4 +- .../build_anomaly_table_items.d.ts | 2 +- .../build_anomaly_table_items.js | 2 +- .../get_partition_fields_values.ts | 4 +- .../ml/server/models/results_service/index.ts | 0 .../models/results_service/results_service.ts | 6 +- x-pack/plugins/ml/server/plugin.ts | 168 +++++++++++++ .../plugins/ml/server/routes/README.md | 0 .../plugins/ml/server/routes/annotations.ts | 21 +- .../ml/server/routes/anomaly_detectors.ts | 38 +-- .../plugins/ml/server/routes/apidoc.json | 0 .../plugins/ml/server/routes/calendars.ts | 18 +- .../ml/server/routes/data_frame_analytics.ts | 30 +-- .../ml/server/routes/data_visualizer.ts | 12 +- .../plugins/ml/server/routes/datafeeds.ts | 28 +-- .../ml/server/routes/fields_service.ts | 12 +- .../ml/server/routes/file_data_visualizer.ts | 20 +- .../plugins/ml/server/routes/filters.ts | 20 +- .../plugins/ml/server/routes/indices.ts | 8 +- .../ml/server/routes/job_audit_messages.ts | 10 +- .../plugins/ml/server/routes/job_service.ts | 48 ++-- .../ml/server/routes/job_validation.ts | 26 +- .../license_check_pre_routing_factory.ts} | 12 +- .../plugins/ml/server/routes/modules.ts | 18 +- .../ml/server/routes/notification_settings.ts | 8 +- .../ml/server/routes/results_service.ts | 18 +- .../routes/schemas}/annotations_schema.ts | 0 .../schemas}/anomaly_detectors_schema.ts | 0 .../routes/schemas}/calendars_schema.ts | 0 .../routes/schemas}/data_analytics_schema.ts | 0 .../routes/schemas}/data_visualizer_schema.ts | 0 .../routes/schemas}/datafeeds_schema.ts | 0 .../routes/schemas}/fields_service_schema.ts | 0 .../server/routes/schemas}/filters_schema.ts | 0 .../routes/schemas}/job_service_schema.ts | 0 .../routes/schemas}/job_validation_schema.ts | 0 .../ml/server/routes/schemas}/modules.ts | 0 .../routes/schemas}/results_service_schema.ts | 0 .../plugins/ml/server/routes/system.ts | 31 ++- x-pack/plugins/ml/server/types.ts | 43 ++++ 339 files changed, 655 insertions(+), 873 deletions(-) delete mode 100644 x-pack/legacy/plugins/ml/kibana.json delete mode 100644 x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.d.ts delete mode 100644 x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.js delete mode 100644 x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.test.ts delete mode 100644 x-pack/legacy/plugins/ml/server/client/call_with_request_factory.js delete mode 100644 x-pack/legacy/plugins/ml/server/lib/__tests__/security_utils.js delete mode 100644 x-pack/legacy/plugins/ml/server/lib/security_utils.d.ts delete mode 100644 x-pack/legacy/plugins/ml/server/lib/security_utils.js delete mode 100644 x-pack/legacy/plugins/ml/server/new_platform/plugin.ts create mode 100644 x-pack/plugins/ml/kibana.json rename x-pack/{legacy => }/plugins/ml/server/client/__tests__/elasticsearch_ml.js (100%) rename x-pack/{legacy => }/plugins/ml/server/client/elasticsearch_ml.js (100%) rename x-pack/{legacy => }/plugins/ml/server/client/error_wrapper.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/client/errors.js (100%) rename x-pack/{legacy => }/plugins/ml/server/client/log.ts (94%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server}/index.ts (57%) rename x-pack/{legacy => }/plugins/ml/server/lib/__tests__/query_utils.js (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_annotations/index.d.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_annotations/index.js (95%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_license/check_license.test.ts (81%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_license/check_license.ts (75%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_license/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_privileges/__mocks__/call_with_request.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_privileges/check_privileges.test.ts (91%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_privileges/check_privileges.ts (94%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_privileges/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_privileges/privileges.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/check_privileges/upgrade.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/ml_telemetry/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/ml_telemetry/make_ml_usage_collector.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts (85%) rename x-pack/{legacy => }/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts (74%) rename x-pack/{legacy => }/plugins/ml/server/lib/query_utils.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/sample_data_sets/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/lib/spaces_utils.ts (75%) rename x-pack/{legacy => }/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_response.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/annotation_service/annotation.test.ts (96%) rename x-pack/{legacy => }/plugins/ml/server/models/annotation_service/annotation.ts (96%) rename x-pack/{legacy => }/plugins/ml/server/models/annotation_service/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts (75%) rename x-pack/{legacy => }/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.js (98%) rename x-pack/{legacy => }/plugins/ml/server/models/bucket_span_estimator/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/bucket_span_estimator/intervals.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/bucket_span_estimator/polled_data_checker.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/bucket_span_estimator/single_series_checker.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.d.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/calculate_model_memory_limit/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/calendar/calendar_manager.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/calendar/event_manager.ts (94%) rename x-pack/{legacy => }/plugins/ml/server/models/calendar/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_frame_analytics/analytics_audit_messages.ts (88%) rename x-pack/{legacy => }/plugins/ml/server/models/data_frame_analytics/index.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts (97%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/data_recognizer.ts (99%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/dashboard/ml_http_access_explorer_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/search/ml_http_access_filebeat_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_events_timechart_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_map_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_source_ip_timechart_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_status_code_timechart_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_top_source_ips_table_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_top_urls_table_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_unique_count_url_timechart_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_low_request_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_source_ip_request_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_source_ip_url_count_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_status_code_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_visitor_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/low_request_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_request_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_url_count_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/status_code_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/visitor_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/abnormal_span_durations_jsbase.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/anomalous_error_rate_for_user_agents_jsbase.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_abnormal_span_durations_jsbase.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_anomalous_error_rate_for_user_agents_jsbase.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_decreased_throughput_jsbase.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_high_count_by_user_agent_jsbase.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/decreased_throughput_jsbase.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/high_count_by_user_agent_jsbase.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/abnormal_span_durations_nodejs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/abnormal_trace_durations_nodejs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_abnormal_span_durations_nodejs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_abnormal_trace_durations_nodejs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_decreased_throughput_nodejs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/decreased_throughput_nodejs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_transaction/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_response_time.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/dashboard/ml_auditbeat_docker_process_event_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/dashboard/ml_auditbeat_docker_process_explorer_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/search/ml_auditbeat_docker_process_events_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_event_rate_by_process_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_event_rate_vis_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_occurrence_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/datafeed_docker_high_count_process_events_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/datafeed_docker_rare_process_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/dashboard/ml_auditbeat_hosts_process_event_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/dashboard/ml_auditbeat_hosts_process_explorer_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/search/ml_auditbeat_hosts_process_events_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_event_rate_by_process_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_event_rate_vis_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_occurrence_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/datafeed_hosts_high_count_process_events_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/datafeed_hosts_rare_process_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/datafeed_log_entry_rate.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/log_entry_rate.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/datafeed_log_entry_categories_count.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/log_entry_categories_count.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_high_mean_cpu_iowait_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_max_disk_utilization_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_metricbeat_outages_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/high_mean_cpu_iowait_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/max_disk_utilization_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/metricbeat_outages_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/dashboard/ml_http_access_explorer_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/search/ml_http_access_filebeat_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_events_timechart_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_map_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_source_ip_timechart_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_status_code_timechart_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_top_source_ips_table_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_top_urls_table_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_unique_count_url_timechart_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_low_request_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_source_ip_request_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_source_ip_url_count_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_status_code_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_visitor_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/low_request_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_request_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_url_count_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/status_code_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/visitor_rate_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/ml/datafeed_high_sum_total_sales.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/ml/high_sum_total_sales.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_low_request_rate.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_response_code_rates.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_url_scanning.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/low_request_rate.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/response_code_rates.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/url_scanning.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_port_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_service.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_url_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_process_all_hosts_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_user_name_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_rare_process_by_host_linux_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_port_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_service.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_url_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_process_all_hosts_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_user_name_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/rare_process_by_host_linux_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/ml/datafeed_suspicious_login_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/ml/suspicious_login_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_dns_tunneling.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_dns_question.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_server_domain.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_urls.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_user_agent.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_dns_tunneling.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_dns_question.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_server_domain.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_urls.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_user_agent.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_rare_process_by_host_windows_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_network_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_path_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_process_all_hosts_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_process_creation.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_script.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_service.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_user_name_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_rare_user_runas_event.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/rare_process_by_host_windows_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_network_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_path_activity_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_process_all_hosts_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_process_creation.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_script.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_service.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_user_name_ecs.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_rare_user_runas_event.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/logo.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/manifest.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/ml/datafeed_windows_rare_user_type10_remote_login.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/ml/windows_rare_user_type10_remote_login.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/data_visualizer/data_visualizer.ts (99%) rename x-pack/{legacy => }/plugins/ml/server/models/data_visualizer/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/fields_service/fields_service.d.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/fields_service/fields_service.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/fields_service/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts (95%) rename x-pack/{legacy => }/plugins/ml/server/models/file_data_visualizer/import_data.ts (97%) rename x-pack/{legacy => }/plugins/ml/server/models/file_data_visualizer/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/filter/filter_manager.ts (98%) rename x-pack/{legacy => }/plugins/ml/server/models/filter/index.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/filter/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_audit_messages/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_audit_messages/job_audit_messages.d.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_audit_messages/job_audit_messages.js (98%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/datafeeds.js (97%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/error_utils.js (94%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/groups.js (95%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/index.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/jobs.js (98%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job/categorization/examples.ts (95%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job/categorization/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts (92%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job/categorization/validation_results.ts (96%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job/charts.ts (87%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job/line_chart.ts (92%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job/population_chart.ts (95%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/cloudwatch_field_caps.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/farequote_field_caps.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/kibana_saved_objects.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/rollup_caps.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/cloudwatch_rollup_job_caps.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps_empty.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts (97%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/field_service.ts (96%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts (93%) rename x-pack/{legacy => }/plugins/ml/server/models/job_service/new_job_caps/rollup.ts (92%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/job_validation.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/mock_farequote_cardinality.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/mock_farequote_search_response.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/mock_field_caps.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/mock_it_search_response.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/mock_time_field.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/mock_time_field_nested.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/mock_time_range.json (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js (98%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/job_validation.d.ts (83%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/job_validation.js (94%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/messages.js (99%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/validate_bucket_span.js (93%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/validate_cardinality.d.ts (78%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/validate_cardinality.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/validate_influencers.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/validate_job_object.js (100%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/validate_model_memory_limit.js (98%) rename x-pack/{legacy => }/plugins/ml/server/models/job_validation/validate_time_range.js (93%) rename x-pack/{legacy => }/plugins/ml/server/models/results_service/build_anomaly_table_items.d.ts (89%) rename x-pack/{legacy => }/plugins/ml/server/models/results_service/build_anomaly_table_items.js (99%) rename x-pack/{legacy => }/plugins/ml/server/models/results_service/get_partition_fields_values.ts (95%) rename x-pack/{legacy => }/plugins/ml/server/models/results_service/index.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/models/results_service/results_service.ts (97%) create mode 100644 x-pack/plugins/ml/server/plugin.ts rename x-pack/{legacy => }/plugins/ml/server/routes/README.md (100%) rename x-pack/{legacy => }/plugins/ml/server/routes/annotations.ts (83%) rename x-pack/{legacy => }/plugins/ml/server/routes/anomaly_detectors.ts (89%) rename x-pack/{legacy => }/plugins/ml/server/routes/apidoc.json (100%) rename x-pack/{legacy => }/plugins/ml/server/routes/calendars.ts (84%) rename x-pack/{legacy => }/plugins/ml/server/routes/data_frame_analytics.ts (89%) rename x-pack/{legacy => }/plugins/ml/server/routes/data_visualizer.ts (89%) rename x-pack/{legacy => }/plugins/ml/server/routes/datafeeds.ts (86%) rename x-pack/{legacy => }/plugins/ml/server/routes/fields_service.ts (84%) rename x-pack/{legacy => }/plugins/ml/server/routes/file_data_visualizer.ts (87%) rename x-pack/{legacy => }/plugins/ml/server/routes/filters.ts (87%) rename x-pack/{legacy => }/plugins/ml/server/routes/indices.ts (80%) rename x-pack/{legacy => }/plugins/ml/server/routes/job_audit_messages.ts (84%) rename x-pack/{legacy => }/plugins/ml/server/routes/job_service.ts (88%) rename x-pack/{legacy => }/plugins/ml/server/routes/job_validation.ts (85%) rename x-pack/{legacy/plugins/ml/server/new_platform/licence_check_pre_routing_factory.ts => plugins/ml/server/routes/license_check_pre_routing_factory.ts} (71%) rename x-pack/{legacy => }/plugins/ml/server/routes/modules.ts (88%) rename x-pack/{legacy => }/plugins/ml/server/routes/notification_settings.ts (75%) rename x-pack/{legacy => }/plugins/ml/server/routes/results_service.ts (88%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/annotations_schema.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/anomaly_detectors_schema.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/calendars_schema.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/data_analytics_schema.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/data_visualizer_schema.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/datafeeds_schema.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/fields_service_schema.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/filters_schema.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/job_service_schema.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/job_validation_schema.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/modules.ts (100%) rename x-pack/{legacy/plugins/ml/server/new_platform => plugins/ml/server/routes/schemas}/results_service_schema.ts (100%) rename x-pack/{legacy => }/plugins/ml/server/routes/system.ts (88%) create mode 100644 x-pack/plugins/ml/server/types.ts diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index bb084b3bb72a1..66342266f1dbc 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -26,7 +26,7 @@ "xpack.logstash": "legacy/plugins/logstash", "xpack.main": "legacy/plugins/xpack_main", "xpack.maps": "legacy/plugins/maps", - "xpack.ml": "legacy/plugins/ml", + "xpack.ml": ["plugins/ml", "legacy/plugins/ml"], "xpack.monitoring": "legacy/plugins/monitoring", "xpack.remoteClusters": "plugins/remote_clusters", "xpack.reporting": ["plugins/reporting", "legacy/plugins/reporting"], diff --git a/x-pack/legacy/plugins/ml/common/constants/app.ts b/x-pack/legacy/plugins/ml/common/constants/app.ts index 140a709b0c42b..bbec35a17faa5 100644 --- a/x-pack/legacy/plugins/ml/common/constants/app.ts +++ b/x-pack/legacy/plugins/ml/common/constants/app.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export const API_BASE_PATH = '/api/transform/'; +export const PLUGIN_ID = 'ml'; diff --git a/x-pack/legacy/plugins/ml/common/constants/license.ts b/x-pack/legacy/plugins/ml/common/constants/license.ts index 2027e2c8b1865..183844c9ef980 100644 --- a/x-pack/legacy/plugins/ml/common/constants/license.ts +++ b/x-pack/legacy/plugins/ml/common/constants/license.ts @@ -8,3 +8,5 @@ export enum LICENSE_TYPE { BASIC, FULL, // >= platinum } + +export const VALID_FULL_LICENSE_MODES = ['platinum', 'enterprise', 'trial']; diff --git a/x-pack/legacy/plugins/ml/index.ts b/x-pack/legacy/plugins/ml/index.ts index 09f1b9ccedce4..47df7c8c3e5e6 100755 --- a/x-pack/legacy/plugins/ml/index.ts +++ b/x-pack/legacy/plugins/ml/index.ts @@ -6,23 +6,13 @@ import { resolve } from 'path'; import { i18n } from '@kbn/i18n'; -import KbnServer, { Server } from 'src/legacy/server/kbn_server'; -import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { plugin } from './server/new_platform'; -import { CloudSetup } from '../../../plugins/cloud/server'; +import { Server } from 'src/legacy/server/kbn_server'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; -import { - MlInitializerContext, - MlCoreSetup, - MlHttpServiceSetup, -} from './server/new_platform/plugin'; +// @ts-ignore: could not find declaration file for module +import { mirrorPluginStatus } from '../../server/lib/mirror_plugin_status'; // @ts-ignore: could not find declaration file for module import mappings from './mappings'; -interface MlServer extends Server { - addAppLinksToSampleDataset: () => {}; -} - export const ml = (kibana: any) => { return new kibana.Plugin({ require: ['kibana', 'elasticsearch', 'xpack_main'], @@ -60,43 +50,8 @@ export const ml = (kibana: any) => { }, }, - async init(server: MlServer) { - const kbnServer = (server as unknown) as KbnServer; - - const initializerContext = ({ - legacyConfig: server.config(), - logger: { - get(...contextParts: string[]) { - return kbnServer.newPlatform.coreContext.logger.get('plugins', 'ml', ...contextParts); - }, - }, - } as unknown) as MlInitializerContext; - - const mlHttpService: MlHttpServiceSetup = { - ...kbnServer.newPlatform.setup.core.http, - route: server.route.bind(server), - }; - - const core: MlCoreSetup = { - injectUiAppVars: server.injectUiAppVars, - http: mlHttpService, - savedObjects: server.savedObjects, - coreSavedObjects: kbnServer.newPlatform.start.core.savedObjects, - elasticsearch: kbnServer.newPlatform.setup.core.elasticsearch, - }; - const { usageCollection, cloud, home } = kbnServer.newPlatform.setup.plugins; - const plugins = { - elasticsearch: server.plugins.elasticsearch, // legacy - security: server.newPlatform.setup.plugins.security, - xpackMain: server.plugins.xpack_main, - spaces: server.plugins.spaces, - home, - usageCollection: usageCollection as UsageCollectionSetup, - cloud: cloud as CloudSetup, - ml: this, - }; - - plugin(initializerContext).setup(core, plugins); + async init(server: Server) { + mirrorPluginStatus(server.plugins.xpack_main, this); }, }); }; diff --git a/x-pack/legacy/plugins/ml/kibana.json b/x-pack/legacy/plugins/ml/kibana.json deleted file mode 100644 index f36b484818690..0000000000000 --- a/x-pack/legacy/plugins/ml/kibana.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "ml", - "version": "0.0.1", - "kibanaVersion": "kibana", - "configPath": ["ml"], - "server": true, - "ui": true -} diff --git a/x-pack/legacy/plugins/ml/public/application/license/check_license.tsx b/x-pack/legacy/plugins/ml/public/application/license/check_license.tsx index 96e6aab377962..4af753ddb4d1f 100644 --- a/x-pack/legacy/plugins/ml/public/application/license/check_license.tsx +++ b/x-pack/legacy/plugins/ml/public/application/license/check_license.tsx @@ -82,9 +82,16 @@ function setLicenseExpired(features: any) { } } } - +// Temporary hack for cutting over server to NP function getFeatures() { - return xpackInfo.get('features.ml'); + return { + isAvailable: true, + showLinks: true, + enableLinks: true, + licenseType: 1, + hasExpired: false, + }; + // return xpackInfo.get('features.ml'); } function redirectToKibana() { diff --git a/x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.d.ts b/x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.d.ts deleted file mode 100644 index bf2e656afff12..0000000000000 --- a/x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.d.ts +++ /dev/null @@ -1,9 +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 { ElasticsearchPlugin } from 'src/legacy/core_plugins/elasticsearch'; - -export function callWithInternalUserFactory(elasticsearchPlugin: ElasticsearchPlugin): any; diff --git a/x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.js b/x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.js deleted file mode 100644 index 2e5431bdd6ce2..0000000000000 --- a/x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { once } from 'lodash'; - -const _callWithInternalUser = once(elasticsearchPlugin => { - const { callWithInternalUser } = elasticsearchPlugin.getCluster('admin'); - return callWithInternalUser; -}); - -export const callWithInternalUserFactory = elasticsearchPlugin => { - return (...args) => { - return _callWithInternalUser(elasticsearchPlugin)(...args); - }; -}; diff --git a/x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.test.ts b/x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.test.ts deleted file mode 100644 index be016cc13ed0f..0000000000000 --- a/x-pack/legacy/plugins/ml/server/client/call_with_internal_user_factory.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { callWithInternalUserFactory } from './call_with_internal_user_factory'; - -describe('call_with_internal_user_factory', () => { - describe('callWithInternalUserFactory', () => { - let elasticsearchPlugin: any; - let callWithInternalUser: any; - - beforeEach(() => { - callWithInternalUser = jest.fn(); - elasticsearchPlugin = { - getCluster: jest.fn(() => ({ callWithInternalUser })), - }; - }); - - it('should use internal user "admin"', () => { - const callWithInternalUserInstance = callWithInternalUserFactory(elasticsearchPlugin); - callWithInternalUserInstance(); - - expect(elasticsearchPlugin.getCluster).toHaveBeenCalledWith('admin'); - }); - }); -}); diff --git a/x-pack/legacy/plugins/ml/server/client/call_with_request_factory.js b/x-pack/legacy/plugins/ml/server/client/call_with_request_factory.js deleted file mode 100644 index b39a58b317500..0000000000000 --- a/x-pack/legacy/plugins/ml/server/client/call_with_request_factory.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { once } from 'lodash'; -import { elasticsearchJsPlugin } from './elasticsearch_ml'; - -const callWithRequest = once(elasticsearchPlugin => { - const config = { plugins: [elasticsearchJsPlugin] }; - const cluster = elasticsearchPlugin.createCluster('ml', config); - - return cluster.callWithRequest; -}); - -export const callWithRequestFactory = (elasticsearchPlugin, request) => { - return (...args) => { - return callWithRequest(elasticsearchPlugin)(request, ...args); - }; -}; diff --git a/x-pack/legacy/plugins/ml/server/lib/__tests__/security_utils.js b/x-pack/legacy/plugins/ml/server/lib/__tests__/security_utils.js deleted file mode 100644 index 6e0181f49072e..0000000000000 --- a/x-pack/legacy/plugins/ml/server/lib/__tests__/security_utils.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { isSecurityDisabled } from '../security_utils'; - -describe('ML - security utils', () => { - function mockXpackMainPluginFactory(isAvailable = true, isEnabled = true) { - return { - info: { - isAvailable: () => isAvailable, - feature: () => ({ - isEnabled: () => isEnabled, - }), - }, - }; - } - - describe('isSecurityDisabled', () => { - it('returns not disabled for given mock server object #1', () => { - expect(isSecurityDisabled(mockXpackMainPluginFactory())).to.be(false); - }); - - it('returns not disabled for given mock server object #2', () => { - expect(isSecurityDisabled(mockXpackMainPluginFactory(false))).to.be(false); - }); - - it('returns disabled for given mock server object #3', () => { - expect(isSecurityDisabled(mockXpackMainPluginFactory(true, false))).to.be(true); - }); - }); -}); diff --git a/x-pack/legacy/plugins/ml/server/lib/security_utils.d.ts b/x-pack/legacy/plugins/ml/server/lib/security_utils.d.ts deleted file mode 100644 index 26fdff73b3460..0000000000000 --- a/x-pack/legacy/plugins/ml/server/lib/security_utils.d.ts +++ /dev/null @@ -1,9 +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 { XPackMainPlugin } from '../../../xpack_main/server/xpack_main'; - -export function isSecurityDisabled(xpackMainPlugin: XPackMainPlugin): boolean; diff --git a/x-pack/legacy/plugins/ml/server/lib/security_utils.js b/x-pack/legacy/plugins/ml/server/lib/security_utils.js deleted file mode 100644 index 27109e645b185..0000000000000 --- a/x-pack/legacy/plugins/ml/server/lib/security_utils.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -/* - * Contains utility functions related to x-pack security. - */ - -export function isSecurityDisabled(xpackMainPlugin) { - const xpackInfo = xpackMainPlugin && xpackMainPlugin.info; - // we assume that `xpack.isAvailable()` always returns `true` because we're inside x-pack - // if for whatever reason it returns `false`, `isSecurityDisabled()` would also return `false` - // which would result in follow-up behavior assuming security is enabled. This is intentional, - // because it results in more defensive behavior. - const securityInfo = xpackInfo && xpackInfo.isAvailable() && xpackInfo.feature('security'); - return securityInfo && securityInfo.isEnabled() === false; -} diff --git a/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts b/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts deleted file mode 100644 index 43c276ac63a13..0000000000000 --- a/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts +++ /dev/null @@ -1,238 +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 Boom from 'boom'; -import { i18n } from '@kbn/i18n'; -import { ServerRoute } from 'hapi'; -import { KibanaConfig, SavedObjectsLegacyService } from 'src/legacy/server/kbn_server'; -import { - Logger, - PluginInitializerContext, - CoreSetup, - IRouter, - IScopedClusterClient, - SavedObjectsServiceStart, -} from 'src/core/server'; -import { ElasticsearchPlugin } from 'src/legacy/core_plugins/elasticsearch'; -import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { ElasticsearchServiceSetup } from 'src/core/server'; -import { CloudSetup } from '../../../../../plugins/cloud/server'; -import { XPackMainPlugin } from '../../../xpack_main/server/xpack_main'; -import { addLinksToSampleDatasets } from '../lib/sample_data_sets'; -import { checkLicense } from '../lib/check_license'; -// @ts-ignore: could not find declaration file for module -import { mirrorPluginStatus } from '../../../../server/lib/mirror_plugin_status'; -import { LICENSE_TYPE } from '../../common/constants/license'; -import { annotationRoutes } from '../routes/annotations'; -import { jobRoutes } from '../routes/anomaly_detectors'; -import { dataFeedRoutes } from '../routes/datafeeds'; -import { indicesRoutes } from '../routes/indices'; -import { jobValidationRoutes } from '../routes/job_validation'; -import { makeMlUsageCollector } from '../lib/ml_telemetry'; -import { notificationRoutes } from '../routes/notification_settings'; -import { systemRoutes } from '../routes/system'; -import { dataFrameAnalyticsRoutes } from '../routes/data_frame_analytics'; -import { dataRecognizer } from '../routes/modules'; -import { dataVisualizerRoutes } from '../routes/data_visualizer'; -import { calendars } from '../routes/calendars'; -// @ts-ignore: could not find declaration file for module -import { fieldsService } from '../routes/fields_service'; -import { filtersRoutes } from '../routes/filters'; -import { resultsServiceRoutes } from '../routes/results_service'; -import { jobServiceRoutes } from '../routes/job_service'; -import { jobAuditMessagesRoutes } from '../routes/job_audit_messages'; -import { fileDataVisualizerRoutes } from '../routes/file_data_visualizer'; -import { initMlServerLog, LogInitialization } from '../client/log'; -import { HomeServerPluginSetup } from '../../../../../../src/plugins/home/server'; -// @ts-ignore: could not find declaration file for module -import { elasticsearchJsPlugin } from '../client/elasticsearch_ml'; - -export const PLUGIN_ID = 'ml'; - -type CoreHttpSetup = CoreSetup['http']; -export interface MlHttpServiceSetup extends CoreHttpSetup { - route(route: ServerRoute | ServerRoute[]): void; -} - -export interface MlXpackMainPlugin extends XPackMainPlugin { - status?: any; -} - -export interface MlCoreSetup { - injectUiAppVars: (id: string, callback: () => {}) => any; - http: MlHttpServiceSetup; - savedObjects: SavedObjectsLegacyService; - coreSavedObjects: SavedObjectsServiceStart; - elasticsearch: ElasticsearchServiceSetup; -} -export interface MlInitializerContext extends PluginInitializerContext { - legacyConfig: KibanaConfig; - log: Logger; -} -export interface PluginsSetup { - elasticsearch: ElasticsearchPlugin; - xpackMain: MlXpackMainPlugin; - security: any; - spaces: any; - usageCollection?: UsageCollectionSetup; - cloud?: CloudSetup; - home?: HomeServerPluginSetup; - // TODO: this is temporary for `mirrorPluginStatus` - ml: any; -} - -export interface RouteInitialization { - commonRouteConfig: any; - config?: any; - elasticsearchPlugin: ElasticsearchPlugin; - elasticsearchService: ElasticsearchServiceSetup; - route(route: ServerRoute | ServerRoute[]): void; - router: IRouter; - xpackMainPlugin: MlXpackMainPlugin; - savedObjects?: SavedObjectsServiceStart; - spacesPlugin: any; - securityPlugin: any; - cloud?: CloudSetup; -} - -declare module 'kibana/server' { - interface RequestHandlerContext { - ml?: { - mlClient: IScopedClusterClient; - }; - } -} - -export class Plugin { - private readonly pluginId: string = PLUGIN_ID; - private config: any; - private log: Logger; - - constructor(initializerContext: MlInitializerContext) { - this.config = initializerContext.legacyConfig; - this.log = initializerContext.logger.get(); - } - - public setup(core: MlCoreSetup, plugins: PluginsSetup) { - const xpackMainPlugin: MlXpackMainPlugin = plugins.xpackMain; - const { http, coreSavedObjects } = core; - const pluginId = this.pluginId; - - mirrorPluginStatus(xpackMainPlugin, plugins.ml); - xpackMainPlugin.status.once('green', () => { - // Register a function that is called whenever the xpack info changes, - // to re-compute the license check results for this plugin - const mlFeature = xpackMainPlugin.info.feature(pluginId); - mlFeature.registerLicenseCheckResultsGenerator(checkLicense); - - // Add links to the Kibana sample data sets if ml is enabled - // and there is a full license (trial or platinum). - if (mlFeature.isEnabled() === true && plugins.home) { - const licenseCheckResults = mlFeature.getLicenseCheckResults(); - if (licenseCheckResults.licenseType === LICENSE_TYPE.FULL) { - addLinksToSampleDatasets({ - addAppLinksToSampleDataset: plugins.home.sampleData.addAppLinksToSampleDataset, - }); - } - } - }); - - xpackMainPlugin.registerFeature({ - id: 'ml', - name: i18n.translate('xpack.ml.featureRegistry.mlFeatureName', { - defaultMessage: 'Machine Learning', - }), - icon: 'machineLearningApp', - navLinkId: 'ml', - app: ['ml', 'kibana'], - catalogue: ['ml'], - privileges: {}, - reserved: { - privilege: { - savedObject: { - all: [], - read: [], - }, - ui: [], - }, - description: i18n.translate('xpack.ml.feature.reserved.description', { - defaultMessage: - 'To grant users access, you should also assign either the machine_learning_user or machine_learning_admin role.', - }), - }, - }); - - // Add server routes and initialize the plugin here - const commonRouteConfig = { - pre: [ - function forbidApiAccess() { - const licenseCheckResults = xpackMainPlugin.info - .feature(pluginId) - .getLicenseCheckResults(); - if (licenseCheckResults.isAvailable) { - return null; - } else { - throw Boom.forbidden(licenseCheckResults.message); - } - }, - ], - }; - - // Can access via new platform router's handler function 'context' parameter - context.ml.mlClient - const mlClient = core.elasticsearch.createClient('ml', { plugins: [elasticsearchJsPlugin] }); - http.registerRouteHandlerContext('ml', (context, request) => { - return { - mlClient: mlClient.asScoped(request), - }; - }); - - const routeInitializationDeps: RouteInitialization = { - commonRouteConfig, - route: http.route, - router: http.createRouter(), - elasticsearchPlugin: plugins.elasticsearch, - elasticsearchService: core.elasticsearch, - xpackMainPlugin: plugins.xpackMain, - spacesPlugin: plugins.spaces, - securityPlugin: plugins.security, - }; - - const extendedRouteInitializationDeps: RouteInitialization = { - ...routeInitializationDeps, - config: this.config, - savedObjects: coreSavedObjects, - spacesPlugin: plugins.spaces, - cloud: plugins.cloud, - }; - - const logInitializationDeps: LogInitialization = { - log: this.log, - }; - - annotationRoutes(routeInitializationDeps); - jobRoutes(routeInitializationDeps); - dataFeedRoutes(routeInitializationDeps); - dataFrameAnalyticsRoutes(routeInitializationDeps); - indicesRoutes(routeInitializationDeps); - jobValidationRoutes(extendedRouteInitializationDeps); - notificationRoutes(routeInitializationDeps); - systemRoutes(extendedRouteInitializationDeps); - dataRecognizer(extendedRouteInitializationDeps); - dataVisualizerRoutes(routeInitializationDeps); - calendars(routeInitializationDeps); - fieldsService(routeInitializationDeps); - filtersRoutes(routeInitializationDeps); - resultsServiceRoutes(routeInitializationDeps); - jobServiceRoutes(routeInitializationDeps); - jobAuditMessagesRoutes(routeInitializationDeps); - fileDataVisualizerRoutes(extendedRouteInitializationDeps); - - initMlServerLog(logInitializationDeps); - makeMlUsageCollector(plugins.usageCollection, coreSavedObjects); - } - - public stop() {} -} diff --git a/x-pack/plugins/ml/kibana.json b/x-pack/plugins/ml/kibana.json new file mode 100644 index 0000000000000..e944af6821c0b --- /dev/null +++ b/x-pack/plugins/ml/kibana.json @@ -0,0 +1,9 @@ +{ + "id": "ml", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["ml"], + "requiredPlugins": ["cloud", "features", "home", "licensing", "security", "spaces", "usageCollection"], + "server": true, + "ui": false +} diff --git a/x-pack/legacy/plugins/ml/server/client/__tests__/elasticsearch_ml.js b/x-pack/plugins/ml/server/client/__tests__/elasticsearch_ml.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/client/__tests__/elasticsearch_ml.js rename to x-pack/plugins/ml/server/client/__tests__/elasticsearch_ml.js diff --git a/x-pack/legacy/plugins/ml/server/client/elasticsearch_ml.js b/x-pack/plugins/ml/server/client/elasticsearch_ml.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/client/elasticsearch_ml.js rename to x-pack/plugins/ml/server/client/elasticsearch_ml.js diff --git a/x-pack/legacy/plugins/ml/server/client/error_wrapper.ts b/x-pack/plugins/ml/server/client/error_wrapper.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/client/error_wrapper.ts rename to x-pack/plugins/ml/server/client/error_wrapper.ts diff --git a/x-pack/legacy/plugins/ml/server/client/errors.js b/x-pack/plugins/ml/server/client/errors.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/client/errors.js rename to x-pack/plugins/ml/server/client/errors.js diff --git a/x-pack/legacy/plugins/ml/server/client/log.ts b/x-pack/plugins/ml/server/client/log.ts similarity index 94% rename from x-pack/legacy/plugins/ml/server/client/log.ts rename to x-pack/plugins/ml/server/client/log.ts index ae82383ead605..8ee5882f6c2c1 100644 --- a/x-pack/legacy/plugins/ml/server/client/log.ts +++ b/x-pack/plugins/ml/server/client/log.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger } from '../../../../../../src/core/server'; +import { Logger } from '../../../../../src/core/server'; export interface LogInitialization { log: Logger; diff --git a/x-pack/legacy/plugins/ml/server/new_platform/index.ts b/x-pack/plugins/ml/server/index.ts similarity index 57% rename from x-pack/legacy/plugins/ml/server/new_platform/index.ts rename to x-pack/plugins/ml/server/index.ts index b03f2dac613b0..55e87ed6f0c6a 100644 --- a/x-pack/legacy/plugins/ml/server/new_platform/index.ts +++ b/x-pack/plugins/ml/server/index.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Plugin, MlInitializerContext } from './plugin'; +import { PluginInitializerContext } from 'kibana/server'; +import { MlServerPlugin } from './plugin'; -export function plugin(initializerContext: MlInitializerContext) { - return new Plugin(initializerContext); -} +export const plugin = (ctx: PluginInitializerContext) => new MlServerPlugin(ctx); diff --git a/x-pack/legacy/plugins/ml/server/lib/__tests__/query_utils.js b/x-pack/plugins/ml/server/lib/__tests__/query_utils.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/__tests__/query_utils.js rename to x-pack/plugins/ml/server/lib/__tests__/query_utils.js diff --git a/x-pack/legacy/plugins/ml/server/lib/check_annotations/index.d.ts b/x-pack/plugins/ml/server/lib/check_annotations/index.d.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/check_annotations/index.d.ts rename to x-pack/plugins/ml/server/lib/check_annotations/index.d.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/check_annotations/index.js b/x-pack/plugins/ml/server/lib/check_annotations/index.js similarity index 95% rename from x-pack/legacy/plugins/ml/server/lib/check_annotations/index.js rename to x-pack/plugins/ml/server/lib/check_annotations/index.js index 186c27b0326d7..55a90c0cec322 100644 --- a/x-pack/legacy/plugins/ml/server/lib/check_annotations/index.js +++ b/x-pack/plugins/ml/server/lib/check_annotations/index.js @@ -10,7 +10,7 @@ import { ML_ANNOTATIONS_INDEX_ALIAS_READ, ML_ANNOTATIONS_INDEX_ALIAS_WRITE, ML_ANNOTATIONS_INDEX_PATTERN, -} from '../../../common/constants/index_patterns'; +} from '../../../../../legacy/plugins/ml/common/constants/index_patterns'; // Annotations Feature is available if: // - ML_ANNOTATIONS_INDEX_PATTERN index is present diff --git a/x-pack/legacy/plugins/ml/server/lib/check_license/check_license.test.ts b/x-pack/plugins/ml/server/lib/check_license/check_license.test.ts similarity index 81% rename from x-pack/legacy/plugins/ml/server/lib/check_license/check_license.test.ts rename to x-pack/plugins/ml/server/lib/check_license/check_license.test.ts index 1d80a226486bb..942dbe3722617 100644 --- a/x-pack/legacy/plugins/ml/server/lib/check_license/check_license.test.ts +++ b/x-pack/plugins/ml/server/lib/check_license/check_license.test.ts @@ -7,12 +7,12 @@ import expect from '@kbn/expect'; import sinon from 'sinon'; import { set } from 'lodash'; -import { XPackInfo } from '../../../../xpack_main/server/lib/xpack_info'; +import { LicenseCheckResult } from '../../types'; import { checkLicense } from './check_license'; describe('check_license', () => { - let mockLicenseInfo: XPackInfo; - beforeEach(() => (mockLicenseInfo = {} as XPackInfo)); + let mockLicenseInfo: LicenseCheckResult; + beforeEach(() => (mockLicenseInfo = {} as LicenseCheckResult)); describe('license information is undefined', () => { it('should set isAvailable to false', () => { @@ -33,7 +33,9 @@ describe('check_license', () => { }); describe('license information is not available', () => { - beforeEach(() => (mockLicenseInfo.isAvailable = () => false)); + beforeEach(() => { + mockLicenseInfo.isAvailable = false; + }); it('should set isAvailable to false', () => { expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false); @@ -54,8 +56,8 @@ describe('check_license', () => { describe('license information is available', () => { beforeEach(() => { - mockLicenseInfo.isAvailable = () => true; - set(mockLicenseInfo, 'license.getType', () => 'basic'); + mockLicenseInfo.isAvailable = true; + mockLicenseInfo.type = 'basic'; }); describe('& ML is disabled in Elasticsearch', () => { @@ -66,7 +68,7 @@ describe('check_license', () => { sinon .stub() .withArgs('ml') - .returns({ isEnabled: () => false }) + .returns({ isEnabled: false }) ); }); @@ -89,21 +91,17 @@ describe('check_license', () => { describe('& ML is enabled in Elasticsearch', () => { beforeEach(() => { - set( - mockLicenseInfo, - 'feature', - sinon - .stub() - .withArgs('ml') - .returns({ isEnabled: () => true }) - ); + mockLicenseInfo.isEnabled = true; }); describe('& license is >= platinum', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isOneOf', () => true)); - + beforeEach(() => { + mockLicenseInfo.type = 'platinum'; + }); describe('& license is active', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true)); + beforeEach(() => { + mockLicenseInfo.isActive = true; + }); it('should set isAvailable to true', () => { expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true); @@ -123,7 +121,9 @@ describe('check_license', () => { }); describe('& license is expired', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => false)); + beforeEach(() => { + mockLicenseInfo.isActive = false; + }); it('should set isAvailable to true', () => { expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true); @@ -144,10 +144,14 @@ describe('check_license', () => { }); describe('& license is basic', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isOneOf', () => false)); + beforeEach(() => { + mockLicenseInfo.type = 'basic'; + }); describe('& license is active', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true)); + beforeEach(() => { + mockLicenseInfo.isActive = true; + }); it('should set isAvailable to true', () => { expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true); diff --git a/x-pack/legacy/plugins/ml/server/lib/check_license/check_license.ts b/x-pack/plugins/ml/server/lib/check_license/check_license.ts similarity index 75% rename from x-pack/legacy/plugins/ml/server/lib/check_license/check_license.ts rename to x-pack/plugins/ml/server/lib/check_license/check_license.ts index c88ab087a8198..5bf3d590a1912 100644 --- a/x-pack/legacy/plugins/ml/server/lib/check_license/check_license.ts +++ b/x-pack/plugins/ml/server/lib/check_license/check_license.ts @@ -5,8 +5,11 @@ */ import { i18n } from '@kbn/i18n'; -import { LICENSE_TYPE } from '../../../common/constants/license'; -import { XPackInfo } from '../../../../../../legacy/plugins/xpack_main/server/lib/xpack_info'; +import { + LICENSE_TYPE, + VALID_FULL_LICENSE_MODES, +} from '../../../../../legacy/plugins/ml/common/constants/license'; +import { LicenseCheckResult } from '../../types'; interface Response { isAvailable: boolean; @@ -17,10 +20,10 @@ interface Response { message?: string; } -export function checkLicense(xpackLicenseInfo: XPackInfo): Response { +export function checkLicense(licenseCheckResult: LicenseCheckResult): Response { // If, for some reason, we cannot get the license information // from Elasticsearch, assume worst case and disable the Machine Learning UI - if (!xpackLicenseInfo || !xpackLicenseInfo.isAvailable()) { + if (licenseCheckResult === undefined || !licenseCheckResult.isAvailable) { return { isAvailable: false, showLinks: true, @@ -35,7 +38,7 @@ export function checkLicense(xpackLicenseInfo: XPackInfo): Response { }; } - const featureEnabled = xpackLicenseInfo.feature('ml').isEnabled(); + const featureEnabled = licenseCheckResult.isEnabled; if (!featureEnabled) { return { isAvailable: false, @@ -47,12 +50,11 @@ export function checkLicense(xpackLicenseInfo: XPackInfo): Response { }; } - const VALID_FULL_LICENSE_MODES = ['platinum', 'enterprise', 'trial']; - - const isLicenseModeValid = xpackLicenseInfo.license.isOneOf(VALID_FULL_LICENSE_MODES); + const isLicenseModeValid = + licenseCheckResult.type && VALID_FULL_LICENSE_MODES.includes(licenseCheckResult.type); const licenseType = isLicenseModeValid === true ? LICENSE_TYPE.FULL : LICENSE_TYPE.BASIC; - const isLicenseActive = xpackLicenseInfo.license.isActive(); - const licenseTypeName = xpackLicenseInfo.license.getType(); + const isLicenseActive = licenseCheckResult.isActive; + const licenseTypeName = licenseCheckResult.type; // Platinum or trial license is valid but not active, i.e. expired if (licenseType === LICENSE_TYPE.FULL && isLicenseActive === false) { diff --git a/x-pack/legacy/plugins/ml/server/lib/check_license/index.ts b/x-pack/plugins/ml/server/lib/check_license/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/check_license/index.ts rename to x-pack/plugins/ml/server/lib/check_license/index.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/check_privileges/__mocks__/call_with_request.ts b/x-pack/plugins/ml/server/lib/check_privileges/__mocks__/call_with_request.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/check_privileges/__mocks__/call_with_request.ts rename to x-pack/plugins/ml/server/lib/check_privileges/__mocks__/call_with_request.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/check_privileges/check_privileges.test.ts b/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.test.ts similarity index 91% rename from x-pack/legacy/plugins/ml/server/lib/check_privileges/check_privileges.test.ts rename to x-pack/plugins/ml/server/lib/check_privileges/check_privileges.test.ts index da8ef25b2f4df..0690aa53576a5 100644 --- a/x-pack/legacy/plugins/ml/server/lib/check_privileges/check_privileges.test.ts +++ b/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.test.ts @@ -8,81 +8,29 @@ import { callWithRequestProvider } from './__mocks__/call_with_request'; import { privilegesProvider } from './check_privileges'; import { mlPrivileges } from './privileges'; -const xpackMainPluginWithSecurity = { - info: { - isAvailable: () => true, - feature: (f: string) => { - switch (f) { - case 'ml': - return { isEnabled: () => true }; - case 'security': - return { isEnabled: () => true }; - } - }, - license: { - isOneOf: () => true, - isActive: () => true, - getType: () => 'platinum', - }, - }, -} as any; +const licenseCheckResultWithSecurity = { + isAvailable: true, + isEnabled: true, + isSecurityDisabled: false, + type: 'platinum', + isActive: true, +}; -const xpackMainPluginWithOutSecurity = { - info: { - isAvailable: () => true, - feature: (f: string) => { - switch (f) { - case 'ml': - return { isEnabled: () => true }; - case 'security': - return { isEnabled: () => false }; - } - }, - license: { - isOneOf: () => true, - isActive: () => true, - getType: () => 'platinum', - }, - }, -} as any; +const licenseCheckResultWithOutSecurity = { + ...licenseCheckResultWithSecurity, + isSecurityDisabled: true, +}; -const xpackMainPluginWithOutSecurityBasicLicense = { - info: { - isAvailable: () => true, - feature: (f: string) => { - switch (f) { - case 'ml': - return { isEnabled: () => true }; - case 'security': - return { isEnabled: () => false }; - } - }, - license: { - isOneOf: () => false, - isActive: () => true, - getType: () => 'basic', - }, - }, -} as any; +const licenseCheckResultWithOutSecurityBasicLicense = { + ...licenseCheckResultWithSecurity, + isSecurityDisabled: true, + type: 'basic', +}; -const xpackMainPluginWithSecurityBasicLicense = { - info: { - isAvailable: () => true, - feature: (f: string) => { - switch (f) { - case 'ml': - return { isEnabled: () => true }; - case 'security': - return { isEnabled: () => true }; - } - }, - license: { - isOneOf: () => false, - isActive: () => true, - getType: () => 'basic', - }, - }, -} as any; +const licenseCheckResultWithSecurityBasicLicense = { + ...licenseCheckResultWithSecurity, + type: 'basic', +}; const mlIsEnabled = async () => true; const mlIsNotEnabled = async () => false; @@ -99,7 +47,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithSecurity, + licenseCheckResultWithSecurity, mlIsEnabled ); const { capabilities } = await getPrivileges(); @@ -114,7 +62,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithSecurity, + licenseCheckResultWithSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -149,7 +97,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('fullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithSecurity, + licenseCheckResultWithSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -184,7 +132,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('upgradeWithFullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithSecurity, + licenseCheckResultWithSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -219,7 +167,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('upgradeWithPartialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithSecurity, + licenseCheckResultWithSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -254,7 +202,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithSecurityBasicLicense, + licenseCheckResultWithSecurityBasicLicense, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -289,7 +237,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('fullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithSecurityBasicLicense, + licenseCheckResultWithSecurityBasicLicense, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -324,7 +272,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('fullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithSecurity, + licenseCheckResultWithSecurity, mlIsNotEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -361,7 +309,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithOutSecurity, + licenseCheckResultWithOutSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -396,7 +344,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('upgradeWithFullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithOutSecurity, + licenseCheckResultWithOutSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -431,7 +379,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('upgradeWithPartialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithOutSecurity, + licenseCheckResultWithOutSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -466,7 +414,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithOutSecurityBasicLicense, + licenseCheckResultWithOutSecurityBasicLicense, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -501,7 +449,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('fullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithOutSecurityBasicLicense, + licenseCheckResultWithOutSecurityBasicLicense, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -536,7 +484,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - xpackMainPluginWithOutSecurity, + licenseCheckResultWithOutSecurity, mlIsNotEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); diff --git a/x-pack/legacy/plugins/ml/server/lib/check_privileges/check_privileges.ts b/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.ts similarity index 94% rename from x-pack/legacy/plugins/ml/server/lib/check_privileges/check_privileges.ts rename to x-pack/plugins/ml/server/lib/check_privileges/check_privileges.ts index 617778afbe121..a427780d13344 100644 --- a/x-pack/legacy/plugins/ml/server/lib/check_privileges/check_privileges.ts +++ b/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.ts @@ -5,12 +5,14 @@ */ import { IScopedClusterClient } from 'kibana/server'; -import { Privileges, getDefaultPrivileges } from '../../../common/types/privileges'; -import { XPackMainPlugin } from '../../../../xpack_main/server/xpack_main'; -import { isSecurityDisabled } from '../../lib/security_utils'; +import { + Privileges, + getDefaultPrivileges, +} from '../../../../../legacy/plugins/ml/common/types/privileges'; import { upgradeCheckProvider } from './upgrade'; import { checkLicense } from '../check_license'; -import { LICENSE_TYPE } from '../../../common/constants/license'; +import { LICENSE_TYPE } from '../../../../../legacy/plugins/ml/common/constants/license'; +import { LicenseCheckResult } from '../../types'; import { mlPrivileges } from './privileges'; @@ -25,7 +27,7 @@ interface Response { export function privilegesProvider( callAsCurrentUser: IScopedClusterClient['callAsCurrentUser'], - xpackMainPlugin: XPackMainPlugin, + licenseCheckResult: LicenseCheckResult, isMlEnabledInSpace: () => Promise, ignoreSpaces: boolean = false ) { @@ -35,8 +37,8 @@ export function privilegesProvider( const privileges = getDefaultPrivileges(); const upgradeInProgress = await isUpgradeInProgress(); - const securityDisabled = isSecurityDisabled(xpackMainPlugin); - const license = checkLicense(xpackMainPlugin.info); + const securityDisabled = licenseCheckResult.isSecurityDisabled; + const license = checkLicense(licenseCheckResult); const isPlatinumOrTrialLicense = license.licenseType === LICENSE_TYPE.FULL; const mlFeatureEnabledInSpace = await isMlEnabledInSpace(); diff --git a/x-pack/legacy/plugins/ml/server/lib/check_privileges/index.ts b/x-pack/plugins/ml/server/lib/check_privileges/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/check_privileges/index.ts rename to x-pack/plugins/ml/server/lib/check_privileges/index.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/check_privileges/privileges.ts b/x-pack/plugins/ml/server/lib/check_privileges/privileges.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/check_privileges/privileges.ts rename to x-pack/plugins/ml/server/lib/check_privileges/privileges.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/check_privileges/upgrade.ts b/x-pack/plugins/ml/server/lib/check_privileges/upgrade.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/check_privileges/upgrade.ts rename to x-pack/plugins/ml/server/lib/check_privileges/upgrade.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/ml_telemetry/index.ts b/x-pack/plugins/ml/server/lib/ml_telemetry/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/ml_telemetry/index.ts rename to x-pack/plugins/ml/server/lib/ml_telemetry/index.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/ml_telemetry/make_ml_usage_collector.ts b/x-pack/plugins/ml/server/lib/ml_telemetry/make_ml_usage_collector.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/ml_telemetry/make_ml_usage_collector.ts rename to x-pack/plugins/ml/server/lib/ml_telemetry/make_ml_usage_collector.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts similarity index 85% rename from x-pack/legacy/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts rename to x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts index 9d14ffb31be63..c03396445f868 100644 --- a/x-pack/legacy/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts +++ b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts @@ -55,10 +55,9 @@ describe('ml_telemetry', () => { }); describe('incrementFileDataVisualizerIndexCreationCount', () => { - let savedObjects: any; - let internalRepository: any; + let savedObjectsClient: any; - function createInternalRepositoryInstance( + function createSavedObjectsClientInstance( telemetryEnabled?: boolean, indexCreationCount?: number ) { @@ -93,42 +92,39 @@ describe('ml_telemetry', () => { } function mockInit(telemetryEnabled?: boolean, indexCreationCount?: number): void { - internalRepository = createInternalRepositoryInstance(telemetryEnabled, indexCreationCount); - savedObjects = { - createInternalRepository: jest.fn(() => internalRepository), - }; + savedObjectsClient = createSavedObjectsClientInstance(telemetryEnabled, indexCreationCount); } it('should not increment if telemetry status cannot be determined', async () => { mockInit(); - await incrementFileDataVisualizerIndexCreationCount(savedObjects); + await incrementFileDataVisualizerIndexCreationCount(savedObjectsClient); - expect(internalRepository.create.mock.calls).toHaveLength(0); + expect(savedObjectsClient.create.mock.calls).toHaveLength(0); }); it('should not increment if telemetry status is disabled', async () => { mockInit(false); - await incrementFileDataVisualizerIndexCreationCount(savedObjects); + await incrementFileDataVisualizerIndexCreationCount(savedObjectsClient); - expect(internalRepository.create.mock.calls).toHaveLength(0); + expect(savedObjectsClient.create.mock.calls).toHaveLength(0); }); it('should initialize index_creation_count with 1', async () => { mockInit(true); - await incrementFileDataVisualizerIndexCreationCount(savedObjects); + await incrementFileDataVisualizerIndexCreationCount(savedObjectsClient); - expect(internalRepository.create.mock.calls[0][0]).toBe('ml-telemetry'); - expect(internalRepository.create.mock.calls[0][1]).toEqual({ + expect(savedObjectsClient.create.mock.calls[0][0]).toBe('ml-telemetry'); + expect(savedObjectsClient.create.mock.calls[0][1]).toEqual({ file_data_visualizer: { index_creation_count: 1 }, }); }); it('should increment index_creation_count to 2', async () => { mockInit(true, 1); - await incrementFileDataVisualizerIndexCreationCount(savedObjects); + await incrementFileDataVisualizerIndexCreationCount(savedObjectsClient); - expect(internalRepository.create.mock.calls[0][0]).toBe('ml-telemetry'); - expect(internalRepository.create.mock.calls[0][1]).toEqual({ + expect(savedObjectsClient.create.mock.calls[0][0]).toBe('ml-telemetry'); + expect(savedObjectsClient.create.mock.calls[0][1]).toEqual({ file_data_visualizer: { index_creation_count: 2 }, }); }); diff --git a/x-pack/legacy/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts similarity index 74% rename from x-pack/legacy/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts rename to x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts index d76b1ee94e21e..8cf24213961b1 100644 --- a/x-pack/legacy/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts +++ b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - SavedObjectAttributes, - SavedObjectsServiceStart, - ISavedObjectsRepository, -} from 'src/core/server'; +import { SavedObjectAttributes, SavedObjectsClientContract } from 'src/core/server'; export interface MlTelemetry extends SavedObjectAttributes { file_data_visualizer: { @@ -31,21 +27,20 @@ export function createMlTelemetry(count: number = 0): MlTelemetry { } // savedObjects export function storeMlTelemetry( - internalRepository: ISavedObjectsRepository, + savedObjectsClient: SavedObjectsClientContract, mlTelemetry: MlTelemetry ): void { - internalRepository.create('ml-telemetry', mlTelemetry, { + savedObjectsClient.create('ml-telemetry', mlTelemetry, { id: ML_TELEMETRY_DOC_ID, overwrite: true, }); } export async function incrementFileDataVisualizerIndexCreationCount( - savedObjects: SavedObjectsServiceStart + savedObjectsClient: SavedObjectsClientContract ): Promise { - const internalRepository = await savedObjects.createInternalRepository(); try { - const { attributes } = await internalRepository.get('telemetry', 'telemetry'); + const { attributes } = await savedObjectsClient.get('telemetry', 'telemetry'); if (attributes.enabled === false) { return; @@ -59,7 +54,7 @@ export async function incrementFileDataVisualizerIndexCreationCount( let indicesCount = 1; try { - const { attributes } = (await internalRepository.get( + const { attributes } = (await savedObjectsClient.get( 'ml-telemetry', ML_TELEMETRY_DOC_ID )) as MlTelemetrySavedObject; @@ -69,5 +64,5 @@ export async function incrementFileDataVisualizerIndexCreationCount( } const mlTelemetry = createMlTelemetry(indicesCount); - storeMlTelemetry(internalRepository, mlTelemetry); + storeMlTelemetry(savedObjectsClient, mlTelemetry); } diff --git a/x-pack/legacy/plugins/ml/server/lib/query_utils.ts b/x-pack/plugins/ml/server/lib/query_utils.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/query_utils.ts rename to x-pack/plugins/ml/server/lib/query_utils.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/sample_data_sets/index.ts b/x-pack/plugins/ml/server/lib/sample_data_sets/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/sample_data_sets/index.ts rename to x-pack/plugins/ml/server/lib/sample_data_sets/index.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts b/x-pack/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts rename to x-pack/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts diff --git a/x-pack/legacy/plugins/ml/server/lib/spaces_utils.ts b/x-pack/plugins/ml/server/lib/spaces_utils.ts similarity index 75% rename from x-pack/legacy/plugins/ml/server/lib/spaces_utils.ts rename to x-pack/plugins/ml/server/lib/spaces_utils.ts index 92373bae4ea1d..ed684eadb9570 100644 --- a/x-pack/legacy/plugins/ml/server/lib/spaces_utils.ts +++ b/x-pack/plugins/ml/server/lib/spaces_utils.ts @@ -5,20 +5,19 @@ */ import { Request } from 'hapi'; -import { Space } from '../../../../../plugins/spaces/server'; -import { LegacySpacesPlugin } from '../../../spaces'; +import { Space, SpacesPluginSetup } from '../../../spaces/server'; interface GetActiveSpaceResponse { valid: boolean; space?: Space; } -export function spacesUtilsProvider(spacesPlugin: LegacySpacesPlugin, request: Request) { +export function spacesUtilsProvider(spacesPlugin: SpacesPluginSetup, request: Request) { async function activeSpace(): Promise { try { return { valid: true, - space: await spacesPlugin.getActiveSpace(request), + space: await spacesPlugin.spacesService.getActiveSpace(request), }; } catch (e) { return { diff --git a/x-pack/legacy/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json b/x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json rename to x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json diff --git a/x-pack/legacy/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_response.json b/x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_response.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_response.json rename to x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_response.json diff --git a/x-pack/legacy/plugins/ml/server/models/annotation_service/annotation.test.ts b/x-pack/plugins/ml/server/models/annotation_service/annotation.test.ts similarity index 96% rename from x-pack/legacy/plugins/ml/server/models/annotation_service/annotation.test.ts rename to x-pack/plugins/ml/server/models/annotation_service/annotation.test.ts index 7e0649d15bfb0..d7a13154a6f37 100644 --- a/x-pack/legacy/plugins/ml/server/models/annotation_service/annotation.test.ts +++ b/x-pack/plugins/ml/server/models/annotation_service/annotation.test.ts @@ -8,9 +8,12 @@ import getAnnotationsRequestMock from './__mocks__/get_annotations_request.json' import getAnnotationsResponseMock from './__mocks__/get_annotations_response.json'; import { RequestHandlerContext } from 'src/core/server'; -import { ANNOTATION_TYPE } from '../../../common/constants/annotations'; -import { ML_ANNOTATIONS_INDEX_ALIAS_WRITE } from '../../../common/constants/index_patterns'; -import { Annotation, isAnnotations } from '../../../common/types/annotations'; +import { ANNOTATION_TYPE } from '../../../../../legacy/plugins/ml/common/constants/annotations'; +import { ML_ANNOTATIONS_INDEX_ALIAS_WRITE } from '../../../../../legacy/plugins/ml/common/constants/index_patterns'; +import { + Annotation, + isAnnotations, +} from '../../../../../legacy/plugins/ml/common/types/annotations'; import { DeleteParams, GetResponse, IndexAnnotationArgs } from './annotation'; import { annotationServiceProvider } from './index'; diff --git a/x-pack/legacy/plugins/ml/server/models/annotation_service/annotation.ts b/x-pack/plugins/ml/server/models/annotation_service/annotation.ts similarity index 96% rename from x-pack/legacy/plugins/ml/server/models/annotation_service/annotation.ts rename to x-pack/plugins/ml/server/models/annotation_service/annotation.ts index 399305ea2603e..042d7bbc80653 100644 --- a/x-pack/legacy/plugins/ml/server/models/annotation_service/annotation.ts +++ b/x-pack/plugins/ml/server/models/annotation_service/annotation.ts @@ -8,18 +8,18 @@ import Boom from 'boom'; import _ from 'lodash'; import { RequestHandlerContext } from 'src/core/server'; -import { ANNOTATION_TYPE } from '../../../common/constants/annotations'; +import { ANNOTATION_TYPE } from '../../../../../legacy/plugins/ml/common/constants/annotations'; import { ML_ANNOTATIONS_INDEX_ALIAS_READ, ML_ANNOTATIONS_INDEX_ALIAS_WRITE, -} from '../../../common/constants/index_patterns'; +} from '../../../../../legacy/plugins/ml/common/constants/index_patterns'; import { Annotation, Annotations, isAnnotation, isAnnotations, -} from '../../../common/types/annotations'; +} from '../../../../../legacy/plugins/ml/common/types/annotations'; // TODO All of the following interface/type definitions should // eventually be replaced by the proper upstream definitions diff --git a/x-pack/legacy/plugins/ml/server/models/annotation_service/index.ts b/x-pack/plugins/ml/server/models/annotation_service/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/annotation_service/index.ts rename to x-pack/plugins/ml/server/models/annotation_service/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js b/x-pack/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js rename to x-pack/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js diff --git a/x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts b/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts similarity index 75% rename from x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts rename to x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts index ea986feab4e99..e39a0177c31b9 100644 --- a/x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts +++ b/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts @@ -5,10 +5,10 @@ */ import { APICaller } from 'src/core/server'; -import { BucketSpanEstimatorData } from '../../../public/application/services/ml_api_service'; +import { BucketSpanEstimatorData } from '../../../../../legacy/plugins/ml/public/application/services/ml_api_service'; export function estimateBucketSpanFactory( callAsCurrentUser: APICaller, callAsInternalUser: APICaller, - xpackMainPlugin: any + isSecurityDisabled: boolean ): (config: BucketSpanEstimatorData) => Promise; diff --git a/x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.js b/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.js similarity index 98% rename from x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.js rename to x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.js index aec677dd57d61..53b9d75304963 100644 --- a/x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.js +++ b/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.js @@ -12,9 +12,11 @@ import { INTERVALS } from './intervals'; import { singleSeriesCheckerFactory } from './single_series_checker'; import { polledDataCheckerFactory } from './polled_data_checker'; -import { isSecurityDisabled } from '../../lib/security_utils'; - -export function estimateBucketSpanFactory(callAsCurrentUser, callAsInternalUser, xpackMainPlugin) { +export function estimateBucketSpanFactory( + callAsCurrentUser, + callAsInternalUser, + isSecurityDisabled +) { const PolledDataChecker = polledDataCheckerFactory(callAsCurrentUser); const SingleSeriesChecker = singleSeriesCheckerFactory(callAsCurrentUser); @@ -384,7 +386,7 @@ export function estimateBucketSpanFactory(callAsCurrentUser, callAsInternalUser, }); } - if (isSecurityDisabled(xpackMainPlugin)) { + if (isSecurityDisabled) { getBucketSpanEstimation(); } else { // if security is enabled, check that the user has permission to diff --git a/x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/index.ts b/x-pack/plugins/ml/server/models/bucket_span_estimator/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/index.ts rename to x-pack/plugins/ml/server/models/bucket_span_estimator/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/intervals.js b/x-pack/plugins/ml/server/models/bucket_span_estimator/intervals.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/intervals.js rename to x-pack/plugins/ml/server/models/bucket_span_estimator/intervals.js diff --git a/x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/polled_data_checker.js b/x-pack/plugins/ml/server/models/bucket_span_estimator/polled_data_checker.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/polled_data_checker.js rename to x-pack/plugins/ml/server/models/bucket_span_estimator/polled_data_checker.js diff --git a/x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/single_series_checker.js b/x-pack/plugins/ml/server/models/bucket_span_estimator/single_series_checker.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/bucket_span_estimator/single_series_checker.js rename to x-pack/plugins/ml/server/models/bucket_span_estimator/single_series_checker.js diff --git a/x-pack/legacy/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.d.ts b/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.d.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.d.ts rename to x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.d.ts diff --git a/x-pack/legacy/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.js b/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.js rename to x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.js diff --git a/x-pack/legacy/plugins/ml/server/models/calculate_model_memory_limit/index.ts b/x-pack/plugins/ml/server/models/calculate_model_memory_limit/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/calculate_model_memory_limit/index.ts rename to x-pack/plugins/ml/server/models/calculate_model_memory_limit/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/calendar/calendar_manager.ts b/x-pack/plugins/ml/server/models/calendar/calendar_manager.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/calendar/calendar_manager.ts rename to x-pack/plugins/ml/server/models/calendar/calendar_manager.ts diff --git a/x-pack/legacy/plugins/ml/server/models/calendar/event_manager.ts b/x-pack/plugins/ml/server/models/calendar/event_manager.ts similarity index 94% rename from x-pack/legacy/plugins/ml/server/models/calendar/event_manager.ts rename to x-pack/plugins/ml/server/models/calendar/event_manager.ts index 488839f68b3fe..0a3108016da0e 100644 --- a/x-pack/legacy/plugins/ml/server/models/calendar/event_manager.ts +++ b/x-pack/plugins/ml/server/models/calendar/event_manager.ts @@ -6,7 +6,7 @@ import Boom from 'boom'; -import { GLOBAL_CALENDAR } from '../../../common/constants/calendars'; +import { GLOBAL_CALENDAR } from '../../../../../legacy/plugins/ml/common/constants/calendars'; export interface CalendarEvent { calendar_id?: string; diff --git a/x-pack/legacy/plugins/ml/server/models/calendar/index.ts b/x-pack/plugins/ml/server/models/calendar/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/calendar/index.ts rename to x-pack/plugins/ml/server/models/calendar/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/data_frame_analytics/analytics_audit_messages.ts b/x-pack/plugins/ml/server/models/data_frame_analytics/analytics_audit_messages.ts similarity index 88% rename from x-pack/legacy/plugins/ml/server/models/data_frame_analytics/analytics_audit_messages.ts rename to x-pack/plugins/ml/server/models/data_frame_analytics/analytics_audit_messages.ts index abe389165182f..a8757e289dcf7 100644 --- a/x-pack/legacy/plugins/ml/server/models/data_frame_analytics/analytics_audit_messages.ts +++ b/x-pack/plugins/ml/server/models/data_frame_analytics/analytics_audit_messages.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { callWithRequestType } from '../../../common/types/kibana'; -import { ML_NOTIFICATION_INDEX_PATTERN } from '../../../common/constants/index_patterns'; -import { JobMessage } from '../../../common/types/audit_message'; +import { callWithRequestType } from '../../../../../legacy/plugins/ml/common/types/kibana'; +import { ML_NOTIFICATION_INDEX_PATTERN } from '../../../../../legacy/plugins/ml/common/constants/index_patterns'; +import { JobMessage } from '../../../../../legacy/plugins/ml/common/types/audit_message'; const SIZE = 50; diff --git a/x-pack/legacy/plugins/ml/server/models/data_frame_analytics/index.js b/x-pack/plugins/ml/server/models/data_frame_analytics/index.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_frame_analytics/index.js rename to x-pack/plugins/ml/server/models/data_frame_analytics/index.js diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts similarity index 97% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts rename to x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts index de23950e5cc1c..c51f65714bc05 100644 --- a/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts @@ -5,7 +5,7 @@ */ import { RequestHandlerContext } from 'kibana/server'; -import { Module } from '../../../common/types/modules'; +import { Module } from '../../../../../legacy/plugins/ml/common/types/modules'; import { DataRecognizer } from '../data_recognizer'; describe('ML - data recognizer', () => { diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts similarity index 99% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.ts rename to x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts index 553de75e38e05..8d2a6c9955da3 100644 --- a/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts @@ -10,7 +10,7 @@ import numeral from '@elastic/numeral'; import { CallAPIOptions, RequestHandlerContext, SavedObjectsClientContract } from 'kibana/server'; import { IndexPatternAttributes } from 'src/plugins/data/server'; import { merge } from 'lodash'; -import { MlJob } from '../../../common/types/jobs'; +import { MlJob } from '../../../../../legacy/plugins/ml/common/types/jobs'; import { KibanaObjects, ModuleDataFeed, @@ -23,8 +23,11 @@ import { JobResponse, KibanaObjectResponse, DataRecognizerConfigResponse, -} from '../../../common/types/modules'; -import { getLatestDataOrBucketTimestamp, prefixDatafeedId } from '../../../common/util/job_utils'; +} from '../../../../../legacy/plugins/ml/common/types/modules'; +import { + getLatestDataOrBucketTimestamp, + prefixDatafeedId, +} from '../../../../../legacy/plugins/ml/common/util/job_utils'; import { mlLog } from '../../client/log'; // @ts-ignore import { jobServiceProvider } from '../job_service'; diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/index.ts b/x-pack/plugins/ml/server/models/data_recognizer/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/index.ts rename to x-pack/plugins/ml/server/models/data_recognizer/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/dashboard/ml_http_access_explorer_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/dashboard/ml_http_access_explorer_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/dashboard/ml_http_access_explorer_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/dashboard/ml_http_access_explorer_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/search/ml_http_access_filebeat_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/search/ml_http_access_filebeat_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/search/ml_http_access_filebeat_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/search/ml_http_access_filebeat_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_events_timechart_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_events_timechart_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_events_timechart_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_events_timechart_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_map_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_map_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_map_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_map_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_source_ip_timechart_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_source_ip_timechart_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_source_ip_timechart_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_source_ip_timechart_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_status_code_timechart_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_status_code_timechart_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_status_code_timechart_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_status_code_timechart_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_top_source_ips_table_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_top_source_ips_table_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_top_source_ips_table_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_top_source_ips_table_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_top_urls_table_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_top_urls_table_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_top_urls_table_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_top_urls_table_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_unique_count_url_timechart_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_unique_count_url_timechart_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_unique_count_url_timechart_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/kibana/visualization/ml_http_access_unique_count_url_timechart_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_low_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_low_request_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_low_request_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_low_request_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_source_ip_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_source_ip_request_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_source_ip_request_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_source_ip_request_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_source_ip_url_count_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_source_ip_url_count_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_source_ip_url_count_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_source_ip_url_count_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_status_code_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_status_code_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_status_code_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_status_code_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_visitor_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_visitor_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_visitor_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/datafeed_visitor_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/low_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/low_request_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/low_request_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/low_request_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_request_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_request_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_request_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_url_count_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_url_count_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_url_count_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_url_count_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/status_code_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/status_code_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/status_code_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/status_code_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/visitor_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/visitor_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/visitor_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/visitor_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/abnormal_span_durations_jsbase.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/abnormal_span_durations_jsbase.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/abnormal_span_durations_jsbase.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/abnormal_span_durations_jsbase.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/anomalous_error_rate_for_user_agents_jsbase.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/anomalous_error_rate_for_user_agents_jsbase.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/anomalous_error_rate_for_user_agents_jsbase.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/anomalous_error_rate_for_user_agents_jsbase.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_abnormal_span_durations_jsbase.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_abnormal_span_durations_jsbase.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_abnormal_span_durations_jsbase.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_abnormal_span_durations_jsbase.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_anomalous_error_rate_for_user_agents_jsbase.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_anomalous_error_rate_for_user_agents_jsbase.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_anomalous_error_rate_for_user_agents_jsbase.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_anomalous_error_rate_for_user_agents_jsbase.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_decreased_throughput_jsbase.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_decreased_throughput_jsbase.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_decreased_throughput_jsbase.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_decreased_throughput_jsbase.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_high_count_by_user_agent_jsbase.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_high_count_by_user_agent_jsbase.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_high_count_by_user_agent_jsbase.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/datafeed_high_count_by_user_agent_jsbase.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/decreased_throughput_jsbase.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/decreased_throughput_jsbase.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/decreased_throughput_jsbase.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/decreased_throughput_jsbase.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/high_count_by_user_agent_jsbase.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/high_count_by_user_agent_jsbase.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/high_count_by_user_agent_jsbase.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_jsbase/ml/high_count_by_user_agent_jsbase.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/abnormal_span_durations_nodejs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/abnormal_span_durations_nodejs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/abnormal_span_durations_nodejs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/abnormal_span_durations_nodejs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/abnormal_trace_durations_nodejs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/abnormal_trace_durations_nodejs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/abnormal_trace_durations_nodejs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/abnormal_trace_durations_nodejs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_abnormal_span_durations_nodejs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_abnormal_span_durations_nodejs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_abnormal_span_durations_nodejs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_abnormal_span_durations_nodejs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_abnormal_trace_durations_nodejs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_abnormal_trace_durations_nodejs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_abnormal_trace_durations_nodejs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_abnormal_trace_durations_nodejs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_decreased_throughput_nodejs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_decreased_throughput_nodejs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_decreased_throughput_nodejs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/datafeed_decreased_throughput_nodejs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/decreased_throughput_nodejs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/decreased_throughput_nodejs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/decreased_throughput_nodejs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_nodejs/ml/decreased_throughput_nodejs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_transaction/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_transaction/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_response_time.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_response_time.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_response_time.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_response_time.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/dashboard/ml_auditbeat_docker_process_event_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/dashboard/ml_auditbeat_docker_process_event_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/dashboard/ml_auditbeat_docker_process_event_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/dashboard/ml_auditbeat_docker_process_event_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/dashboard/ml_auditbeat_docker_process_explorer_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/dashboard/ml_auditbeat_docker_process_explorer_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/dashboard/ml_auditbeat_docker_process_explorer_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/dashboard/ml_auditbeat_docker_process_explorer_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/search/ml_auditbeat_docker_process_events_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/search/ml_auditbeat_docker_process_events_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/search/ml_auditbeat_docker_process_events_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/search/ml_auditbeat_docker_process_events_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_event_rate_by_process_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_event_rate_by_process_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_event_rate_by_process_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_event_rate_by_process_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_event_rate_vis_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_event_rate_vis_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_event_rate_vis_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_event_rate_vis_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_occurrence_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_occurrence_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_occurrence_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/kibana/visualization/ml_auditbeat_docker_process_occurrence_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/datafeed_docker_high_count_process_events_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/datafeed_docker_high_count_process_events_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/datafeed_docker_high_count_process_events_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/datafeed_docker_high_count_process_events_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/datafeed_docker_rare_process_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/datafeed_docker_rare_process_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/datafeed_docker_rare_process_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/datafeed_docker_rare_process_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/dashboard/ml_auditbeat_hosts_process_event_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/dashboard/ml_auditbeat_hosts_process_event_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/dashboard/ml_auditbeat_hosts_process_event_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/dashboard/ml_auditbeat_hosts_process_event_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/dashboard/ml_auditbeat_hosts_process_explorer_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/dashboard/ml_auditbeat_hosts_process_explorer_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/dashboard/ml_auditbeat_hosts_process_explorer_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/dashboard/ml_auditbeat_hosts_process_explorer_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/search/ml_auditbeat_hosts_process_events_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/search/ml_auditbeat_hosts_process_events_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/search/ml_auditbeat_hosts_process_events_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/search/ml_auditbeat_hosts_process_events_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_event_rate_by_process_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_event_rate_by_process_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_event_rate_by_process_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_event_rate_by_process_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_event_rate_vis_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_event_rate_vis_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_event_rate_vis_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_event_rate_vis_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_occurrence_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_occurrence_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_occurrence_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/kibana/visualization/ml_auditbeat_hosts_process_occurrence_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/datafeed_hosts_high_count_process_events_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/datafeed_hosts_high_count_process_events_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/datafeed_hosts_high_count_process_events_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/datafeed_hosts_high_count_process_events_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/datafeed_hosts_rare_process_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/datafeed_hosts_rare_process_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/datafeed_hosts_rare_process_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/datafeed_hosts_rare_process_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/datafeed_log_entry_rate.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/datafeed_log_entry_rate.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/datafeed_log_entry_rate.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/datafeed_log_entry_rate.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/log_entry_rate.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/log_entry_rate.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/log_entry_rate.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/log_entry_rate.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/datafeed_log_entry_categories_count.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/datafeed_log_entry_categories_count.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/datafeed_log_entry_categories_count.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/datafeed_log_entry_categories_count.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/log_entry_categories_count.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/log_entry_categories_count.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/log_entry_categories_count.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/log_entry_categories_count.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_high_mean_cpu_iowait_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_high_mean_cpu_iowait_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_high_mean_cpu_iowait_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_high_mean_cpu_iowait_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_max_disk_utilization_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_max_disk_utilization_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_max_disk_utilization_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_max_disk_utilization_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_metricbeat_outages_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_metricbeat_outages_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_metricbeat_outages_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/datafeed_metricbeat_outages_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/high_mean_cpu_iowait_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/high_mean_cpu_iowait_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/high_mean_cpu_iowait_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/high_mean_cpu_iowait_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/max_disk_utilization_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/max_disk_utilization_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/max_disk_utilization_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/max_disk_utilization_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/metricbeat_outages_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/metricbeat_outages_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/metricbeat_outages_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/ml/metricbeat_outages_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/dashboard/ml_http_access_explorer_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/dashboard/ml_http_access_explorer_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/dashboard/ml_http_access_explorer_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/dashboard/ml_http_access_explorer_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/search/ml_http_access_filebeat_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/search/ml_http_access_filebeat_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/search/ml_http_access_filebeat_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/search/ml_http_access_filebeat_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_events_timechart_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_events_timechart_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_events_timechart_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_events_timechart_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_map_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_map_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_map_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_map_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_source_ip_timechart_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_source_ip_timechart_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_source_ip_timechart_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_source_ip_timechart_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_status_code_timechart_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_status_code_timechart_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_status_code_timechart_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_status_code_timechart_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_top_source_ips_table_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_top_source_ips_table_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_top_source_ips_table_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_top_source_ips_table_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_top_urls_table_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_top_urls_table_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_top_urls_table_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_top_urls_table_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_unique_count_url_timechart_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_unique_count_url_timechart_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_unique_count_url_timechart_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/kibana/visualization/ml_http_access_unique_count_url_timechart_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_low_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_low_request_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_low_request_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_low_request_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_source_ip_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_source_ip_request_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_source_ip_request_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_source_ip_request_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_source_ip_url_count_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_source_ip_url_count_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_source_ip_url_count_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_source_ip_url_count_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_status_code_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_status_code_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_status_code_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_status_code_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_visitor_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_visitor_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_visitor_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/datafeed_visitor_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/low_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/low_request_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/low_request_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/low_request_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_request_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_request_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_request_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_url_count_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_url_count_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_url_count_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_url_count_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/status_code_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/status_code_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/status_code_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/status_code_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/visitor_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/visitor_rate_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/visitor_rate_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/visitor_rate_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/ml/datafeed_high_sum_total_sales.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/ml/datafeed_high_sum_total_sales.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/ml/datafeed_high_sum_total_sales.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/ml/datafeed_high_sum_total_sales.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/ml/high_sum_total_sales.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/ml/high_sum_total_sales.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/ml/high_sum_total_sales.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/ml/high_sum_total_sales.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_low_request_rate.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_low_request_rate.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_low_request_rate.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_low_request_rate.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_response_code_rates.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_response_code_rates.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_response_code_rates.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_response_code_rates.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_url_scanning.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_url_scanning.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_url_scanning.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/datafeed_url_scanning.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/low_request_rate.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/low_request_rate.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/low_request_rate.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/low_request_rate.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/response_code_rates.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/response_code_rates.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/response_code_rates.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/response_code_rates.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/url_scanning.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/url_scanning.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/url_scanning.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/ml/url_scanning.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_port_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_port_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_port_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_port_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_service.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_service.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_service.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_service.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_url_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_url_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_url_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_network_url_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_process_all_hosts_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_process_all_hosts_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_process_all_hosts_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_process_all_hosts_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_user_name_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_user_name_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_user_name_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_linux_anomalous_user_name_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_rare_process_by_host_linux_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_rare_process_by_host_linux_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_rare_process_by_host_linux_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/datafeed_rare_process_by_host_linux_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_port_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_port_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_port_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_port_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_service.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_service.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_service.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_service.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_url_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_url_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_url_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_network_url_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_process_all_hosts_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_process_all_hosts_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_process_all_hosts_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_process_all_hosts_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_user_name_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_user_name_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_user_name_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/linux_anomalous_user_name_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/rare_process_by_host_linux_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/rare_process_by_host_linux_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/rare_process_by_host_linux_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/ml/rare_process_by_host_linux_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/ml/datafeed_suspicious_login_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/ml/datafeed_suspicious_login_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/ml/datafeed_suspicious_login_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/ml/datafeed_suspicious_login_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/ml/suspicious_login_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/ml/suspicious_login_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/ml/suspicious_login_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/ml/suspicious_login_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_dns_tunneling.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_dns_tunneling.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_dns_tunneling.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_dns_tunneling.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_dns_question.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_dns_question.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_dns_question.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_dns_question.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_server_domain.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_server_domain.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_server_domain.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_server_domain.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_urls.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_urls.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_urls.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_urls.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_user_agent.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_user_agent.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_user_agent.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_user_agent.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_dns_tunneling.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_dns_tunneling.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_dns_tunneling.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_dns_tunneling.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_dns_question.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_dns_question.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_dns_question.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_dns_question.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_server_domain.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_server_domain.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_server_domain.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_server_domain.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_urls.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_urls.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_urls.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_urls.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_user_agent.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_user_agent.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_user_agent.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/packetbeat_rare_user_agent.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_rare_process_by_host_windows_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_rare_process_by_host_windows_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_rare_process_by_host_windows_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_rare_process_by_host_windows_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_network_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_network_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_network_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_network_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_path_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_path_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_path_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_path_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_process_all_hosts_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_process_all_hosts_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_process_all_hosts_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_process_all_hosts_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_process_creation.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_process_creation.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_process_creation.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_process_creation.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_script.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_script.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_script.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_script.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_service.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_service.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_service.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_service.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_user_name_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_user_name_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_user_name_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_anomalous_user_name_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_rare_user_runas_event.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_rare_user_runas_event.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_rare_user_runas_event.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/datafeed_windows_rare_user_runas_event.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/rare_process_by_host_windows_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/rare_process_by_host_windows_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/rare_process_by_host_windows_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/rare_process_by_host_windows_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_network_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_network_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_network_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_network_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_path_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_path_activity_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_path_activity_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_path_activity_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_process_all_hosts_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_process_all_hosts_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_process_all_hosts_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_process_all_hosts_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_process_creation.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_process_creation.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_process_creation.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_process_creation.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_script.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_script.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_script.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_script.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_service.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_service.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_service.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_service.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_user_name_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_user_name_ecs.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_user_name_ecs.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_anomalous_user_name_ecs.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_rare_user_runas_event.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_rare_user_runas_event.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_rare_user_runas_event.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/ml/windows_rare_user_runas_event.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/logo.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/logo.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/logo.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/manifest.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/manifest.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/manifest.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/ml/datafeed_windows_rare_user_type10_remote_login.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/ml/datafeed_windows_rare_user_type10_remote_login.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/ml/datafeed_windows_rare_user_type10_remote_login.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/ml/datafeed_windows_rare_user_type10_remote_login.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/ml/windows_rare_user_type10_remote_login.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/ml/windows_rare_user_type10_remote_login.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/ml/windows_rare_user_type10_remote_login.json rename to x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/ml/windows_rare_user_type10_remote_login.json diff --git a/x-pack/legacy/plugins/ml/server/models/data_visualizer/data_visualizer.ts b/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts similarity index 99% rename from x-pack/legacy/plugins/ml/server/models/data_visualizer/data_visualizer.ts rename to x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts index b0a61b1232dc0..9463f74e1e746 100644 --- a/x-pack/legacy/plugins/ml/server/models/data_visualizer/data_visualizer.ts +++ b/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts @@ -6,8 +6,8 @@ import { CallAPIOptions, IScopedClusterClient } from 'src/core/server'; import _ from 'lodash'; -import { ML_JOB_FIELD_TYPES } from '../../../common/constants/field_types'; -import { getSafeAggregationName } from '../../../common/util/job_utils'; +import { ML_JOB_FIELD_TYPES } from '../../../../../legacy/plugins/ml/common/constants/field_types'; +import { getSafeAggregationName } from '../../../../../legacy/plugins/ml/common/util/job_utils'; import { buildBaseFilterCriteria, buildSamplerAggregation, diff --git a/x-pack/legacy/plugins/ml/server/models/data_visualizer/index.ts b/x-pack/plugins/ml/server/models/data_visualizer/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/data_visualizer/index.ts rename to x-pack/plugins/ml/server/models/data_visualizer/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/fields_service/fields_service.d.ts b/x-pack/plugins/ml/server/models/fields_service/fields_service.d.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/fields_service/fields_service.d.ts rename to x-pack/plugins/ml/server/models/fields_service/fields_service.d.ts diff --git a/x-pack/legacy/plugins/ml/server/models/fields_service/fields_service.js b/x-pack/plugins/ml/server/models/fields_service/fields_service.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/fields_service/fields_service.js rename to x-pack/plugins/ml/server/models/fields_service/fields_service.js diff --git a/x-pack/legacy/plugins/ml/server/models/fields_service/index.ts b/x-pack/plugins/ml/server/models/fields_service/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/fields_service/index.ts rename to x-pack/plugins/ml/server/models/fields_service/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts b/x-pack/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts similarity index 95% rename from x-pack/legacy/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts rename to x-pack/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts index 9f30f609c60b6..1d0452f2337f9 100644 --- a/x-pack/legacy/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts +++ b/x-pack/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts @@ -6,7 +6,7 @@ import Boom from 'boom'; import { RequestHandlerContext } from 'kibana/server'; -import { FindFileStructureResponse } from '../../../common/types/file_datavisualizer'; +import { FindFileStructureResponse } from '../../../../../legacy/plugins/ml/common/types/file_datavisualizer'; export type InputData = any[]; diff --git a/x-pack/legacy/plugins/ml/server/models/file_data_visualizer/import_data.ts b/x-pack/plugins/ml/server/models/file_data_visualizer/import_data.ts similarity index 97% rename from x-pack/legacy/plugins/ml/server/models/file_data_visualizer/import_data.ts rename to x-pack/plugins/ml/server/models/file_data_visualizer/import_data.ts index 008efb43a6c07..e4de71ad0793d 100644 --- a/x-pack/legacy/plugins/ml/server/models/file_data_visualizer/import_data.ts +++ b/x-pack/plugins/ml/server/models/file_data_visualizer/import_data.ts @@ -5,7 +5,7 @@ */ import { RequestHandlerContext } from 'kibana/server'; -import { INDEX_META_DATA_CREATED_BY } from '../../../common/constants/file_datavisualizer'; +import { INDEX_META_DATA_CREATED_BY } from '../../../../../legacy/plugins/ml/common/constants/file_datavisualizer'; import { InputData } from './file_data_visualizer'; export interface Settings { diff --git a/x-pack/legacy/plugins/ml/server/models/file_data_visualizer/index.ts b/x-pack/plugins/ml/server/models/file_data_visualizer/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/file_data_visualizer/index.ts rename to x-pack/plugins/ml/server/models/file_data_visualizer/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/filter/filter_manager.ts b/x-pack/plugins/ml/server/models/filter/filter_manager.ts similarity index 98% rename from x-pack/legacy/plugins/ml/server/models/filter/filter_manager.ts rename to x-pack/plugins/ml/server/models/filter/filter_manager.ts index f40663a5eb6b2..baba495257aca 100644 --- a/x-pack/legacy/plugins/ml/server/models/filter/filter_manager.ts +++ b/x-pack/plugins/ml/server/models/filter/filter_manager.ts @@ -7,7 +7,10 @@ import Boom from 'boom'; import { IScopedClusterClient } from 'src/core/server'; -import { DetectorRule, DetectorRuleScope } from '../../../common/types/detector_rules'; +import { + DetectorRule, + DetectorRuleScope, +} from '../../../../../legacy/plugins/ml/common/types/detector_rules'; export interface Filter { filter_id: string; diff --git a/x-pack/legacy/plugins/ml/server/models/filter/index.js b/x-pack/plugins/ml/server/models/filter/index.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/filter/index.js rename to x-pack/plugins/ml/server/models/filter/index.js diff --git a/x-pack/legacy/plugins/ml/server/models/filter/index.ts b/x-pack/plugins/ml/server/models/filter/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/filter/index.ts rename to x-pack/plugins/ml/server/models/filter/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/job_audit_messages/index.ts b/x-pack/plugins/ml/server/models/job_audit_messages/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_audit_messages/index.ts rename to x-pack/plugins/ml/server/models/job_audit_messages/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/job_audit_messages/job_audit_messages.d.ts b/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.d.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_audit_messages/job_audit_messages.d.ts rename to x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.d.ts diff --git a/x-pack/legacy/plugins/ml/server/models/job_audit_messages/job_audit_messages.js b/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.js similarity index 98% rename from x-pack/legacy/plugins/ml/server/models/job_audit_messages/job_audit_messages.js rename to x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.js index 2cdfc0ef4f4c5..b434846d6f0f4 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_audit_messages/job_audit_messages.js +++ b/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ML_NOTIFICATION_INDEX_PATTERN } from '../../../common/constants/index_patterns'; +import { ML_NOTIFICATION_INDEX_PATTERN } from '../../../../../legacy/plugins/ml/common/constants/index_patterns'; import moment from 'moment'; const SIZE = 1000; diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/datafeeds.js b/x-pack/plugins/ml/server/models/job_service/datafeeds.js similarity index 97% rename from x-pack/legacy/plugins/ml/server/models/job_service/datafeeds.js rename to x-pack/plugins/ml/server/models/job_service/datafeeds.js index c3b54fff0682d..961b712610512 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/datafeeds.js +++ b/x-pack/plugins/ml/server/models/job_service/datafeeds.js @@ -5,7 +5,10 @@ */ import { i18n } from '@kbn/i18n'; -import { JOB_STATE, DATAFEED_STATE } from '../../../common/constants/states'; +import { + JOB_STATE, + DATAFEED_STATE, +} from '../../../../../legacy/plugins/ml/common/constants/states'; import { fillResultsWithTimeouts, isRequestTimeout } from './error_utils'; export function datafeedsProvider(callWithRequest) { diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/error_utils.js b/x-pack/plugins/ml/server/models/job_service/error_utils.js similarity index 94% rename from x-pack/legacy/plugins/ml/server/models/job_service/error_utils.js rename to x-pack/plugins/ml/server/models/job_service/error_utils.js index 6f25b5870f85c..21e45110e7093 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/error_utils.js +++ b/x-pack/plugins/ml/server/models/job_service/error_utils.js @@ -5,7 +5,10 @@ */ import { i18n } from '@kbn/i18n'; -import { JOB_STATE, DATAFEED_STATE } from '../../../common/constants/states'; +import { + JOB_STATE, + DATAFEED_STATE, +} from '../../../../../legacy/plugins/ml/common/constants/states'; const REQUEST_TIMEOUT = 'RequestTimeout'; diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/groups.js b/x-pack/plugins/ml/server/models/job_service/groups.js similarity index 95% rename from x-pack/legacy/plugins/ml/server/models/job_service/groups.js rename to x-pack/plugins/ml/server/models/job_service/groups.js index 6fbc071ef9854..b30e9cdc6048b 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/groups.js +++ b/x-pack/plugins/ml/server/models/job_service/groups.js @@ -5,7 +5,7 @@ */ import { CalendarManager } from '../calendar'; -import { GLOBAL_CALENDAR } from '../../../common/constants/calendars'; +import { GLOBAL_CALENDAR } from '../../../../../legacy/plugins/ml/common/constants/calendars'; export function groupsProvider(callWithRequest) { const calMngr = new CalendarManager(callWithRequest); diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/index.js b/x-pack/plugins/ml/server/models/job_service/index.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/index.js rename to x-pack/plugins/ml/server/models/job_service/index.js diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/jobs.js b/x-pack/plugins/ml/server/models/job_service/jobs.js similarity index 98% rename from x-pack/legacy/plugins/ml/server/models/job_service/jobs.js rename to x-pack/plugins/ml/server/models/job_service/jobs.js index b4b476c1f926e..16d3c30bb0a28 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/jobs.js +++ b/x-pack/plugins/ml/server/models/job_service/jobs.js @@ -5,7 +5,10 @@ */ import { i18n } from '@kbn/i18n'; -import { JOB_STATE, DATAFEED_STATE } from '../../../common/constants/states'; +import { + JOB_STATE, + DATAFEED_STATE, +} from '../../../../../legacy/plugins/ml/common/constants/states'; import { datafeedsProvider } from './datafeeds'; import { jobAuditMessagesProvider } from '../job_audit_messages'; import { resultsServiceProvider } from '../results_service'; @@ -14,7 +17,7 @@ import { fillResultsWithTimeouts, isRequestTimeout } from './error_utils'; import { getLatestDataOrBucketTimestamp, isTimeSeriesViewJob, -} from '../../../common/util/job_utils'; +} from '../../../../../legacy/plugins/ml/common/util/job_utils'; import { groupsProvider } from './groups'; import { uniq } from 'lodash'; diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/examples.ts b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/examples.ts similarity index 95% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/examples.ts rename to x-pack/plugins/ml/server/models/job_service/new_job/categorization/examples.ts index ea2c71b04f56d..1a098fdf16bb7 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/examples.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/examples.ts @@ -6,13 +6,13 @@ import { chunk } from 'lodash'; import { SearchResponse } from 'elasticsearch'; -import { CATEGORY_EXAMPLES_SAMPLE_SIZE } from '../../../../../common/constants/new_job'; +import { CATEGORY_EXAMPLES_SAMPLE_SIZE } from '../../../../../../../legacy/plugins/ml/common/constants/new_job'; import { Token, CategorizationAnalyzer, CategoryFieldExample, -} from '../../../../../common/types/categories'; -import { callWithRequestType } from '../../../../../common/types/kibana'; +} from '../../../../../../../legacy/plugins/ml/common/types/categories'; +import { callWithRequestType } from '../../../../../../../legacy/plugins/ml/common/types/kibana'; import { ValidationResults } from './validation_results'; const CHUNK_SIZE = 100; diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/index.ts b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/index.ts rename to x-pack/plugins/ml/server/models/job_service/new_job/categorization/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts similarity index 92% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts rename to x-pack/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts index 3361cc454e2b7..c8eb0002a31c8 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts @@ -5,9 +5,12 @@ */ import { SearchResponse } from 'elasticsearch'; -import { ML_RESULTS_INDEX_PATTERN } from '../../../../../common/constants/index_patterns'; -import { CategoryId, Category } from '../../../../../common/types/categories'; -import { callWithRequestType } from '../../../../../common/types/kibana'; +import { ML_RESULTS_INDEX_PATTERN } from '../../../../../../../legacy/plugins/ml/common/constants/index_patterns'; +import { + CategoryId, + Category, +} from '../../../../../../../legacy/plugins/ml/common/types/categories'; +import { callWithRequestType } from '../../../../../../../legacy/plugins/ml/common/types/kibana'; export function topCategoriesProvider(callWithRequest: callWithRequestType) { async function getTotalCategories(jobId: string): Promise<{ total: number }> { diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/validation_results.ts b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/validation_results.ts similarity index 96% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/validation_results.ts rename to x-pack/plugins/ml/server/models/job_service/new_job/categorization/validation_results.ts index 34e63eabb405e..bb1106b4d6396 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/validation_results.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/validation_results.ts @@ -9,13 +9,13 @@ import { CATEGORY_EXAMPLES_VALIDATION_STATUS, CATEGORY_EXAMPLES_ERROR_LIMIT, CATEGORY_EXAMPLES_WARNING_LIMIT, -} from '../../../../../common/constants/new_job'; +} from '../../../../../../../legacy/plugins/ml/common/constants/new_job'; import { FieldExampleCheck, CategoryFieldExample, VALIDATION_RESULT, -} from '../../../../../common/types/categories'; -import { getMedianStringLength } from '../../../../../common/util/string_utils'; +} from '../../../../../../../legacy/plugins/ml/common/types/categories'; +import { getMedianStringLength } from '../../../../../../../legacy/plugins/ml/common/util/string_utils'; const VALID_TOKEN_COUNT = 3; const MEDIAN_LINE_LENGTH_LIMIT = 400; diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/charts.ts b/x-pack/plugins/ml/server/models/job_service/new_job/charts.ts similarity index 87% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job/charts.ts rename to x-pack/plugins/ml/server/models/job_service/new_job/charts.ts index 88ae8caa91e4a..e662e3ca03ded 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/charts.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job/charts.ts @@ -6,7 +6,7 @@ import { newJobLineChartProvider } from './line_chart'; import { newJobPopulationChartProvider } from './population_chart'; -import { callWithRequestType } from '../../../../common/types/kibana'; +import { callWithRequestType } from '../../../../../../legacy/plugins/ml/common/types/kibana'; export function newJobChartsProvider(callWithRequest: callWithRequestType) { const { newJobLineChart } = newJobLineChartProvider(callWithRequest); diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/index.ts b/x-pack/plugins/ml/server/models/job_service/new_job/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job/index.ts rename to x-pack/plugins/ml/server/models/job_service/new_job/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/line_chart.ts b/x-pack/plugins/ml/server/models/job_service/new_job/line_chart.ts similarity index 92% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job/line_chart.ts rename to x-pack/plugins/ml/server/models/job_service/new_job/line_chart.ts index c1a5ad5e38ecc..3dfe935c655d5 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/line_chart.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job/line_chart.ts @@ -5,9 +5,12 @@ */ import { get } from 'lodash'; -import { AggFieldNamePair, EVENT_RATE_FIELD_ID } from '../../../../common/types/fields'; -import { callWithRequestType } from '../../../../common/types/kibana'; -import { ML_MEDIAN_PERCENTS } from '../../../../common/util/job_utils'; +import { + AggFieldNamePair, + EVENT_RATE_FIELD_ID, +} from '../../../../../../legacy/plugins/ml/common/types/fields'; +import { callWithRequestType } from '../../../../../../legacy/plugins/ml/common/types/kibana'; +import { ML_MEDIAN_PERCENTS } from '../../../../../../legacy/plugins/ml/common/util/job_utils'; type DtrIndex = number; type TimeStamp = number; diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/population_chart.ts b/x-pack/plugins/ml/server/models/job_service/new_job/population_chart.ts similarity index 95% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job/population_chart.ts rename to x-pack/plugins/ml/server/models/job_service/new_job/population_chart.ts index ee35f13c44ee6..d1ef9773f8f17 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/population_chart.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job/population_chart.ts @@ -5,9 +5,12 @@ */ import { get } from 'lodash'; -import { AggFieldNamePair, EVENT_RATE_FIELD_ID } from '../../../../common/types/fields'; -import { callWithRequestType } from '../../../../common/types/kibana'; -import { ML_MEDIAN_PERCENTS } from '../../../../common/util/job_utils'; +import { + AggFieldNamePair, + EVENT_RATE_FIELD_ID, +} from '../../../../../../legacy/plugins/ml/common/types/fields'; +import { callWithRequestType } from '../../../../../../legacy/plugins/ml/common/types/kibana'; +import { ML_MEDIAN_PERCENTS } from '../../../../../../legacy/plugins/ml/common/util/job_utils'; const OVER_FIELD_EXAMPLES_COUNT = 40; diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/cloudwatch_field_caps.json b/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/cloudwatch_field_caps.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/cloudwatch_field_caps.json rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/cloudwatch_field_caps.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/farequote_field_caps.json b/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/farequote_field_caps.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/farequote_field_caps.json rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/farequote_field_caps.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/kibana_saved_objects.json b/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/kibana_saved_objects.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/kibana_saved_objects.json rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/kibana_saved_objects.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/rollup_caps.json b/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/rollup_caps.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/rollup_caps.json rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/rollup_caps.json 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/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/cloudwatch_rollup_job_caps.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/cloudwatch_rollup_job_caps.json rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/cloudwatch_rollup_job_caps.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps.json b/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps.json rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps_empty.json b/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps_empty.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps_empty.json rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps_empty.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts similarity index 97% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts index efe06f8b5ad4a..475612f276c72 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts @@ -4,12 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Aggregation, METRIC_AGG_TYPE } from '../../../../common/types/fields'; +import { + Aggregation, + METRIC_AGG_TYPE, +} from '../../../../../../legacy/plugins/ml/common/types/fields'; import { ML_JOB_AGGREGATION, KIBANA_AGGREGATION, ES_AGGREGATION, -} from '../../../../common/constants/aggregation_types'; +} from '../../../../../../legacy/plugins/ml/common/constants/aggregation_types'; // 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 diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts similarity index 96% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts index 5827201a63661..446c71dd40f68 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts @@ -12,9 +12,9 @@ import { FieldId, NewJobCaps, METRIC_AGG_TYPE, -} from '../../../../common/types/fields'; -import { ES_FIELD_TYPES } from '../../../../../../../../src/plugins/data/server'; -import { ML_JOB_AGGREGATION } from '../../../../common/constants/aggregation_types'; +} from '../../../../../../legacy/plugins/ml/common/types/fields'; +import { ES_FIELD_TYPES } from '../../../../../../../src/plugins/data/server'; +import { ML_JOB_AGGREGATION } from '../../../../../../legacy/plugins/ml/common/constants/aggregation_types'; import { rollupServiceProvider, RollupJob, RollupFields } from './rollup'; import { aggregations, mlOnlyAggregations } from './aggregations'; diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/index.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/index.ts rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts similarity index 93% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts index 3a9d979ccb22c..0a967c760a193 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts @@ -5,7 +5,11 @@ */ import { SavedObjectsClientContract } from 'kibana/server'; -import { Aggregation, Field, NewJobCaps } from '../../../../common/types/fields'; +import { + Aggregation, + Field, + NewJobCaps, +} from '../../../../../../legacy/plugins/ml/common/types/fields'; import { fieldServiceProvider } from './field_service'; interface NewJobCapsResponse { diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/rollup.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts similarity index 92% rename from x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/rollup.ts rename to x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts index 1e9ce3d8d5022..4cbdfe4f360e0 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/rollup.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts @@ -7,8 +7,8 @@ import { SavedObject } from 'src/core/server'; import { IndexPatternAttributes } from 'src/plugins/data/server'; import { SavedObjectsClientContract } from 'kibana/server'; -import { FieldId } from '../../../../common/types/fields'; -import { ES_AGGREGATION } from '../../../../common/constants/aggregation_types'; +import { FieldId } from '../../../../../../legacy/plugins/ml/common/types/fields'; +import { ES_AGGREGATION } from '../../../../../../legacy/plugins/ml/common/constants/aggregation_types'; export type RollupFields = Record]>; diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/job_validation.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/job_validation.js rename to x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_farequote_cardinality.json b/x-pack/plugins/ml/server/models/job_validation/__tests__/mock_farequote_cardinality.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_farequote_cardinality.json rename to x-pack/plugins/ml/server/models/job_validation/__tests__/mock_farequote_cardinality.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_farequote_search_response.json b/x-pack/plugins/ml/server/models/job_validation/__tests__/mock_farequote_search_response.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_farequote_search_response.json rename to x-pack/plugins/ml/server/models/job_validation/__tests__/mock_farequote_search_response.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_field_caps.json b/x-pack/plugins/ml/server/models/job_validation/__tests__/mock_field_caps.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_field_caps.json rename to x-pack/plugins/ml/server/models/job_validation/__tests__/mock_field_caps.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_it_search_response.json b/x-pack/plugins/ml/server/models/job_validation/__tests__/mock_it_search_response.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_it_search_response.json rename to x-pack/plugins/ml/server/models/job_validation/__tests__/mock_it_search_response.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_time_field.json b/x-pack/plugins/ml/server/models/job_validation/__tests__/mock_time_field.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_time_field.json rename to x-pack/plugins/ml/server/models/job_validation/__tests__/mock_time_field.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_time_field_nested.json b/x-pack/plugins/ml/server/models/job_validation/__tests__/mock_time_field_nested.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_time_field_nested.json rename to x-pack/plugins/ml/server/models/job_validation/__tests__/mock_time_field_nested.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_time_range.json b/x-pack/plugins/ml/server/models/job_validation/__tests__/mock_time_range.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_time_range.json rename to x-pack/plugins/ml/server/models/job_validation/__tests__/mock_time_range.json diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js similarity index 98% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js rename to x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js index 3dc2bee1e8705..023e0f5b614ed 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js +++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js @@ -6,7 +6,7 @@ import expect from '@kbn/expect'; import { validateBucketSpan } from '../validate_bucket_span'; -import { SKIP_BUCKET_SPAN_ESTIMATION } from '../../../../common/constants/validation'; +import { SKIP_BUCKET_SPAN_ESTIMATION } from '../../../../../../legacy/plugins/ml/common/constants/validation'; // farequote2017 snapshot snapshot mock search response // it returns a mock for the response of PolledDataChecker's search request diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js rename to x-pack/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js rename to x-pack/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js rename to x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js rename to x-pack/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/index.ts b/x-pack/plugins/ml/server/models/job_validation/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/index.ts rename to x-pack/plugins/ml/server/models/job_validation/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/job_validation.d.ts b/x-pack/plugins/ml/server/models/job_validation/job_validation.d.ts similarity index 83% rename from x-pack/legacy/plugins/ml/server/models/job_validation/job_validation.d.ts rename to x-pack/plugins/ml/server/models/job_validation/job_validation.d.ts index 4580602b0af23..bb8a372eaba30 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_validation/job_validation.d.ts +++ b/x-pack/plugins/ml/server/models/job_validation/job_validation.d.ts @@ -6,7 +6,7 @@ import { APICaller } from 'src/core/server'; import { TypeOf } from '@kbn/config-schema'; -import { validateJobSchema } from '../../new_platform/job_validation_schema'; +import { validateJobSchema } from '../../routes/schemas/job_validation_schema'; type ValidateJobPayload = TypeOf; @@ -15,5 +15,5 @@ export function validateJob( payload: ValidateJobPayload, kbnVersion: string, callAsInternalUser: APICaller, - xpackMainPlugin: any + isSecurityDisabled: boolean ): string[]; diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/job_validation.js b/x-pack/plugins/ml/server/models/job_validation/job_validation.js similarity index 94% rename from x-pack/legacy/plugins/ml/server/models/job_validation/job_validation.js rename to x-pack/plugins/ml/server/models/job_validation/job_validation.js index ab1fbb39ee706..d453c9add97d1 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_validation/job_validation.js +++ b/x-pack/plugins/ml/server/models/job_validation/job_validation.js @@ -8,11 +8,14 @@ import { i18n } from '@kbn/i18n'; import Boom from 'boom'; import { fieldsServiceProvider } from '../fields_service'; -import { renderTemplate } from '../../../common/util/string_utils'; +import { renderTemplate } from '../../../../../legacy/plugins/ml/common/util/string_utils'; import { getMessages } from './messages'; -import { VALIDATION_STATUS } from '../../../common/constants/validation'; +import { VALIDATION_STATUS } from '../../../../../legacy/plugins/ml/common/constants/validation'; -import { basicJobValidation, uniqWithIsEqual } from '../../../common/util/job_utils'; +import { + basicJobValidation, + uniqWithIsEqual, +} from '../../../../../legacy/plugins/ml/common/util/job_utils'; import { validateBucketSpan } from './validate_bucket_span'; import { validateCardinality } from './validate_cardinality'; import { validateInfluencers } from './validate_influencers'; @@ -24,7 +27,7 @@ export async function validateJob( payload, kbnVersion = 'current', callAsInternalUser, - xpackMainPlugin + isSecurityDisabled ) { const messages = getMessages(); @@ -112,7 +115,7 @@ export async function validateJob( job, duration, callAsInternalUser, - xpackMainPlugin + isSecurityDisabled )) ); validationMessages.push(...(await validateTimeRange(callWithRequest, job, duration))); diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/messages.js b/x-pack/plugins/ml/server/models/job_validation/messages.js similarity index 99% rename from x-pack/legacy/plugins/ml/server/models/job_validation/messages.js rename to x-pack/plugins/ml/server/models/job_validation/messages.js index 2c0c218bf86b5..33931f03facc3 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_validation/messages.js +++ b/x-pack/plugins/ml/server/models/job_validation/messages.js @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { JOB_ID_MAX_LENGTH } from '../../../common/constants/validation'; +import { JOB_ID_MAX_LENGTH } from '../../../../../legacy/plugins/ml/common/constants/validation'; let messages; diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_bucket_span.js b/x-pack/plugins/ml/server/models/job_validation/validate_bucket_span.js similarity index 93% rename from x-pack/legacy/plugins/ml/server/models/job_validation/validate_bucket_span.js rename to x-pack/plugins/ml/server/models/job_validation/validate_bucket_span.js index 2914f086c1a83..9e96e2219fb0f 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_bucket_span.js +++ b/x-pack/plugins/ml/server/models/job_validation/validate_bucket_span.js @@ -5,9 +5,9 @@ */ import { estimateBucketSpanFactory } from '../../models/bucket_span_estimator'; -import { mlFunctionToESAggregation } from '../../../common/util/job_utils'; -import { SKIP_BUCKET_SPAN_ESTIMATION } from '../../../common/constants/validation'; -import { parseInterval } from '../../../common/util/parse_interval'; +import { mlFunctionToESAggregation } from '../../../../../legacy/plugins/ml/common/util/job_utils'; +import { SKIP_BUCKET_SPAN_ESTIMATION } from '../../../../../legacy/plugins/ml/common/constants/validation'; +import { parseInterval } from '../../../../../legacy/plugins/ml/common/util/parse_interval'; import { validateJobObject } from './validate_job_object'; @@ -51,7 +51,7 @@ export async function validateBucketSpan( job, duration, callAsInternalUser, - xpackMainPlugin + isSecurityDisabled ) { validateJobObject(job); @@ -124,7 +124,7 @@ export async function validateBucketSpan( estimateBucketSpanFactory( callWithRequest, callAsInternalUser, - xpackMainPlugin + isSecurityDisabled )(data) .then(resolve) // this catch gets triggered when the estimation code runs without error diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_cardinality.d.ts b/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.d.ts similarity index 78% rename from x-pack/legacy/plugins/ml/server/models/job_validation/validate_cardinality.d.ts rename to x-pack/plugins/ml/server/models/job_validation/validate_cardinality.d.ts index dc10905533788..d3930ecf44c8d 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_cardinality.d.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.d.ts @@ -5,7 +5,10 @@ */ import { APICaller } from 'src/core/server'; -import { Job, Datafeed } from '../../../public/application/jobs/new_job/common/job_creator/configs'; +import { + Job, + Datafeed, +} from '../../../../../legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs'; interface ValidateCardinalityConfig extends Job { datafeed_config?: Datafeed; diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_cardinality.js b/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/validate_cardinality.js rename to x-pack/plugins/ml/server/models/job_validation/validate_cardinality.js diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_influencers.js b/x-pack/plugins/ml/server/models/job_validation/validate_influencers.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/validate_influencers.js rename to x-pack/plugins/ml/server/models/job_validation/validate_influencers.js diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_job_object.js b/x-pack/plugins/ml/server/models/job_validation/validate_job_object.js similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/job_validation/validate_job_object.js rename to x-pack/plugins/ml/server/models/job_validation/validate_job_object.js diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_model_memory_limit.js b/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.js similarity index 98% rename from x-pack/legacy/plugins/ml/server/models/job_validation/validate_model_memory_limit.js rename to x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.js index 733ed9c3c22c6..354a3124a534f 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_model_memory_limit.js +++ b/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.js @@ -7,7 +7,7 @@ import numeral from '@elastic/numeral'; import { validateJobObject } from './validate_job_object'; import { calculateModelMemoryLimitProvider } from '../../models/calculate_model_memory_limit'; -import { ALLOWED_DATA_UNITS } from '../../../common/constants/validation'; +import { ALLOWED_DATA_UNITS } from '../../../../../legacy/plugins/ml/common/constants/validation'; // The minimum value the backend expects is 1MByte const MODEL_MEMORY_LIMIT_MINIMUM_BYTES = 1048576; diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_time_range.js b/x-pack/plugins/ml/server/models/job_validation/validate_time_range.js similarity index 93% rename from x-pack/legacy/plugins/ml/server/models/job_validation/validate_time_range.js rename to x-pack/plugins/ml/server/models/job_validation/validate_time_range.js index df14d37266496..e6a92b45649b0 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_validation/validate_time_range.js +++ b/x-pack/plugins/ml/server/models/job_validation/validate_time_range.js @@ -6,8 +6,8 @@ import _ from 'lodash'; -import { ES_FIELD_TYPES } from '../../../../../../../src/plugins/data/server'; -import { parseInterval } from '../../../common/util/parse_interval'; +import { ES_FIELD_TYPES } from '../../../../../../src/plugins/data/server'; +import { parseInterval } from '../../../../../legacy/plugins/ml/common/util/parse_interval'; import { validateJobObject } from './validate_job_object'; const BUCKET_SPAN_COMPARE_FACTOR = 25; diff --git a/x-pack/legacy/plugins/ml/server/models/results_service/build_anomaly_table_items.d.ts b/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.d.ts similarity index 89% rename from x-pack/legacy/plugins/ml/server/models/results_service/build_anomaly_table_items.d.ts rename to x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.d.ts index 2bd19985c8518..f2d74fb915299 100644 --- a/x-pack/legacy/plugins/ml/server/models/results_service/build_anomaly_table_items.d.ts +++ b/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.d.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AnomalyRecordDoc } from '../../../common/types/anomalies'; +import { AnomalyRecordDoc } from '../../../../../legacy/plugins/ml/common/types/anomalies'; export interface AnomaliesTableRecord { time: number; diff --git a/x-pack/legacy/plugins/ml/server/models/results_service/build_anomaly_table_items.js b/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.js similarity index 99% rename from x-pack/legacy/plugins/ml/server/models/results_service/build_anomaly_table_items.js rename to x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.js index 4934a0ba07081..fc4280c74994d 100644 --- a/x-pack/legacy/plugins/ml/server/models/results_service/build_anomaly_table_items.js +++ b/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.js @@ -12,7 +12,7 @@ import { getEntityFieldValue, showActualForFunction, showTypicalForFunction, -} from '../../../common/util/anomaly_utils'; +} from '../../../../../legacy/plugins/ml/common/util/anomaly_utils'; // Builds the items for display in the anomalies table from the supplied list of anomaly records. // Provide the timezone to use for aggregating anomalies (by day or hour) as set in the diff --git a/x-pack/legacy/plugins/ml/server/models/results_service/get_partition_fields_values.ts b/x-pack/plugins/ml/server/models/results_service/get_partition_fields_values.ts similarity index 95% rename from x-pack/legacy/plugins/ml/server/models/results_service/get_partition_fields_values.ts rename to x-pack/plugins/ml/server/models/results_service/get_partition_fields_values.ts index 99eeaacc8de9c..5d536059cb0a2 100644 --- a/x-pack/legacy/plugins/ml/server/models/results_service/get_partition_fields_values.ts +++ b/x-pack/plugins/ml/server/models/results_service/get_partition_fields_values.ts @@ -5,8 +5,8 @@ */ import Boom from 'boom'; -import { ML_RESULTS_INDEX_PATTERN } from '../../../common/constants/index_patterns'; -import { callWithRequestType } from '../../../common/types/kibana'; +import { ML_RESULTS_INDEX_PATTERN } from '../../../../../legacy/plugins/ml/common/constants/index_patterns'; +import { callWithRequestType } from '../../../../../legacy/plugins/ml/common/types/kibana'; import { CriteriaField } from './results_service'; const PARTITION_FIELDS = ['partition_field', 'over_field', 'by_field'] as const; diff --git a/x-pack/legacy/plugins/ml/server/models/results_service/index.ts b/x-pack/plugins/ml/server/models/results_service/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/models/results_service/index.ts rename to x-pack/plugins/ml/server/models/results_service/index.ts diff --git a/x-pack/legacy/plugins/ml/server/models/results_service/results_service.ts b/x-pack/plugins/ml/server/models/results_service/results_service.ts similarity index 97% rename from x-pack/legacy/plugins/ml/server/models/results_service/results_service.ts rename to x-pack/plugins/ml/server/models/results_service/results_service.ts index 555a58fbb5333..324cbb91ca8c1 100644 --- a/x-pack/legacy/plugins/ml/server/models/results_service/results_service.ts +++ b/x-pack/plugins/ml/server/models/results_service/results_service.ts @@ -9,10 +9,10 @@ import moment from 'moment'; import { SearchResponse } from 'elasticsearch'; import { RequestHandlerContext } from 'kibana/server'; import { buildAnomalyTableItems, AnomaliesTableRecord } from './build_anomaly_table_items'; -import { ML_RESULTS_INDEX_PATTERN } from '../../../common/constants/index_patterns'; -import { ANOMALIES_TABLE_DEFAULT_QUERY_SIZE } from '../../../common/constants/search'; +import { ML_RESULTS_INDEX_PATTERN } from '../../../../../legacy/plugins/ml/common/constants/index_patterns'; +import { ANOMALIES_TABLE_DEFAULT_QUERY_SIZE } from '../../../../../legacy/plugins/ml/common/constants/search'; import { getPartitionFieldsValuesFactory } from './get_partition_fields_values'; -import { AnomalyRecordDoc } from '../../../common/types/anomalies'; +import { AnomalyRecordDoc } from '../../../../../legacy/plugins/ml/common/types/anomalies'; // Service for carrying out Elasticsearch queries to obtain data for the // ML Results dashboards. diff --git a/x-pack/plugins/ml/server/plugin.ts b/x-pack/plugins/ml/server/plugin.ts new file mode 100644 index 0000000000000..b5adf1fedec79 --- /dev/null +++ b/x-pack/plugins/ml/server/plugin.ts @@ -0,0 +1,168 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { CoreSetup, IScopedClusterClient, Logger, PluginInitializerContext } from 'src/core/server'; +import { LicenseCheckResult, PluginsSetup, RouteInitialization } from './types'; +import { PLUGIN_ID } from '../../../legacy/plugins/ml/common/constants/app'; +import { VALID_FULL_LICENSE_MODES } from '../../../legacy/plugins/ml/common/constants/license'; + +// @ts-ignore: could not find declaration file for module +import { elasticsearchJsPlugin } from './client/elasticsearch_ml'; +import { makeMlUsageCollector } from './lib/ml_telemetry'; +import { initMlServerLog } from './client/log'; +import { addLinksToSampleDatasets } from './lib/sample_data_sets'; + +import { annotationRoutes } from './routes/annotations'; +import { calendars } from './routes/calendars'; +import { dataFeedRoutes } from './routes/datafeeds'; +import { dataFrameAnalyticsRoutes } from './routes/data_frame_analytics'; +import { dataRecognizer } from './routes/modules'; +import { dataVisualizerRoutes } from './routes/data_visualizer'; +import { fieldsService } from './routes/fields_service'; +import { fileDataVisualizerRoutes } from './routes/file_data_visualizer'; +import { filtersRoutes } from './routes/filters'; +import { indicesRoutes } from './routes/indices'; +import { jobAuditMessagesRoutes } from './routes/job_audit_messages'; +import { jobRoutes } from './routes/anomaly_detectors'; +import { jobServiceRoutes } from './routes/job_service'; +import { jobValidationRoutes } from './routes/job_validation'; +import { notificationRoutes } from './routes/notification_settings'; +import { resultsServiceRoutes } from './routes/results_service'; +import { systemRoutes } from './routes/system'; + +declare module 'kibana/server' { + interface RequestHandlerContext { + ml?: { + mlClient: IScopedClusterClient; + }; + } +} + +export class MlServerPlugin { + private readonly pluginId: string = PLUGIN_ID; + private log: Logger; + private version: string; + + private licenseCheckResults: LicenseCheckResult = { + isAvailable: false, + isActive: false, + isEnabled: false, + isSecurityDisabled: false, + }; + + constructor(ctx: PluginInitializerContext) { + this.log = ctx.logger.get(); + this.version = ctx.env.packageInfo.branch; + } + + public setup(coreSetup: CoreSetup, plugins: PluginsSetup) { + let sampleLinksInitialized = false; + + plugins.features.registerFeature({ + id: PLUGIN_ID, + name: i18n.translate('xpack.ml.featureRegistry.mlFeatureName', { + defaultMessage: 'Machine Learning', + }), + icon: 'machineLearningApp', + navLinkId: PLUGIN_ID, + app: [PLUGIN_ID, 'kibana'], + catalogue: [PLUGIN_ID], + privileges: {}, + reserved: { + privilege: { + savedObject: { + all: [], + read: [], + }, + ui: [], + }, + description: i18n.translate('xpack.ml.feature.reserved.description', { + defaultMessage: + 'To grant users access, you should also assign either the machine_learning_user or machine_learning_admin role.', + }), + }, + }); + + // Can access via router's handler function 'context' parameter - context.ml.mlClient + const mlClient = coreSetup.elasticsearch.createClient(PLUGIN_ID, { + plugins: [elasticsearchJsPlugin], + }); + + coreSetup.http.registerRouteHandlerContext(PLUGIN_ID, (context, request) => { + return { + mlClient: mlClient.asScoped(request), + }; + }); + + const routeInit: RouteInitialization = { + router: coreSetup.http.createRouter(), + getLicenseCheckResults: () => this.licenseCheckResults, + }; + + annotationRoutes(routeInit, plugins.security); + calendars(routeInit); + dataFeedRoutes(routeInit); + dataFrameAnalyticsRoutes(routeInit); + dataRecognizer(routeInit); + dataVisualizerRoutes(routeInit); + fieldsService(routeInit); + fileDataVisualizerRoutes(routeInit); + filtersRoutes(routeInit); + indicesRoutes(routeInit); + jobAuditMessagesRoutes(routeInit); + jobRoutes(routeInit); + jobServiceRoutes(routeInit); + notificationRoutes(routeInit); + resultsServiceRoutes(routeInit); + jobValidationRoutes(routeInit, this.version); + systemRoutes(routeInit, { + spacesPlugin: plugins.spaces, + cloud: plugins.cloud, + }); + initMlServerLog({ log: this.log }); + coreSetup.getStartServices().then(([core]) => { + makeMlUsageCollector(plugins.usageCollection, core.savedObjects); + }); + + plugins.licensing.license$.subscribe(async license => { + const { isEnabled: securityIsEnabled } = license.getFeature('security'); + // @ts-ignore isAvailable is not read + const { isAvailable, isEnabled } = license.getFeature(this.pluginId); + + this.licenseCheckResults = { + isActive: license.isActive, + // This `isAvailable` check for the ml plugin returns false for a basic license + // ML should be available on basic with reduced functionality (only file data visualizer) + // TODO: This will need to be updated in the second step of this cutover to NP. + isAvailable: isEnabled, + isEnabled, + isSecurityDisabled: securityIsEnabled === false, + type: license.type, + }; + + if (sampleLinksInitialized === false) { + sampleLinksInitialized = true; + // Add links to the Kibana sample data sets if ml is enabled + // and license is trial or platinum. + if (isEnabled === true && plugins.home) { + if ( + this.licenseCheckResults.type && + VALID_FULL_LICENSE_MODES.includes(this.licenseCheckResults.type) + ) { + addLinksToSampleDatasets({ + addAppLinksToSampleDataset: plugins.home.sampleData.addAppLinksToSampleDataset, + }); + } + } + } + }); + } + + public start() {} + + public stop() {} +} diff --git a/x-pack/legacy/plugins/ml/server/routes/README.md b/x-pack/plugins/ml/server/routes/README.md similarity index 100% rename from x-pack/legacy/plugins/ml/server/routes/README.md rename to x-pack/plugins/ml/server/routes/README.md diff --git a/x-pack/legacy/plugins/ml/server/routes/annotations.ts b/x-pack/plugins/ml/server/routes/annotations.ts similarity index 83% rename from x-pack/legacy/plugins/ml/server/routes/annotations.ts rename to x-pack/plugins/ml/server/routes/annotations.ts index 20f52b4b051c4..bcc0238c366a3 100644 --- a/x-pack/legacy/plugins/ml/server/routes/annotations.ts +++ b/x-pack/plugins/ml/server/routes/annotations.ts @@ -9,18 +9,19 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; +import { SecurityPluginSetup } from '../../../security/server'; import { isAnnotationsFeatureAvailable } from '../lib/check_annotations'; import { annotationServiceProvider } from '../models/annotation_service'; import { wrapError } from '../client/error_wrapper'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; -import { RouteInitialization } from '../new_platform/plugin'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; +import { RouteInitialization } from '../types'; import { deleteAnnotationSchema, getAnnotationsSchema, indexAnnotationSchema, -} from '../new_platform/annotations_schema'; +} from './schemas/annotations_schema'; -import { ANNOTATION_USER_UNKNOWN } from '../../common/constants/annotations'; +import { ANNOTATION_USER_UNKNOWN } from '../../../../legacy/plugins/ml/common/constants/annotations'; function getAnnotationsFeatureUnavailableErrorMessage() { return Boom.badRequest( @@ -34,7 +35,10 @@ function getAnnotationsFeatureUnavailableErrorMessage() { /** * Routes for annotations */ -export function annotationRoutes({ xpackMainPlugin, router, securityPlugin }: RouteInitialization) { +export function annotationRoutes( + { router, getLicenseCheckResults }: RouteInitialization, + securityPlugin: SecurityPluginSetup +) { /** * @apiGroup Annotations * @@ -57,7 +61,7 @@ export function annotationRoutes({ xpackMainPlugin, router, securityPlugin }: Ro body: schema.object(getAnnotationsSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { getAnnotations } = annotationServiceProvider(context); const resp = await getAnnotations(request.body); @@ -88,7 +92,7 @@ export function annotationRoutes({ xpackMainPlugin, router, securityPlugin }: Ro body: schema.object(indexAnnotationSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const annotationsFeatureAvailable = await isAnnotationsFeatureAvailable( context.ml!.mlClient.callAsCurrentUser @@ -99,6 +103,7 @@ export function annotationRoutes({ xpackMainPlugin, router, securityPlugin }: Ro const { indexAnnotation } = annotationServiceProvider(context); const user = securityPlugin.authc.getCurrentUser(request) || {}; + // @ts-ignore username doesn't exist on {} const resp = await indexAnnotation(request.body, user.username || ANNOTATION_USER_UNKNOWN); return response.ok({ @@ -126,7 +131,7 @@ export function annotationRoutes({ xpackMainPlugin, router, securityPlugin }: Ro params: schema.object(deleteAnnotationSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const annotationsFeatureAvailable = await isAnnotationsFeatureAvailable( context.ml!.mlClient.callAsCurrentUser diff --git a/x-pack/legacy/plugins/ml/server/routes/anomaly_detectors.ts b/x-pack/plugins/ml/server/routes/anomaly_detectors.ts similarity index 89% rename from x-pack/legacy/plugins/ml/server/routes/anomaly_detectors.ts rename to x-pack/plugins/ml/server/routes/anomaly_detectors.ts index 99dbdec9e945b..7bf2fb7bc6903 100644 --- a/x-pack/legacy/plugins/ml/server/routes/anomaly_detectors.ts +++ b/x-pack/plugins/ml/server/routes/anomaly_detectors.ts @@ -6,17 +6,17 @@ import { schema } from '@kbn/config-schema'; import { wrapError } from '../client/error_wrapper'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; -import { RouteInitialization } from '../new_platform/plugin'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; +import { RouteInitialization } from '../types'; import { anomalyDetectionJobSchema, anomalyDetectionUpdateJobSchema, -} from '../new_platform/anomaly_detectors_schema'; +} from './schemas/anomaly_detectors_schema'; /** * Routes for the anomaly detectors */ -export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { +export function jobRoutes({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup AnomalyDetectors * @@ -32,7 +32,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { path: '/api/ml/anomaly_detectors', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobs'); return response.ok({ @@ -62,7 +62,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobs', { jobId }); @@ -90,7 +90,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { path: '/api/ml/anomaly_detectors/_stats', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobStats'); return response.ok({ @@ -120,7 +120,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobStats', { jobId }); @@ -152,7 +152,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { body: schema.object({ ...anomalyDetectionJobSchema }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.addJob', { @@ -187,7 +187,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { body: schema.object({ ...anomalyDetectionUpdateJobSchema }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.updateJob', { @@ -221,7 +221,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.openJob', { @@ -254,7 +254,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const options: { jobId: string; force?: boolean } = { jobId: request.params.jobId, @@ -291,7 +291,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const options: { jobId: string; force?: boolean } = { jobId: request.params.jobId, @@ -326,7 +326,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { body: schema.any(), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.validateDetector', { body: request.body, @@ -359,7 +359,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { body: schema.object({ duration: schema.any() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const jobId = request.params.jobId; const duration = request.body.duration; @@ -407,7 +407,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.records', { jobId: request.params.jobId, @@ -456,7 +456,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.buckets', { jobId: request.params.jobId, @@ -499,7 +499,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.overallBuckets', { jobId: request.params.jobId, @@ -537,7 +537,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const options = { jobId: request.params.jobId, diff --git a/x-pack/legacy/plugins/ml/server/routes/apidoc.json b/x-pack/plugins/ml/server/routes/apidoc.json similarity index 100% rename from x-pack/legacy/plugins/ml/server/routes/apidoc.json rename to x-pack/plugins/ml/server/routes/apidoc.json diff --git a/x-pack/legacy/plugins/ml/server/routes/calendars.ts b/x-pack/plugins/ml/server/routes/calendars.ts similarity index 84% rename from x-pack/legacy/plugins/ml/server/routes/calendars.ts rename to x-pack/plugins/ml/server/routes/calendars.ts index 8e4e1c4c14751..ae494d3578890 100644 --- a/x-pack/legacy/plugins/ml/server/routes/calendars.ts +++ b/x-pack/plugins/ml/server/routes/calendars.ts @@ -6,10 +6,10 @@ import { RequestHandlerContext } from 'src/core/server'; import { schema } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; -import { RouteInitialization } from '../new_platform/plugin'; -import { calendarSchema } from '../new_platform/calendars_schema'; +import { RouteInitialization } from '../types'; +import { calendarSchema } from './schemas/calendars_schema'; import { CalendarManager, Calendar, FormCalendar } from '../models/calendar'; function getAllCalendars(context: RequestHandlerContext) { @@ -42,13 +42,13 @@ function getCalendarsByIds(context: RequestHandlerContext, calendarIds: string) return cal.getCalendarsByIds(calendarIds); } -export function calendars({ xpackMainPlugin, router }: RouteInitialization) { +export function calendars({ router, getLicenseCheckResults }: RouteInitialization) { router.get( { path: '/api/ml/calendars', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getAllCalendars(context); @@ -68,7 +68,7 @@ export function calendars({ xpackMainPlugin, router }: RouteInitialization) { params: schema.object({ calendarIds: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { let returnValue; try { const calendarIds = request.params.calendarIds.split(','); @@ -95,7 +95,7 @@ export function calendars({ xpackMainPlugin, router }: RouteInitialization) { body: schema.object({ ...calendarSchema }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const body = request.body; const resp = await newCalendar(context, body); @@ -117,7 +117,7 @@ export function calendars({ xpackMainPlugin, router }: RouteInitialization) { body: schema.object({ ...calendarSchema }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { calendarId } = request.params; const body = request.body; @@ -139,7 +139,7 @@ export function calendars({ xpackMainPlugin, router }: RouteInitialization) { params: schema.object({ calendarId: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { calendarId } = request.params; const resp = await deleteCalendar(context, calendarId); diff --git a/x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts similarity index 89% rename from x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts rename to x-pack/plugins/ml/server/routes/data_frame_analytics.ts index 6541fa541a59f..0a93320c05eb5 100644 --- a/x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts +++ b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts @@ -7,18 +7,18 @@ import { schema } from '@kbn/config-schema'; import { wrapError } from '../client/error_wrapper'; import { analyticsAuditMessagesProvider } from '../models/data_frame_analytics/analytics_audit_messages'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; -import { RouteInitialization } from '../new_platform/plugin'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; +import { RouteInitialization } from '../types'; import { dataAnalyticsJobConfigSchema, dataAnalyticsEvaluateSchema, dataAnalyticsExplainSchema, -} from '../new_platform/data_analytics_schema'; +} from './schemas/data_analytics_schema'; /** * Routes for the data frame analytics */ -export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteInitialization) { +export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup DataFrameAnalytics * @@ -36,7 +36,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti params: schema.object({ analyticsId: schema.maybe(schema.string()) }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.getDataFrameAnalytics'); return response.ok({ @@ -64,7 +64,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti params: schema.object({ analyticsId: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { analyticsId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.getDataFrameAnalytics', { @@ -91,7 +91,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti path: '/api/ml/data_frame/analytics/_stats', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser( 'ml.getDataFrameAnalyticsStats' @@ -121,7 +121,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti params: schema.object({ analyticsId: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { analyticsId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser( @@ -159,7 +159,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti body: schema.object(dataAnalyticsJobConfigSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { analyticsId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser( @@ -192,7 +192,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti body: schema.object({ ...dataAnalyticsEvaluateSchema }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser( 'ml.evaluateDataFrameAnalytics', @@ -232,7 +232,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti body: schema.object({ ...dataAnalyticsExplainSchema }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser( 'ml.explainDataFrameAnalytics', @@ -267,7 +267,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { analyticsId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser( @@ -303,7 +303,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { analyticsId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.startDataFrameAnalytics', { @@ -337,7 +337,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const options: { analyticsId: string; force?: boolean | undefined } = { analyticsId: request.params.analyticsId, @@ -377,7 +377,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti params: schema.object({ analyticsId: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { analyticsId } = request.params; const { getAnalyticsAuditMessages } = analyticsAuditMessagesProvider( diff --git a/x-pack/legacy/plugins/ml/server/routes/data_visualizer.ts b/x-pack/plugins/ml/server/routes/data_visualizer.ts similarity index 89% rename from x-pack/legacy/plugins/ml/server/routes/data_visualizer.ts rename to x-pack/plugins/ml/server/routes/data_visualizer.ts index df7e4b7010877..e4d068784def1 100644 --- a/x-pack/legacy/plugins/ml/server/routes/data_visualizer.ts +++ b/x-pack/plugins/ml/server/routes/data_visualizer.ts @@ -11,9 +11,9 @@ import { Field } from '../models/data_visualizer/data_visualizer'; import { dataVisualizerFieldStatsSchema, dataVisualizerOverallStatsSchema, -} from '../new_platform/data_visualizer_schema'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; -import { RouteInitialization } from '../new_platform/plugin'; +} from './schemas/data_visualizer_schema'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; +import { RouteInitialization } from '../types'; function getOverallStats( context: RequestHandlerContext, @@ -68,7 +68,7 @@ function getStatsForFields( /** * Routes for the index data visualizer. */ -export function dataVisualizerRoutes({ xpackMainPlugin, router }: RouteInitialization) { +export function dataVisualizerRoutes({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup DataVisualizer * @@ -83,7 +83,7 @@ export function dataVisualizerRoutes({ xpackMainPlugin, router }: RouteInitializ path: '/api/ml/data_visualizer/get_field_stats/{indexPatternTitle}', validate: dataVisualizerFieldStatsSchema, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { params: { indexPatternTitle }, @@ -135,7 +135,7 @@ export function dataVisualizerRoutes({ xpackMainPlugin, router }: RouteInitializ path: '/api/ml/data_visualizer/get_overall_stats/{indexPatternTitle}', validate: dataVisualizerOverallStatsSchema, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { params: { indexPatternTitle }, diff --git a/x-pack/legacy/plugins/ml/server/routes/datafeeds.ts b/x-pack/plugins/ml/server/routes/datafeeds.ts similarity index 86% rename from x-pack/legacy/plugins/ml/server/routes/datafeeds.ts rename to x-pack/plugins/ml/server/routes/datafeeds.ts index 9335403616cf7..e3bce4c1328e4 100644 --- a/x-pack/legacy/plugins/ml/server/routes/datafeeds.ts +++ b/x-pack/plugins/ml/server/routes/datafeeds.ts @@ -5,15 +5,15 @@ */ import { schema } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; -import { RouteInitialization } from '../new_platform/plugin'; -import { startDatafeedSchema, datafeedConfigSchema } from '../new_platform/datafeeds_schema'; +import { RouteInitialization } from '../types'; +import { startDatafeedSchema, datafeedConfigSchema } from './schemas/datafeeds_schema'; /** * Routes for datafeed service */ -export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) { +export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup DatafeedService * @@ -26,7 +26,7 @@ export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) path: '/api/ml/datafeeds', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await context.ml!.mlClient.callAsCurrentUser('ml.datafeeds'); @@ -53,7 +53,7 @@ export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) params: schema.object({ datafeedId: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const resp = await context.ml!.mlClient.callAsCurrentUser('ml.datafeeds', { datafeedId }); @@ -79,7 +79,7 @@ export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) path: '/api/ml/datafeeds/_stats', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await context.ml!.mlClient.callAsCurrentUser('ml.datafeedStats'); @@ -106,7 +106,7 @@ export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) params: schema.object({ datafeedId: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const resp = await context.ml!.mlClient.callAsCurrentUser('ml.datafeedStats', { @@ -137,7 +137,7 @@ export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) body: datafeedConfigSchema, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const resp = await context.ml!.mlClient.callAsCurrentUser('ml.addDatafeed', { @@ -169,7 +169,7 @@ export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) body: datafeedConfigSchema, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const resp = await context.ml!.mlClient.callAsCurrentUser('ml.updateDatafeed', { @@ -201,7 +201,7 @@ export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) query: schema.maybe(schema.object({ force: schema.maybe(schema.any()) })), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const options: { datafeedId: string; force?: boolean } = { datafeedId: request.params.jobId, @@ -237,7 +237,7 @@ export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) body: startDatafeedSchema, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const { start, end } = request.body; @@ -271,7 +271,7 @@ export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) params: schema.object({ datafeedId: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const datafeedId = request.params.datafeedId; @@ -302,7 +302,7 @@ export function dataFeedRoutes({ xpackMainPlugin, router }: RouteInitialization) params: schema.object({ datafeedId: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const resp = await context.ml!.mlClient.callAsCurrentUser('ml.datafeedPreview', { diff --git a/x-pack/legacy/plugins/ml/server/routes/fields_service.ts b/x-pack/plugins/ml/server/routes/fields_service.ts similarity index 84% rename from x-pack/legacy/plugins/ml/server/routes/fields_service.ts rename to x-pack/plugins/ml/server/routes/fields_service.ts index 4827adf23d7b4..bc092190c2c62 100644 --- a/x-pack/legacy/plugins/ml/server/routes/fields_service.ts +++ b/x-pack/plugins/ml/server/routes/fields_service.ts @@ -5,13 +5,13 @@ */ import { RequestHandlerContext } from 'src/core/server'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; -import { RouteInitialization } from '../new_platform/plugin'; +import { RouteInitialization } from '../types'; import { getCardinalityOfFieldsSchema, getTimeFieldRangeSchema, -} from '../new_platform/fields_service_schema'; +} from './schemas/fields_service_schema'; import { fieldsServiceProvider } from '../models/fields_service'; function getCardinalityOfFields(context: RequestHandlerContext, payload: any) { @@ -29,7 +29,7 @@ function getTimeFieldRange(context: RequestHandlerContext, payload: any) { /** * Routes for fields service */ -export function fieldsService({ xpackMainPlugin, router }: RouteInitialization) { +export function fieldsService({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup FieldsService * @@ -44,7 +44,7 @@ export function fieldsService({ xpackMainPlugin, router }: RouteInitialization) body: getCardinalityOfFieldsSchema, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getCardinalityOfFields(context, request.body); @@ -71,7 +71,7 @@ export function fieldsService({ xpackMainPlugin, router }: RouteInitialization) body: getTimeFieldRangeSchema, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getTimeFieldRange(context, request.body); diff --git a/x-pack/legacy/plugins/ml/server/routes/file_data_visualizer.ts b/x-pack/plugins/ml/server/routes/file_data_visualizer.ts similarity index 87% rename from x-pack/legacy/plugins/ml/server/routes/file_data_visualizer.ts rename to x-pack/plugins/ml/server/routes/file_data_visualizer.ts index d5a992c933293..1d724a8843350 100644 --- a/x-pack/legacy/plugins/ml/server/routes/file_data_visualizer.ts +++ b/x-pack/plugins/ml/server/routes/file_data_visualizer.ts @@ -6,7 +6,7 @@ import { schema } from '@kbn/config-schema'; import { RequestHandlerContext } from 'kibana/server'; -import { MAX_BYTES } from '../../common/constants/file_datavisualizer'; +import { MAX_BYTES } from '../../../../legacy/plugins/ml/common/constants/file_datavisualizer'; import { wrapError } from '../client/error_wrapper'; import { InputOverrides, @@ -18,8 +18,8 @@ import { Mappings, } from '../models/file_data_visualizer'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; -import { RouteInitialization } from '../new_platform/plugin'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; +import { RouteInitialization } from '../types'; import { incrementFileDataVisualizerIndexCreationCount } from '../lib/ml_telemetry'; function analyzeFiles(context: RequestHandlerContext, data: InputData, overrides: InputOverrides) { @@ -43,12 +43,7 @@ function importData( /** * Routes for the file data visualizer. */ -export function fileDataVisualizerRoutes({ - router, - xpackMainPlugin, - savedObjects, - elasticsearchPlugin, -}: RouteInitialization) { +export function fileDataVisualizerRoutes({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup FileDataVisualizer * @@ -87,7 +82,7 @@ export function fileDataVisualizerRoutes({ }, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const result = await analyzeFiles(context, request.body, request.query); return response.ok({ body: result }); @@ -129,7 +124,7 @@ export function fileDataVisualizerRoutes({ }, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { id } = request.query; const { index, data, settings, mappings, ingestPipeline } = request.body; @@ -138,7 +133,8 @@ export function fileDataVisualizerRoutes({ // follow-up import calls to just add additional data will include the `id` of the created // index, we'll ignore those and don't increment the counter. if (id === undefined) { - await incrementFileDataVisualizerIndexCreationCount(savedObjects!); + // @ts-ignore + await incrementFileDataVisualizerIndexCreationCount(context.core.savedObjects.client); } const result = await importData( diff --git a/x-pack/legacy/plugins/ml/server/routes/filters.ts b/x-pack/plugins/ml/server/routes/filters.ts similarity index 87% rename from x-pack/legacy/plugins/ml/server/routes/filters.ts rename to x-pack/plugins/ml/server/routes/filters.ts index a06f8d4f8b727..d5530668b2606 100644 --- a/x-pack/legacy/plugins/ml/server/routes/filters.ts +++ b/x-pack/plugins/ml/server/routes/filters.ts @@ -6,10 +6,10 @@ import { RequestHandlerContext } from 'src/core/server'; import { schema } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; -import { RouteInitialization } from '../new_platform/plugin'; -import { createFilterSchema, updateFilterSchema } from '../new_platform/filters_schema'; +import { RouteInitialization } from '../types'; +import { createFilterSchema, updateFilterSchema } from './schemas/filters_schema'; import { FilterManager, FormFilter } from '../models/filter'; // TODO - add function for returning a list of just the filter IDs. @@ -44,7 +44,7 @@ function deleteFilter(context: RequestHandlerContext, filterId: string) { return mgr.deleteFilter(filterId); } -export function filtersRoutes({ xpackMainPlugin, router }: RouteInitialization) { +export function filtersRoutes({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup Filters * @@ -60,7 +60,7 @@ export function filtersRoutes({ xpackMainPlugin, router }: RouteInitialization) path: '/api/ml/filters', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getAllFilters(context); @@ -90,7 +90,7 @@ export function filtersRoutes({ xpackMainPlugin, router }: RouteInitialization) params: schema.object({ filterId: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getFilter(context, request.params.filterId); return response.ok({ @@ -119,7 +119,7 @@ export function filtersRoutes({ xpackMainPlugin, router }: RouteInitialization) body: schema.object(createFilterSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const body = request.body; const resp = await newFilter(context, body); @@ -151,7 +151,7 @@ export function filtersRoutes({ xpackMainPlugin, router }: RouteInitialization) body: schema.object(updateFilterSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { filterId } = request.params; const body = request.body; @@ -182,7 +182,7 @@ export function filtersRoutes({ xpackMainPlugin, router }: RouteInitialization) params: schema.object({ filterId: schema.string() }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { filterId } = request.params; const resp = await deleteFilter(context, filterId); @@ -212,7 +212,7 @@ export function filtersRoutes({ xpackMainPlugin, router }: RouteInitialization) path: '/api/ml/filters/_stats', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getAllFilterStats(context); diff --git a/x-pack/legacy/plugins/ml/server/routes/indices.ts b/x-pack/plugins/ml/server/routes/indices.ts similarity index 80% rename from x-pack/legacy/plugins/ml/server/routes/indices.ts rename to x-pack/plugins/ml/server/routes/indices.ts index 0ee15f1321e9c..e01a7a0cbad28 100644 --- a/x-pack/legacy/plugins/ml/server/routes/indices.ts +++ b/x-pack/plugins/ml/server/routes/indices.ts @@ -6,13 +6,13 @@ import { schema } from '@kbn/config-schema'; import { wrapError } from '../client/error_wrapper'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; -import { RouteInitialization } from '../new_platform/plugin'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; +import { RouteInitialization } from '../types'; /** * Indices routes. */ -export function indicesRoutes({ xpackMainPlugin, router }: RouteInitialization) { +export function indicesRoutes({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup Indices * @@ -30,7 +30,7 @@ export function indicesRoutes({ xpackMainPlugin, router }: RouteInitialization) }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { body: { index, fields: requestFields }, diff --git a/x-pack/legacy/plugins/ml/server/routes/job_audit_messages.ts b/x-pack/plugins/ml/server/routes/job_audit_messages.ts similarity index 84% rename from x-pack/legacy/plugins/ml/server/routes/job_audit_messages.ts rename to x-pack/plugins/ml/server/routes/job_audit_messages.ts index 76986b935b993..38df28e17ec0d 100644 --- a/x-pack/legacy/plugins/ml/server/routes/job_audit_messages.ts +++ b/x-pack/plugins/ml/server/routes/job_audit_messages.ts @@ -5,15 +5,15 @@ */ import { schema } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; -import { RouteInitialization } from '../new_platform/plugin'; +import { RouteInitialization } from '../types'; import { jobAuditMessagesProvider } from '../models/job_audit_messages'; /** * Routes for job audit message routes */ -export function jobAuditMessagesRoutes({ xpackMainPlugin, router }: RouteInitialization) { +export function jobAuditMessagesRoutes({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup JobAuditMessages * @@ -29,7 +29,7 @@ export function jobAuditMessagesRoutes({ xpackMainPlugin, router }: RouteInitial query: schema.maybe(schema.object({ from: schema.maybe(schema.any()) })), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { getJobAuditMessages } = jobAuditMessagesProvider( context.ml!.mlClient.callAsCurrentUser @@ -62,7 +62,7 @@ export function jobAuditMessagesRoutes({ xpackMainPlugin, router }: RouteInitial query: schema.maybe(schema.object({ from: schema.maybe(schema.any()) })), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { getJobAuditMessages } = jobAuditMessagesProvider( context.ml!.mlClient.callAsCurrentUser diff --git a/x-pack/legacy/plugins/ml/server/routes/job_service.ts b/x-pack/plugins/ml/server/routes/job_service.ts similarity index 88% rename from x-pack/legacy/plugins/ml/server/routes/job_service.ts rename to x-pack/plugins/ml/server/routes/job_service.ts index 5ddbd4cdfd5a5..e15888088d3a1 100644 --- a/x-pack/legacy/plugins/ml/server/routes/job_service.ts +++ b/x-pack/plugins/ml/server/routes/job_service.ts @@ -7,10 +7,9 @@ import Boom from 'boom'; import { schema } from '@kbn/config-schema'; import { IScopedClusterClient } from 'src/core/server'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; -import { RouteInitialization } from '../new_platform/plugin'; -import { isSecurityDisabled } from '../lib/security_utils'; +import { RouteInitialization } from '../types'; import { categorizationFieldExamplesSchema, chartSchema, @@ -21,7 +20,7 @@ import { lookBackProgressSchema, topCategoriesSchema, updateGroupsSchema, -} from '../new_platform/job_service_schema'; +} from './schemas/job_service_schema'; // @ts-ignore no declaration module import { jobServiceProvider } from '../models/job_service'; import { categorizationExamplesProvider } from '../models/job_service/new_job'; @@ -29,11 +28,12 @@ import { categorizationExamplesProvider } from '../models/job_service/new_job'; /** * Routes for job service */ -export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitialization) { +export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitialization) { async function hasPermissionToCreateJobs( callAsCurrentUser: IScopedClusterClient['callAsCurrentUser'] ) { - if (isSecurityDisabled(xpackMainPlugin) === true) { + const { isSecurityDisabled } = getLicenseCheckResults(); + if (isSecurityDisabled === true) { return true; } @@ -63,7 +63,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(forceStartDatafeedSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { forceStartDatafeeds } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { datafeedIds, start, end } = request.body; @@ -92,7 +92,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(datafeedIdsSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { stopDatafeeds } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { datafeedIds } = request.body; @@ -121,7 +121,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(jobIdsSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { deleteJobs } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobIds } = request.body; @@ -150,7 +150,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(jobIdsSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { closeJobs } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobIds } = request.body; @@ -179,7 +179,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(jobIdsSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { jobsSummary } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobIds } = request.body; @@ -208,7 +208,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(jobsWithTimerangeSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { jobsWithTimerange } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { dateFormatTz } = request.body; @@ -237,7 +237,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(jobIdsSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { createFullJobsList } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobIds } = request.body; @@ -264,7 +264,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio path: '/api/ml/jobs/groups', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { getAllGroups } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const resp = await getAllGroups(); @@ -292,7 +292,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(updateGroupsSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { updateGroups } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobs } = request.body; @@ -319,7 +319,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio path: '/api/ml/jobs/deleting_jobs_tasks', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { deletingJobTasks } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const resp = await deletingJobTasks(); @@ -347,7 +347,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(jobIdsSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { jobsExist } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobIds } = request.body; @@ -377,7 +377,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio query: schema.maybe(schema.object({ rollup: schema.maybe(schema.string()) })), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { indexPattern } = request.params; const isRollup = request.query.rollup === 'true'; @@ -408,7 +408,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(chartSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { indexPatternTitle, @@ -461,7 +461,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(chartSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { indexPatternTitle, @@ -509,7 +509,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio path: '/api/ml/jobs/all_jobs_and_group_ids', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { getAllJobAndGroupIds } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const resp = await getAllJobAndGroupIds(); @@ -537,7 +537,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(lookBackProgressSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { getLookBackProgress } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobId, start, end } = request.body; @@ -566,7 +566,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(categorizationFieldExamplesSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { // due to the use of the _analyze endpoint which is called by the kibana user, // basic job creation privileges are required to use this endpoint @@ -625,7 +625,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio body: schema.object(topCategoriesSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { topCategories } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobId, count } = request.body; diff --git a/x-pack/legacy/plugins/ml/server/routes/job_validation.ts b/x-pack/plugins/ml/server/routes/job_validation.ts similarity index 85% rename from x-pack/legacy/plugins/ml/server/routes/job_validation.ts rename to x-pack/plugins/ml/server/routes/job_validation.ts index 64c9ccd27720a..ae2e6885ba0f3 100644 --- a/x-pack/legacy/plugins/ml/server/routes/job_validation.ts +++ b/x-pack/plugins/ml/server/routes/job_validation.ts @@ -7,15 +7,15 @@ import Boom from 'boom'; import { RequestHandlerContext } from 'src/core/server'; import { schema, TypeOf } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; -import { RouteInitialization } from '../new_platform/plugin'; +import { RouteInitialization } from '../types'; import { estimateBucketSpanSchema, modelMemoryLimitSchema, validateCardinalitySchema, validateJobSchema, -} from '../new_platform/job_validation_schema'; +} from './schemas/job_validation_schema'; import { estimateBucketSpanFactory } from '../models/bucket_span_estimator'; import { calculateModelMemoryLimitProvider } from '../models/calculate_model_memory_limit'; import { validateJob, validateCardinality } from '../models/job_validation'; @@ -25,7 +25,10 @@ type CalculateModelMemoryLimitPayload = TypeOf; /** * Routes for job validation */ -export function jobValidationRoutes({ config, xpackMainPlugin, router }: RouteInitialization) { +export function jobValidationRoutes( + { getLicenseCheckResults, router }: RouteInitialization, + version: string +) { function calculateModelMemoryLimit( context: RequestHandlerContext, payload: CalculateModelMemoryLimitPayload @@ -67,13 +70,13 @@ export function jobValidationRoutes({ config, xpackMainPlugin, router }: RouteIn body: estimateBucketSpanSchema, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { let errorResp; const resp = await estimateBucketSpanFactory( context.ml!.mlClient.callAsCurrentUser, context.core.elasticsearch.adminClient.callAsInternalUser, - xpackMainPlugin + getLicenseCheckResults().isSecurityDisabled )(request.body) // this catch gets triggered when the estimation code runs without error // but isn't able to come up with a bucket span estimation. @@ -114,7 +117,7 @@ export function jobValidationRoutes({ config, xpackMainPlugin, router }: RouteIn body: modelMemoryLimitSchema, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await calculateModelMemoryLimit(context, request.body); @@ -141,7 +144,7 @@ export function jobValidationRoutes({ config, xpackMainPlugin, router }: RouteIn body: schema.object(validateCardinalitySchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await validateCardinality( context.ml!.mlClient.callAsCurrentUser, @@ -171,16 +174,15 @@ export function jobValidationRoutes({ config, xpackMainPlugin, router }: RouteIn body: validateJobSchema, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { - // pkg.branch corresponds to the version used in documentation links. - const version = config.get('pkg.branch'); + // version corresponds to the version used in documentation links. const resp = await validateJob( context.ml!.mlClient.callAsCurrentUser, request.body, version, context.core.elasticsearch.adminClient.callAsInternalUser, - xpackMainPlugin + getLicenseCheckResults().isSecurityDisabled ); return response.ok({ diff --git a/x-pack/legacy/plugins/ml/server/new_platform/licence_check_pre_routing_factory.ts b/x-pack/plugins/ml/server/routes/license_check_pre_routing_factory.ts similarity index 71% rename from x-pack/legacy/plugins/ml/server/new_platform/licence_check_pre_routing_factory.ts rename to x-pack/plugins/ml/server/routes/license_check_pre_routing_factory.ts index cc77d2872fb90..a371af1abf2d1 100644 --- a/x-pack/legacy/plugins/ml/server/new_platform/licence_check_pre_routing_factory.ts +++ b/x-pack/plugins/ml/server/routes/license_check_pre_routing_factory.ts @@ -10,10 +10,10 @@ import { RequestHandler, RequestHandlerContext, } from 'src/core/server'; -import { PLUGIN_ID, MlXpackMainPlugin } from './plugin'; +import { LicenseCheckResult } from '../types'; export const licensePreRoutingFactory = ( - xpackMainPlugin: MlXpackMainPlugin, + getLicenseCheckResults: () => LicenseCheckResult, handler: RequestHandler ): RequestHandler => { // License checking and enable/disable logic @@ -22,14 +22,10 @@ export const licensePreRoutingFactory = ( request: KibanaRequest, response: KibanaResponseFactory ) { - const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN_ID).getLicenseCheckResults(); + const licenseCheckResults = getLicenseCheckResults(); if (!licenseCheckResults.isAvailable) { - return response.forbidden({ - body: { - message: licenseCheckResults.message, - }, - }); + return response.forbidden(); } return handler(ctx, request, response); diff --git a/x-pack/legacy/plugins/ml/server/routes/modules.ts b/x-pack/plugins/ml/server/routes/modules.ts similarity index 88% rename from x-pack/legacy/plugins/ml/server/routes/modules.ts rename to x-pack/plugins/ml/server/routes/modules.ts index a40fb1c9149ca..c9b005d4e43f9 100644 --- a/x-pack/legacy/plugins/ml/server/routes/modules.ts +++ b/x-pack/plugins/ml/server/routes/modules.ts @@ -6,12 +6,12 @@ import { schema } from '@kbn/config-schema'; import { RequestHandlerContext } from 'kibana/server'; -import { DatafeedOverride, JobOverride } from '../../common/types/modules'; +import { DatafeedOverride, JobOverride } from '../../../../legacy/plugins/ml/common/types/modules'; import { wrapError } from '../client/error_wrapper'; import { DataRecognizer } from '../models/data_recognizer'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; -import { getModuleIdParamSchema, setupModuleBodySchema } from '../new_platform/modules'; -import { RouteInitialization } from '../new_platform/plugin'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; +import { getModuleIdParamSchema, setupModuleBodySchema } from './schemas/modules'; +import { RouteInitialization } from '../types'; function recognize(context: RequestHandlerContext, indexPatternTitle: string) { const dr = new DataRecognizer(context); @@ -65,7 +65,7 @@ function dataRecognizerJobsExist(context: RequestHandlerContext, moduleId: strin /** * Recognizer routes. */ -export function dataRecognizer({ xpackMainPlugin, router }: RouteInitialization) { +export function dataRecognizer({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup DataRecognizer * @@ -84,7 +84,7 @@ export function dataRecognizer({ xpackMainPlugin, router }: RouteInitialization) }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { indexPatternTitle } = request.params; const results = await recognize(context, indexPatternTitle); @@ -114,7 +114,7 @@ export function dataRecognizer({ xpackMainPlugin, router }: RouteInitialization) }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { let { moduleId } = request.params; if (moduleId === '') { @@ -150,7 +150,7 @@ export function dataRecognizer({ xpackMainPlugin, router }: RouteInitialization) body: setupModuleBodySchema, }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { moduleId } = request.params; @@ -207,7 +207,7 @@ export function dataRecognizer({ xpackMainPlugin, router }: RouteInitialization) }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const { moduleId } = request.params; const result = await dataRecognizerJobsExist(context, moduleId); diff --git a/x-pack/legacy/plugins/ml/server/routes/notification_settings.ts b/x-pack/plugins/ml/server/routes/notification_settings.ts similarity index 75% rename from x-pack/legacy/plugins/ml/server/routes/notification_settings.ts rename to x-pack/plugins/ml/server/routes/notification_settings.ts index c65627543b21d..b68d2441333f9 100644 --- a/x-pack/legacy/plugins/ml/server/routes/notification_settings.ts +++ b/x-pack/plugins/ml/server/routes/notification_settings.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; -import { RouteInitialization } from '../new_platform/plugin'; +import { RouteInitialization } from '../types'; /** * Routes for notification settings */ -export function notificationRoutes({ xpackMainPlugin, router }: RouteInitialization) { +export function notificationRoutes({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup NotificationSettings * @@ -24,7 +24,7 @@ export function notificationRoutes({ xpackMainPlugin, router }: RouteInitializat path: '/api/ml/notification_settings', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const params = { includeDefaults: true, diff --git a/x-pack/legacy/plugins/ml/server/routes/results_service.ts b/x-pack/plugins/ml/server/routes/results_service.ts similarity index 88% rename from x-pack/legacy/plugins/ml/server/routes/results_service.ts rename to x-pack/plugins/ml/server/routes/results_service.ts index 5d107b2d97809..77c998acc9f27 100644 --- a/x-pack/legacy/plugins/ml/server/routes/results_service.ts +++ b/x-pack/plugins/ml/server/routes/results_service.ts @@ -6,16 +6,16 @@ import { RequestHandlerContext } from 'src/core/server'; import { schema } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; -import { RouteInitialization } from '../new_platform/plugin'; +import { RouteInitialization } from '../types'; import { anomaliesTableDataSchema, categoryDefinitionSchema, categoryExamplesSchema, maxAnomalyScoreSchema, partitionFieldValuesSchema, -} from '../new_platform/results_service_schema'; +} from './schemas/results_service_schema'; import { resultsServiceProvider } from '../models/results_service'; function getAnomaliesTableData(context: RequestHandlerContext, payload: any) { @@ -74,7 +74,7 @@ function getPartitionFieldsValues(context: RequestHandlerContext, payload: any) /** * Routes for results service */ -export function resultsServiceRoutes({ xpackMainPlugin, router }: RouteInitialization) { +export function resultsServiceRoutes({ router, getLicenseCheckResults }: RouteInitialization) { /** * @apiGroup ResultsService * @@ -89,7 +89,7 @@ export function resultsServiceRoutes({ xpackMainPlugin, router }: RouteInitializ body: schema.object(anomaliesTableDataSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getAnomaliesTableData(context, request.body); @@ -116,7 +116,7 @@ export function resultsServiceRoutes({ xpackMainPlugin, router }: RouteInitializ body: schema.object(categoryDefinitionSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getCategoryDefinition(context, request.body); @@ -143,7 +143,7 @@ export function resultsServiceRoutes({ xpackMainPlugin, router }: RouteInitializ body: schema.object(maxAnomalyScoreSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getMaxAnomalyScore(context, request.body); @@ -170,7 +170,7 @@ export function resultsServiceRoutes({ xpackMainPlugin, router }: RouteInitializ body: schema.object(categoryExamplesSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getCategoryExamples(context, request.body); @@ -197,7 +197,7 @@ export function resultsServiceRoutes({ xpackMainPlugin, router }: RouteInitializ body: schema.object(partitionFieldValuesSchema), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const resp = await getPartitionFieldsValues(context, request.body); diff --git a/x-pack/legacy/plugins/ml/server/new_platform/annotations_schema.ts b/x-pack/plugins/ml/server/routes/schemas/annotations_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/annotations_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/annotations_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/anomaly_detectors_schema.ts b/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/anomaly_detectors_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/calendars_schema.ts b/x-pack/plugins/ml/server/routes/schemas/calendars_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/calendars_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/calendars_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/data_analytics_schema.ts b/x-pack/plugins/ml/server/routes/schemas/data_analytics_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/data_analytics_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/data_analytics_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/data_visualizer_schema.ts b/x-pack/plugins/ml/server/routes/schemas/data_visualizer_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/data_visualizer_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/data_visualizer_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/datafeeds_schema.ts b/x-pack/plugins/ml/server/routes/schemas/datafeeds_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/datafeeds_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/datafeeds_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/fields_service_schema.ts b/x-pack/plugins/ml/server/routes/schemas/fields_service_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/fields_service_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/fields_service_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/filters_schema.ts b/x-pack/plugins/ml/server/routes/schemas/filters_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/filters_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/filters_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/job_service_schema.ts b/x-pack/plugins/ml/server/routes/schemas/job_service_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/job_service_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/job_service_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/job_validation_schema.ts b/x-pack/plugins/ml/server/routes/schemas/job_validation_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/job_validation_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/job_validation_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/modules.ts b/x-pack/plugins/ml/server/routes/schemas/modules.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/modules.ts rename to x-pack/plugins/ml/server/routes/schemas/modules.ts diff --git a/x-pack/legacy/plugins/ml/server/new_platform/results_service_schema.ts b/x-pack/plugins/ml/server/routes/schemas/results_service_schema.ts similarity index 100% rename from x-pack/legacy/plugins/ml/server/new_platform/results_service_schema.ts rename to x-pack/plugins/ml/server/routes/schemas/results_service_schema.ts diff --git a/x-pack/legacy/plugins/ml/server/routes/system.ts b/x-pack/plugins/ml/server/routes/system.ts similarity index 88% rename from x-pack/legacy/plugins/ml/server/routes/system.ts rename to x-pack/plugins/ml/server/routes/system.ts index 5861b53d74875..36a9ea1447f58 100644 --- a/x-pack/legacy/plugins/ml/server/routes/system.ts +++ b/x-pack/plugins/ml/server/routes/system.ts @@ -11,20 +11,17 @@ import { RequestHandlerContext } from 'kibana/server'; import { wrapError } from '../client/error_wrapper'; import { mlLog } from '../client/log'; import { privilegesProvider } from '../lib/check_privileges'; -import { isSecurityDisabled } from '../lib/security_utils'; import { spacesUtilsProvider } from '../lib/spaces_utils'; -import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; -import { RouteInitialization } from '../new_platform/plugin'; +import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; +import { RouteInitialization, SystemRouteDeps } from '../types'; /** * System routes */ -export function systemRoutes({ - router, - xpackMainPlugin, - spacesPlugin, - cloud, -}: RouteInitialization) { +export function systemRoutes( + { getLicenseCheckResults, router }: RouteInitialization, + { spacesPlugin, cloud }: SystemRouteDeps +) { async function getNodeCount(context: RequestHandlerContext) { const filterPath = 'nodes.*.attributes'; const resp = await context.ml!.mlClient.callAsInternalUser('nodes.info', { @@ -59,7 +56,7 @@ export function systemRoutes({ body: schema.maybe(schema.any()), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { let upgradeInProgress = false; try { @@ -80,7 +77,7 @@ export function systemRoutes({ } } - if (isSecurityDisabled(xpackMainPlugin)) { + if (getLicenseCheckResults().isSecurityDisabled) { // if xpack.security.enabled has been explicitly set to false // return that security is disabled and don't call the privilegeCheck endpoint return response.ok({ @@ -119,7 +116,7 @@ export function systemRoutes({ }), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const ignoreSpaces = request.query && request.query.ignoreSpaces === 'true'; // if spaces is disabled force isMlEnabledInSpace to be true @@ -130,7 +127,7 @@ export function systemRoutes({ const { getPrivileges } = privilegesProvider( context.ml!.mlClient.callAsCurrentUser, - xpackMainPlugin, + getLicenseCheckResults(), isMlEnabledInSpace, ignoreSpaces ); @@ -155,11 +152,11 @@ export function systemRoutes({ path: '/api/ml/ml_node_count', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { // check for basic license first for consistency with other // security disabled checks - if (isSecurityDisabled(xpackMainPlugin)) { + if (getLicenseCheckResults().isSecurityDisabled) { return response.ok({ body: await getNodeCount(context), }); @@ -206,7 +203,7 @@ export function systemRoutes({ path: '/api/ml/info', validate: false, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { const info = await context.ml!.mlClient.callAsCurrentUser('ml.info'); const cloudId = cloud && cloud.cloudId; @@ -234,7 +231,7 @@ export function systemRoutes({ body: schema.maybe(schema.any()), }, }, - licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { try { return response.ok({ body: await context.ml!.mlClient.callAsCurrentUser('search', request.body), diff --git a/x-pack/plugins/ml/server/types.ts b/x-pack/plugins/ml/server/types.ts new file mode 100644 index 0000000000000..550abadb3c06f --- /dev/null +++ b/x-pack/plugins/ml/server/types.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 { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { HomeServerPluginSetup } from 'src/plugins/home/server'; +import { IRouter } from 'src/core/server'; +import { CloudSetup } from '../../cloud/server'; +import { SecurityPluginSetup } from '../../security/server'; +import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; +import { LicensingPluginSetup } from '../../licensing/server'; +import { SpacesPluginSetup } from '../../spaces/server'; + +export interface LicenseCheckResult { + isAvailable: boolean; + isActive: boolean; + isEnabled: boolean; + isSecurityDisabled: boolean; + status?: string; + type?: string; +} + +export interface SystemRouteDeps { + cloud: CloudSetup; + spacesPlugin: SpacesPluginSetup; +} + +export interface PluginsSetup { + cloud: CloudSetup; + features: FeaturesPluginSetup; + home: HomeServerPluginSetup; + licensing: LicensingPluginSetup; + security: SecurityPluginSetup; + spaces: SpacesPluginSetup; + usageCollection: UsageCollectionSetup; +} + +export interface RouteInitialization { + router: IRouter; + getLicenseCheckResults: () => LicenseCheckResult; +} From 0cede6a705db65ef450426db3c584fcabab42780 Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Thu, 27 Feb 2020 19:17:07 -0700 Subject: [PATCH 56/64] Prep agg types for new platform (#57064) --- packages/kbn-utility-types/README.md | 1 + packages/kbn-utility-types/index.ts | 2 +- .../actions/filters/brush_event.test.ts | 49 +- src/legacy/core_plugins/data/public/index.ts | 12 +- src/legacy/core_plugins/data/public/plugin.ts | 6 +- .../public/search/aggs/agg_config.test.ts | 497 ++++++ .../data/public/search/aggs/agg_config.ts | 61 +- .../public/search/aggs/agg_configs.test.ts | 503 ++++++ .../data/public/search/aggs/agg_configs.ts | 76 +- .../public/search/aggs/agg_params.test.ts | 2 - .../data/public/search/aggs/agg_type.test.ts | 16 +- .../data/public/search/aggs/agg_type.ts | 5 +- .../search/aggs/agg_types_registry.test.ts | 91 ++ .../public/search/aggs/agg_types_registry.ts | 68 + .../search/aggs/buckets/_bucket_agg_type.ts | 12 +- .../search/aggs/buckets/_interval_options.ts | 1 + .../create_filter/date_histogram.test.ts | 12 +- .../buckets/create_filter/date_range.test.ts | 7 +- .../buckets/create_filter/filters.test.ts | 13 +- .../buckets/create_filter/histogram.test.ts | 12 +- .../buckets/create_filter/ip_range.test.ts | 11 +- .../aggs/buckets/create_filter/range.test.ts | 12 +- .../aggs/buckets/create_filter/terms.test.ts | 11 +- .../search/aggs/buckets/date_histogram.ts | 8 +- .../search/aggs/buckets/date_range.test.ts | 25 +- .../public/search/aggs/buckets/date_range.ts | 12 +- .../data/public/search/aggs/buckets/filter.ts | 1 + .../public/search/aggs/buckets/filters.ts | 26 +- .../search/aggs/buckets/geo_hash.test.ts | 7 +- .../public/search/aggs/buckets/geo_tile.ts | 3 +- .../search/aggs/buckets/histogram.test.ts | 33 +- .../public/search/aggs/buckets/histogram.ts | 12 +- .../public/search/aggs/buckets/ip_range.ts | 12 +- .../buckets/migrate_include_exclude_format.ts | 4 +- .../public/search/aggs/buckets/range.test.ts | 12 +- .../aggs/buckets/significant_terms.test.ts | 9 +- .../public/search/aggs/buckets/terms.test.ts | 8 +- .../aggs/filter/agg_type_filters.test.ts | 5 +- .../search/aggs/filter/agg_type_filters.ts | 1 + .../search/aggs/filter/prop_filter.test.ts | 19 +- .../data/public/search/aggs/index.test.ts | 2 - .../data/public/search/aggs/index.ts | 9 +- .../public/search/aggs/metrics/bucket_avg.ts | 1 - .../public/search/aggs/metrics/bucket_max.ts | 1 - .../public/search/aggs/metrics/bucket_min.ts | 1 + .../public/search/aggs/metrics/cardinality.ts | 5 +- .../data/public/search/aggs/metrics/count.ts | 7 +- .../lib/get_response_agg_config_class.ts | 1 + .../metrics/lib/parent_pipeline_agg_helper.ts | 1 - .../lib/sibling_pipeline_agg_helper.ts | 1 - .../public/search/aggs/metrics/median.test.ts | 7 +- .../data/public/search/aggs/metrics/median.ts | 4 +- .../search/aggs/metrics/metric_agg_type.ts | 7 +- .../data/public/search/aggs/metrics/min.ts | 1 + .../aggs/metrics/parent_pipeline.test.ts | 18 +- .../aggs/metrics/percentile_ranks.test.ts | 8 +- .../search/aggs/metrics/percentile_ranks.ts | 7 +- .../search/aggs/metrics/percentiles.test.ts | 6 +- .../public/search/aggs/metrics/percentiles.ts | 4 - .../aggs/metrics/sibling_pipeline.test.ts | 22 +- .../search/aggs/metrics/std_deviation.test.ts | 6 +- .../search/aggs/metrics/top_hit.test.ts | 6 +- .../public/search/aggs/param_types/agg.ts | 4 +- .../public/search/aggs/param_types/base.ts | 4 +- .../search/aggs/param_types/field.test.ts | 2 - .../public/search/aggs/param_types/field.ts | 5 +- .../param_types/filter/field_filters.test.ts | 11 +- .../aggs/param_types/filter/field_filters.ts | 8 +- .../search/aggs/param_types/json.test.ts | 8 +- .../public/search/aggs/param_types/json.ts | 4 +- .../search/aggs/param_types/optioned.test.ts | 2 - .../search/aggs/param_types/optioned.ts | 6 +- .../search/aggs/param_types/string.test.ts | 8 +- .../public/search/aggs/param_types/string.ts | 4 +- .../public/search/aggs/test_helpers/index.ts} | 4 +- .../test_helpers/mock_agg_types_registry.ts | 57 + .../aggs/test_helpers/mock_data_services.ts | 54 + .../data/public/search/aggs/types.ts | 2 +- .../data/public/search/aggs/utils.test.tsx | 2 - .../data/public/search/aggs/utils.ts | 39 +- .../data/public/search/expressions/esaggs.ts | 4 +- .../data/public/search/expressions/utils.ts | 5 +- .../core_plugins/data/public/search/mocks.ts | 85 + .../data/public/search/search_service.ts | 60 +- .../data/public/search/tabify/buckets.test.ts | 2 - .../public/search/tabify/get_columns.test.ts | 22 +- .../search/tabify/response_writer.test.ts | 20 +- .../data/public/search/tabify/tabify.test.ts | 16 +- .../brush_event.test.mocks.ts => services.ts} | 13 +- .../components/sidebar/state/reducers.ts | 18 +- .../public/legacy_imports.ts | 2 +- .../public/table_vis_controller.test.ts | 4 +- .../visualizations/public/legacy_imports.ts | 2 +- .../public/np_ready/public/vis_impl.js | 6 +- src/legacy/ui/public/agg_types/index.ts | 9 +- .../ui/public/vis/__tests__/_agg_config.js | 485 ------ .../ui/public/vis/__tests__/_agg_configs.js | 420 ----- .../data/common/field_formats/mocks.ts | 49 + src/plugins/data/public/mocks.ts | 28 +- .../data/public/search/search_source/mocks.ts | 19 - .../editor_frame_service/service.test.tsx | 4 - .../__snapshots__/zeek_details.test.tsx.snap | 1448 ++++++++--------- 102 files changed, 2646 insertions(+), 2101 deletions(-) create mode 100644 src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts create mode 100644 src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts create mode 100644 src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts create mode 100644 src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts rename src/legacy/{ui/public/vis/__tests__/index.js => core_plugins/data/public/search/aggs/test_helpers/index.ts} (86%) create mode 100644 src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts create mode 100644 src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.ts create mode 100644 src/legacy/core_plugins/data/public/search/mocks.ts rename src/legacy/core_plugins/data/public/{actions/filters/brush_event.test.mocks.ts => services.ts} (76%) delete mode 100644 src/legacy/ui/public/vis/__tests__/_agg_config.js delete mode 100644 src/legacy/ui/public/vis/__tests__/_agg_configs.js create mode 100644 src/plugins/data/common/field_formats/mocks.ts diff --git a/packages/kbn-utility-types/README.md b/packages/kbn-utility-types/README.md index 829fd21e14366..b57e98e379707 100644 --- a/packages/kbn-utility-types/README.md +++ b/packages/kbn-utility-types/README.md @@ -18,6 +18,7 @@ type B = UnwrapPromise; // string ## Reference +- `Assign` — From `U` assign properties to `T` (just like object assign). - `Ensure` — Makes sure `T` is of type `X`. - `ObservableLike` — Minimal interface for an object resembling an `Observable`. - `PublicContract` — Returns an object with public keys only. diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 808935ed4cb5b..657d9f547de66 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -18,7 +18,7 @@ */ import { PromiseType } from 'utility-types'; -export { $Values, Required, Optional, Class } from 'utility-types'; +export { $Values, Assign, Class, Optional, Required } from 'utility-types'; /** * A type that may or may not be a `Promise`. diff --git a/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts b/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts index 0e18c7c707fa3..eb29530f92fee 100644 --- a/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts +++ b/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts @@ -19,34 +19,14 @@ import moment from 'moment'; -jest.mock('../../search/aggs', () => ({ - AggConfigs: function AggConfigs() { - return { - createAggConfig: ({ params }: Record) => ({ - params, - getIndexPattern: () => ({ - timeFieldName: 'time', - }), - }), - }; - }, -})); - -jest.mock('../../../../../../plugins/data/public/services', () => ({ - getIndexPatterns: () => { - return { - get: async () => { - return { - id: 'logstash-*', - timeFieldName: 'time', - }; - }, - }; - }, -})); - import { onBrushEvent, BrushEvent } from './brush_event'; +import { mockDataServices } from '../../search/aggs/test_helpers'; +import { IndexPatternsContract } from '../../../../../../plugins/data/public'; +import { dataPluginMock } from '../../../../../../plugins/data/public/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setIndexPatterns } from '../../../../../../plugins/data/public/services'; + describe('brushEvent', () => { const DAY_IN_MS = 24 * 60 * 60 * 1000; const JAN_01_2014 = 1388559600000; @@ -59,11 +39,28 @@ describe('brushEvent', () => { }, getIndexPattern: () => ({ timeFieldName: 'time', + fields: { + getByName: () => undefined, + filter: () => [], + }, }), }, ]; beforeEach(() => { + mockDataServices(); + setIndexPatterns(({ + ...dataPluginMock.createStartContract().indexPatterns, + get: async () => ({ + id: 'indexPatternId', + timeFieldName: 'time', + fields: { + getByName: () => undefined, + filter: () => [], + }, + }), + } as unknown) as IndexPatternsContract); + baseEvent = { data: { ordered: { diff --git a/src/legacy/core_plugins/data/public/index.ts b/src/legacy/core_plugins/data/public/index.ts index 8cde5d0a1fc11..8d730d18a1755 100644 --- a/src/legacy/core_plugins/data/public/index.ts +++ b/src/legacy/core_plugins/data/public/index.ts @@ -35,18 +35,18 @@ export { } from '../../../../plugins/data/public'; export { // agg_types - AggParam, - AggParamOption, - DateRangeKey, + AggParam, // only the type is used externally, only in vis editor + AggParamOption, // only the type is used externally + DateRangeKey, // only used in field formatter deserialization, which will live in data IAggConfig, IAggConfigs, IAggType, IFieldParamType, IMetricAggType, - IpRangeKey, + IpRangeKey, // only used in field formatter deserialization, which will live in data ISchemas, - OptionedParamEditorProps, - OptionedValueProp, + OptionedParamEditorProps, // only type is used externally + OptionedValueProp, // only type is used externally } from './search/types'; /** @public static code */ diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index e13e8e34eaebe..e2b8ca5dda78c 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -36,6 +36,7 @@ import { setOverlays, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../plugins/data/public/services'; +import { setSearchServiceShim } from './services'; import { SELECT_RANGE_ACTION, selectRangeAction } from './actions/select_range_action'; import { VALUE_CLICK_ACTION, valueClickAction } from './actions/value_click_action'; import { @@ -112,6 +113,9 @@ export class DataPlugin } public start(core: CoreStart, { data, uiActions }: DataPluginStartDependencies): DataStart { + const search = this.search.start(core); + setSearchServiceShim(search); + setUiSettings(core.uiSettings); setQueryService(data.query); setIndexPatterns(data.indexPatterns); @@ -123,7 +127,7 @@ export class DataPlugin uiActions.attachAction(VALUE_CLICK_TRIGGER, VALUE_CLICK_ACTION); return { - search: this.search.start(core), + search, }; } diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts new file mode 100644 index 0000000000000..7769aa29184d3 --- /dev/null +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts @@ -0,0 +1,497 @@ +/* + * 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 { identity } from 'lodash'; + +import { AggConfig, IAggConfig } from './agg_config'; +import { AggConfigs, CreateAggConfigParams } from './agg_configs'; +import { AggType } from './agg_types'; +import { AggTypesRegistryStart } from './agg_types_registry'; +import { mockDataServices, mockAggTypesRegistry } from './test_helpers'; +import { IndexPatternField, IndexPattern } from '../../../../../../plugins/data/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { stubIndexPatternWithFields } from '../../../../../../plugins/data/public/stubs'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { dataPluginMock } from '../../../../../../plugins/data/public/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setFieldFormats } from '../../../../../../plugins/data/public/services'; + +describe('AggConfig', () => { + let indexPattern: IndexPattern; + let typesRegistry: AggTypesRegistryStart; + + beforeEach(() => { + jest.restoreAllMocks(); + mockDataServices(); + indexPattern = stubIndexPatternWithFields as IndexPattern; + typesRegistry = mockAggTypesRegistry(); + }); + + describe('#toDsl', () => { + it('calls #write()', () => { + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const configStates = { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }; + const aggConfig = ac.createAggConfig(configStates); + + const spy = jest.spyOn(aggConfig, 'write').mockImplementation(() => ({ params: {} })); + aggConfig.toDsl(); + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('uses the type name as the agg name', () => { + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const configStates = { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }; + const aggConfig = ac.createAggConfig(configStates); + + jest.spyOn(aggConfig, 'write').mockImplementation(() => ({ params: {} })); + const dsl = aggConfig.toDsl(); + expect(dsl).toHaveProperty('date_histogram'); + }); + + it('uses the params from #write() output as the agg params', () => { + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const configStates = { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }; + const aggConfig = ac.createAggConfig(configStates); + + const football = {}; + jest.spyOn(aggConfig, 'write').mockImplementation(() => ({ params: football })); + const dsl = aggConfig.toDsl(); + expect(dsl.date_histogram).toBe(football); + }); + + it('includes subAggs from #write() output', () => { + const configStates = [ + { + enabled: true, + type: 'avg', + schema: 'metric', + params: {}, + }, + { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }, + ]; + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + + const histoConfig = ac.byName('date_histogram')[0]; + const avgConfig = ac.byName('avg')[0]; + const football = {}; + + jest + .spyOn(histoConfig, 'write') + .mockImplementation(() => ({ params: {}, subAggs: [avgConfig] })); + jest.spyOn(avgConfig, 'write').mockImplementation(() => ({ params: football })); + + const dsl = histoConfig.toDsl(); + expect(dsl).toHaveProperty('aggs'); + expect(dsl.aggs).toHaveProperty(avgConfig.id); + expect(dsl.aggs[avgConfig.id]).toHaveProperty('avg'); + expect(dsl.aggs[avgConfig.id].avg).toBe(football); + }); + }); + + describe('::ensureIds', () => { + it('accepts an array of objects and assigns ids to them', () => { + const objs = [{}, {}, {}, {}]; + AggConfig.ensureIds(objs); + expect(objs[0]).toHaveProperty('id', '1'); + expect(objs[1]).toHaveProperty('id', '2'); + expect(objs[2]).toHaveProperty('id', '3'); + expect(objs[3]).toHaveProperty('id', '4'); + }); + + it('assigns ids relative to the other only item in the list', () => { + const objs = [{ id: '100' }, {}]; + AggConfig.ensureIds(objs); + expect(objs[0]).toHaveProperty('id', '100'); + expect(objs[1]).toHaveProperty('id', '101'); + }); + + it('assigns ids relative to the other items in the list', () => { + const objs = [{ id: '100' }, { id: '200' }, { id: '500' }, { id: '350' }, {}]; + AggConfig.ensureIds(objs); + expect(objs[0]).toHaveProperty('id', '100'); + expect(objs[1]).toHaveProperty('id', '200'); + expect(objs[2]).toHaveProperty('id', '500'); + expect(objs[3]).toHaveProperty('id', '350'); + expect(objs[4]).toHaveProperty('id', '501'); + }); + + it('uses ::nextId to get the starting value', () => { + jest.spyOn(AggConfig, 'nextId').mockImplementation(() => 534); + const objs = AggConfig.ensureIds([{}]); + expect(objs[0]).toHaveProperty('id', '534'); + }); + + it('only calls ::nextId once', () => { + const start = 420; + const spy = jest.spyOn(AggConfig, 'nextId').mockImplementation(() => start); + const objs = AggConfig.ensureIds([{}, {}, {}, {}, {}, {}, {}]); + + expect(spy).toHaveBeenCalledTimes(1); + objs.forEach((obj, i) => { + expect(obj).toHaveProperty('id', String(start + i)); + }); + }); + }); + + describe('::nextId', () => { + it('accepts a list of objects and picks the next id', () => { + const next = AggConfig.nextId([{ id: '100' }, { id: '500' }] as IAggConfig[]); + expect(next).toBe(501); + }); + + it('handles an empty list', () => { + const next = AggConfig.nextId([]); + expect(next).toBe(1); + }); + + it('fails when the list is not defined', () => { + expect(() => { + AggConfig.nextId((undefined as unknown) as IAggConfig[]); + }).toThrowError(); + }); + }); + + describe('#toJsonDataEquals', () => { + const testsIdentical = [ + [ + { + enabled: true, + type: 'count', + schema: 'metric', + params: { field: '@timestamp' }, + }, + ], + [ + { + enabled: true, + type: 'avg', + schema: 'metric', + params: {}, + }, + { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }, + ], + ]; + + testsIdentical.forEach((configState, index) => { + it(`identical aggregations (${index})`, () => { + const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry }); + expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true); + }); + }); + + const testsIdenticalDifferentOrder = [ + { + config1: [ + { + enabled: true, + type: 'avg', + schema: 'metric', + params: {}, + }, + { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }, + ], + config2: [ + { + enabled: true, + schema: 'metric', + type: 'avg', + params: {}, + }, + { + enabled: true, + schema: 'segment', + type: 'date_histogram', + params: {}, + }, + ], + }, + ]; + + testsIdenticalDifferentOrder.forEach((test, index) => { + it(`identical aggregations (${index}) - init json is in different order`, () => { + const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry }); + expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true); + }); + }); + + const testsDifferent = [ + { + config1: [ + { + enabled: true, + type: 'avg', + schema: 'metric', + params: {}, + }, + { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }, + ], + config2: [ + { + enabled: true, + type: 'max', + schema: 'metric', + params: {}, + }, + { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }, + ], + }, + { + config1: [ + { + enabled: true, + type: 'count', + schema: 'metric', + params: { field: '@timestamp' }, + }, + ], + config2: [ + { + enabled: true, + type: 'count', + schema: 'metric', + params: { field: '@timestamp' }, + }, + { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }, + ], + }, + ]; + + testsDifferent.forEach((test, index) => { + it(`different aggregations (${index})`, () => { + const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry }); + expect(ac1.jsonDataEquals(ac2.aggs)).toBe(false); + }); + }); + }); + + describe('#toJSON', () => { + it('includes the aggs id, params, type and schema', () => { + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const configStates = { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }; + const aggConfig = ac.createAggConfig(configStates); + + expect(aggConfig.id).toBe('1'); + expect(typeof aggConfig.params).toBe('object'); + expect(aggConfig.type).toBeInstanceOf(AggType); + expect(aggConfig.type).toHaveProperty('name', 'date_histogram'); + expect(typeof aggConfig.schema).toBe('object'); + expect(aggConfig.schema).toHaveProperty('name', 'segment'); + + const state = aggConfig.toJSON(); + expect(state).toHaveProperty('id', '1'); + expect(typeof state.params).toBe('object'); + expect(state).toHaveProperty('type', 'date_histogram'); + expect(state).toHaveProperty('schema', 'segment'); + }); + + it('test serialization order is identical (for visual consistency)', () => { + const configStates = [ + { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: {}, + }, + ]; + const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry }); + + // this relies on the assumption that js-engines consistently loop over properties in insertion order. + // most likely the case, but strictly speaking not guaranteed by the JS and JSON specifications. + expect(JSON.stringify(ac1.aggs) === JSON.stringify(ac2.aggs)).toBe(true); + }); + }); + + describe('#makeLabel', () => { + let aggConfig: AggConfig; + + beforeEach(() => { + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + aggConfig = ac.createAggConfig({ type: 'count' } as CreateAggConfigParams); + }); + + it('uses the custom label if it is defined', () => { + aggConfig.params.customLabel = 'Custom label'; + const label = aggConfig.makeLabel(); + expect(label).toBe(aggConfig.params.customLabel); + }); + + it('default label should be "Count"', () => { + const label = aggConfig.makeLabel(); + expect(label).toBe('Count'); + }); + + it('default label should be "Percentage of Count" when percentageMode is set to true', () => { + const label = aggConfig.makeLabel(true); + expect(label).toBe('Percentage of Count'); + }); + + it('empty label if the type is not defined', () => { + aggConfig.type = (undefined as unknown) as AggType; + const label = aggConfig.makeLabel(); + expect(label).toBe(''); + }); + }); + + describe('#fieldFormatter - custom getFormat handler', () => { + it('returns formatter from getFormat handler', () => { + setFieldFormats({ + ...dataPluginMock.createStartContract().fieldFormats, + getDefaultInstance: jest.fn().mockImplementation(() => ({ + getConverterFor: jest.fn().mockImplementation(() => (t: string) => t), + })) as any, + }); + + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const configStates = { + enabled: true, + type: 'count', + schema: 'metric', + params: { field: '@timestamp' }, + }; + const aggConfig = ac.createAggConfig(configStates); + + const fieldFormatter = aggConfig.fieldFormatter(); + expect(fieldFormatter).toBeDefined(); + expect(fieldFormatter('text')).toBe('text'); + }); + }); + + // TODO: Converting these field formatter tests from browser tests to unit + // tests makes them much less helpful due to the extensive use of mocking. + // We should revisit these and rewrite them into something more useful. + describe('#fieldFormatter - no custom getFormat handler', () => { + let aggConfig: AggConfig; + + beforeEach(() => { + setFieldFormats({ + ...dataPluginMock.createStartContract().fieldFormats, + getDefaultInstance: jest.fn().mockImplementation(() => ({ + getConverterFor: (t?: string) => t || identity, + })) as any, + }); + indexPattern.fields.getByName = name => + ({ + format: { + getConverterFor: (t?: string) => t || identity, + }, + } as IndexPatternField); + + const configStates = { + enabled: true, + type: 'histogram', + schema: 'bucket', + params: { + field: { + format: { + getConverterFor: (t?: string) => t || identity, + }, + }, + }, + }; + const ac = new AggConfigs(indexPattern, [configStates], { typesRegistry }); + aggConfig = ac.createAggConfig(configStates); + }); + + it("returns the field's formatter", () => { + expect(aggConfig.fieldFormatter().toString()).toBe( + aggConfig + .getField() + .format.getConverterFor() + .toString() + ); + }); + + it('returns the string format if the field does not have a format', () => { + const agg = aggConfig; + agg.params.field = { type: 'number', format: null }; + const fieldFormatter = agg.fieldFormatter(); + expect(fieldFormatter).toBeDefined(); + expect(fieldFormatter('text')).toBe('text'); + }); + + it('returns the string format if there is no field', () => { + const agg = aggConfig; + delete agg.params.field; + const fieldFormatter = agg.fieldFormatter(); + expect(fieldFormatter).toBeDefined(); + expect(fieldFormatter('text')).toBe('text'); + }); + + it('returns the html converter if "html" is passed in', () => { + const field = indexPattern.fields.getByName('bytes'); + expect(aggConfig.fieldFormatter('html').toString()).toBe( + field!.format.getConverterFor('html').toString() + ); + }); + }); +}); diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts index 2b21c5c4868a5..659bec3f702e3 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts @@ -17,16 +17,8 @@ * under the License. */ -/** - * @name AggConfig - * - * @description This class represents an aggregation, which is displayed in the left-hand nav of - * the Visualize app. - */ - import _ from 'lodash'; import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; import { IAggType } from './agg_type'; import { AggGroupNames } from './agg_groups'; import { writeParams } from './agg_params'; @@ -38,18 +30,20 @@ import { FieldFormatsContentType, KBN_FIELD_TYPES, } from '../../../../../../plugins/data/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getFieldFormats } from '../../../../../../plugins/data/public/services'; export interface AggConfigOptions { - enabled: boolean; - type: string; - params: any; + type: IAggType; + enabled?: boolean; id?: string; - schema?: string; + params?: Record; + schema?: string | Schema; } const unknownSchema: Schema = { name: 'unknown', - title: 'Unknown', + title: 'Unknown', // only here for illustrative purposes hideCustomLabel: true, aggFilter: [], min: 1, @@ -65,21 +59,6 @@ const unknownSchema: Schema = { }, }; -const getTypeFromRegistry = (type: string): IAggType => { - // We need to inline require here, since we're having a cyclic dependency - // from somewhere inside agg_types back to AggConfig. - const aggTypes = require('../aggs').aggTypes; - const registeredType = - aggTypes.metrics.find((agg: IAggType) => agg.name === type) || - aggTypes.buckets.find((agg: IAggType) => agg.name === type); - - if (!registeredType) { - throw new Error('unknown type'); - } - - return registeredType; -}; - const getSchemaFromRegistry = (schemas: any, schema: string): Schema => { let registeredSchema = schemas ? schemas.byName[schema] : null; if (!registeredSchema) { @@ -90,6 +69,13 @@ const getSchemaFromRegistry = (schemas: any, schema: string): Schema => { return registeredSchema; }; +/** + * @name AggConfig + * + * @description This class represents an aggregation, which is displayed in the left-hand nav of + * the Visualize app. + */ + // TODO need to make a more explicit interface for this export type IAggConfig = AggConfig; @@ -101,9 +87,9 @@ export class AggConfig { * @param {array[object]} list - a list of objects, objects can be anything really * @return {array} - the list that was passed in */ - static ensureIds(list: AggConfig[]) { - const have: AggConfig[] = []; - const haveNot: AggConfig[] = []; + static ensureIds(list: any[]) { + const have: IAggConfig[] = []; + const haveNot: AggConfigOptions[] = []; list.forEach(function(obj) { (obj.id ? have : haveNot).push(obj); }); @@ -121,7 +107,7 @@ export class AggConfig { * * @return {array} list - a list of objects with id properties */ - static nextId(list: AggConfig[]) { + static nextId(list: IAggConfig[]) { return ( 1 + list.reduce(function(max, obj) { @@ -161,10 +147,10 @@ export class AggConfig { // set the params to the values from opts, or just to the defaults this.setParams(opts.params || {}); - // @ts-ignore - this.__type = this.__type; // @ts-ignore this.__schema = this.__schema; + // @ts-ignore + this.__type = this.__type; } /** @@ -394,7 +380,8 @@ export class AggConfig { } fieldOwnFormatter(contentType?: FieldFormatsContentType, defaultFormat?: any) { - const fieldFormatsService = npStart.plugins.data.fieldFormats; + const fieldFormatsService = getFieldFormats(); + const field = this.getField(); let format = field && field.format; if (!format) format = defaultFormat; @@ -456,8 +443,8 @@ export class AggConfig { }); } - public setType(type: string | IAggType) { - this.type = typeof type === 'string' ? getTypeFromRegistry(type) : type; + public setType(type: IAggType) { + this.type = type; } public get schema() { diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts new file mode 100644 index 0000000000000..29f16b1e4f0bf --- /dev/null +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts @@ -0,0 +1,503 @@ +/* + * 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 { indexBy } from 'lodash'; +import { AggConfig } from './agg_config'; +import { AggConfigs } from './agg_configs'; +import { AggTypesRegistryStart } from './agg_types_registry'; +import { Schemas } from './schemas'; +import { AggGroupNames } from './agg_groups'; +import { mockDataServices, mockAggTypesRegistry } from './test_helpers'; +import { IndexPatternField, IndexPattern } from '../../../../../../plugins/data/public'; +import { + stubIndexPattern, + stubIndexPatternWithFields, + // eslint-disable-next-line @kbn/eslint/no-restricted-paths +} from '../../../../../../plugins/data/public/stubs'; + +describe('AggConfigs', () => { + let indexPattern: IndexPattern; + let typesRegistry: AggTypesRegistryStart; + + beforeEach(() => { + indexPattern = stubIndexPatternWithFields as IndexPattern; + typesRegistry = mockAggTypesRegistry(); + }); + + describe('constructor', () => { + it('handles passing just a type', () => { + const configStates = [ + { + enabled: true, + type: 'histogram', + params: {}, + }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + expect(ac.aggs).toHaveLength(1); + }); + + it('attempts to ensure that all states have an id', () => { + const configStates = [ + { + enabled: true, + type: 'histogram', + params: {}, + }, + { + enabled: true, + type: 'date_histogram', + params: {}, + }, + { + enabled: true, + type: 'terms', + params: {}, + schema: 'split', + }, + ]; + + const spy = jest.spyOn(AggConfig, 'ensureIds'); + new AggConfigs(indexPattern, configStates, { typesRegistry }); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy.mock.calls[0]).toEqual([configStates]); + spy.mockRestore(); + }); + + describe('defaults', () => { + const schemas = new Schemas([ + { + group: AggGroupNames.Metrics, + name: 'metric', + title: 'Simple', + min: 1, + max: 2, + defaults: [ + { schema: 'metric', type: 'count' }, + { schema: 'metric', type: 'avg' }, + { schema: 'metric', type: 'sum' }, + ], + }, + { + group: AggGroupNames.Buckets, + name: 'segment', + title: 'Example', + min: 0, + max: 1, + defaults: [ + { schema: 'segment', type: 'terms' }, + { schema: 'segment', type: 'filters' }, + ], + }, + ]); + + it('should only set the number of defaults defined by the max', () => { + const ac = new AggConfigs(indexPattern, [], { + schemas: schemas.all, + typesRegistry, + }); + expect(ac.bySchemaName('metric')).toHaveLength(2); + }); + + it('should set the defaults defined in the schema when none exist', () => { + const ac = new AggConfigs(indexPattern, [], { + schemas: schemas.all, + typesRegistry, + }); + expect(ac.aggs).toHaveLength(3); + }); + + it('should NOT set the defaults defined in the schema when some exist', () => { + const configStates = [ + { + enabled: true, + type: 'date_histogram', + params: {}, + schema: 'segment', + }, + ]; + const ac = new AggConfigs(indexPattern, configStates, { + schemas: schemas.all, + typesRegistry, + }); + expect(ac.aggs).toHaveLength(3); + expect(ac.bySchemaName('segment')[0].type.name).toEqual('date_histogram'); + }); + }); + }); + + describe('#createAggConfig', () => { + it('accepts a configState which is provided as an AggConfig object', () => { + const configStates = [ + { + enabled: true, + type: 'histogram', + params: {}, + }, + { + enabled: true, + type: 'date_histogram', + params: {}, + }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + expect(ac.aggs).toHaveLength(2); + + ac.createAggConfig( + new AggConfig(ac, { + enabled: true, + type: typesRegistry.get('terms'), + params: {}, + schema: 'split', + }) + ); + expect(ac.aggs).toHaveLength(3); + }); + + it('adds new AggConfig entries to AggConfigs by default', () => { + const configStates = [ + { + enabled: true, + type: 'histogram', + params: {}, + }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + expect(ac.aggs).toHaveLength(1); + + ac.createAggConfig({ + enabled: true, + type: 'terms', + params: {}, + schema: 'split', + }); + expect(ac.aggs).toHaveLength(2); + }); + + it('does not add an agg to AggConfigs if addToAggConfigs: false', () => { + const configStates = [ + { + enabled: true, + type: 'histogram', + params: {}, + }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + expect(ac.aggs).toHaveLength(1); + + ac.createAggConfig( + { + enabled: true, + type: 'terms', + params: {}, + schema: 'split', + }, + { addToAggConfigs: false } + ); + expect(ac.aggs).toHaveLength(1); + }); + }); + + describe('#getRequestAggs', () => { + it('performs a stable sort, but moves metrics to the bottom', () => { + const configStates = [ + { type: 'avg', enabled: true, params: {}, schema: 'metric' }, + { type: 'terms', enabled: true, params: {}, schema: 'split' }, + { type: 'histogram', enabled: true, params: {}, schema: 'split' }, + { type: 'sum', enabled: true, params: {}, schema: 'metric' }, + { type: 'date_histogram', enabled: true, params: {}, schema: 'segment' }, + { type: 'filters', enabled: true, params: {}, schema: 'split' }, + { type: 'percentiles', enabled: true, params: {}, schema: 'metric' }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const sorted = ac.getRequestAggs(); + const aggs = indexBy(ac.aggs, agg => agg.type.name); + + expect(sorted.shift()).toBe(aggs.terms); + expect(sorted.shift()).toBe(aggs.histogram); + expect(sorted.shift()).toBe(aggs.date_histogram); + expect(sorted.shift()).toBe(aggs.filters); + expect(sorted.shift()).toBe(aggs.avg); + expect(sorted.shift()).toBe(aggs.sum); + expect(sorted.shift()).toBe(aggs.percentiles); + expect(sorted).toHaveLength(0); + }); + }); + + describe('#getResponseAggs', () => { + it('returns all request aggs for basic aggs', () => { + const configStates = [ + { type: 'terms', enabled: true, params: {}, schema: 'split' }, + { type: 'date_histogram', enabled: true, params: {}, schema: 'segment' }, + { type: 'count', enabled: true, params: {}, schema: 'metric' }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const sorted = ac.getResponseAggs(); + const aggs = indexBy(ac.aggs, agg => agg.type.name); + + expect(sorted.shift()).toBe(aggs.terms); + expect(sorted.shift()).toBe(aggs.date_histogram); + expect(sorted.shift()).toBe(aggs.count); + expect(sorted).toHaveLength(0); + }); + + it('expands aggs that have multiple responses', () => { + const configStates = [ + { type: 'terms', enabled: true, params: {}, schema: 'split' }, + { type: 'date_histogram', enabled: true, params: {}, schema: 'segment' }, + { type: 'percentiles', enabled: true, params: { percents: [1, 2, 3] }, schema: 'metric' }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const sorted = ac.getResponseAggs(); + const aggs = indexBy(ac.aggs, agg => agg.type.name); + + expect(sorted.shift()).toBe(aggs.terms); + expect(sorted.shift()).toBe(aggs.date_histogram); + expect(sorted.shift()!.id!).toBe(aggs.percentiles.id + '.' + 1); + expect(sorted.shift()!.id!).toBe(aggs.percentiles.id + '.' + 2); + expect(sorted.shift()!.id!).toBe(aggs.percentiles.id + '.' + 3); + expect(sorted).toHaveLength(0); + }); + }); + + describe('#toDsl', () => { + const schemas = new Schemas([ + { + group: AggGroupNames.Buckets, + name: 'segment', + }, + { + group: AggGroupNames.Buckets, + name: 'split', + }, + ]); + + beforeEach(() => { + mockDataServices(); + indexPattern = stubIndexPattern as IndexPattern; + indexPattern.fields.getByName = name => (name as unknown) as IndexPatternField; + }); + + it('uses the sorted aggs', () => { + const configStates = [{ enabled: true, type: 'avg', params: { field: 'bytes' } }]; + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const spy = jest.spyOn(AggConfigs.prototype, 'getRequestAggs'); + ac.toDsl(); + expect(spy).toHaveBeenCalledTimes(1); + spy.mockRestore(); + }); + + it('calls aggConfig#toDsl() on each aggConfig and compiles the nested output', () => { + const configStates = [ + { enabled: true, type: 'date_histogram', params: {}, schema: 'segment' }, + { enabled: true, type: 'terms', params: {}, schema: 'split' }, + { enabled: true, type: 'count', params: {} }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { + typesRegistry, + schemas: schemas.all, + }); + + const aggInfos = ac.aggs.map(aggConfig => { + const football = {}; + aggConfig.toDsl = jest.fn().mockImplementation(() => football); + + return { + id: aggConfig.id, + football, + }; + }); + + (function recurse(lvl: Record): void { + const info = aggInfos.shift(); + if (!info) return; + + expect(lvl).toHaveProperty(info.id); + expect(lvl[info.id]).toBe(info.football); + + if (lvl[info.id].aggs) { + return recurse(lvl[info.id].aggs); + } + })(ac.toDsl()); + + expect(aggInfos).toHaveLength(1); + }); + + it("skips aggs that don't have a dsl representation", () => { + const configStates = [ + { + enabled: true, + type: 'date_histogram', + params: { field: '@timestamp', interval: '10s' }, + schema: 'segment', + }, + { + enabled: true, + type: 'count', + params: {}, + schema: 'metric', + }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const dsl = ac.toDsl(); + const histo = ac.byName('date_histogram')[0]; + const count = ac.byName('count')[0]; + + expect(dsl).toHaveProperty(histo.id); + expect(typeof dsl[histo.id]).toBe('object'); + expect(dsl[histo.id]).not.toHaveProperty('aggs'); + expect(dsl).not.toHaveProperty(count.id); + }); + + it('writes multiple metric aggregations at the same level', () => { + const configStates = [ + { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: { field: '@timestamp', interval: '10s' }, + }, + { enabled: true, type: 'avg', schema: 'metric', params: { field: 'bytes' } }, + { enabled: true, type: 'sum', schema: 'metric', params: { field: 'bytes' } }, + { enabled: true, type: 'min', schema: 'metric', params: { field: 'bytes' } }, + { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { + typesRegistry, + schemas: schemas.all, + }); + const dsl = ac.toDsl(); + const histo = ac.byName('date_histogram')[0]; + const metrics = ac.bySchemaGroup('metrics'); + + expect(dsl).toHaveProperty(histo.id); + expect(typeof dsl[histo.id]).toBe('object'); + expect(dsl[histo.id]).toHaveProperty('aggs'); + + metrics.forEach(metric => { + expect(dsl[histo.id].aggs).toHaveProperty(metric.id); + expect(dsl[histo.id].aggs[metric.id]).not.toHaveProperty('aggs'); + }); + }); + + it('writes multiple metric aggregations at every level if the vis is hierarchical', () => { + const configStates = [ + { enabled: true, type: 'terms', schema: 'segment', params: { field: 'bytes', orderBy: 1 } }, + { enabled: true, type: 'terms', schema: 'segment', params: { field: 'bytes', orderBy: 1 } }, + { enabled: true, id: '1', type: 'avg', schema: 'metric', params: { field: 'bytes' } }, + { enabled: true, type: 'sum', schema: 'metric', params: { field: 'bytes' } }, + { enabled: true, type: 'min', schema: 'metric', params: { field: 'bytes' } }, + { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const topLevelDsl = ac.toDsl(true); + const buckets = ac.bySchemaGroup('buckets'); + const metrics = ac.bySchemaGroup('metrics'); + + (function checkLevel(dsl) { + const bucket = buckets.shift(); + if (!bucket) return; + + expect(dsl).toHaveProperty(bucket.id); + + expect(typeof dsl[bucket.id]).toBe('object'); + expect(dsl[bucket.id]).toHaveProperty('aggs'); + + metrics.forEach((metric: AggConfig) => { + expect(dsl[bucket.id].aggs).toHaveProperty(metric.id); + expect(dsl[bucket.id].aggs[metric.id]).not.toHaveProperty('aggs'); + }); + + if (buckets.length) { + checkLevel(dsl[bucket.id].aggs); + } + })(topLevelDsl); + }); + + it('adds the parent aggs of nested metrics at every level if the vis is hierarchical', () => { + const configStates = [ + { + enabled: true, + id: '1', + type: 'avg_bucket', + schema: 'metric', + params: { + customBucket: { + id: '1-bucket', + type: 'date_histogram', + schema: 'bucketAgg', + params: { + field: '@timestamp', + interval: '10s', + }, + }, + customMetric: { + id: '1-metric', + type: 'count', + schema: 'metricAgg', + params: {}, + }, + }, + }, + { + enabled: true, + id: '2', + type: 'terms', + schema: 'bucket', + params: { + field: 'clientip', + }, + }, + { + enabled: true, + id: '3', + type: 'terms', + schema: 'bucket', + params: { + field: 'machine.os.raw', + }, + }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const topLevelDsl = ac.toDsl(true)['2']; + + expect(Object.keys(topLevelDsl.aggs)).toContain('1'); + expect(Object.keys(topLevelDsl.aggs)).toContain('1-bucket'); + expect(topLevelDsl.aggs['1'].avg_bucket).toHaveProperty('buckets_path', '1-bucket>_count'); + expect(Object.keys(topLevelDsl.aggs['3'].aggs)).toContain('1'); + expect(Object.keys(topLevelDsl.aggs['3'].aggs)).toContain('1-bucket'); + expect(topLevelDsl.aggs['3'].aggs['1'].avg_bucket).toHaveProperty( + 'buckets_path', + '1-bucket>_count' + ); + }); + }); +}); diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts index 8e091ed5f21ae..ab70e66b1e138 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts @@ -17,17 +17,12 @@ * under the License. */ -/** - * @name AggConfig - * - * @extends IndexedArray - * - * @description A "data structure"-like class with methods for indexing and - * accessing instances of AggConfig. - */ - import _ from 'lodash'; +import { Assign } from '@kbn/utility-types'; + import { AggConfig, AggConfigOptions, IAggConfig } from './agg_config'; +import { IAggType } from './agg_type'; +import { AggTypesRegistryStart } from './agg_types_registry'; import { Schema } from './schemas'; import { AggGroupNames } from './agg_groups'; import { @@ -55,6 +50,24 @@ function parseParentAggs(dslLvlCursor: any, dsl: any) { } } +export interface AggConfigsOptions { + schemas?: Schemas; + typesRegistry: AggTypesRegistryStart; +} + +export type CreateAggConfigParams = Assign; + +/** + * @name AggConfigs + * + * @description A "data structure"-like class with methods for indexing and + * accessing instances of AggConfig. This should never be instantiated directly + * outside of this plugin. Rather, downstream plugins should do this via + * `createAggConfigs()` + * + * @internal + */ + // TODO need to make a more explicit interface for this export type IAggConfigs = AggConfigs; @@ -62,23 +75,31 @@ export class AggConfigs { public indexPattern: IndexPattern; public schemas: any; public timeRange?: TimeRange; + private readonly typesRegistry: AggTypesRegistryStart; aggs: IAggConfig[]; - constructor(indexPattern: IndexPattern, configStates = [] as any, schemas?: any) { + constructor( + indexPattern: IndexPattern, + configStates: CreateAggConfigParams[] = [], + opts: AggConfigsOptions + ) { + this.typesRegistry = opts.typesRegistry; + configStates = AggConfig.ensureIds(configStates); this.aggs = []; this.indexPattern = indexPattern; - this.schemas = schemas; + this.schemas = opts.schemas; configStates.forEach((params: any) => this.createAggConfig(params)); - if (schemas) { - this.initializeDefaultsFromSchemas(schemas); + if (this.schemas) { + this.initializeDefaultsFromSchemas(this.schemas); } } + // do this wherever the schemas were passed in, & pass in state defaults instead initializeDefaultsFromSchemas(schemas: Schemas) { // Set the defaults for any schema which has them. If the defaults // for some reason has more then the max only set the max number @@ -91,10 +112,11 @@ export class AggConfigs { }) .each((schema: any) => { if (!this.aggs.find((agg: AggConfig) => agg.schema && agg.schema.name === schema.name)) { + // the result here should be passable as a configState const defaults = schema.defaults.slice(0, schema.max); _.each(defaults, defaultState => { const state = _.defaults({ id: AggConfig.nextId(this.aggs) }, defaultState); - this.aggs.push(new AggConfig(this, state as AggConfigOptions)); + this.createAggConfig(state as AggConfigOptions); }); } }) @@ -124,28 +146,36 @@ export class AggConfigs { if (!enabledOnly) return true; return agg.enabled; }; - const aggConfigs = new AggConfigs( - this.indexPattern, - this.aggs.filter(filterAggs), - this.schemas - ); + + const aggConfigs = new AggConfigs(this.indexPattern, this.aggs.filter(filterAggs), { + schemas: this.schemas, + typesRegistry: this.typesRegistry, + }); + return aggConfigs; } createAggConfig = ( - params: AggConfig | AggConfigOptions, + params: CreateAggConfigParams, { addToAggConfigs = true } = {} ) => { + const { type } = params; let aggConfig; + if (params instanceof AggConfig) { aggConfig = params; params.parent = this; } else { - aggConfig = new AggConfig(this, params); + aggConfig = new AggConfig(this, { + ...params, + type: typeof type === 'string' ? this.typesRegistry.get(type) : type, + }); } + if (addToAggConfigs) { this.aggs.push(aggConfig); } + return aggConfig as T; }; @@ -166,10 +196,10 @@ export class AggConfigs { return true; } - toDsl(hierarchical: boolean = false) { + toDsl(hierarchical: boolean = false): Record { const dslTopLvl = {}; let dslLvlCursor: Record; - let nestedMetrics: Array<{ config: AggConfig; dsl: any }> | []; + let nestedMetrics: Array<{ config: AggConfig; dsl: Record }> | []; if (hierarchical) { // collect all metrics, and filter out the ones that we won't be copying diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts index 30ab272537dad..b08fcf309e9ed 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts @@ -23,8 +23,6 @@ import { FieldParamType } from './param_types/field'; import { OptionedParamType } from './param_types/optioned'; import { AggParamType } from '../aggs/param_types/agg'; -jest.mock('ui/new_platform'); - describe('AggParams class', () => { describe('constructor args', () => { it('accepts an array of param defs', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts index 6d4c2d1317f50..c78e56dd25887 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts @@ -19,11 +19,16 @@ import { AggType, AggTypeConfig } from './agg_type'; import { IAggConfig } from './agg_config'; -import { npStart } from 'ui/new_platform'; - -jest.mock('ui/new_platform'); +import { mockDataServices } from './test_helpers'; +import { dataPluginMock } from '../../../../../../plugins/data/public/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setFieldFormats } from '../../../../../../plugins/data/public/services'; describe('AggType Class', () => { + beforeEach(() => { + mockDataServices(); + }); + describe('constructor', () => { it("requires a valid config object as it's first param", () => { expect(() => { @@ -153,7 +158,10 @@ describe('AggType Class', () => { }); it('returns default formatter', () => { - npStart.plugins.data.fieldFormats.getDefaultInstance = jest.fn(() => 'default') as any; + setFieldFormats({ + ...dataPluginMock.createStartContract().fieldFormats, + getDefaultInstance: jest.fn(() => 'default') as any, + }); const aggType = new AggType({ name: 'name', diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts index 5ccf0f65c0e92..3cd9496d3f23d 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts @@ -19,7 +19,6 @@ import { constant, noop, identity } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; import { initParams } from './agg_params'; import { AggConfig } from './agg_config'; @@ -32,6 +31,8 @@ import { IFieldFormat, ISearchSource, } from '../../../../../../plugins/data/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getFieldFormats } from '../../../../../../plugins/data/public/services'; export interface AggTypeConfig< TAggConfig extends AggConfig = AggConfig, @@ -65,7 +66,7 @@ export interface AggTypeConfig< const getFormat = (agg: AggConfig) => { const field = agg.getField(); - const fieldFormatsService = npStart.plugins.data.fieldFormats; + const fieldFormatsService = getFieldFormats(); return field ? field.format : fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.STRING); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts new file mode 100644 index 0000000000000..405f83e237de8 --- /dev/null +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts @@ -0,0 +1,91 @@ +/* + * 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 { + AggTypesRegistry, + AggTypesRegistrySetup, + AggTypesRegistryStart, +} from './agg_types_registry'; +import { BucketAggType } from './buckets/_bucket_agg_type'; +import { MetricAggType } from './metrics/metric_agg_type'; + +const bucketType = { name: 'terms', type: 'bucket' } as BucketAggType; +const metricType = { name: 'count', type: 'metric' } as MetricAggType; + +describe('AggTypesRegistry', () => { + let registry: AggTypesRegistry; + let setup: AggTypesRegistrySetup; + let start: AggTypesRegistryStart; + + beforeEach(() => { + registry = new AggTypesRegistry(); + setup = registry.setup(); + start = registry.start(); + }); + + it('registerBucket adds new buckets', () => { + setup.registerBucket(bucketType); + expect(start.getBuckets()).toEqual([bucketType]); + }); + + it('registerBucket throws error when registering duplicate bucket', () => { + expect(() => { + setup.registerBucket(bucketType); + setup.registerBucket(bucketType); + }).toThrow(/already been registered with name: terms/); + }); + + it('registerMetric adds new metrics', () => { + setup.registerMetric(metricType); + expect(start.getMetrics()).toEqual([metricType]); + }); + + it('registerMetric throws error when registering duplicate metric', () => { + expect(() => { + setup.registerMetric(metricType); + setup.registerMetric(metricType); + }).toThrow(/already been registered with name: count/); + }); + + it('gets either buckets or metrics by id', () => { + setup.registerBucket(bucketType); + setup.registerMetric(metricType); + expect(start.get('terms')).toEqual(bucketType); + expect(start.get('count')).toEqual(metricType); + }); + + it('getBuckets retrieves only buckets', () => { + setup.registerBucket(bucketType); + expect(start.getBuckets()).toEqual([bucketType]); + }); + + it('getMetrics retrieves only metrics', () => { + setup.registerMetric(metricType); + expect(start.getMetrics()).toEqual([metricType]); + }); + + it('getAll returns all buckets and metrics', () => { + setup.registerBucket(bucketType); + setup.registerMetric(metricType); + expect(start.getAll()).toEqual({ + buckets: [bucketType], + metrics: [metricType], + }); + }); +}); diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts new file mode 100644 index 0000000000000..8a8746106ae58 --- /dev/null +++ b/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts @@ -0,0 +1,68 @@ +/* + * 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 { BucketAggType } from './buckets/_bucket_agg_type'; +import { MetricAggType } from './metrics/metric_agg_type'; + +export type AggTypesRegistrySetup = ReturnType; +export type AggTypesRegistryStart = ReturnType; + +export class AggTypesRegistry { + private readonly bucketAggs = new Map(); + private readonly metricAggs = new Map(); + + setup = () => { + return { + registerBucket: >(type: T): void => { + const { name } = type; + if (this.bucketAggs.get(name)) { + throw new Error(`Bucket agg has already been registered with name: ${name}`); + } + this.bucketAggs.set(name, type); + }, + registerMetric: >(type: T): void => { + const { name } = type; + if (this.metricAggs.get(name)) { + throw new Error(`Metric agg has already been registered with name: ${name}`); + } + this.metricAggs.set(name, type); + }, + }; + }; + + start = () => { + return { + get: (name: string) => { + return this.bucketAggs.get(name) || this.metricAggs.get(name); + }, + getBuckets: () => { + return Array.from(this.bucketAggs.values()); + }, + getMetrics: () => { + return Array.from(this.metricAggs.values()); + }, + getAll: () => { + return { + buckets: Array.from(this.bucketAggs.values()), + metrics: Array.from(this.metricAggs.values()), + }; + }, + }; + }; +} diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts index 546d054c5af97..d6ab58d5250a8 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts @@ -17,16 +17,16 @@ * under the License. */ -import { AggConfig } from '../agg_config'; +import { IAggConfig } from '../agg_config'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; import { AggType, AggTypeConfig } from '../agg_type'; import { AggParamType } from '../param_types/agg'; -export interface IBucketAggConfig extends AggConfig { +export interface IBucketAggConfig extends IAggConfig { type: InstanceType; } -export interface BucketAggParam +export interface BucketAggParam extends AggParamType { scriptable?: boolean; filterFieldTypes?: KBN_FIELD_TYPES | KBN_FIELD_TYPES[] | '*'; @@ -34,12 +34,12 @@ export interface BucketAggParam const bucketType = 'buckets'; -interface BucketAggTypeConfig +interface BucketAggTypeConfig extends AggTypeConfig> { - getKey?: (bucket: any, key: any, agg: AggConfig) => any; + getKey?: (bucket: any, key: any, agg: IAggConfig) => any; } -export class BucketAggType extends AggType< +export class BucketAggType extends AggType< TBucketAggConfig, BucketAggParam > { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts index e196687607d19..393d3b745250f 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { i18n } from '@kbn/i18n'; import { IBucketAggConfig } from './_bucket_agg_type'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts index 0d3f58c50a42e..2b47dc384bca2 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts @@ -21,14 +21,22 @@ import moment from 'moment'; import { createFilterDateHistogram } from './date_histogram'; import { intervalOptions } from '../_interval_options'; import { AggConfigs } from '../../agg_configs'; -import { IBucketDateHistogramAggConfig } from '../date_histogram'; +import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; +import { dateHistogramBucketAgg, IBucketDateHistogramAggConfig } from '../date_histogram'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { RangeFilter } from '../../../../../../../../plugins/data/public'; +// TODO: remove this once time buckets is migrated jest.mock('ui/new_platform'); describe('AggConfig Filters', () => { describe('date_histogram', () => { + beforeEach(() => { + mockDataServices(); + }); + + const typesRegistry = mockAggTypesRegistry([dateHistogramBucketAgg]); + let agg: IBucketDateHistogramAggConfig; let filter: RangeFilter; let bucketStart: any; @@ -56,7 +64,7 @@ describe('AggConfig Filters', () => { params: { field: field.name, interval, customInterval: '5d' }, }, ], - null + { typesRegistry } ); const bucketKey = 1422579600000; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts index 41e806668337e..c594c7718e58b 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts @@ -18,16 +18,17 @@ */ import moment from 'moment'; +import { dateRangeBucketAgg } from '../date_range'; import { createFilterDateRange } from './date_range'; import { fieldFormats, FieldFormatsGetConfigFn } from '../../../../../../../../plugins/data/public'; import { AggConfigs } from '../../agg_configs'; +import { mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; -jest.mock('ui/new_platform'); - describe('AggConfig Filters', () => { describe('Date range', () => { + const typesRegistry = mockAggTypesRegistry([dateRangeBucketAgg]); const getConfig = (() => {}) as FieldFormatsGetConfigFn; const getAggConfigs = () => { const field = { @@ -55,7 +56,7 @@ describe('AggConfig Filters', () => { }, }, ], - null + { typesRegistry } ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts index 34cf996826865..3b9c771e0f15f 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts @@ -16,14 +16,21 @@ * specific language governing permissions and limitations * under the License. */ + +import { filtersBucketAgg } from '../filters'; import { createFilterFilters } from './filters'; import { AggConfigs } from '../../agg_configs'; +import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; import { IBucketAggConfig } from '../_bucket_agg_type'; -jest.mock('ui/new_platform'); - describe('AggConfig Filters', () => { describe('filters', () => { + beforeEach(() => { + mockDataServices(); + }); + + const typesRegistry = mockAggTypesRegistry([filtersBucketAgg]); + const getAggConfigs = () => { const field = { name: 'bytes', @@ -52,7 +59,7 @@ describe('AggConfig Filters', () => { }, }, ], - null + { typesRegistry } ); }; it('should return a filters filter', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts index 9f845847df5d9..b046c802c58c1 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts @@ -16,16 +16,22 @@ * specific language governing permissions and limitations * under the License. */ + import { createFilterHistogram } from './histogram'; import { AggConfigs } from '../../agg_configs'; +import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; import { fieldFormats, FieldFormatsGetConfigFn } from '../../../../../../../../plugins/data/public'; -jest.mock('ui/new_platform'); - describe('AggConfig Filters', () => { describe('histogram', () => { + beforeEach(() => { + mockDataServices(); + }); + + const typesRegistry = mockAggTypesRegistry(); + const getConfig = (() => {}) as FieldFormatsGetConfigFn; const getAggConfigs = () => { const field = { @@ -55,7 +61,7 @@ describe('AggConfig Filters', () => { }, }, ], - null + { typesRegistry } ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts index e92ba5cb2852a..7572c48390dc2 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts @@ -17,17 +17,18 @@ * under the License. */ +import { ipRangeBucketAgg } from '../ip_range'; import { createFilterIpRange } from './ip_range'; -import { AggConfigs } from '../../agg_configs'; +import { AggConfigs, CreateAggConfigParams } from '../../agg_configs'; +import { mockAggTypesRegistry } from '../../test_helpers'; import { fieldFormats } from '../../../../../../../../plugins/data/public'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; -jest.mock('ui/new_platform'); - describe('AggConfig Filters', () => { describe('IP range', () => { - const getAggConfigs = (aggs: Array>) => { + const typesRegistry = mockAggTypesRegistry([ipRangeBucketAgg]); + const getAggConfigs = (aggs: CreateAggConfigParams[]) => { const field = { name: 'ip', format: fieldFormats.IpFormat, @@ -42,7 +43,7 @@ describe('AggConfig Filters', () => { }, } as any; - return new AggConfigs(indexPattern, aggs, null); + return new AggConfigs(indexPattern, aggs, { typesRegistry }); }; it('should return a range filter for ip_range agg', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts index 33344ca0a3484..324d425290832 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts @@ -17,16 +17,22 @@ * under the License. */ +import { rangeBucketAgg } from '../range'; import { createFilterRange } from './range'; import { fieldFormats, FieldFormatsGetConfigFn } from '../../../../../../../../plugins/data/public'; import { AggConfigs } from '../../agg_configs'; +import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; -jest.mock('ui/new_platform'); - describe('AggConfig Filters', () => { describe('range', () => { + beforeEach(() => { + mockDataServices(); + }); + + const typesRegistry = mockAggTypesRegistry([rangeBucketAgg]); + const getConfig = (() => {}) as FieldFormatsGetConfigFn; const getAggConfigs = () => { const field = { @@ -56,7 +62,7 @@ describe('AggConfig Filters', () => { }, }, ], - null + { typesRegistry } ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts index 7c6e769437ca1..6db6eb11a5f52 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts @@ -17,17 +17,18 @@ * under the License. */ +import { termsBucketAgg } from '../terms'; import { createFilterTerms } from './terms'; -import { AggConfigs } from '../../agg_configs'; +import { AggConfigs, CreateAggConfigParams } from '../../agg_configs'; +import { mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; import { Filter, ExistsFilter } from '../../../../../../../../plugins/data/public'; -jest.mock('ui/new_platform'); - describe('AggConfig Filters', () => { describe('terms', () => { - const getAggConfigs = (aggs: Array>) => { + const typesRegistry = mockAggTypesRegistry([termsBucketAgg]); + const getAggConfigs = (aggs: CreateAggConfigParams[]) => { const indexPattern = { id: '1234', title: 'logstash-*', @@ -42,7 +43,7 @@ describe('AggConfig Filters', () => { indexPattern, }; - return new AggConfigs(indexPattern, aggs, null); + return new AggConfigs(indexPattern, aggs, { typesRegistry }); }; it('should return a match_phrase filter for terms', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts index dc0f9baa6d0cc..a5368135728d4 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts @@ -21,8 +21,7 @@ import _ from 'lodash'; import moment from 'moment-timezone'; import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; -import { timefilter } from 'ui/timefilter'; +// TODO need to move TimeBuckets import { TimeBuckets } from 'ui/time_buckets'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; @@ -33,6 +32,8 @@ import { writeParams } from '../agg_params'; import { isMetricAggType } from '../metrics/metric_agg_type'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getQueryService, getUiSettings } from '../../../../../../../plugins/data/public/services'; const detectedTimezone = moment.tz.guess(); const tzOffset = moment().format('Z'); @@ -40,6 +41,7 @@ const tzOffset = moment().format('Z'); const getInterval = (agg: IBucketAggConfig): string => _.get(agg, ['params', 'interval']); export const setBounds = (agg: IBucketDateHistogramAggConfig, force?: boolean) => { + const { timefilter } = getQueryService().timefilter; if (agg.buckets._alreadySet && !force) return; agg.buckets._alreadySet = true; const bounds = agg.params.timeRange ? timefilter.calculateBounds(agg.params.timeRange) : null; @@ -221,7 +223,7 @@ export const dateHistogramBucketAgg = new BucketAggType { + beforeEach(() => { + mockDataServices(); + }); + + const typesRegistry = mockAggTypesRegistry([dateRangeBucketAgg]); + const getAggConfigs = (params: Record = {}, hasIncludeTypeMeta: boolean = true) => { const field = { name: 'bytes', @@ -58,7 +67,7 @@ describe('date_range params', () => { params, }, ], - null + { typesRegistry } ); }; @@ -95,7 +104,11 @@ describe('date_range params', () => { }); it('should use the Kibana time_zone if no parameter specified', () => { - npStart.core.uiSettings.get = jest.fn(() => 'kibanaTimeZone' as any); + const core = coreMock.createStart(); + setUiSettings({ + ...core.uiSettings, + get: () => 'kibanaTimeZone' as any, + }); const aggConfigs = getAggConfigs( { @@ -106,6 +119,8 @@ describe('date_range params', () => { const dateRange = aggConfigs.aggs[0]; const params = dateRange.toDsl()[BUCKET_TYPES.DATE_RANGE]; + setUiSettings(core.uiSettings); // clean up + expect(params.time_zone).toBe('kibanaTimeZone'); }); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts index 1dc24ca80035c..933cdd0577f8d 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts @@ -16,18 +16,20 @@ * specific language governing permissions and limitations * under the License. */ + import { get } from 'lodash'; import moment from 'moment-timezone'; import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; -import { convertDateRangeToString, DateRangeKey } from './lib/date_range'; import { BUCKET_TYPES } from './bucket_agg_types'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { createFilterDateRange } from './create_filter/date_range'; import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../../../plugins/data/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getFieldFormats, getUiSettings } from '../../../../../../../plugins/data/public/services'; -export { convertDateRangeToString, DateRangeKey }; +import { convertDateRangeToString, DateRangeKey } from './lib/date_range'; +export { convertDateRangeToString, DateRangeKey }; // for BWC const dateRangeTitle = i18n.translate('data.search.aggs.buckets.dateRangeTitle', { defaultMessage: 'Date Range', @@ -41,7 +43,7 @@ export const dateRangeBucketAgg = new BucketAggType({ return { from, to }; }, getFormat(agg) { - const fieldFormatsService = npStart.plugins.data.fieldFormats; + const fieldFormatsService = getFieldFormats(); const formatter = agg.fieldOwnFormatter( fieldFormats.TEXT_CONTEXT_TYPE, @@ -92,7 +94,7 @@ export const dateRangeBucketAgg = new BucketAggType({ ]); } if (!tz) { - const config = npStart.core.uiSettings; + const config = getUiSettings(); const detectedTimezone = moment.tz.guess(); const tzOffset = moment().format('Z'); const isDefaultTimezone = config.isDefault('dateFormat:tz'); diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts index b52e2d6cfd4df..80efc0cf92071 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { i18n } from '@kbn/i18n'; import { BucketAggType } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts index 6eaf788b83c04..2852f3e4bdf46 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts @@ -18,19 +18,21 @@ */ import _ from 'lodash'; -import angular from 'angular'; - import { i18n } from '@kbn/i18n'; import chrome from 'ui/chrome'; + import { createFilterFilters } from './create_filter/filters'; +import { toAngularJSON } from '../utils'; import { BucketAggType } from './_bucket_agg_type'; +import { BUCKET_TYPES } from './bucket_agg_types'; import { Storage } from '../../../../../../../plugins/kibana_utils/public'; + import { getQueryLog, esQuery, Query } from '../../../../../../../plugins/data/public'; -import { BUCKET_TYPES } from './bucket_agg_types'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getUiSettings } from '../../../../../../../plugins/data/public/services'; const config = chrome.getUiSettingsClient(); -const storage = new Storage(window.localStorage); const filtersTitle = i18n.translate('data.search.aggs.buckets.filtersTitle', { defaultMessage: 'Filters', @@ -52,15 +54,17 @@ export const filtersBucketAgg = new BucketAggType({ params: [ { name: 'filters', + // TODO need to get rid of reference to `config` below default: [{ input: { query: '', language: config.get('search:queryLanguage') }, label: '' }], write(aggConfig, output) { + const uiSettings = getUiSettings(); const inFilters: FilterValue[] = aggConfig.params.filters; if (!_.size(inFilters)) return; inFilters.forEach(filter => { const persistedLog = getQueryLog( - config, - storage, + uiSettings, + new Storage(window.localStorage), 'vis_default_editor', filter.input.language ); @@ -77,7 +81,13 @@ export const filtersBucketAgg = new BucketAggType({ return; } - const query = esQuery.buildEsQuery(aggConfig.getIndexPattern(), [input], [], config); + const esQueryConfigs = esQuery.getEsQueryConfig(uiSettings); + const query = esQuery.buildEsQuery( + aggConfig.getIndexPattern(), + [input], + [], + esQueryConfigs + ); if (!query) { console.log('malformed filter agg params, missing "query" on input'); // eslint-disable-line no-console @@ -90,7 +100,7 @@ export const filtersBucketAgg = new BucketAggType({ matchAllLabel || (typeof filter.input.query === 'string' ? filter.input.query - : angular.toJson(filter.input.query)); + : toAngularJSON(filter.input.query)); filters[label] = { query }; }, {} diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts index f0ad595476486..09dd03c759155 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts @@ -19,12 +19,13 @@ import { geoHashBucketAgg } from './geo_hash'; import { AggConfigs, IAggConfigs } from '../agg_configs'; +import { mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; import { IBucketAggConfig } from './_bucket_agg_type'; -jest.mock('ui/new_platform'); - describe('Geohash Agg', () => { + // const typesRegistry = mockAggTypesRegistry([geoHashBucketAgg]); + const typesRegistry = mockAggTypesRegistry(); const getAggConfigs = (params?: Record) => { const indexPattern = { id: '1234', @@ -62,7 +63,7 @@ describe('Geohash Agg', () => { }, }, ], - null + { typesRegistry } ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts index 57e8f6e8c5ded..9142a30338163 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts @@ -19,7 +19,6 @@ import { i18n } from '@kbn/i18n'; import { noop } from 'lodash'; -import { AggConfigOptions } from '../agg_config'; import { BucketAggType } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; @@ -57,7 +56,7 @@ export const geoTileBucketAgg = new BucketAggType({ aggs.push(agg); if (useGeocentroid) { - const aggConfig: AggConfigOptions = { + const aggConfig = { type: METRIC_TYPES.GEO_CENTROID, enabled: true, params: { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts index 4e89d7db1ff64..11dc8e42fd653 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts @@ -17,16 +17,23 @@ * under the License. */ -import { npStart } from 'ui/new_platform'; -import { AggConfigs } from '../index'; +import { AggConfigs } from '../agg_configs'; +import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; import { IBucketHistogramAggConfig, histogramBucketAgg, AutoBounds } from './histogram'; import { BucketAggType } from './_bucket_agg_type'; - -jest.mock('ui/new_platform'); +import { coreMock } from '../../../../../../../../src/core/public/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setUiSettings } from '../../../../../../../plugins/data/public/services'; describe('Histogram Agg', () => { - const getAggConfigs = (params: Record = {}) => { + beforeEach(() => { + mockDataServices(); + }); + + const typesRegistry = mockAggTypesRegistry([histogramBucketAgg]); + + const getAggConfigs = (params: Record) => { const indexPattern = { id: '1234', title: 'logstash-*', @@ -45,16 +52,13 @@ describe('Histogram Agg', () => { indexPattern, [ { - field: { - name: 'field', - }, id: 'test', type: BUCKET_TYPES.HISTOGRAM, schema: 'segment', params, }, ], - null + { typesRegistry } ); }; @@ -158,10 +162,15 @@ describe('Histogram Agg', () => { aggConfig.setAutoBounds(autoBounds); } - // mock histogram:maxBars value; - npStart.core.uiSettings.get = jest.fn(() => maxBars as any); + const core = coreMock.createStart(); + setUiSettings({ + ...core.uiSettings, + get: () => maxBars as any, + }); - return aggConfig.write(aggConfigs).params; + const interval = aggConfig.write(aggConfigs).params; + setUiSettings(core.uiSettings); // clean up + return interval; }; it('will respect the histogram:maxBars setting', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts index f7e9ef45961e0..70df2f230db09 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts @@ -19,13 +19,13 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; -import { toastNotifications } from 'ui/notify'; -import { npStart } from 'ui/new_platform'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { createFilterHistogram } from './create_filter/histogram'; -import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; import { BUCKET_TYPES } from './bucket_agg_types'; +import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getNotifications, getUiSettings } from '../../../../../../../plugins/data/public/services'; export interface AutoBounds { min: number; @@ -37,8 +37,6 @@ export interface IBucketHistogramAggConfig extends IBucketAggConfig { getAutoBounds: () => AutoBounds; } -const getUIConfig = () => npStart.core.uiSettings; - export const histogramBucketAgg = new BucketAggType({ name: BUCKET_TYPES.HISTOGRAM, title: i18n.translate('data.search.aggs.buckets.histogramTitle', { @@ -116,7 +114,7 @@ export const histogramBucketAgg = new BucketAggType({ }) .catch((e: Error) => { if (e.name === 'AbortError') return; - toastNotifications.addWarning( + getNotifications().toasts.addWarning( i18n.translate('data.search.aggs.histogram.missingMaxMinValuesWarning', { defaultMessage: 'Unable to retrieve max and min values to auto-scale histogram buckets. This may lead to poor visualization performance.', @@ -136,7 +134,7 @@ export const histogramBucketAgg = new BucketAggType({ const range = autoBounds.max - autoBounds.min; const bars = range / interval; - const config = getUIConfig(); + const config = getUiSettings(); if (bars > config.get('histogram:maxBars')) { const minInterval = range / config.get('histogram:maxBars'); diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts index 91bdf53e7f809..3fb464d8fa7a8 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts @@ -19,15 +19,17 @@ import { noop, map, omit, isNull } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; -import { IpRangeKey, convertIPRangeToString } from './lib/ip_range'; import { BucketAggType } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; -// @ts-ignore import { createFilterIpRange } from './create_filter/ip_range'; import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../../../plugins/data/public'; -export { IpRangeKey, convertIPRangeToString }; + +import { IpRangeKey, convertIPRangeToString } from './lib/ip_range'; +export { IpRangeKey, convertIPRangeToString }; // for BWC + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getFieldFormats } from '../../../../../../../plugins/data/public/services'; const ipRangeTitle = i18n.translate('data.search.aggs.buckets.ipRangeTitle', { defaultMessage: 'IPv4 Range', @@ -44,7 +46,7 @@ export const ipRangeBucketAgg = new BucketAggType({ return { type: 'range', from: bucket.from, to: bucket.to }; }, getFormat(agg) { - const fieldFormatsService = npStart.plugins.data.fieldFormats; + const fieldFormatsService = getFieldFormats(); const formatter = agg.fieldOwnFormatter( fieldFormats.TEXT_CONTEXT_TYPE, fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.IP) diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts index 77e84e044de55..d94477b588f8d 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts @@ -19,10 +19,10 @@ import { isString, isObject } from 'lodash'; import { IBucketAggConfig, BucketAggType, BucketAggParam } from './_bucket_agg_type'; -import { AggConfig } from '../agg_config'; +import { IAggConfig } from '../agg_config'; export const isType = (type: string) => { - return (agg: AggConfig): boolean => { + return (agg: IAggConfig): boolean => { const field = agg.params.field; return field && field.type === type; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts index b1b0c4bc30a58..096b19fe7de66 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts @@ -17,12 +17,12 @@ * under the License. */ +import { rangeBucketAgg } from './range'; import { AggConfigs } from '../agg_configs'; +import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; import { FieldFormatsGetConfigFn, fieldFormats } from '../../../../../../../plugins/data/public'; -jest.mock('ui/new_platform'); - const buckets = [ { to: 1024, @@ -44,6 +44,12 @@ const buckets = [ ]; describe('Range Agg', () => { + beforeEach(() => { + mockDataServices(); + }); + + const typesRegistry = mockAggTypesRegistry([rangeBucketAgg]); + const getConfig = (() => {}) as FieldFormatsGetConfigFn; const getAggConfigs = () => { const field = { @@ -80,7 +86,7 @@ describe('Range Agg', () => { }, }, ], - null + { typesRegistry } ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts index 37b829bfc20fb..cee3ed506c29c 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts @@ -17,17 +17,16 @@ * under the License. */ -import { AggConfigs } from '../index'; -import { IAggConfigs } from '../types'; +import { AggConfigs, IAggConfigs } from '../agg_configs'; +import { mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; import { significantTermsBucketAgg } from './significant_terms'; import { IBucketAggConfig } from './_bucket_agg_type'; -jest.mock('ui/new_platform'); - describe('Significant Terms Agg', () => { describe('order agg editor UI', () => { describe('convert include/exclude from old format', () => { + const typesRegistry = mockAggTypesRegistry([significantTermsBucketAgg]); const getAggConfigs = (params: Record = {}) => { const indexPattern = { id: '1234', @@ -53,7 +52,7 @@ describe('Significant Terms Agg', () => { params, }, ], - null + { typesRegistry } ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts index 24ac332ae4d55..9a4f28afd3edf 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts @@ -17,13 +17,13 @@ * under the License. */ -import { AggConfigs } from '../index'; +import { AggConfigs } from '../agg_configs'; +import { mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; -jest.mock('ui/new_platform'); - describe('Terms Agg', () => { describe('order agg editor UI', () => { + const typesRegistry = mockAggTypesRegistry(); const getAggConfigs = (params: Record = {}) => { const indexPattern = { id: '1234', @@ -48,7 +48,7 @@ describe('Terms Agg', () => { type: BUCKET_TYPES.TERMS, }, ], - null + { typesRegistry } ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts index cc1288d339692..0de1c31d02f96 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts @@ -19,13 +19,12 @@ import { IndexPattern } from '../../../../../../../plugins/data/public'; import { AggTypeFilters } from './agg_type_filters'; -import { AggConfig } from '..'; -import { IAggType } from '../types'; +import { IAggConfig, IAggType } from '../types'; describe('AggTypeFilters', () => { let registry: AggTypeFilters; const indexPattern = ({ id: '1234', fields: [], title: 'foo' } as unknown) as IndexPattern; - const aggConfig = {} as AggConfig; + const aggConfig = {} as IAggConfig; beforeEach(() => { registry = new AggTypeFilters(); diff --git a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts index d3b38ce041d7e..13a4cc0856b09 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { IndexPattern } from 'src/plugins/data/public'; import { IAggConfig, IAggType } from '../types'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts b/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts index 431e1161e0dbd..32cda7b950e93 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts @@ -17,7 +17,6 @@ * under the License. */ -import expect from '@kbn/expect'; import { propFilter } from './prop_filter'; describe('prop filter', () => { @@ -47,48 +46,48 @@ describe('prop filter', () => { it('returns list when no filters are provided', () => { const objects = getObjects('table', 'table', 'pie'); - expect(nameFilter(objects)).to.eql(objects); + expect(nameFilter(objects)).toEqual(objects); }); it('returns list when empty list of filters is provided', () => { const objects = getObjects('table', 'table', 'pie'); - expect(nameFilter(objects, [])).to.eql(objects); + expect(nameFilter(objects, [])).toEqual(objects); }); it('should keep only the tables', () => { const objects = getObjects('table', 'table', 'pie'); - expect(nameFilter(objects, 'table')).to.eql(getObjects('table', 'table')); + expect(nameFilter(objects, 'table')).toEqual(getObjects('table', 'table')); }); it('should support comma-separated values', () => { const objects = getObjects('table', 'line', 'pie'); - expect(nameFilter(objects, 'table,line')).to.eql(getObjects('table', 'line')); + expect(nameFilter(objects, 'table,line')).toEqual(getObjects('table', 'line')); }); it('should support an array of values', () => { const objects = getObjects('table', 'line', 'pie'); - expect(nameFilter(objects, ['table', 'line'])).to.eql(getObjects('table', 'line')); + expect(nameFilter(objects, ['table', 'line'])).toEqual(getObjects('table', 'line')); }); it('should return all objects', () => { const objects = getObjects('table', 'line', 'pie'); - expect(nameFilter(objects, '*')).to.eql(objects); + expect(nameFilter(objects, '*')).toEqual(objects); }); it('should allow negation', () => { const objects = getObjects('table', 'line', 'pie'); - expect(nameFilter(objects, ['!line'])).to.eql(getObjects('table', 'pie')); + expect(nameFilter(objects, ['!line'])).toEqual(getObjects('table', 'pie')); }); it('should support a function for specifying what should be kept', () => { const objects = getObjects('table', 'line', 'pie'); const line = (value: string) => value === 'line'; - expect(nameFilter(objects, line)).to.eql(getObjects('line')); + expect(nameFilter(objects, line)).toEqual(getObjects('line')); }); it('gracefully handles a filter function with zero arity', () => { const objects = getObjects('table', 'line', 'pie'); const rejectEverything = () => false; - expect(nameFilter(objects, rejectEverything)).to.eql([]); + expect(nameFilter(objects, rejectEverything)).toEqual([]); }); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/index.test.ts b/src/legacy/core_plugins/data/public/search/aggs/index.test.ts index a867769a77fc1..4d0cd55b09d53 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/index.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/index.test.ts @@ -25,8 +25,6 @@ import { isMetricAggType } from './metrics/metric_agg_type'; const bucketAggs = aggTypes.buckets; const metricAggs = aggTypes.metrics; -jest.mock('ui/new_platform'); - describe('AggTypesComponent', () => { describe('bucket aggs', () => { it('all extend BucketAggType', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/index.ts b/src/legacy/core_plugins/data/public/search/aggs/index.ts index 0bdb92b8de65e..f6914c36f6c05 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/index.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/index.ts @@ -17,8 +17,13 @@ * under the License. */ -export { aggTypes } from './agg_types'; +export { + AggTypesRegistry, + AggTypesRegistrySetup, + AggTypesRegistryStart, +} from './agg_types_registry'; export { AggType } from './agg_type'; +export { aggTypes } from './agg_types'; export { AggConfig } from './agg_config'; export { AggConfigs } from './agg_configs'; export { FieldParamType } from './param_types'; @@ -52,4 +57,4 @@ export { METRIC_TYPES } from './metrics/metric_agg_types'; export { ISchemas, Schema, Schemas } from './schemas'; // types -export { IAggConfig, IAggConfigs } from './types'; +export { CreateAggConfigParams, IAggConfig, IAggConfigs } from './types'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts index 9fb28f8631bc6..11bb559274729 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts @@ -19,7 +19,6 @@ import { i18n } from '@kbn/i18n'; import { get } from 'lodash'; - import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts index 83837f0de5114..0668a9bcf57a8 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts @@ -18,7 +18,6 @@ */ import { i18n } from '@kbn/i18n'; - import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts index d96197693dc2e..8f728cb5e7e42 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { i18n } from '@kbn/i18n'; import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts index 147e925521088..4f7b6e555ca33 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts @@ -18,10 +18,11 @@ */ import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getFieldFormats } from '../../../../../../../plugins/data/public/services'; const uniqueCountTitle = i18n.translate('data.search.aggs.metrics.uniqueCountTitle', { defaultMessage: 'Unique Count', @@ -37,7 +38,7 @@ export const cardinalityMetricAgg = new MetricAggType({ }); }, getFormat() { - const fieldFormatsService = npStart.plugins.data.fieldFormats; + const fieldFormatsService = getFieldFormats(); return fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }, diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts index 14a9bd073ff2b..8b3e0a488c68a 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts @@ -18,10 +18,11 @@ */ import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; -import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; +import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getFieldFormats } from '../../../../../../../plugins/data/public/services'; export const countMetricAgg = new MetricAggType({ name: METRIC_TYPES.COUNT, @@ -35,7 +36,7 @@ export const countMetricAgg = new MetricAggType({ }); }, getFormat() { - const fieldFormatsService = npStart.plugins.data.fieldFormats; + const fieldFormatsService = getFieldFormats(); return fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }, diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts index 054543de3dd06..00d866e6f2b3e 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { assign } from 'lodash'; import { IMetricAggConfig } from '../metric_agg_type'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts index e24aca08271c7..88549ee3019ee 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts @@ -23,7 +23,6 @@ import { noop, identity } from 'lodash'; import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers'; import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type'; import { parentPipelineAggWriter } from './parent_pipeline_agg_writer'; - import { Schemas } from '../../schemas'; import { fieldFormats } from '../../../../../../../../plugins/data/public'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts index e7c98e575fdb4..05e009cc9da30 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts @@ -21,7 +21,6 @@ import { identity } from 'lodash'; import { i18n } from '@kbn/i18n'; import { siblingPipelineAggWriter } from './sibling_pipeline_agg_writer'; import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers'; - import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type'; import { Schemas } from '../../schemas'; import { fieldFormats } from '../../../../../../../../plugins/data/public'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts index 4755a873e6977..ad55837ec9a30 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts @@ -17,15 +17,16 @@ * under the License. */ +import { medianMetricAgg } from './median'; import { AggConfigs, IAggConfigs } from '../agg_configs'; +import { mockAggTypesRegistry } from '../test_helpers'; import { METRIC_TYPES } from './metric_agg_types'; -jest.mock('ui/new_platform'); - describe('AggTypeMetricMedianProvider class', () => { let aggConfigs: IAggConfigs; beforeEach(() => { + const typesRegistry = mockAggTypesRegistry([medianMetricAgg]); const field = { name: 'bytes', }; @@ -50,7 +51,7 @@ describe('AggTypeMetricMedianProvider class', () => { }, }, ], - null + { typesRegistry } ); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts index 53a5ffff418f1..68fc98261118c 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts @@ -16,12 +16,10 @@ * specific language governing permissions and limitations * under the License. */ + import { i18n } from '@kbn/i18n'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; - -// @ts-ignore -import { percentilesMetricAgg } from './percentiles'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; const medianTitle = i18n.translate('data.search.aggs.metrics.medianTitle', { diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts index 3bae7b92618dc..952dcc96de833 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts @@ -18,13 +18,14 @@ */ import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; import { AggType, AggTypeConfig } from '../agg_type'; import { AggParamType } from '../param_types/agg'; import { AggConfig } from '../agg_config'; +import { FilterFieldTypes } from '../param_types/field'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; -import { FilterFieldTypes } from '../param_types/field'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getFieldFormats } from '../../../../../../../plugins/data/public/services'; export interface IMetricAggConfig extends AggConfig { type: InstanceType; @@ -78,7 +79,7 @@ export class MetricAggType { - const fieldFormatsService = npStart.plugins.data.fieldFormats; + const fieldFormatsService = getFieldFormats(); const field = agg.getField(); return field ? field.format diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts index 4885105163435..1806c6d9d7710 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { i18n } from '@kbn/i18n'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts index 11fc39c20bdc4..58b4ee530a8c2 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts @@ -17,12 +17,12 @@ * 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 '../agg_configs'; +import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; jest.mock('../schemas', () => { @@ -34,9 +34,13 @@ jest.mock('../schemas', () => { }; }); -jest.mock('ui/new_platform'); - describe('parent pipeline aggs', function() { + beforeEach(() => { + mockDataServices(); + }); + + const typesRegistry = mockAggTypesRegistry(); + const metrics = [ { name: 'derivative', title: 'Derivative', provider: derivativeMetricAgg }, { name: 'cumulative_sum', title: 'Cumulative Sum', provider: cumulativeSumMetricAgg }, @@ -94,7 +98,7 @@ describe('parent pipeline aggs', function() { schema: 'metric', }, ], - null + { typesRegistry } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) @@ -220,16 +224,16 @@ describe('parent pipeline aggs', function() { }); const searchSource: any = {}; - const customMetricSpy = sinon.spy(); + const customMetricSpy = jest.fn(); 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); + param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource, {}); }); - expect(customMetricSpy.calledWith(customMetric, searchSource)).toBe(true); + expect(customMetricSpy.mock.calls[0]).toEqual([customMetric, searchSource, {}]); }); }); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts index 655e918ce07de..628f1cd204ee5 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts @@ -19,14 +19,16 @@ import { IPercentileRanksAggConfig, percentileRanksMetricAgg } from './percentile_ranks'; import { AggConfigs, IAggConfigs } from '../agg_configs'; +import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; import { METRIC_TYPES } from './metric_agg_types'; -jest.mock('ui/new_platform'); - describe('AggTypesMetricsPercentileRanksProvider class', function() { let aggConfigs: IAggConfigs; beforeEach(() => { + mockDataServices(); + + const typesRegistry = mockAggTypesRegistry([percentileRanksMetricAgg]); const field = { name: 'bytes', }; @@ -58,7 +60,7 @@ describe('AggTypesMetricsPercentileRanksProvider class', function() { }, }, ], - null + { typesRegistry } ); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts index 38b47a7e97d2f..1d640a9c1fa42 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts @@ -18,20 +18,17 @@ */ import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; import { MetricAggType } from './metric_agg_type'; import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; - import { getPercentileValue } from './percentiles_get_value'; import { METRIC_TYPES } from './metric_agg_types'; import { fieldFormats, KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getFieldFormats } from '../../../../../../../plugins/data/public/services'; // required by the values editor - export type IPercentileRanksAggConfig = IResponseAggConfig; -const getFieldFormats = () => npStart.plugins.data.fieldFormats; - const valueProps = { makeLabel(this: IPercentileRanksAggConfig) { const fieldFormatsService = getFieldFormats(); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts index dd1aaca973e47..e077bc0f8c773 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts @@ -19,14 +19,14 @@ import { IPercentileAggConfig, percentilesMetricAgg } from './percentiles'; import { AggConfigs, IAggConfigs } from '../agg_configs'; +import { mockAggTypesRegistry } from '../test_helpers'; import { METRIC_TYPES } from './metric_agg_types'; -jest.mock('ui/new_platform'); - describe('AggTypesMetricsPercentilesProvider class', () => { let aggConfigs: IAggConfigs; beforeEach(() => { + const typesRegistry = mockAggTypesRegistry([percentilesMetricAgg]); const field = { name: 'bytes', }; @@ -58,7 +58,7 @@ describe('AggTypesMetricsPercentilesProvider class', () => { }, }, ], - null + { typesRegistry } ); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts index 39dc0d0f181e9..49e927d07d8dd 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts @@ -18,15 +18,11 @@ */ import { i18n } from '@kbn/i18n'; - import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; - import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; import { getPercentileValue } from './percentiles_get_value'; - -// @ts-ignore import { ordinalSuffix } from './lib/ordinal_suffix'; export type IPercentileAggConfig = IResponseAggConfig; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts index d643cf0d2a478..d3456bacceb6a 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts @@ -17,7 +17,6 @@ * under the License. */ -import { spy } from 'sinon'; import { bucketSumMetricAgg } from './bucket_sum'; import { bucketAvgMetricAgg } from './bucket_avg'; import { bucketMinMetricAgg } from './bucket_min'; @@ -25,6 +24,7 @@ import { bucketMaxMetricAgg } from './bucket_max'; import { AggConfigs } from '../agg_configs'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; +import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; jest.mock('../schemas', () => { class MockedSchemas { @@ -35,9 +35,13 @@ jest.mock('../schemas', () => { }; }); -jest.mock('ui/new_platform'); - describe('sibling pipeline aggs', () => { + beforeEach(() => { + mockDataServices(); + }); + + const typesRegistry = mockAggTypesRegistry(); + const metrics = [ { name: 'sum_bucket', title: 'Overall Sum', provider: bucketSumMetricAgg }, { name: 'avg_bucket', title: 'Overall Average', provider: bucketAvgMetricAgg }, @@ -96,7 +100,7 @@ describe('sibling pipeline aggs', () => { }, }, ], - null + { typesRegistry } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) @@ -162,8 +166,8 @@ describe('sibling pipeline aggs', () => { init(); const searchSource: any = {}; - const customMetricSpy = spy(); - const customBucketSpy = spy(); + const customMetricSpy = jest.fn(); + const customBucketSpy = jest.fn(); const { customMetric, customBucket } = aggConfig.params; // Attach a modifyAggConfigOnSearchRequestStart with a spy to the first parameter @@ -171,11 +175,11 @@ describe('sibling pipeline aggs', () => { customBucket.type.params[0].modifyAggConfigOnSearchRequestStart = customBucketSpy; aggConfig.type.params.forEach(param => { - param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource); + param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource, {}); }); - expect(customMetricSpy.calledWith(customMetric, searchSource)).toBe(true); - expect(customBucketSpy.calledWith(customBucket, searchSource)).toBe(true); + expect(customMetricSpy.mock.calls[0]).toEqual([customMetric, searchSource, {}]); + expect(customBucketSpy.mock.calls[0]).toEqual([customBucket, searchSource, {}]); }); }); }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts index 3125026a52185..0679831b1e6ac 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts @@ -19,11 +19,11 @@ import { IStdDevAggConfig, stdDeviationMetricAgg } from './std_deviation'; import { AggConfigs } from '../agg_configs'; +import { mockAggTypesRegistry } from '../test_helpers'; import { METRIC_TYPES } from './metric_agg_types'; -jest.mock('ui/new_platform'); - describe('AggTypeMetricStandardDeviationProvider class', () => { + const typesRegistry = mockAggTypesRegistry([stdDeviationMetricAgg]); const getAggConfigs = (customLabel?: string) => { const field = { name: 'memory', @@ -52,7 +52,7 @@ describe('AggTypeMetricStandardDeviationProvider class', () => { }, }, ], - null + { typesRegistry } ); }; diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts index a973de4fe8659..ad1f42f5c563e 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts @@ -20,11 +20,10 @@ import { dropRight, last } from 'lodash'; import { topHitMetricAgg } from './top_hit'; import { AggConfigs } from '../agg_configs'; +import { mockAggTypesRegistry } from '../test_helpers'; import { IMetricAggConfig } from './metric_agg_type'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; -jest.mock('ui/new_platform'); - describe('Top hit metric', () => { let aggDsl: Record; let aggConfig: IMetricAggConfig; @@ -37,6 +36,7 @@ describe('Top hit metric', () => { fieldType = KBN_FIELD_TYPES.NUMBER, size = 1, }: any) => { + const typesRegistry = mockAggTypesRegistry([topHitMetricAgg]); const field = { name: fieldName, displayName: fieldName, @@ -81,7 +81,7 @@ describe('Top hit metric', () => { params, }, ], - null + { typesRegistry } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts index 2e7c11004b472..d31abe64491d0 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts @@ -17,10 +17,10 @@ * under the License. */ -import { AggConfig } from '../agg_config'; +import { AggConfig, IAggConfig } from '../agg_config'; import { BaseParamType } from './base'; -export class AggParamType extends BaseParamType< +export class AggParamType extends BaseParamType< TAggConfig > { makeAgg: (agg: TAggConfig, state?: any) => TAggConfig; diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts index 1523cb03eb966..95ad71a616ab2 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts @@ -18,10 +18,10 @@ */ import { IAggConfigs } from '../agg_configs'; -import { AggConfig } from '../agg_config'; +import { IAggConfig } from '../agg_config'; import { FetchOptions, ISearchSource } from '../../../../../../../plugins/data/public'; -export class BaseParamType { +export class BaseParamType { name: string; type: string; displayName: string; diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts index fa88754ac60b9..7338c41f920d7 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts @@ -25,8 +25,6 @@ import { IAggConfig } from '../agg_config'; import { IMetricAggConfig } from '../metrics/metric_agg_type'; import { Schema } from '../schemas'; -jest.mock('ui/new_platform'); - describe('Field', () => { const indexPattern = { id: '1234', diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts index 40c30f6210a83..bb5707cbb482e 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts @@ -19,7 +19,6 @@ import { i18n } from '@kbn/i18n'; import { isFunction } from 'lodash'; -import { npStart } from 'ui/new_platform'; import { IAggConfig } from '../agg_config'; import { SavedObjectNotFound } from '../../../../../../../plugins/kibana_utils/public'; import { BaseParamType } from './base'; @@ -30,6 +29,8 @@ import { indexPatterns, KBN_FIELD_TYPES, } from '../../../../../../../plugins/data/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getNotifications } from '../../../../../../../plugins/data/public/services'; const filterByType = propFilter('type'); @@ -93,7 +94,7 @@ export class FieldParamType extends BaseParamType { // @ts-ignore const validField = this.getAvailableFields(aggConfig).find((f: any) => f.name === fieldName); if (!validField) { - npStart.core.notifications.toasts.addDanger( + getNotifications().toasts.addDanger( i18n.translate( 'data.search.aggs.paramTypes.field.invalidSavedFieldParameterErrorMessage', { diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts index bc36bb46d3d16..1a453a225797d 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts @@ -17,27 +17,26 @@ * under the License. */ -import { IndexedArray } from 'ui/indexed_array'; import { AggTypeFieldFilters } from './field_filters'; -import { AggConfig } from '../../agg_config'; +import { IAggConfig } from '../../agg_config'; import { IndexPatternField } from '../../../../../../../../plugins/data/public'; describe('AggTypeFieldFilters', () => { let registry: AggTypeFieldFilters; - const aggConfig = {} as AggConfig; + const aggConfig = {} as IAggConfig; beforeEach(() => { registry = new AggTypeFieldFilters(); }); it('should filter nothing without registered filters', async () => { - const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexedArray; + const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexPatternField[]; const filtered = registry.filter(fields, aggConfig); expect(filtered).toEqual(fields); }); it('should pass all fields to the registered filter', async () => { - const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexedArray; + const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexPatternField[]; const filter = jest.fn(); registry.addFilter(filter); registry.filter(fields, aggConfig); @@ -46,7 +45,7 @@ describe('AggTypeFieldFilters', () => { }); it('should allow registered filters to filter out fields', async () => { - const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexedArray; + const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexPatternField[]; let filtered = registry.filter(fields, aggConfig); expect(filtered).toEqual(fields); diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts index 7d1348ab5423b..1cbf0c9ae3624 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts @@ -17,9 +17,9 @@ * under the License. */ import { IndexPatternField } from 'src/plugins/data/public'; -import { AggConfig } from '../../agg_config'; +import { IAggConfig } from '../../agg_config'; -type AggTypeFieldFilter = (field: IndexPatternField, aggConfig: AggConfig) => boolean; +type AggTypeFieldFilter = (field: IndexPatternField, aggConfig: IAggConfig) => boolean; /** * A registry to store {@link AggTypeFieldFilter} which are used to filter down @@ -41,11 +41,11 @@ class AggTypeFieldFilters { /** * Returns the {@link any|fields} filtered by all registered filters. * - * @param fields An IndexedArray of fields that will be filtered down by this registry. + * @param fields An array of fields that will be filtered down by this registry. * @param aggConfig The aggConfig for which the returning list will be used. * @return A filtered list of the passed fields. */ - public filter(fields: IndexPatternField[], aggConfig: AggConfig) { + public filter(fields: IndexPatternField[], aggConfig: IAggConfig) { const allFilters = Array.from(this.filters); const allowedAggTypeFields = fields.filter(field => { const isAggTypeFieldAllowed = allFilters.every(filter => filter(field, aggConfig)); diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts index 827299814c62a..12fd29b3a1452 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts @@ -19,13 +19,11 @@ import { BaseParamType } from './base'; import { JsonParamType } from './json'; -import { AggConfig } from '../agg_config'; - -jest.mock('ui/new_platform'); +import { IAggConfig } from '../agg_config'; describe('JSON', function() { const paramName = 'json_test'; - let aggConfig: AggConfig; + let aggConfig: IAggConfig; let output: Record; const initAggParam = (config: Record = {}) => @@ -36,7 +34,7 @@ describe('JSON', function() { }); beforeEach(function() { - aggConfig = { params: {} } as AggConfig; + aggConfig = { params: {} } as IAggConfig; output = { params: {} }; }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts index 771919b0bb56b..bf85b3b890c35 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts @@ -19,7 +19,7 @@ import _ from 'lodash'; -import { AggConfig } from '../agg_config'; +import { IAggConfig } from '../agg_config'; import { BaseParamType } from './base'; export class JsonParamType extends BaseParamType { @@ -29,7 +29,7 @@ export class JsonParamType extends BaseParamType { this.name = config.name || 'json'; if (!config.write) { - this.write = (aggConfig: AggConfig, output: Record) => { + this.write = (aggConfig: IAggConfig, output: Record) => { let paramJson; const param = aggConfig.params[this.name]; diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts index 6b58d81914097..c03d6cdfa1c70 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts @@ -20,8 +20,6 @@ import { BaseParamType } from './base'; import { OptionedParamType } from './optioned'; -jest.mock('ui/new_platform'); - describe('Optioned', () => { describe('constructor', () => { it('it is an instance of BaseParamType', () => { diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts index 5ffda3740af49..9eb7ceda60711 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts @@ -17,14 +17,14 @@ * under the License. */ -import { AggConfig } from '../agg_config'; +import { IAggConfig } from '../agg_config'; import { BaseParamType } from './base'; export interface OptionedValueProp { value: string; text: string; disabled?: boolean; - isCompatible: (agg: AggConfig) => boolean; + isCompatible: (agg: IAggConfig) => boolean; } export interface OptionedParamEditorProps { @@ -40,7 +40,7 @@ export class OptionedParamType extends BaseParamType { super(config); if (!config.write) { - this.write = (aggConfig: AggConfig, output: Record) => { + this.write = (aggConfig: IAggConfig, output: Record) => { output.params[this.name] = aggConfig.params[this.name].value; }; } diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts index fd5ccebde993e..29ec9741611a3 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts @@ -19,13 +19,11 @@ import { BaseParamType } from './base'; import { StringParamType } from './string'; -import { AggConfig } from '../agg_config'; - -jest.mock('ui/new_platform'); +import { IAggConfig } from '../agg_config'; describe('String', function() { let paramName = 'json_test'; - let aggConfig: AggConfig; + let aggConfig: IAggConfig; let output: Record; const initAggParam = (config: Record = {}) => @@ -36,7 +34,7 @@ describe('String', function() { }); beforeEach(() => { - aggConfig = { params: {} } as AggConfig; + aggConfig = { params: {} } as IAggConfig; output = { params: {} }; }); diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts index 58ba99f8a6d63..750606eb8433b 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts @@ -17,7 +17,7 @@ * under the License. */ -import { AggConfig } from '../agg_config'; +import { IAggConfig } from '../agg_config'; import { BaseParamType } from './base'; export class StringParamType extends BaseParamType { @@ -25,7 +25,7 @@ export class StringParamType extends BaseParamType { super(config); if (!config.write) { - this.write = (aggConfig: AggConfig, output: Record) => { + this.write = (aggConfig: IAggConfig, output: Record) => { if (aggConfig.params[this.name] && aggConfig.params[this.name].length) { output.params[this.name] = aggConfig.params[this.name]; } diff --git a/src/legacy/ui/public/vis/__tests__/index.js b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/index.ts similarity index 86% rename from src/legacy/ui/public/vis/__tests__/index.js rename to src/legacy/core_plugins/data/public/search/aggs/test_helpers/index.ts index 46074f2c5197b..131f921586144 100644 --- a/src/legacy/ui/public/vis/__tests__/index.js +++ b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/index.ts @@ -17,5 +17,5 @@ * under the License. */ -import './_agg_config'; -import './_agg_configs'; +export { mockAggTypesRegistry } from './mock_agg_types_registry'; +export { mockDataServices } from './mock_data_services'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts new file mode 100644 index 0000000000000..d6bb793866493 --- /dev/null +++ b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts @@ -0,0 +1,57 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { AggTypesRegistry, AggTypesRegistryStart } from '../agg_types_registry'; +import { aggTypes } from '../agg_types'; +import { BucketAggType } from '../buckets/_bucket_agg_type'; +import { MetricAggType } from '../metrics/metric_agg_type'; + +/** + * Testing utility which creates a new instance of AggTypesRegistry, + * registers the provided agg types, and returns AggTypesRegistry.start() + * + * This is useful if your test depends on a certain agg type to be present + * in the registry. + * + * @param [types] - Optional array of AggTypes to register. + * If no value is provided, all default types will be registered. + * + * @internal + */ +export function mockAggTypesRegistry | MetricAggType>( + types?: T[] +): AggTypesRegistryStart { + const registry = new AggTypesRegistry(); + const registrySetup = registry.setup(); + + if (types) { + types.forEach(type => { + if (type instanceof BucketAggType) { + registrySetup.registerBucket(type); + } else if (type instanceof MetricAggType) { + registrySetup.registerMetric(type); + } + }); + } else { + aggTypes.buckets.forEach(type => registrySetup.registerBucket(type)); + aggTypes.metrics.forEach(type => registrySetup.registerMetric(type)); + } + + return registry.start(); +} diff --git a/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.ts b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.ts new file mode 100644 index 0000000000000..c4e78ab8f6422 --- /dev/null +++ b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.ts @@ -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 { coreMock } from '../../../../../../../../src/core/public/mocks'; +import { dataPluginMock } from '../../../../../../../plugins/data/public/mocks'; +import { searchStartMock } from '../../mocks'; +import { setSearchServiceShim } from '../../../services'; +import { + setFieldFormats, + setIndexPatterns, + setNotifications, + setOverlays, + setQueryService, + setSearchService, + setUiSettings, + // eslint-disable-next-line @kbn/eslint/no-restricted-paths +} from '../../../../../../../plugins/data/public/services'; + +/** + * Testing helper which calls all of the service setters used in the + * data plugin. Services are added using their provided mocks. + * + * @internal + */ +export function mockDataServices() { + const core = coreMock.createStart(); + const data = dataPluginMock.createStartContract(); + const searchShim = searchStartMock(); + + setSearchServiceShim(searchShim); + setFieldFormats(data.fieldFormats); + setIndexPatterns(data.indexPatterns); + setNotifications(core.notifications); + setOverlays(core.overlays); + setQueryService(data.query); + setSearchService(data.search); + setUiSettings(core.uiSettings); +} diff --git a/src/legacy/core_plugins/data/public/search/aggs/types.ts b/src/legacy/core_plugins/data/public/search/aggs/types.ts index 2c918abf99fca..5d02f426b5896 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/types.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/types.ts @@ -18,7 +18,7 @@ */ export { IAggConfig } from './agg_config'; -export { IAggConfigs } from './agg_configs'; +export { CreateAggConfigParams, IAggConfigs } from './agg_configs'; export { IAggType } from './agg_type'; export { AggParam, AggParamOption } from './agg_params'; export { IFieldParamType } from './param_types'; diff --git a/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx b/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx index a3c7f24f3927d..c0662c98755a3 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx +++ b/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx @@ -19,8 +19,6 @@ import { isValidJson } from './utils'; -jest.mock('ui/new_platform'); - const input = { valid: '{ "test": "json input" }', invalid: 'strings are not json', diff --git a/src/legacy/core_plugins/data/public/search/aggs/utils.ts b/src/legacy/core_plugins/data/public/search/aggs/utils.ts index 62f07ce44ab46..67ea373f438fb 100644 --- a/src/legacy/core_plugins/data/public/search/aggs/utils.ts +++ b/src/legacy/core_plugins/data/public/search/aggs/utils.ts @@ -26,7 +26,7 @@ import { isValidEsInterval } from '../../../common'; * @param {string} value a string that should be validated * @returns {boolean} true if value is a valid JSON or if value is an empty string, or a string with whitespaces, otherwise false */ -function isValidJson(value: string): boolean { +export function isValidJson(value: string): boolean { if (!value || value.length === 0) { return true; } @@ -49,7 +49,7 @@ function isValidJson(value: string): boolean { } } -function isValidInterval(value: string, baseInterval?: string) { +export function isValidInterval(value: string, baseInterval?: string) { if (baseInterval) { return _parseWithBase(value, baseInterval); } else { @@ -69,4 +69,37 @@ function _parseWithBase(value: string, baseInterval: string) { } } -export { isValidJson, isValidInterval }; +// An inlined version of angular.toJSON() +// source: https://github.com/angular/angular.js/blob/master/src/Angular.js#L1312 +// @internal +export function toAngularJSON(obj: any, pretty?: any): string { + if (obj === undefined) return ''; + if (typeof pretty === 'number') { + pretty = pretty ? 2 : null; + } + return JSON.stringify(obj, toJsonReplacer, pretty); +} + +function isWindow(obj: any) { + return obj && obj.window === obj; +} + +function isScope(obj: any) { + return obj && obj.$evalAsync && obj.$watch; +} + +function toJsonReplacer(key: any, value: any) { + let val = value; + + if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { + val = undefined; + } else if (isWindow(value)) { + val = '$WINDOW'; + } else if (value && window.document === value) { + val = '$DOCUMENT'; + } else if (isScope(value)) { + val = '$SCOPE'; + } + + return val; +} diff --git a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts index 7a5d927d0f219..24dd1c4944bfb 100644 --- a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts +++ b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts @@ -19,7 +19,7 @@ import { get, has } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { AggConfigs, IAggConfigs } from 'ui/agg_types'; +import { createAggConfigs, IAggConfigs } from 'ui/agg_types'; import { createFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; import { KibanaContext, @@ -258,7 +258,7 @@ export const esaggs = (): ExpressionFunctionDefinition { - const aggConfigs = new AggConfigs(indexPattern); + const { aggs } = getSearchServiceShim(); + const aggConfigs = aggs.createAggConfigs(indexPattern); const aggConfig = aggConfigs.createAggConfig({ enabled: true, type, diff --git a/src/legacy/core_plugins/data/public/search/mocks.ts b/src/legacy/core_plugins/data/public/search/mocks.ts new file mode 100644 index 0000000000000..86b6a928dc5b4 --- /dev/null +++ b/src/legacy/core_plugins/data/public/search/mocks.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. + */ + +import { SearchSetup, SearchStart } from './search_service'; +import { AggTypesRegistrySetup, AggTypesRegistryStart } from './aggs/agg_types_registry'; +import { AggConfigs } from './aggs/agg_configs'; +import { mockAggTypesRegistry } from './aggs/test_helpers'; + +const aggTypeBaseParamMock = () => ({ + name: 'some_param', + type: 'some_param_type', + displayName: 'some_agg_type_param', + required: false, + advanced: false, + default: {}, + write: jest.fn(), + serialize: jest.fn().mockImplementation(() => {}), + deserialize: jest.fn().mockImplementation(() => {}), + options: [], +}); + +const aggTypeConfigMock = () => ({ + name: 'some_name', + title: 'some_title', + params: [aggTypeBaseParamMock()], +}); + +export const aggTypesRegistrySetupMock = (): MockedKeys => ({ + registerBucket: jest.fn(), + registerMetric: jest.fn(), +}); + +export const aggTypesRegistryStartMock = (): MockedKeys => ({ + get: jest.fn().mockImplementation(aggTypeConfigMock), + getBuckets: jest.fn().mockImplementation(() => [aggTypeConfigMock()]), + getMetrics: jest.fn().mockImplementation(() => [aggTypeConfigMock()]), + getAll: jest.fn().mockImplementation(() => ({ + buckets: [aggTypeConfigMock()], + metrics: [aggTypeConfigMock()], + })), +}); + +export const searchSetupMock = (): MockedKeys => ({ + aggs: { + types: aggTypesRegistrySetupMock(), + }, +}); + +export const searchStartMock = (): MockedKeys => ({ + aggs: { + createAggConfigs: jest.fn().mockImplementation((indexPattern, configStates = [], schemas) => { + return new AggConfigs(indexPattern, configStates, { + schemas, + typesRegistry: mockAggTypesRegistry(), + }); + }), + types: mockAggTypesRegistry(), + __LEGACY: { + AggConfig: jest.fn() as any, + AggType: jest.fn(), + aggTypeFieldFilters: jest.fn() as any, + FieldParamType: jest.fn(), + MetricAggType: jest.fn(), + parentPipelineAggHelper: jest.fn() as any, + setBounds: jest.fn(), + siblingPipelineAggHelper: jest.fn() as any, + }, + }, +}); diff --git a/src/legacy/core_plugins/data/public/search/search_service.ts b/src/legacy/core_plugins/data/public/search/search_service.ts index 45f9ff17328ad..6754c0e3551af 100644 --- a/src/legacy/core_plugins/data/public/search/search_service.ts +++ b/src/legacy/core_plugins/data/public/search/search_service.ts @@ -18,11 +18,16 @@ */ import { CoreSetup, CoreStart } from '../../../../../core/public'; +import { IndexPattern } from '../../../../../plugins/data/public'; import { aggTypes, AggType, + AggTypesRegistry, + AggTypesRegistrySetup, + AggTypesRegistryStart, AggConfig, AggConfigs, + CreateAggConfigParams, FieldParamType, MetricAggType, aggTypeFieldFilters, @@ -32,20 +37,28 @@ import { } from './aggs'; interface AggsSetup { - types: typeof aggTypes; + types: AggTypesRegistrySetup; } -interface AggsStart { - types: typeof aggTypes; +interface AggsStartLegacy { AggConfig: typeof AggConfig; - AggConfigs: typeof AggConfigs; AggType: typeof AggType; aggTypeFieldFilters: typeof aggTypeFieldFilters; FieldParamType: typeof FieldParamType; MetricAggType: typeof MetricAggType; parentPipelineAggHelper: typeof parentPipelineAggHelper; - siblingPipelineAggHelper: typeof siblingPipelineAggHelper; setBounds: typeof setBounds; + siblingPipelineAggHelper: typeof siblingPipelineAggHelper; +} + +interface AggsStart { + createAggConfigs: ( + indexPattern: IndexPattern, + configStates?: CreateAggConfigParams[], + schemas?: Record + ) => InstanceType; + types: AggTypesRegistryStart; + __LEGACY: AggsStartLegacy; } export interface SearchSetup { @@ -63,28 +76,41 @@ export interface SearchStart { * it will move into the existing search service in src/plugins/data/public/search */ export class SearchService { + private readonly aggTypesRegistry = new AggTypesRegistry(); + public setup(core: CoreSetup): SearchSetup { + const aggTypesSetup = this.aggTypesRegistry.setup(); + aggTypes.buckets.forEach(b => aggTypesSetup.registerBucket(b)); + aggTypes.metrics.forEach(m => aggTypesSetup.registerMetric(m)); + return { aggs: { - types: aggTypes, // TODO convert to registry - // TODO add other items as needed + types: aggTypesSetup, }, }; } public start(core: CoreStart): SearchStart { + const aggTypesStart = this.aggTypesRegistry.start(); return { aggs: { - types: aggTypes, // TODO convert to registry - AggConfig, // TODO make static - AggConfigs, - AggType, - aggTypeFieldFilters, - FieldParamType, - MetricAggType, - parentPipelineAggHelper, // TODO make static - siblingPipelineAggHelper, // TODO make static - setBounds, // TODO make static + createAggConfigs: (indexPattern, configStates = [], schemas) => { + return new AggConfigs(indexPattern, configStates, { + schemas, + typesRegistry: aggTypesStart, + }); + }, + types: aggTypesStart, + __LEGACY: { + AggConfig, // TODO make static + AggType, + aggTypeFieldFilters, + FieldParamType, + MetricAggType, + parentPipelineAggHelper, // TODO make static + setBounds, // TODO make static + siblingPipelineAggHelper, // TODO make static + }, }, }; } diff --git a/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts b/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts index ef2748102623a..98048cb25db2f 100644 --- a/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts +++ b/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts @@ -20,8 +20,6 @@ import { TabifyBuckets } from './buckets'; import { AggGroupNames } from '../aggs'; -jest.mock('ui/new_platform'); - describe('Buckets wrapper', () => { const check = (aggResp: any, count: number, keys: string[]) => { test('reads the length', () => { diff --git a/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts b/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts index cfd4cd7de640b..6c5dc790ef976 100644 --- a/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts +++ b/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts @@ -18,12 +18,17 @@ */ import { tabifyGetColumns } from './get_columns'; -import { AggConfigs, AggGroupNames, Schemas } from '../aggs'; import { TabbedAggColumn } from './types'; - -jest.mock('ui/new_platform'); +import { AggConfigs, AggGroupNames, Schemas } from '../aggs'; +import { mockAggTypesRegistry, mockDataServices } from '../aggs/test_helpers'; describe('get columns', () => { + beforeEach(() => { + mockDataServices(); + }); + + const typesRegistry = mockAggTypesRegistry(); + const createAggConfigs = (aggs: any[] = []) => { const field = { name: '@timestamp', @@ -38,18 +43,17 @@ describe('get columns', () => { }, } as any; - return new AggConfigs( - indexPattern, - aggs, - new Schemas([ + return new AggConfigs(indexPattern, aggs, { + typesRegistry, + schemas: new Schemas([ { group: AggGroupNames.Metrics, name: 'metric', min: 1, defaults: [{ schema: 'metric', type: 'count' }], }, - ]).all - ); + ]).all, + }); }; test('should inject a count metric if no aggs exist', () => { diff --git a/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts b/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts index f5df0a683ca00..94301eedac74a 100644 --- a/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts +++ b/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts @@ -19,14 +19,19 @@ import { TabbedAggResponseWriter } from './response_writer'; import { AggConfigs, AggGroupNames, Schemas, BUCKET_TYPES } from '../aggs'; +import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers'; import { TabbedResponseWriterOptions } from './types'; -jest.mock('ui/new_platform'); - describe('TabbedAggResponseWriter class', () => { + beforeEach(() => { + mockDataServices(); + }); + let responseWriter: TabbedAggResponseWriter; + const typesRegistry = mockAggTypesRegistry(); + const splitAggConfig = [ { type: BUCKET_TYPES.TERMS, @@ -66,18 +71,17 @@ describe('TabbedAggResponseWriter class', () => { } as any; return new TabbedAggResponseWriter( - new AggConfigs( - indexPattern, - aggs, - new Schemas([ + new AggConfigs(indexPattern, aggs, { + typesRegistry, + schemas: new Schemas([ { group: AggGroupNames.Metrics, name: 'metric', min: 1, defaults: [{ schema: 'metric', type: 'count' }], }, - ]).all - ), + ]).all, + }), { metricsAtAllLevels: false, partialRows: false, diff --git a/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts b/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts index 13fe7719b0a85..db4ad3bdea96b 100644 --- a/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts +++ b/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts @@ -20,11 +20,12 @@ import { IndexPattern } from '../../../../../../plugins/data/public'; import { tabifyAggResponse } from './tabify'; import { IAggConfig, IAggConfigs, AggGroupNames, Schemas, AggConfigs } from '../aggs'; +import { mockAggTypesRegistry } from '../aggs/test_helpers'; import { metricOnly, threeTermBuckets } from 'fixtures/fake_hierarchical_data'; -jest.mock('ui/new_platform'); - describe('tabifyAggResponse Integration', () => { + const typesRegistry = mockAggTypesRegistry(); + const createAggConfigs = (aggs: IAggConfig[] = []) => { const field = { name: '@timestamp', @@ -39,18 +40,17 @@ describe('tabifyAggResponse Integration', () => { }, } as unknown) as IndexPattern; - return new AggConfigs( - indexPattern, - aggs, - new Schemas([ + return new AggConfigs(indexPattern, aggs, { + typesRegistry, + schemas: new Schemas([ { group: AggGroupNames.Metrics, name: 'metric', min: 1, defaults: [{ schema: 'metric', type: 'count' }], }, - ]).all - ); + ]).all, + }); }; const mockAggConfig = (agg: any): IAggConfig => (agg as unknown) as IAggConfig; diff --git a/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.mocks.ts b/src/legacy/core_plugins/data/public/services.ts similarity index 76% rename from src/legacy/core_plugins/data/public/actions/filters/brush_event.test.mocks.ts rename to src/legacy/core_plugins/data/public/services.ts index 2cecfd0fe8b76..7ecd041c70e22 100644 --- a/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.mocks.ts +++ b/src/legacy/core_plugins/data/public/services.ts @@ -17,12 +17,9 @@ * under the License. */ -import { chromeServiceMock } from '../../../../../../core/public/mocks'; +import { createGetterSetter } from '../../../../plugins/kibana_utils/public'; +import { SearchStart } from './search/search_service'; -jest.doMock('ui/new_platform', () => ({ - npStart: { - core: { - chrome: chromeServiceMock.createStartContract(), - }, - }, -})); +export const [getSearchServiceShim, setSearchServiceShim] = createGetterSetter( + 'searchShim' +); diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts b/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts index 6591aa5fb53d5..6ae4e415f8caa 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts +++ b/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts @@ -20,7 +20,8 @@ import { cloneDeep } from 'lodash'; import { Vis, VisState } from 'src/legacy/core_plugins/visualizations/public'; -import { AggConfigs, IAggConfig, AggGroupNames } from '../../../legacy_imports'; + +import { createAggConfigs, IAggConfig, AggGroupNames } from '../../../legacy_imports'; import { EditorStateActionTypes } from './constants'; import { getEnabledMetricAggsCount } from '../../agg_group_helper'; import { EditorAction } from './actions'; @@ -32,7 +33,8 @@ function initEditorState(vis: Vis) { function editorStateReducer(state: VisState, action: EditorAction): VisState { switch (action.type) { case EditorStateActionTypes.ADD_NEW_AGG: { - const aggConfig = state.aggs.createAggConfig(action.payload as IAggConfig, { + const payloadAggConfig = action.payload as IAggConfig; + const aggConfig = state.aggs.createAggConfig(payloadAggConfig, { addToAggConfigs: false, }); aggConfig.brandNew = true; @@ -40,7 +42,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } @@ -63,7 +65,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } @@ -88,7 +90,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } @@ -129,7 +131,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } @@ -141,7 +143,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } @@ -163,7 +165,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState { return { ...state, - aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), }; } diff --git a/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts b/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts index 832f73752a99b..8aed263c4e4d1 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts @@ -22,12 +22,12 @@ export { AggType, IAggType, IAggConfig, - AggConfigs, IAggConfigs, AggParam, AggGroupNames, aggGroupNamesMap, aggTypes, + createAggConfigs, FieldParamType, IFieldParamType, BUCKET_TYPES, diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts index 0e1e48d00a1b2..736152c7014dc 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts @@ -34,7 +34,7 @@ import { stubFields } from '../../../../plugins/data/public/stubs'; import { tableVisResponseHandler } from './table_vis_response_handler'; import { coreMock } from '../../../../core/public/mocks'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { AggConfigs } from 'ui/agg_types'; +import { createAggConfigs } from 'ui/agg_types'; import { tabifyAggResponse, IAggConfig } from './legacy_imports'; jest.mock('ui/new_platform'); @@ -113,7 +113,7 @@ describe('Table Vis - Controller', () => { return ({ type: tableVisTypeDefinition, params: Object.assign({}, tableVisTypeDefinition.visConfig.defaults, params), - aggs: new AggConfigs( + aggs: createAggConfigs( stubIndexPattern, [ { type: 'count', schema: 'metric' }, diff --git a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts index fb7a157b53a9a..0a3b1938436c0 100644 --- a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts +++ b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts @@ -18,10 +18,10 @@ */ export { - AggConfigs, IAggConfig, IAggConfigs, isDateHistogramBucketAggConfig, setBounds, } from '../../data/public'; +export { createAggConfigs } from 'ui/agg_types'; export { createSavedSearchesLoader } from '../../../../plugins/discover/public'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js index 2f36322c67256..15a826cc6ddbe 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js @@ -30,7 +30,7 @@ import { EventEmitter } from 'events'; import _ from 'lodash'; import { PersistedState } from '../../../../../../../src/plugins/visualizations/public'; -import { AggConfigs } from '../../legacy_imports'; +import { createAggConfigs } from '../../legacy_imports'; import { updateVisualizationConfig } from './legacy/vis_update'; import { getTypes } from './services'; @@ -83,7 +83,7 @@ class VisImpl extends EventEmitter { updateVisualizationConfig(state.params, this.params); if (state.aggs || !this.aggs) { - this.aggs = new AggConfigs( + this.aggs = createAggConfigs( this.indexPattern, state.aggs ? state.aggs.aggs || state.aggs : [], this.type.schemas.all @@ -125,7 +125,7 @@ class VisImpl extends EventEmitter { copyCurrentState(includeDisabled = false) { const state = this.getCurrentState(includeDisabled); - state.aggs = new AggConfigs( + state.aggs = createAggConfigs( this.indexPattern, state.aggs.aggs || state.aggs, this.type.schemas.all diff --git a/src/legacy/ui/public/agg_types/index.ts b/src/legacy/ui/public/agg_types/index.ts index ac5d0bed7ef15..ffc300251c4bb 100644 --- a/src/legacy/ui/public/agg_types/index.ts +++ b/src/legacy/ui/public/agg_types/index.ts @@ -27,18 +27,19 @@ import { start as dataStart } from '../../../core_plugins/data/public/legacy'; // runtime contracts +const { types } = dataStart.search.aggs; +export const aggTypes = types.getAll(); +export const { createAggConfigs } = dataStart.search.aggs; export const { - types: aggTypes, AggConfig, - AggConfigs, AggType, aggTypeFieldFilters, FieldParamType, MetricAggType, parentPipelineAggHelper, - siblingPipelineAggHelper, setBounds, -} = dataStart.search.aggs; + siblingPipelineAggHelper, +} = dataStart.search.aggs.__LEGACY; // types export { diff --git a/src/legacy/ui/public/vis/__tests__/_agg_config.js b/src/legacy/ui/public/vis/__tests__/_agg_config.js deleted file mode 100644 index 9e53044f681ba..0000000000000 --- a/src/legacy/ui/public/vis/__tests__/_agg_config.js +++ /dev/null @@ -1,485 +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 sinon from 'sinon'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { AggType, AggConfig } from '../../agg_types'; -import { start as visualizationsStart } from '../../../../core_plugins/visualizations/public/np_ready/public/legacy'; - -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; - -describe('AggConfig', function() { - let indexPattern; - - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private) { - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - }) - ); - - describe('#toDsl', function() { - it('calls #write()', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }); - - const aggConfig = vis.aggs.byName('date_histogram')[0]; - const stub = sinon.stub(aggConfig, 'write').returns({ params: {} }); - - aggConfig.toDsl(); - expect(stub.callCount).to.be(1); - }); - - it('uses the type name as the agg name', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }); - - const aggConfig = vis.aggs.byName('date_histogram')[0]; - sinon.stub(aggConfig, 'write').returns({ params: {} }); - - const dsl = aggConfig.toDsl(); - expect(dsl).to.have.property('date_histogram'); - }); - - it('uses the params from #write() output as the agg params', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }); - - const aggConfig = vis.aggs.byName('date_histogram')[0]; - const football = {}; - - sinon.stub(aggConfig, 'write').returns({ params: football }); - - const dsl = aggConfig.toDsl(); - expect(dsl.date_histogram).to.be(football); - }); - - it('includes subAggs from #write() output', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { - type: 'avg', - schema: 'metric', - }, - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }); - - const histoConfig = vis.aggs.byName('date_histogram')[0]; - const avgConfig = vis.aggs.byName('avg')[0]; - const football = {}; - - sinon.stub(histoConfig, 'write').returns({ params: {}, subAggs: [avgConfig] }); - sinon.stub(avgConfig, 'write').returns({ params: football }); - - const dsl = histoConfig.toDsl(); - - // didn't use .eql() because of variable key names, and final check is strict - expect(dsl).to.have.property('aggs'); - expect(dsl.aggs).to.have.property(avgConfig.id); - expect(dsl.aggs[avgConfig.id]).to.have.property('avg'); - expect(dsl.aggs[avgConfig.id].avg).to.be(football); - }); - }); - - describe('::ensureIds', function() { - it('accepts an array of objects and assigns ids to them', function() { - const objs = [{}, {}, {}, {}]; - AggConfig.ensureIds(objs); - expect(objs[0]).to.have.property('id', '1'); - expect(objs[1]).to.have.property('id', '2'); - expect(objs[2]).to.have.property('id', '3'); - expect(objs[3]).to.have.property('id', '4'); - }); - - it('assigns ids relative to the other only item in the list', function() { - const objs = [{ id: '100' }, {}]; - AggConfig.ensureIds(objs); - expect(objs[0]).to.have.property('id', '100'); - expect(objs[1]).to.have.property('id', '101'); - }); - - it('assigns ids relative to the other items in the list', function() { - const objs = [{ id: '100' }, { id: '200' }, { id: '500' }, { id: '350' }, {}]; - AggConfig.ensureIds(objs); - expect(objs[0]).to.have.property('id', '100'); - expect(objs[1]).to.have.property('id', '200'); - expect(objs[2]).to.have.property('id', '500'); - expect(objs[3]).to.have.property('id', '350'); - expect(objs[4]).to.have.property('id', '501'); - }); - - it('uses ::nextId to get the starting value', function() { - sinon.stub(AggConfig, 'nextId').returns(534); - const objs = AggConfig.ensureIds([{}]); - AggConfig.nextId.restore(); - expect(objs[0]).to.have.property('id', '534'); - }); - - it('only calls ::nextId once', function() { - const start = 420; - sinon.stub(AggConfig, 'nextId').returns(start); - const objs = AggConfig.ensureIds([{}, {}, {}, {}, {}, {}, {}]); - - expect(AggConfig.nextId).to.have.property('callCount', 1); - - AggConfig.nextId.restore(); - objs.forEach(function(obj, i) { - expect(obj).to.have.property('id', String(start + i)); - }); - }); - }); - - describe('::nextId', function() { - it('accepts a list of objects and picks the next id', function() { - const next = AggConfig.nextId([{ id: 100 }, { id: 500 }]); - expect(next).to.be(501); - }); - - it('handles an empty list', function() { - const next = AggConfig.nextId([]); - expect(next).to.be(1); - }); - - it('fails when the list is not defined', function() { - expect(function() { - AggConfig.nextId(); - }).to.throwError(); - }); - }); - - describe('#toJsonDataEquals', function() { - const testsIdentical = [ - { - type: 'metric', - aggs: [ - { - type: 'count', - schema: 'metric', - params: { field: '@timestamp' }, - }, - ], - }, - { - type: 'histogram', - aggs: [ - { - type: 'avg', - schema: 'metric', - }, - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }, - ]; - - testsIdentical.forEach((visConfig, index) => { - it(`identical aggregations (${index})`, function() { - const vis1 = new visualizationsStart.Vis(indexPattern, visConfig); - const vis2 = new visualizationsStart.Vis(indexPattern, visConfig); - expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(true); - }); - }); - - const testsIdenticalDifferentOrder = [ - { - config1: { - type: 'histogram', - aggs: [ - { - type: 'avg', - schema: 'metric', - }, - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }, - config2: { - type: 'histogram', - aggs: [ - { - schema: 'metric', - type: 'avg', - }, - { - schema: 'segment', - type: 'date_histogram', - }, - ], - }, - }, - ]; - - testsIdenticalDifferentOrder.forEach((test, index) => { - it(`identical aggregations (${index}) - init json is in different order`, function() { - const vis1 = new visualizationsStart.Vis(indexPattern, test.config1); - const vis2 = new visualizationsStart.Vis(indexPattern, test.config2); - expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(true); - }); - }); - - const testsDifferent = [ - { - config1: { - type: 'histogram', - aggs: [ - { - type: 'avg', - schema: 'metric', - }, - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }, - config2: { - type: 'histogram', - aggs: [ - { - type: 'max', - schema: 'metric', - }, - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }, - }, - { - config1: { - type: 'metric', - aggs: [ - { - type: 'count', - schema: 'metric', - params: { field: '@timestamp' }, - }, - ], - }, - config2: { - type: 'metric', - aggs: [ - { - type: 'count', - schema: 'metric', - params: { field: '@timestamp' }, - }, - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }, - }, - ]; - - testsDifferent.forEach((test, index) => { - it(`different aggregations (${index})`, function() { - const vis1 = new visualizationsStart.Vis(indexPattern, test.config1); - const vis2 = new visualizationsStart.Vis(indexPattern, test.config2); - expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(false); - }); - }); - }); - - describe('#toJSON', function() { - it('includes the aggs id, params, type and schema', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }); - - const aggConfig = vis.aggs.byName('date_histogram')[0]; - expect(aggConfig.id).to.be('1'); - expect(aggConfig.params).to.be.an('object'); - expect(aggConfig.type) - .to.be.an(AggType) - .and.have.property('name', 'date_histogram'); - expect(aggConfig.schema) - .to.be.an('object') - .and.have.property('name', 'segment'); - - const state = aggConfig.toJSON(); - expect(state).to.have.property('id', '1'); - expect(state.params).to.be.an('object'); - expect(state).to.have.property('type', 'date_histogram'); - expect(state).to.have.property('schema', 'segment'); - }); - - it('test serialization order is identical (for visual consistency)', function() { - const vis1 = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { - type: 'date_histogram', - schema: 'segment', - }, - ], - }); - const vis2 = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { - schema: 'segment', - type: 'date_histogram', - }, - ], - }); - - //this relies on the assumption that js-engines consistently loop over properties in insertion order. - //most likely the case, but strictly speaking not guaranteed by the JS and JSON specifications. - expect(JSON.stringify(vis1.aggs.aggs) === JSON.stringify(vis2.aggs.aggs)).to.be(true); - }); - }); - - describe('#makeLabel', function() { - it('uses the custom label if it is defined', function() { - const vis = new visualizationsStart.Vis(indexPattern, {}); - const aggConfig = vis.aggs.aggs[0]; - aggConfig.params.customLabel = 'Custom label'; - const label = aggConfig.makeLabel(); - expect(label).to.be(aggConfig.params.customLabel); - }); - it('default label should be "Count"', function() { - const vis = new visualizationsStart.Vis(indexPattern, {}); - const aggConfig = vis.aggs.aggs[0]; - const label = aggConfig.makeLabel(); - expect(label).to.be('Count'); - }); - it('default label should be "Percentage of Count" when percentageMode is set to true', function() { - const vis = new visualizationsStart.Vis(indexPattern, {}); - const aggConfig = vis.aggs.aggs[0]; - const label = aggConfig.makeLabel(true); - expect(label).to.be('Percentage of Count'); - }); - it('empty label if the visualizationsStart.Vis type is not defined', function() { - const vis = new visualizationsStart.Vis(indexPattern, {}); - const aggConfig = vis.aggs.aggs[0]; - aggConfig.type = undefined; - const label = aggConfig.makeLabel(); - expect(label).to.be(''); - }); - }); - - describe('#fieldFormatter - custom getFormat handler', function() { - it('returns formatter from getFormat handler', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'metric', - aggs: [ - { - type: 'count', - schema: 'metric', - params: { field: '@timestamp' }, - }, - ], - }); - - const fieldFormatter = vis.aggs.aggs[0].fieldFormatter(); - - expect(fieldFormatter).to.be.defined; - expect(fieldFormatter('text')).to.be('text'); - }); - }); - - describe('#fieldFormatter - no custom getFormat handler', function() { - const visStateAggWithoutCustomGetFormat = { - aggs: [ - { - type: 'histogram', - schema: 'bucket', - params: { field: 'bytes' }, - }, - ], - }; - let vis; - - beforeEach(function() { - vis = new visualizationsStart.Vis(indexPattern, visStateAggWithoutCustomGetFormat); - }); - - it("returns the field's formatter", function() { - expect(vis.aggs.aggs[0].fieldFormatter().toString()).to.be( - vis.aggs.aggs[0] - .getField() - .format.getConverterFor() - .toString() - ); - }); - - it('returns the string format if the field does not have a format', function() { - const agg = vis.aggs.aggs[0]; - agg.params.field = { type: 'number', format: null }; - const fieldFormatter = agg.fieldFormatter(); - expect(fieldFormatter).to.be.defined; - expect(fieldFormatter('text')).to.be('text'); - }); - - it('returns the string format if their is no field', function() { - const agg = vis.aggs.aggs[0]; - delete agg.params.field; - const fieldFormatter = agg.fieldFormatter(); - expect(fieldFormatter).to.be.defined; - expect(fieldFormatter('text')).to.be('text'); - }); - - it('returns the html converter if "html" is passed in', function() { - const field = indexPattern.fields.getByName('bytes'); - expect(vis.aggs.aggs[0].fieldFormatter('html').toString()).to.be( - field.format.getConverterFor('html').toString() - ); - }); - }); -}); diff --git a/src/legacy/ui/public/vis/__tests__/_agg_configs.js b/src/legacy/ui/public/vis/__tests__/_agg_configs.js deleted file mode 100644 index 172523ec50c8b..0000000000000 --- a/src/legacy/ui/public/vis/__tests__/_agg_configs.js +++ /dev/null @@ -1,420 +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 sinon from 'sinon'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { AggConfig, AggConfigs, AggGroupNames, Schemas } from '../../agg_types'; -import { start as visualizationsStart } from '../../../../core_plugins/visualizations/public/np_ready/public/legacy'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; - -describe('AggConfigs', function() { - let indexPattern; - - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private) { - // load main deps - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - }) - ); - - describe('constructor', function() { - it('handles passing just a vis', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [], - }); - - const ac = new AggConfigs(vis.indexPattern, [], vis.type.schemas.all); - expect(ac.aggs).to.have.length(1); - }); - - it('converts configStates into AggConfig objects if they are not already', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [], - }); - - const ac = new AggConfigs( - vis.indexPattern, - [ - { - type: 'date_histogram', - schema: 'segment', - }, - new AggConfig(vis.aggs, { - type: 'terms', - schema: 'split', - }), - ], - vis.type.schemas.all - ); - - expect(ac.aggs).to.have.length(3); - }); - - it('attempts to ensure that all states have an id', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [], - }); - - const states = [ - { - type: 'date_histogram', - schema: 'segment', - }, - { - type: 'terms', - schema: 'split', - }, - ]; - - const spy = sinon.spy(AggConfig, 'ensureIds'); - new AggConfigs(vis.indexPattern, states, vis.type.schemas.all); - expect(spy.callCount).to.be(1); - expect(spy.firstCall.args[0]).to.be(states); - AggConfig.ensureIds.restore(); - }); - - describe('defaults', function() { - let vis; - beforeEach(function() { - vis = { - indexPattern: indexPattern, - type: { - schemas: new Schemas([ - { - group: AggGroupNames.Metrics, - name: 'metric', - title: 'Simple', - min: 1, - max: 2, - defaults: [ - { schema: 'metric', type: 'count' }, - { schema: 'metric', type: 'avg' }, - { schema: 'metric', type: 'sum' }, - ], - }, - { - group: AggGroupNames.Buckets, - name: 'segment', - title: 'Example', - min: 0, - max: 1, - defaults: [ - { schema: 'segment', type: 'terms' }, - { schema: 'segment', type: 'filters' }, - ], - }, - ]), - }, - }; - }); - - it('should only set the number of defaults defined by the max', function() { - const ac = new AggConfigs(vis.indexPattern, [], vis.type.schemas.all); - expect(ac.bySchemaName('metric')).to.have.length(2); - }); - - it('should set the defaults defined in the schema when none exist', function() { - const ac = new AggConfigs(vis.indexPattern, [], vis.type.schemas.all); - expect(ac.aggs).to.have.length(3); - }); - - it('should NOT set the defaults defined in the schema when some exist', function() { - const ac = new AggConfigs( - vis.indexPattern, - [{ schema: 'segment', type: 'date_histogram' }], - vis.type.schemas.all - ); - expect(ac.aggs).to.have.length(3); - expect(ac.bySchemaName('segment')[0].type.name).to.equal('date_histogram'); - }); - }); - }); - - describe('#getRequestAggs', function() { - it('performs a stable sort, but moves metrics to the bottom', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { type: 'avg', schema: 'metric' }, - { type: 'terms', schema: 'split' }, - { type: 'histogram', schema: 'split' }, - { type: 'sum', schema: 'metric' }, - { type: 'date_histogram', schema: 'segment' }, - { type: 'filters', schema: 'split' }, - { type: 'percentiles', schema: 'metric' }, - ], - }); - - const sorted = vis.aggs.getRequestAggs(); - const aggs = _.indexBy(vis.aggs.aggs, function(agg) { - return agg.type.name; - }); - - expect(sorted.shift()).to.be(aggs.terms); - expect(sorted.shift()).to.be(aggs.histogram); - expect(sorted.shift()).to.be(aggs.date_histogram); - expect(sorted.shift()).to.be(aggs.filters); - expect(sorted.shift()).to.be(aggs.avg); - expect(sorted.shift()).to.be(aggs.sum); - expect(sorted.shift()).to.be(aggs.percentiles); - expect(sorted).to.have.length(0); - }); - }); - - describe('#getResponseAggs', function() { - it('returns all request aggs for basic aggs', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { type: 'terms', schema: 'split' }, - { type: 'date_histogram', schema: 'segment' }, - { type: 'count', schema: 'metric' }, - ], - }); - - const sorted = vis.aggs.getResponseAggs(); - const aggs = _.indexBy(vis.aggs.aggs, function(agg) { - return agg.type.name; - }); - - expect(sorted.shift()).to.be(aggs.terms); - expect(sorted.shift()).to.be(aggs.date_histogram); - expect(sorted.shift()).to.be(aggs.count); - expect(sorted).to.have.length(0); - }); - - it('expands aggs that have multiple responses', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { type: 'terms', schema: 'split' }, - { type: 'date_histogram', schema: 'segment' }, - { type: 'percentiles', schema: 'metric', params: { percents: [1, 2, 3] } }, - ], - }); - - const sorted = vis.aggs.getResponseAggs(); - const aggs = _.indexBy(vis.aggs.aggs, function(agg) { - return agg.type.name; - }); - - expect(sorted.shift()).to.be(aggs.terms); - expect(sorted.shift()).to.be(aggs.date_histogram); - expect(sorted.shift().id).to.be(aggs.percentiles.id + '.' + 1); - expect(sorted.shift().id).to.be(aggs.percentiles.id + '.' + 2); - expect(sorted.shift().id).to.be(aggs.percentiles.id + '.' + 3); - expect(sorted).to.have.length(0); - }); - }); - - describe('#toDsl', function() { - it('uses the sorted aggs', function() { - const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram' }); - sinon.spy(vis.aggs, 'getRequestAggs'); - vis.aggs.toDsl(); - expect(vis.aggs.getRequestAggs).to.have.property('callCount', 1); - }); - - it('calls aggConfig#toDsl() on each aggConfig and compiles the nested output', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { type: 'date_histogram', schema: 'segment' }, - { type: 'filters', schema: 'split' }, - ], - }); - - const aggInfos = vis.aggs.aggs.map(function(aggConfig) { - const football = {}; - - sinon.stub(aggConfig, 'toDsl').returns(football); - - return { - id: aggConfig.id, - football: football, - }; - }); - - (function recurse(lvl) { - const info = aggInfos.shift(); - - expect(lvl).to.have.property(info.id); - expect(lvl[info.id]).to.be(info.football); - - if (lvl[info.id].aggs) { - return recurse(lvl[info.id].aggs); - } - })(vis.aggs.toDsl()); - - expect(aggInfos).to.have.length(1); - }); - - it("skips aggs that don't have a dsl representation", function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { - type: 'date_histogram', - schema: 'segment', - params: { field: '@timestamp', interval: '10s' }, - }, - { type: 'count', schema: 'metric' }, - ], - }); - - const dsl = vis.aggs.toDsl(); - const histo = vis.aggs.byName('date_histogram')[0]; - const count = vis.aggs.byName('count')[0]; - - expect(dsl).to.have.property(histo.id); - expect(dsl[histo.id]).to.be.an('object'); - expect(dsl[histo.id]).to.not.have.property('aggs'); - expect(dsl).to.not.have.property(count.id); - }); - - it('writes multiple metric aggregations at the same level', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { - type: 'date_histogram', - schema: 'segment', - params: { field: '@timestamp', interval: '10s' }, - }, - { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'sum', schema: 'metric', params: { field: 'bytes' } }, - { type: 'min', schema: 'metric', params: { field: 'bytes' } }, - { type: 'max', schema: 'metric', params: { field: 'bytes' } }, - ], - }); - - const dsl = vis.aggs.toDsl(); - - const histo = vis.aggs.byName('date_histogram')[0]; - const metrics = vis.aggs.bySchemaGroup('metrics'); - - expect(dsl).to.have.property(histo.id); - expect(dsl[histo.id]).to.be.an('object'); - expect(dsl[histo.id]).to.have.property('aggs'); - - metrics.forEach(function(metric) { - expect(dsl[histo.id].aggs).to.have.property(metric.id); - expect(dsl[histo.id].aggs[metric.id]).to.not.have.property('aggs'); - }); - }); - - it('writes multiple metric aggregations at every level if the vis is hierarchical', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { type: 'terms', schema: 'segment', params: { field: 'ip', orderBy: 1 } }, - { type: 'terms', schema: 'segment', params: { field: 'extension', orderBy: 1 } }, - { id: 1, type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'sum', schema: 'metric', params: { field: 'bytes' } }, - { type: 'min', schema: 'metric', params: { field: 'bytes' } }, - { type: 'max', schema: 'metric', params: { field: 'bytes' } }, - ], - }); - vis.isHierarchical = _.constant(true); - - const topLevelDsl = vis.aggs.toDsl(vis.isHierarchical()); - const buckets = vis.aggs.bySchemaGroup('buckets'); - const metrics = vis.aggs.bySchemaGroup('metrics'); - - (function checkLevel(dsl) { - const bucket = buckets.shift(); - expect(dsl).to.have.property(bucket.id); - - expect(dsl[bucket.id]).to.be.an('object'); - expect(dsl[bucket.id]).to.have.property('aggs'); - - metrics.forEach(function(metric) { - expect(dsl[bucket.id].aggs).to.have.property(metric.id); - expect(dsl[bucket.id].aggs[metric.id]).to.not.have.property('aggs'); - }); - - if (buckets.length) { - checkLevel(dsl[bucket.id].aggs); - } - })(topLevelDsl); - }); - - it('adds the parent aggs of nested metrics at every level if the vis is hierarchical', function() { - const vis = new visualizationsStart.Vis(indexPattern, { - type: 'histogram', - aggs: [ - { - id: '1', - type: 'avg_bucket', - schema: 'metric', - params: { - customBucket: { - id: '1-bucket', - type: 'date_histogram', - schema: 'bucketAgg', - params: { - field: '@timestamp', - interval: '10s', - }, - }, - customMetric: { - id: '1-metric', - type: 'count', - schema: 'metricAgg', - params: {}, - }, - }, - }, - { - id: '2', - type: 'terms', - schema: 'bucket', - params: { - field: 'geo.src', - }, - }, - { - id: '3', - type: 'terms', - schema: 'bucket', - params: { - field: 'machine.os', - }, - }, - ], - }); - vis.isHierarchical = _.constant(true); - - const topLevelDsl = vis.aggs.toDsl(vis.isHierarchical())['2']; - expect(topLevelDsl.aggs).to.have.keys(['1', '1-bucket']); - expect(topLevelDsl.aggs['1'].avg_bucket).to.have.property('buckets_path', '1-bucket>_count'); - expect(topLevelDsl.aggs['3'].aggs).to.have.keys(['1', '1-bucket']); - expect(topLevelDsl.aggs['3'].aggs['1'].avg_bucket).to.have.property( - 'buckets_path', - '1-bucket>_count' - ); - }); - }); -}); diff --git a/src/plugins/data/common/field_formats/mocks.ts b/src/plugins/data/common/field_formats/mocks.ts new file mode 100644 index 0000000000000..bc38374e147cf --- /dev/null +++ b/src/plugins/data/common/field_formats/mocks.ts @@ -0,0 +1,49 @@ +/* + * 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, IFieldFormatsRegistry } from '.'; + +const fieldFormatMock = ({ + convert: jest.fn(), + getConverterFor: jest.fn(), + getParamDefaults: jest.fn(), + param: jest.fn(), + params: jest.fn(), + toJSON: jest.fn(), + type: jest.fn(), + setupContentType: jest.fn(), +} as unknown) as FieldFormat; + +export const fieldFormatsMock: IFieldFormatsRegistry = { + getByFieldType: jest.fn(), + getDefaultConfig: jest.fn(), + getDefaultInstance: jest.fn().mockImplementation(() => fieldFormatMock) as any, + getDefaultInstanceCacheResolver: jest.fn(), + getDefaultInstancePlain: jest.fn(), + getDefaultType: jest.fn(), + getDefaultTypeName: jest.fn(), + getInstance: jest.fn() as any, + getType: jest.fn(), + getTypeNameByEsTypes: jest.fn(), + init: jest.fn(), + register: jest.fn(), + parseDefaultTypeMap: jest.fn(), + deserialize: jest.fn(), + getTypeWithoutMetaParams: jest.fn(), +}; diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 6a0a33096eaac..27de3b5a29bfd 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -16,13 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -import { - Plugin, - DataPublicPluginSetup, - DataPublicPluginStart, - IndexPatternsContract, - IFieldFormatsRegistry, -} from '.'; + +import { Plugin, DataPublicPluginSetup, DataPublicPluginStart, IndexPatternsContract } from '.'; +import { fieldFormatsMock } from '../common/field_formats/mocks'; import { searchSetupMock } from './search/mocks'; import { queryServiceMock } from './query/mocks'; @@ -35,24 +31,6 @@ const autocompleteMock: any = { hasQuerySuggestions: jest.fn(), }; -const fieldFormatsMock: IFieldFormatsRegistry = { - getByFieldType: jest.fn(), - getDefaultConfig: jest.fn(), - getDefaultInstance: jest.fn() as any, - getDefaultInstanceCacheResolver: jest.fn(), - getDefaultInstancePlain: jest.fn(), - getDefaultType: jest.fn(), - getDefaultTypeName: jest.fn(), - getInstance: jest.fn() as any, - getType: jest.fn(), - getTypeNameByEsTypes: jest.fn(), - init: jest.fn(), - register: jest.fn(), - parseDefaultTypeMap: jest.fn(), - deserialize: jest.fn(), - getTypeWithoutMetaParams: jest.fn(), -}; - const createSetupContract = (): Setup => { const querySetupMock = queryServiceMock.createSetupContract(); const setupContract = { diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index fd72158012de6..700bea741bd6a 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -17,25 +17,6 @@ * under the License. */ -/* - * 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 { ISearchSource } from './search_source'; export const searchSourceMock: MockedKeys = { diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx index ef4b5f6d7b834..2e1645c816140 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx @@ -17,10 +17,6 @@ jest.mock('ui/new_platform'); // mock away actual dependencies to prevent all of it being loaded jest.mock('../../../../../../src/legacy/core_plugins/interpreter/public/registries', () => {}); -jest.mock('../../../../../../src/legacy/core_plugins/data/public/legacy', () => ({ - start: {}, - setup: {}, -})); jest.mock('./embeddable/embeddable_factory', () => ({ EmbeddableFactory: class Mock {}, })); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap index c883983f8cf01..da04b970a494b 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap @@ -2803,7 +2803,7 @@ tr:hover .c3:focus::before {
- - - -
- - -
- - - - + - - -
- - - - - - + - + title="Cu0n232QMyvNtzb75j" + > - - Cu0n232QMyvNtzb75j - - + + - - - - - + viewBox="0 0 16 16" + width={16} + xmlns="http://www.w3.org/2000/svg" + /> + + - - - - - - - -
-
-
-
-
-
-
- -
-
-
-
-
-
-
+ + + + + + + + +
+ + + + + + + +
+ + +
+ +
@@ -3105,7 +3087,7 @@ tr:hover .c3:focus::before {
- - - -
- - -
- - - - + - - -
- - - - - - + - + title="files" + > - - files - - + + - - - - - + viewBox="0 0 16 16" + width={16} + xmlns="http://www.w3.org/2000/svg" + /> + + - - - - - - - -
-
-
-
-
-
-
- -
-
-
-
-
-
-
+ + + + + + + + +
+ + + + + + + +
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�XQjYjxgHSfU&kein@skwcwquR%t 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