diff --git a/.cypress/support/commands.ts b/.cypress/support/commands.ts index e41b7105..714f020c 100644 --- a/.cypress/support/commands.ts +++ b/.cypress/support/commands.ts @@ -50,11 +50,9 @@ Cypress.Commands.add('mockGetDetectorOnAction', function ( funcMockedOn: VoidFunction ) { cy.server(); - cy.route( - 'GET', - buildAdApiUrl(DETECTORS + '*'), - `fixture:${fixtureFileName}` - ).as('getDetectors'); + cy.route2(buildAdApiUrl(DETECTORS + '*'), `fixture:${fixtureFileName}`).as( + 'getDetectors' + ); funcMockedOn(); @@ -66,11 +64,9 @@ Cypress.Commands.add('mockCreateDetectorOnAction', function ( funcMockedOn: VoidFunction ) { cy.server(); - cy.route( - 'POST', - buildAdApiUrl(DETECTORS + '*'), - `fixture:${fixtureFileName}` - ).as('createDetector'); + cy.route2(buildAdApiUrl(DETECTORS + '*'), `fixture:${fixtureFileName}`).as( + 'createDetector' + ); funcMockedOn(); @@ -82,11 +78,9 @@ Cypress.Commands.add('mockSearchIndexOnAction', function ( funcMockedOn: VoidFunction ) { cy.server(); - cy.route( - 'GET', - buildAdApiUrl(INDICES_PATH + '*'), - `fixture:${fixtureFileName}` - ).as('getIndices'); + cy.route2(buildAdApiUrl(INDICES_PATH + '*'), `fixture:${fixtureFileName}`).as( + 'getIndices' + ); funcMockedOn(); @@ -98,7 +92,7 @@ Cypress.Commands.add('mockSearchOnAction', function ( funcMockedOn: VoidFunction ) { cy.server(); - cy.route('POST', buildAdApiUrl(SEARCH_PATH), `fixture:${fixtureFileName}`).as( + cy.route2(buildAdApiUrl(SEARCH_PATH), `fixture:${fixtureFileName}`).as( 'searchES' ); @@ -112,8 +106,7 @@ Cypress.Commands.add('mockGetIndexMappingsOnAction', function ( funcMockedOn: VoidFunction ) { cy.server(); - cy.route( - 'GET', + cy.route2( buildAdApiUrl(MAPPINGS_PATH + '*'), `fixture:${fixtureFileName}` ).as('getMappings'); @@ -129,8 +122,7 @@ Cypress.Commands.add('mockStartDetectorOnAction', function ( funcMockedOn: VoidFunction ) { cy.server(); - cy.route( - 'POST', + cy.route2( buildAdApiUrl([DETECTORS, detectorId, START_PATH].join(SLASH)), `fixture:${fixtureFileName}` ).as('startDetector'); @@ -146,8 +138,7 @@ Cypress.Commands.add('mockStopDetectorOnAction', function ( funcMockedOn: VoidFunction ) { cy.server(); - cy.route( - 'POST', + cy.route2( buildAdApiUrl([DETECTORS, detectorId, STOP_PATH].join(SLASH)), `fixture:${fixtureFileName}` ).as('stopDetector'); @@ -163,8 +154,7 @@ Cypress.Commands.add('mockDeleteDetectorOnAction', function ( funcMockedOn: VoidFunction ) { cy.server(); - cy.route( - 'DELETE', + cy.route2( buildAdApiUrl([DETECTORS, detectorId].join(SLASH)), `fixture:${fixtureFileName}` ).as('deleteDetector'); diff --git a/.cypress/utils/helpers.ts b/.cypress/utils/helpers.ts index b4f82a14..12439290 100644 --- a/.cypress/utils/helpers.ts +++ b/.cypress/utils/helpers.ts @@ -26,7 +26,9 @@ export const buildAdApiUrl = (apiPath: string): string => { }; export const buildServerApiUrl = (appPath: string, apiPath: string): string => { - return [API_URL_PREFIX, appPath, apiPath].join(SLASH); + return [Cypress.config('baseUrl'), API_URL_PREFIX, appPath, apiPath].join( + SLASH + ); }; export const buildAdAppUrl = (pagePath: string): string => { diff --git a/.github/workflows/e2e-tests-workflow.yml b/.github/workflows/e2e-tests-workflow.yml index 171f8389..47d44fd0 100644 --- a/.github/workflows/e2e-tests-workflow.yml +++ b/.github/workflows/e2e-tests-workflow.yml @@ -88,7 +88,7 @@ jobs: sleep 180 - name: Run e2e tests - uses: cypress-io/github-action@v1 + uses: cypress-io/github-action@v2.5.0 with: working-directory: kibana/plugins/anomaly-detection-kibana-plugin command: yarn cy:run --env SECURITY_ENABLED=true @@ -149,7 +149,7 @@ jobs: cd kibana/plugins/anomaly-detection-kibana-plugin yarn kbn bootstrap - name: Run e2e tests - uses: cypress-io/github-action@v1 + uses: cypress-io/github-action@v2.5.0 with: working-directory: kibana/plugins/anomaly-detection-kibana-plugin command: yarn test:e2e diff --git a/.gitignore b/.gitignore index ee0252d1..7aad9af1 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ offline-module-cache/v2/* offline-module-cache/v1/* .cypress/screenshots .cypress/videos +target diff --git a/cypress.json b/cypress.json index e4ef2026..27c89f5b 100644 --- a/cypress.json +++ b/cypress.json @@ -10,6 +10,7 @@ "requestTimeout": 90000, "responseTimeout": 90000, "defaultCommandTimeout": 90000, + "experimentalNetworkStubbing": true, "env": { "SECURITY_ENABLED": false } diff --git a/index.js b/index.js deleted file mode 100644 index b49808f8..00000000 --- a/index.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file 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 'babel-polyfill'; -import { resolve } from 'path'; -import { existsSync } from 'fs'; -import { ADPlugin } from './server/plugin'; -import { DEFAULT_APP_CATEGORIES } from '../../src/core/utils'; - -export default (kibana) => { - return new kibana.Plugin({ - require: ['kibana', 'elasticsearch'], - name: 'opendistro-anomaly-detection-kibana', - uiExports: { - app: { - title: 'Anomaly Detection', - description: - 'Open Distro for Elasticsearch Anomaly Detection Kibana plugin', - main: 'plugins/opendistro-anomaly-detection-kibana/app', - icon: - 'plugins/opendistro-anomaly-detection-kibana/images/anomaly_detection_icon.svg', - category: DEFAULT_APP_CATEGORIES.kibana, - order:8030, - }, - styleSheetPaths: [ - resolve(__dirname, 'public/app.scss'), - resolve(__dirname, 'public/app.css'), - ].find((p) => existsSync(p)), - hacks: [], - }, - - config(Joi) { - return Joi.object({ - enabled: Joi.boolean().default(true), - }).default(); - }, - - init(server) { - // eslint-disable-line no-unused-vars - // Add server routes and initialize the plugin here - // This is core shim for the kibana plugins - const coreSetup = { - elasticsearch: server.plugins.elasticsearch, - config: server.config.bind(server), - http: { - route: server.route.bind(server), - }, - }; - // Core server has logging framework we can utilize that once moved to new kibana platform version. - // https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.md - const initializerContext = { - logger: { - get() { - return { - info: (log) => console.log(log), - error: (log) => console.error(log), - warn: (log) => console.warn(log), - }; - }, - }, - }; - // plugins shim - const pluginsSetup = {}; - new ADPlugin(initializerContext).setup(coreSetup, pluginsSetup); - }, - }); -}; diff --git a/kibana.json b/kibana.json new file mode 100644 index 00000000..e993e5f6 --- /dev/null +++ b/kibana.json @@ -0,0 +1,10 @@ +{ + "id": "opendistroAnomalyDetectionKibana", + "version": "1.11.0.0", + "kibanaVersion": "7.9.1", + "configPath": ["opendistro_anomaly_detection_kibana"], + "requiredPlugins": ["navigation"], + "optionalPlugins": [], + "server": true, + "ui": true +} diff --git a/package.json b/package.json index 80d798aa..58b9601d 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,10 @@ "test:jest": "../../node_modules/.bin/jest --config ./test/jest.config.js", "build": "plugin-helpers build", "release": "./tasks/release.sh", - "start-cy-server": "yarn start --no-base-path --oss", "cy:open": "cypress open", "cy:run": "cypress run", "cy:run-with-security": "cypress run --env SECURITY_ENABLED=true", - "test:e2e": "CHOKIDAR_USEPOLLING=1 CYPRESS_responseTimeout=180000 WAIT_ON_TIMEOUT=900000 start-server-and-test 'yarn start-cy-server' http-get://localhost:5601/app/opendistro-anomaly-detection-kibana 'echo sleeping to wait for server to get ready && sleep 180 && yarn cy:run'" + "test:e2e": "CHOKIDAR_USEPOLLING=1 CYPRESS_responseTimeout=180000 WAIT_ON_TIMEOUT=900000 start-server-and-test 'cd ../../ && yarn start --no-base-path --oss && cd plugins/anomaly-detection-kibana-plugin' http-get://localhost:5601/app/opendistro-anomaly-detection-kibana 'echo sleeping to wait for server to get ready && sleep 180 && yarn cy:run'" }, "lint-staged": { "*.{ts,tsx,js,jsx,json,css,md}": [ @@ -42,7 +41,6 @@ "@testing-library/jest-dom": "^4.0.0", "@testing-library/react": "^8.0.6", "@testing-library/user-event": "^4.2.3", - "@types/angular": "^1.6.55", "@types/chance": "^1.0.6", "@types/elasticsearch": "^5.0.34", "@types/hapi": "^18.0.2", @@ -60,7 +58,7 @@ "babel-jest": "^24.8.0", "babel-polyfill": "^6.26.0", "chance": "^1.1.0", - "cypress": "^4.11.0", + "cypress": "^5.6.0", "eslint": "^5.6.0", "eslint-plugin-babel": "^5.2.0", "eslint-plugin-import": "^2.14.0", @@ -85,7 +83,6 @@ "formik": "^1.5.8", "lodash": "^4.17.19", "plotly.js": "^1.55.2", - "query-string": "^6.8.2", "react-plotly.js": "^2.4.0", "react-redux": "^7.1.0", "react-vis": "^1.11.7", diff --git a/public/anomaly_detection_app.tsx b/public/anomaly_detection_app.tsx new file mode 100644 index 00000000..c769ffff --- /dev/null +++ b/public/anomaly_detection_app.tsx @@ -0,0 +1,51 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import { CoreStart, AppMountParameters } from '../../../src/core/public'; +import React from 'react'; +import ReactDOM from 'react-dom'; +import { HashRouter as Router, Route } from 'react-router-dom'; +import { Main } from './pages/main'; +import { Provider } from 'react-redux'; +import configureStore from './redux/configureStore'; +import { CoreServicesContext } from './components/CoreServices/CoreServices'; + +export function renderApp(coreStart: CoreStart, params: AppMountParameters) { + const http = coreStart.http; + const store = configureStore(http); + + // Load Chart's dark mode CSS (if applicable) + const isDarkMode = coreStart.uiSettings.get('theme:darkMode') || false; + if (isDarkMode) { + require('@elastic/charts/dist/theme_only_dark.css'); + } else { + require('@elastic/charts/dist/theme_only_light.css'); + } + ReactDOM.render( + + + ( + +
+ + )} + /> + + , + params.element + ); + return () => ReactDOM.unmountComponentAtNode(params.element); +} diff --git a/public/app.js b/public/app.js deleted file mode 100644 index 7b921788..00000000 --- a/public/app.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import chrome from 'ui/chrome'; -import { uiModules } from 'ui/modules'; -import { Main } from './pages/main'; -import { HashRouter as Router, Route } from 'react-router-dom'; -import { Provider } from 'react-redux'; - -import configureStore from './redux/configureStore'; -import { darkModeEnabled } from './utils/kibanaUtils'; - -const app = uiModules.get('apps/awsSearchServicesKibanaAdPlugin'); - -//Load Chart's dark mode CSS -if (darkModeEnabled()) { - require('@elastic/charts/dist/theme_only_dark.css'); -} else { - require('@elastic/charts/dist/theme_only_light.css'); -} - -app.config($locationProvider => { - $locationProvider.html5Mode({ - enabled: false, - requireBase: false, - rewriteLinks: false, - }); -}); -app.config(stateManagementConfigProvider => - stateManagementConfigProvider.disable() -); - -function RootController($scope, $element, $http) { - const store = configureStore($http); - const domNode = $element[0]; - render( - - -
} /> - - , - domNode - ); - - $scope.$on('$destroy', () => { - unmountComponentAtNode(domNode); - }); -} - -chrome.setRootController('awsSearchServicesKibanaAdPlugin', RootController); diff --git a/public/components/CoreServices/CoreServices.tsx b/public/components/CoreServices/CoreServices.tsx new file mode 100644 index 00000000..913c80ac --- /dev/null +++ b/public/components/CoreServices/CoreServices.tsx @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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 { createContext } from 'react'; +import { CoreStart } from '../../../../../src/core/public'; + +const CoreServicesContext = createContext(null); + +const CoreServicesConsumer = CoreServicesContext.Consumer; + +export { CoreServicesContext, CoreServicesConsumer }; diff --git a/public/index.ts b/public/index.ts new file mode 100644 index 00000000..267dbcef --- /dev/null +++ b/public/index.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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/public'; +import { AnomalyDetectionKibanaPlugin } from './plugin'; +import './app.scss'; + +export interface AnomalyDetectionKibanaPluginSetup {} +export interface AnomalyDetectionKibanaPluginStart {} + +export function plugin(initializerContext: PluginInitializerContext) { + return new AnomalyDetectionKibanaPlugin(initializerContext); +} diff --git a/public/pages/AnomalyCharts/components/AlertsButton/AlertsButton.tsx b/public/pages/AnomalyCharts/components/AlertsButton/AlertsButton.tsx index 73b7b0f7..902de84b 100644 --- a/public/pages/AnomalyCharts/components/AlertsButton/AlertsButton.tsx +++ b/public/pages/AnomalyCharts/components/AlertsButton/AlertsButton.tsx @@ -15,8 +15,6 @@ import { EuiButton, EuiButtonProps } from '@elastic/eui'; import React, { Fragment } from 'react'; -//@ts-ignore -import { toastNotifications } from 'ui/notify'; import { getAlertingCreateMonitorLink, getAlertingMonitorListLink, @@ -31,27 +29,29 @@ export interface AlertsButtonProps extends EuiButtonProps { unit: string; } -export const AlertsButton = (props: AlertsButtonProps) => ( - - {props.monitor ? ( - - Edit alert settings - - ) : ( - - Set up alerts - - )} - -); +export const AlertsButton = (props: AlertsButtonProps) => { + return ( + + {props.monitor ? ( + + Edit alert settings + + ) : ( + + Set up alerts + + )} + + ); +}; diff --git a/public/pages/AnomalyCharts/components/AlertsFlyout/AlertsFlyout.tsx b/public/pages/AnomalyCharts/components/AlertsFlyout/AlertsFlyout.tsx index bfded684..7ecd0d23 100644 --- a/public/pages/AnomalyCharts/components/AlertsFlyout/AlertsFlyout.tsx +++ b/public/pages/AnomalyCharts/components/AlertsFlyout/AlertsFlyout.tsx @@ -26,8 +26,6 @@ import { EuiSteps, } from '@elastic/eui'; import React from 'react'; -//@ts-ignore -import { toastNotifications } from 'ui/notify'; import { EuiIcon } from '@elastic/eui'; import { Monitor } from '../../../../models/interfaces'; import { AlertsButton } from '../AlertsButton/AlertsButton'; diff --git a/public/pages/AnomalyCharts/components/FeatureChart/FeatureChart.tsx b/public/pages/AnomalyCharts/components/FeatureChart/FeatureChart.tsx index 4aea90d5..89cb9fee 100644 --- a/public/pages/AnomalyCharts/components/FeatureChart/FeatureChart.tsx +++ b/public/pages/AnomalyCharts/components/FeatureChart/FeatureChart.tsx @@ -65,10 +65,11 @@ interface FeatureChartProps { rawFeatureData: FeatureAggregationData[]; titlePrefix?: string; } -const getDisabledChartBackground = () => - darkModeEnabled() ? '#25262E' : '#F0F0F0'; export const FeatureChart = (props: FeatureChartProps) => { + const getDisabledChartBackground = () => + darkModeEnabled() ? '#25262E' : '#F0F0F0'; + const [showCustomExpression, setShowCustomExpression] = useState( false ); diff --git a/public/pages/AnomalyCharts/containers/AnomalyDetailsChart.tsx b/public/pages/AnomalyCharts/containers/AnomalyDetailsChart.tsx index 821fc7cb..769d24fa 100644 --- a/public/pages/AnomalyCharts/containers/AnomalyDetailsChart.tsx +++ b/public/pages/AnomalyCharts/containers/AnomalyDetailsChart.tsx @@ -157,7 +157,7 @@ export const AnomalyDetailsChart = React.memo( searchAlerts(monitorId, startDateTime, endDateTime) ); setIsLoadingAlerts(false); - setTotalAlerts(get(result, 'data.response.totalAlerts')); + setTotalAlerts(get(result, 'response.totalAlerts')); const monitorAlerts = convertAlerts(result); setAlerts(monitorAlerts); const annotations = generateAlertAnnotations(monitorAlerts); diff --git a/public/pages/AnomalyCharts/containers/AnomalyOccurrenceChart.tsx b/public/pages/AnomalyCharts/containers/AnomalyOccurrenceChart.tsx index 41d21e30..7c583110 100644 --- a/public/pages/AnomalyCharts/containers/AnomalyOccurrenceChart.tsx +++ b/public/pages/AnomalyCharts/containers/AnomalyOccurrenceChart.tsx @@ -15,7 +15,6 @@ import React from 'react'; import { EuiBadge } from '@elastic/eui'; -import { get } from 'lodash'; import ContentPanel from '../../../components/ContentPanel/ContentPanel'; import { Monitor, Detector, DateRange } from '../../../models/interfaces'; import { AnomalyDetailsChart } from './AnomalyDetailsChart'; diff --git a/public/pages/AnomalyCharts/containers/__tests__/AnomaliesChart.test.tsx b/public/pages/AnomalyCharts/containers/__tests__/AnomaliesChart.test.tsx index fc958c6a..c7a96c8f 100644 --- a/public/pages/AnomalyCharts/containers/__tests__/AnomaliesChart.test.tsx +++ b/public/pages/AnomalyCharts/containers/__tests__/AnomaliesChart.test.tsx @@ -21,6 +21,8 @@ import { initialState, mockedStore } from '../../../../redux/utils/testUtils'; import { Provider } from 'react-redux'; import { INITIAL_ANOMALY_SUMMARY } from '../../utils/constants'; import { getRandomDetector } from '../../../../redux/reducers/__tests__/utils'; +import { CoreServicesContext } from '../../../../components/CoreServices/CoreServices'; +import { coreServicesMock } from '../../../../../test/mocks'; const initialStartTime = moment('2019-10-10T09:00:00'); const initialEndTime = initialStartTime.clone().add(2, 'd'); @@ -66,17 +68,19 @@ const renderDataFilter = () => ({ }, })} > - + + + ), }); diff --git a/public/pages/AnomalyCharts/containers/__tests__/FeatureBreakDown.test.tsx b/public/pages/AnomalyCharts/containers/__tests__/FeatureBreakDown.test.tsx index fe1f5a24..0ec50424 100644 --- a/public/pages/AnomalyCharts/containers/__tests__/FeatureBreakDown.test.tsx +++ b/public/pages/AnomalyCharts/containers/__tests__/FeatureBreakDown.test.tsx @@ -18,6 +18,8 @@ import { render } from '@testing-library/react'; import { getRandomDetector } from '../../../../redux/reducers/__tests__/utils'; import { FeatureBreakDown } from '../FeatureBreakDown'; import { FeatureAggregationData } from 'public/models/interfaces'; +import { CoreServicesContext } from '../../../../components/CoreServices/CoreServices'; +import { coreServicesMock } from '../../../../../test/mocks'; describe(' spec', () => { const dateRange = { @@ -53,15 +55,17 @@ describe(' spec', () => { test('renders the component', () => { console.error = jest.fn(); const { container } = render( - + + + ); expect(container.firstChild).toMatchSnapshot(); }); diff --git a/public/pages/AnomalyCharts/utils/anomalyChartUtils.ts b/public/pages/AnomalyCharts/utils/anomalyChartUtils.ts index b47b21ad..56695869 100644 --- a/public/pages/AnomalyCharts/utils/anomalyChartUtils.ts +++ b/public/pages/AnomalyCharts/utils/anomalyChartUtils.ts @@ -30,7 +30,7 @@ import { calculateTimeWindowsWithMaxDataPoints } from '../../utils/anomalyResult import { HeatmapCell } from '../containers/AnomalyHeatmapChart'; export const convertAlerts = (response: any): MonitorAlert[] => { - const alerts = get(response, 'data.response.alerts', []); + const alerts = get(response, 'response.alerts', []); return alerts.map((alert: any) => { return { monitorName: get(alert, 'monitor_name'), diff --git a/public/pages/Dashboard/Container/DashboardOverview.tsx b/public/pages/Dashboard/Container/DashboardOverview.tsx index 6392fdcb..93259728 100644 --- a/public/pages/Dashboard/Container/DashboardOverview.tsx +++ b/public/pages/Dashboard/Container/DashboardOverview.tsx @@ -30,10 +30,6 @@ import { EuiLoadingSpinner, EuiSpacer, } from '@elastic/eui'; -//@ts-ignore -import chrome from 'ui/chrome'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; import { AnomalousDetectorsList } from '../Components/AnomalousDetectorsList'; import { GET_ALL_DETECTORS_QUERY_PARAMS, @@ -52,8 +48,12 @@ import { prettifyErrorMessage, NO_PERMISSIONS_KEY_WORD, } from '../../../../server/utils/helpers'; +import { CoreServicesContext } from '../../../components/CoreServices/CoreServices'; +import { CoreStart } from '../../../../../../src/core/public'; export function DashboardOverview() { + const core = React.useContext(CoreServicesContext) as CoreStart; + const dispatch = useDispatch(); const adState = useSelector((state: AppState) => state.ad); @@ -181,8 +181,9 @@ export function DashboardOverview() { useEffect(() => { if (errorGettingDetectors) { console.error(errorGettingDetectors); - toastNotifications.addDanger( - errorGettingDetectors.includes(NO_PERMISSIONS_KEY_WORD) + core.notifications.toasts.addDanger( + typeof errorGettingDetectors === 'string' && + errorGettingDetectors.includes(NO_PERMISSIONS_KEY_WORD) ? prettifyErrorMessage(errorGettingDetectors) : 'Unable to get all detectors.' ); @@ -191,7 +192,7 @@ export function DashboardOverview() { }, [errorGettingDetectors]); useEffect(() => { - chrome.breadcrumbs.set([ + core.chrome.setBreadcrumbs([ BREADCRUMBS.ANOMALY_DETECTOR, BREADCRUMBS.DASHBOARD, ]); diff --git a/public/pages/Dashboard/utils/utils.tsx b/public/pages/Dashboard/utils/utils.tsx index 7dae7acf..22a79c1b 100644 --- a/public/pages/Dashboard/utils/utils.tsx +++ b/public/pages/Dashboard/utils/utils.tsx @@ -357,7 +357,7 @@ export const anomalousDetectorsStaticColumn = [ truncateText: false, textOnly: true, render: (featureAttributes: FeatureAttributes[]) => { - return featureAttributes.map(feature => { + return featureAttributes.map((feature) => { return

{feature.featureName}

; }); }, @@ -451,7 +451,7 @@ export const getLatestAnomalyResultsByTimeRange = async ( ) ); - const searchAnomalyResponse = searchResponse.data.response; + const searchAnomalyResponse = searchResponse.response; const numHits = get(searchAnomalyResponse, 'hits.total.value', 0); if (numHits === 0) { @@ -502,7 +502,7 @@ export const getLatestAnomalyResultsForDetectorsByTimeRange = async ( ) ) ); - const searchAnomalyResponse = searchResponse.data.response; + const searchAnomalyResponse = searchResponse.response; const numHits = get(searchAnomalyResponse, 'hits.total.value', 0); if (numHits === 0) { @@ -530,14 +530,14 @@ export const getLatestAnomalyResultsForDetectorsByTimeRange = async ( numSingleBatchResults = anomalies.length; } while (numSingleBatchResults === MAX_ANOMALIES); - const filteredAnomalyResults = anomalyResults.filter(anomaly => + const filteredAnomalyResults = anomalyResults.filter((anomaly) => detectorAndIdMap.has(get(anomaly, AD_DOC_FIELDS.DETECTOR_ID, '')) ); const orderedLiveAnomalyData = orderBy( filteredAnomalyResults, // sort by data start time in desc order - anomalyData => get(anomalyData, AD_DOC_FIELDS.DATA_START_TIME, ''), + (anomalyData) => get(anomalyData, AD_DOC_FIELDS.DATA_START_TIME, ''), SORT_DIRECTION.DESC ); const latestAnomalousDetectorIds = selectLatestAnomalousDetectorIds( @@ -545,10 +545,11 @@ export const getLatestAnomalyResultsForDetectorsByTimeRange = async ( detectorNum ); if (!isEmpty(latestAnomalousDetectorIds)) { - const finalLiveAnomalyResult = orderedLiveAnomalyData.filter(anomalyData => - latestAnomalousDetectorIds.has( - get(anomalyData, AD_DOC_FIELDS.DETECTOR_ID, '') - ) + const finalLiveAnomalyResult = orderedLiveAnomalyData.filter( + (anomalyData) => + latestAnomalousDetectorIds.has( + get(anomalyData, AD_DOC_FIELDS.DETECTOR_ID, '') + ) ); return finalLiveAnomalyResult; } @@ -562,7 +563,7 @@ const buildDetectorAndIdMap = ( ): Map => { const detectorAndIdMap = new Map(); if (selectedDetectors) { - selectedDetectors.forEach(detector => { + selectedDetectors.forEach((detector) => { detectorAndIdMap.set(detector.id, detector); }); } @@ -576,9 +577,9 @@ const selectLatestAnomalousDetectorIds = ( const anomalousDetectorIds = new Set( orderedAnomalyData .filter( - anomalyData => get(anomalyData, AD_DOC_FIELDS.ANOMALY_GRADE, 0) > 0 + (anomalyData) => get(anomalyData, AD_DOC_FIELDS.ANOMALY_GRADE, 0) > 0 ) - .map(anomalyData => get(anomalyData, AD_DOC_FIELDS.DETECTOR_ID, '')) + .map((anomalyData) => get(anomalyData, AD_DOC_FIELDS.DETECTOR_ID, '')) ); return new Set(Array.from(anomalousDetectorIds).slice(0, neededDetectorNum)); @@ -618,7 +619,7 @@ export const getAnomalyDistributionForDetectorsByTimeRange = async ( const detectorsAggResults = get( result, - `data.response.aggregations.${aggregationName}.buckets`, + `response.aggregations.${aggregationName}.buckets`, [] ); diff --git a/public/pages/DetectorConfig/containers/Features.tsx b/public/pages/DetectorConfig/containers/Features.tsx index 812e09a6..7abf407e 100644 --- a/public/pages/DetectorConfig/containers/Features.tsx +++ b/public/pages/DetectorConfig/containers/Features.tsx @@ -12,7 +12,7 @@ * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import React, { Component } from 'react'; +import React, { useState } from 'react'; import { EuiBasicTable, EuiText, @@ -46,221 +46,216 @@ interface FeaturesState { sortDirection: 'asc' | 'desc'; } -export class Features extends Component { - constructor(props: FeaturesProps) { - super(props); - this.state = { - showCodeModel: get(props.detector, 'featureAttributes', []).map( - () => false - ), - sortField: 'name', - sortDirection: 'asc', - }; - } +export const Features = (props: FeaturesProps) => { + const [featuresState, setFeaturesState] = useState({ + showCodeModel: get(props.detector, 'featureAttributes', []).map( + () => false + ), + sortField: 'name', + sortDirection: 'asc', + }); - private closeModal(index: number) { - const cloneShowCodeModal = [...this.state.showCodeModel]; + const closeModal = (index: number) => { + const cloneShowCodeModal = [...featuresState.showCodeModel]; cloneShowCodeModal[index] = false; - this.setState({ + setFeaturesState({ + ...featuresState, showCodeModel: cloneShowCodeModal, }); - } + }; - private showModal(index: number) { - const cloneShowCodeModal = [...this.state.showCodeModel]; + const showModal = (index: number) => { + const cloneShowCodeModal = [...featuresState.showCodeModel]; cloneShowCodeModal[index] = true; - this.setState({ + setFeaturesState({ + ...featuresState, showCodeModel: cloneShowCodeModal, }); - } + }; - private getModalVisibilityChange = (index: number) => { - return this.state.showCodeModel[index]; + const getModalVisibilityChange = (index: number) => { + return featuresState.showCodeModel[index]; }; - private handleTableChange = (props: any) => { - this.setState({ + const handleTableChange = (props: any) => { + setFeaturesState({ + ...featuresState, sortField: props.sort.field, sortDirection: props.sort.direction, }); }; - private sortedItems(items: Array) { - let sorted = sortBy(items, this.state.sortField); - if (this.state.sortDirection == 'desc') { + const getSortedItems = (items: Array) => { + let sorted = sortBy(items, featuresState.sortField); + if (featuresState.sortDirection == 'desc') { sorted = sorted.reverse(); } return sorted; - } - - public render() { - const featureAttributes = get(this.props.detector, 'featureAttributes', []); - const shingleSize = get(this.props.detector, 'shingleSize', SHINGLE_SIZE); + }; + const featureAttributes = get(props.detector, 'featureAttributes', []); + const shingleSize = get(props.detector, 'shingleSize', SHINGLE_SIZE); - const sorting = { - sort: { - field: this.state.sortField, - direction: this.state.sortDirection, - }, - }; + const sorting = { + sort: { + field: featuresState.sortField, + direction: featuresState.sortDirection, + }, + }; - const items = featureAttributes.map( - (feature: FeatureAttributes, index: number) => ({ - name: feature.featureName, - definition: index, - state: feature.featureEnabled ? 'Enabled' : 'Disabled', - }) - ); + const items = featureAttributes.map( + (feature: FeatureAttributes, index: number) => ({ + name: feature.featureName, + definition: index, + state: feature.featureEnabled ? 'Enabled' : 'Disabled', + }) + ); - const sortedItems = this.sortedItems(items); + const sortedItems = getSortedItems(items); - const columns = [ - { - field: 'name', - name: 'Feature name', - sortable: true, - }, - { - field: 'definition', - name: 'Feature definition', - render: (featureIndex: number) => { - const feature = featureAttributes[featureIndex]; + const columns = [ + { + field: 'name', + name: 'Feature name', + sortable: true, + }, + { + field: 'definition', + name: 'Feature definition', + render: (featureIndex: number) => { + const feature = featureAttributes[featureIndex]; - const metaData = get( - this.props.detector, - `uiMetadata.features.${feature.featureName}`, - {} - ); + const metaData = get( + props.detector, + `uiMetadata.features.${feature.featureName}`, + {} + ); - if ( - Object.keys(metaData).length === 0 || - metaData.featureType == FEATURE_TYPE.CUSTOM - ) { - return ( -
-

- Custom expression:{' '} - this.showModal(featureIndex)} - > - View code - -

+ if ( + Object.keys(metaData).length === 0 || + metaData.featureType == FEATURE_TYPE.CUSTOM + ) { + return ( +
+

+ Custom expression:{' '} + showModal(featureIndex)} + > + View code + +

- {!this.getModalVisibilityChange(featureIndex) ? null : ( - this.closeModal(featureIndex)} - getModalVisibilityChange={() => - this.getModalVisibilityChange(featureIndex) - } - /> - )} -
- ); - } else { - return ( -
-

Field: {metaData.aggregationOf || ''}

-

Aggregation method: {metaData.aggregationBy || ''}

-
- ); - } - }, - }, - { - field: 'state', - name: 'Feature state', + {!getModalVisibilityChange(featureIndex) ? null : ( + closeModal(featureIndex)} + getModalVisibilityChange={() => + getModalVisibilityChange(featureIndex) + } + /> + )} +
+ ); + } else { + return ( +
+

Field: {metaData.aggregationOf || ''}

+

Aggregation method: {metaData.aggregationBy || ''}

+
+ ); + } }, - ]; + }, + { + field: 'state', + name: 'Feature state', + }, + ]; - const getCellProps = () => { - return { - textOnly: true, - }; + const getCellProps = () => { + return { + textOnly: true, }; + }; - const featureNum = Object.keys(featureAttributes).length; + const featureNum = Object.keys(featureAttributes).length; - const setParamsText = `Set the index fields that you want to find anomalies for by defining + const setParamsText = `Set the index fields that you want to find anomalies for by defining the model features. You can also set other model parameters such as window size.`; - const previewText = `After you set the model features and other optional parameters, you can + const previewText = `After you set the model features and other optional parameters, you can preview your anomalies from a sample feature output.`; - return ( - -

- {`${setParamsText} ${previewText} `} - - Learn more   - - -

- - } - actions={[ - Edit, - ]} - > - {featureNum == 0 ? ( - - Model parameters are required to run a detector - - } - body={ - - {setParamsText} -
-
- {previewText} -
- } - actions={[ - - Configure model - , - ]} - /> - ) : ( -
- +

+ {`${setParamsText} ${previewText} `} + - - - - + +

+ + } + actions={[Edit]} + > + {featureNum == 0 ? ( + + Model parameters are required to run a detector + + } + body={ + + {setParamsText} +
+
+ {previewText} +
+ } + actions={[ + + Configure model + , + ]} + /> + ) : ( +
+ + -
- )} -
- ); - } -} + + + +
+ )} +
+ ); +}; diff --git a/public/pages/DetectorConfig/containers/__tests__/DetectorConfig.test.tsx b/public/pages/DetectorConfig/containers/__tests__/DetectorConfig.test.tsx index 991f6940..82c858b2 100644 --- a/public/pages/DetectorConfig/containers/__tests__/DetectorConfig.test.tsx +++ b/public/pages/DetectorConfig/containers/__tests__/DetectorConfig.test.tsx @@ -21,13 +21,7 @@ import { Route, Switch, } from 'react-router-dom'; -import { - render, - fireEvent, - wait, -} from '@testing-library/react'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; +import { render, fireEvent, wait } from '@testing-library/react'; import { DetectorConfig } from '../DetectorConfig'; import { Detector, @@ -38,17 +32,14 @@ import { UiFeature, FeatureAttributes, } from '../../../../models/interfaces'; -import { - getRandomDetector, -} from '../../../../redux/reducers/__tests__/utils'; -import configureStore from '../../../../redux/configureStore'; -import { httpClientMock } from '../../../../../test/mocks'; -import userEvent from '@testing-library/user-event'; +import { getRandomDetector } from '../../../../redux/reducers/__tests__/utils'; +import { coreServicesMock } from '../../../../../test/mocks'; import { toString } from '../MetaData'; import { DATA_TYPES } from '../../../../utils/constants'; import { OPERATORS_MAP } from '../../../createDetector/components/DataFilters/utils/constant'; import { displayText } from '../../../createDetector/components/DataFilters/utils/helpers'; import { mockedStore, initialState } from '../../../../redux/utils/testUtils'; +import { CoreServicesContext } from '../../../../components/CoreServices/CoreServices'; const renderWithRouter = (detector: Detector) => ({ ...render( @@ -67,12 +58,14 @@ const renderWithRouter = (detector: Detector) => ({ ( - + + + )} /> @@ -164,9 +157,7 @@ describe(' spec', () => { const { getByText, queryByText } = renderWithRouter(randomDetector); await wait(() => { getByText('Model parameters are required to run a detector'); - queryByText( - 'Set the index fields' - ); + queryByText('Set the index fields'); getByText('Model configuration'); getByText(randomDetector.name); getByText(randomDetector.indices[0]); @@ -177,9 +168,7 @@ describe(' spec', () => { getByText(randomDetector.description); // filter should be - getByText('-'); - queryByText( - 'Set the index fields' - ); + queryByText('Set the index fields'); }); }); diff --git a/public/pages/DetectorDetail/components/MonitorCallout/MonitorCallout.tsx b/public/pages/DetectorDetail/components/MonitorCallout/MonitorCallout.tsx index 251aaa1d..e0fc7947 100644 --- a/public/pages/DetectorDetail/components/MonitorCallout/MonitorCallout.tsx +++ b/public/pages/DetectorDetail/components/MonitorCallout/MonitorCallout.tsx @@ -15,10 +15,6 @@ import React from 'react'; import { EuiCallOut, EuiLink, EuiIcon } from '@elastic/eui'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; -//@ts-ignore -import chrome from 'ui/chrome'; import { getAlertingMonitorListLink } from '../../../../utils/utils'; interface MonitorCalloutProps { diff --git a/public/pages/DetectorDetail/containers/DetectorDetail.tsx b/public/pages/DetectorDetail/containers/DetectorDetail.tsx index e2888995..e54a5f1a 100644 --- a/public/pages/DetectorDetail/containers/DetectorDetail.tsx +++ b/public/pages/DetectorDetail/containers/DetectorDetail.tsx @@ -28,8 +28,8 @@ import { EuiFieldText, EuiLoadingSpinner, } from '@elastic/eui'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; +import { CoreStart } from '../../../../../../src/core/public'; +import { CoreServicesContext } from '../../../components/CoreServices/CoreServices'; import { get, isEmpty } from 'lodash'; import { RouteComponentProps, Switch, Route, Redirect } from 'react-router-dom'; import { useDispatch } from 'react-redux'; @@ -41,8 +41,6 @@ import { stopDetector, } from '../../../redux/reducers/ad'; import { getErrorMessage, Listener } from '../../../utils/utils'; -//@ts-ignore -import chrome from 'ui/chrome'; import { darkModeEnabled } from '../../../utils/kibanaUtils'; import { BREADCRUMBS, DETECTOR_STATE } from '../../../utils/constants'; import { DetectorControls } from '../components/DetectorControls'; @@ -93,6 +91,7 @@ interface DetectorDetailModel { } export const DetectorDetail = (props: DetectorDetailProps) => { + const core = React.useContext(CoreServicesContext) as CoreStart; const dispatch = useDispatch(); const detectorId = get(props, 'match.params.detectorId', '') as string; const { @@ -124,7 +123,7 @@ export const DetectorDetail = (props: DetectorDetailProps) => { useEffect(() => { if (hasError) { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( errorMessage.includes(NO_PERMISSIONS_KEY_WORD) ? prettifyErrorMessage(errorMessage) : 'Unable to find detector' @@ -135,7 +134,7 @@ export const DetectorDetail = (props: DetectorDetailProps) => { useEffect(() => { if (detector) { - chrome.breadcrumbs.set([ + core.chrome.setBreadcrumbs([ BREADCRUMBS.ANOMALY_DETECTOR, BREADCRUMBS.DETECTORS, { text: detector ? detector.name : '' }, @@ -198,11 +197,11 @@ export const DetectorDetail = (props: DetectorDetailProps) => { const handleStartAdJob = async (detectorId: string) => { try { await dispatch(startDetector(detectorId)); - toastNotifications.addSuccess( + core.notifications.toasts.addSuccess( `Detector job has been started successfully` ); } catch (err) { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( getErrorMessage(err, 'There was a problem starting detector job') ) @@ -213,12 +212,12 @@ export const DetectorDetail = (props: DetectorDetailProps) => { const handleStopAdJob = async (detectorId: string, listener?: Listener) => { try { await dispatch(stopDetector(detectorId)); - toastNotifications.addSuccess( + core.notifications.toasts.addSuccess( 'Detector job has been stopped successfully' ); if (listener) listener.onSuccess(); } catch (err) { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( getErrorMessage(err, 'There was a problem stopping detector job') ) @@ -230,11 +229,13 @@ export const DetectorDetail = (props: DetectorDetailProps) => { const handleDelete = useCallback(async (detectorId: string) => { try { await dispatch(deleteDetector(detectorId)); - toastNotifications.addSuccess(`Detector has been deleted successfully`); + core.notifications.toasts.addSuccess( + `Detector has been deleted successfully` + ); hideDeleteDetectorModal(); props.history.push('/detectors'); } catch (err) { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( getErrorMessage(err, 'There was a problem deleting detector') ) @@ -495,9 +496,9 @@ export const DetectorDetail = (props: DetectorDetailProps) => { ( + render={(resultsProps) => ( handleStartAdJob(detectorId)} onSwitchToConfiguration={handleSwitchToConfigurationTab} @@ -507,9 +508,9 @@ export const DetectorDetail = (props: DetectorDetailProps) => { ( + render={(configProps) => ( ({ url: '', }, }; - return ; + return ( + + + + ); }} /> diff --git a/public/pages/DetectorResults/containers/AnomalyHistory.tsx b/public/pages/DetectorResults/containers/AnomalyHistory.tsx index 01b8f7d8..fc76b388 100644 --- a/public/pages/DetectorResults/containers/AnomalyHistory.tsx +++ b/public/pages/DetectorResults/containers/AnomalyHistory.tsx @@ -59,6 +59,7 @@ import { searchResults } from '../../../redux/reducers/anomalyResults'; import { AnomalyOccurrenceChart } from '../../AnomalyCharts/containers/AnomalyOccurrenceChart'; import { HeatmapCell } from '../../AnomalyCharts/containers/AnomalyHeatmapChart'; import { getAnomalyHistoryWording } from '../../AnomalyCharts/utils/anomalyChartUtils'; +import { darkModeEnabled } from '../../../utils/kibanaUtils'; interface AnomalyHistoryProps { detector: Detector; @@ -100,6 +101,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => { const detectorCategoryField = get(props.detector, 'categoryField', []); const isHCDetector = !isEmpty(detectorCategoryField); + const backgroundColor = darkModeEnabled() ? '#29017' : '#F7F7F7'; useEffect(() => { // We load at most 10k AD result data points for one call. If user choose @@ -185,7 +187,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => { const detectorResultResponse = await dispatch( getDetectorResults(props.detector.id, params) ); - const rawAnomaliesData = get(detectorResultResponse, 'data.response', []); + const rawAnomaliesData = get(detectorResultResponse, 'response', []); const rawAnomaliesResult = { anomalies: get(rawAnomaliesData, 'results', []), featureData: get(rawAnomaliesData, 'featureResults', []), @@ -348,7 +350,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => { ) : ( -
+
{selectedTabId === ANOMALY_HISTORY_TABS.FEATURE_BREAKDOWN ? ( { - chrome.breadcrumbs.set([ + core.chrome.setBreadcrumbs([ BREADCRUMBS.ANOMALY_DETECTOR, BREADCRUMBS.DETECTORS, { text: detector ? detector.name : '' }, @@ -228,7 +229,7 @@ export function AnomalyResults(props: AnomalyResultsProps) { ); const featuresData = get( detectorResultResponse, - 'data.response.featureResults', + 'response.featureResults', [] ); const featureDataPoints = getFeatureDataPointsForDetector( diff --git a/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx b/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx index a561fc22..1eba523d 100644 --- a/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx +++ b/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx @@ -197,12 +197,12 @@ export const AnomalyResultsLiveChart = ( }; const latestAnomalyGrade = get(liveAnomalyResults, 'liveAnomalies', []).find( - anomaly => anomaly.anomalyGrade > 0 + (anomaly) => anomaly.anomalyGrade > 0 ); const fullScreenButton = () => ( setIsFullScreen(isFullScreen => !isFullScreen)} + onClick={() => setIsFullScreen((isFullScreen) => !isFullScreen)} iconType={isFullScreen ? 'exit' : 'fullScreen'} aria-label="View full screen" > @@ -283,9 +283,10 @@ export const AnomalyResultsLiveChart = ( size="s" title={`No anomalies found during the last ${ LIVE_CHART_CONFIG.MONITORING_INTERVALS - } intervals (${LIVE_CHART_CONFIG.MONITORING_INTERVALS * - props.detector.detectionInterval.period - .interval} minutes).`} + } intervals (${ + LIVE_CHART_CONFIG.MONITORING_INTERVALS * + props.detector.detectionInterval.period.interval + } minutes).`} style={{ width: '97%', // ensure width reaches NOW line }} diff --git a/public/pages/DetectorResults/containers/AnomalyResultsTable.tsx b/public/pages/DetectorResults/containers/AnomalyResultsTable.tsx index 630aa3c1..d5951d2e 100644 --- a/public/pages/DetectorResults/containers/AnomalyResultsTable.tsx +++ b/public/pages/DetectorResults/containers/AnomalyResultsTable.tsx @@ -21,8 +21,6 @@ import { } from '@elastic/eui'; import { get } from 'lodash'; import React, { useEffect, useState } from 'react'; -//@ts-ignore -import chrome from 'ui/chrome'; import { SORT_DIRECTION } from '../../../../server/utils/constants'; import ContentPanel from '../../../components/ContentPanel/ContentPanel'; import { diff --git a/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmDeleteDetectorsModal.tsx b/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmDeleteDetectorsModal.tsx index 6de01042..82d10dff 100644 --- a/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmDeleteDetectorsModal.tsx +++ b/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmDeleteDetectorsModal.tsx @@ -29,11 +29,7 @@ import { EuiModalHeaderTitle, EuiLoadingSpinner, } from '@elastic/eui'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; import { get, isEmpty } from 'lodash'; -//@ts-ignore -import chrome from 'ui/chrome'; import { Monitor } from '../../../../models/interfaces'; import { DetectorListItem } from '../../../../models/interfaces'; import { Listener } from '../../../../utils/utils'; @@ -61,15 +57,15 @@ export const ConfirmDeleteDetectorsModal = ( const containsEnabled = containsEnabledDetectors(props.detectors); const detectorsToDisplay = containsEnabled ? props.detectors - .sort(detector => + .sort((detector) => detector.curState === DETECTOR_STATE.INIT || detector.curState === DETECTOR_STATE.RUNNING ? -1 : 1 ) - .sort(detector => (get(props.monitors, `${detector.id}`) ? -1 : 1)) + .sort((detector) => (get(props.monitors, `${detector.id}`) ? -1 : 1)) : containsMonitors - ? props.detectors.sort(detector => + ? props.detectors.sort((detector) => get(props.monitors, `${detector.id}`) ? -1 : 1 ) : props.detectors; @@ -138,7 +134,7 @@ export const ConfirmDeleteDetectorsModal = ( data-test-subj="typeDeleteField" fullWidth={true} placeholder="delete" - onChange={e => { + onChange={(e) => { if (e.target.value === 'delete') { setDeleteTyped(true); } else { diff --git a/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmStartDetectorsModal.tsx b/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmStartDetectorsModal.tsx index 6b3591c7..e8e772c5 100644 --- a/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmStartDetectorsModal.tsx +++ b/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmStartDetectorsModal.tsx @@ -26,10 +26,6 @@ import { EuiModalHeaderTitle, EuiLoadingSpinner, } from '@elastic/eui'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; -//@ts-ignore -import chrome from 'ui/chrome'; import { DetectorListItem } from '../../../../models/interfaces'; import { EuiSpacer } from '@elastic/eui'; import { getNamesGrid } from './utils/helpers'; diff --git a/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmStopDetectorsModal.tsx b/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmStopDetectorsModal.tsx index 19379c1f..b9b9572f 100644 --- a/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmStopDetectorsModal.tsx +++ b/public/pages/DetectorsList/containers/ConfirmActionModals/ConfirmStopDetectorsModal.tsx @@ -27,10 +27,6 @@ import { EuiModalHeaderTitle, EuiLoadingSpinner, } from '@elastic/eui'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; -//@ts-ignore -import chrome from 'ui/chrome'; import { Monitor } from '../../../../models/interfaces'; import { DetectorListItem } from '../../../../models/interfaces'; import { Listener } from '../../../../utils/utils'; @@ -52,7 +48,7 @@ export const ConfirmStopDetectorsModal = ( ) => { const containsMonitors = !isEmpty(props.monitors); const detectorsToDisplay = containsMonitors - ? props.detectors.sort(detector => + ? props.detectors.sort((detector) => get(props.monitors, `${detector.id}`) ? -1 : 1 ) : props.detectors; diff --git a/public/pages/DetectorsList/containers/ConfirmActionModals/__tests__/ConfirmDeleteDetectorsModal.test.tsx b/public/pages/DetectorsList/containers/ConfirmActionModals/__tests__/ConfirmDeleteDetectorsModal.test.tsx index 08a9c7b3..5e5ae0b8 100644 --- a/public/pages/DetectorsList/containers/ConfirmActionModals/__tests__/ConfirmDeleteDetectorsModal.test.tsx +++ b/public/pages/DetectorsList/containers/ConfirmActionModals/__tests__/ConfirmDeleteDetectorsModal.test.tsx @@ -14,7 +14,7 @@ */ import React from 'react'; -import { render, fireEvent, wait, getByText } from '@testing-library/react'; +import { render, fireEvent, wait } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { ConfirmDeleteDetectorsModal } from '../ConfirmDeleteDetectorsModal'; import { DetectorListItem, Monitor } from '../../../../../models/interfaces'; @@ -78,6 +78,7 @@ describe(' spec', () => { const { getByTestId, getByPlaceholderText } = render( ); + await wait(); userEvent.type(getByPlaceholderText('delete'), 'foo'); await wait(); userEvent.click(getByTestId('confirmButton')); @@ -85,17 +86,18 @@ describe(' spec', () => { expect(defaultDeleteProps.onStopDetectors).not.toHaveBeenCalled(); expect(defaultDeleteProps.onDeleteDetectors).not.toHaveBeenCalled(); expect(defaultDeleteProps.onConfirm).not.toHaveBeenCalled(); - }); + }, 10000); test('should have delete button enabled if delete typed', async () => { const { getByTestId, getByPlaceholderText } = render( ); + await wait(); userEvent.type(getByPlaceholderText('delete'), 'delete'); await wait(); userEvent.click(getByTestId('confirmButton')); await wait(); expect(defaultDeleteProps.onConfirm).toHaveBeenCalled(); - }); + }, 10000); test('should not show callout if no detectors are running', async () => { const { queryByText } = render( @@ -128,6 +130,7 @@ describe(' spec', () => { } /> ); + await wait(); expect( queryByText('Some of the selected detectors are currently running.') ).not.toBeNull(); @@ -136,6 +139,7 @@ describe(' spec', () => { const { getByTestId } = render( ); + await wait(); fireEvent.click(getByTestId('cancelButton')); await wait(); expect(defaultDeleteProps.onHide).toHaveBeenCalled(); @@ -156,6 +160,7 @@ describe(' spec', () => { /> ); // Try clicking before 'delete' has been typed + await wait(); userEvent.click(getByTestId('confirmButton')); await wait(); expect(defaultDeleteProps.onStopDetectors).not.toHaveBeenCalled(); diff --git a/public/pages/DetectorsList/containers/ConfirmActionModals/utils/helpers.tsx b/public/pages/DetectorsList/containers/ConfirmActionModals/utils/helpers.tsx index 5aa7fbdf..ea36ee06 100644 --- a/public/pages/DetectorsList/containers/ConfirmActionModals/utils/helpers.tsx +++ b/public/pages/DetectorsList/containers/ConfirmActionModals/utils/helpers.tsx @@ -15,10 +15,6 @@ import React from 'react'; import { EuiLink, EuiText, EuiIcon, EuiDataGrid } from '@elastic/eui'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; -//@ts-ignore -import chrome from 'ui/chrome'; import { getAlertingMonitorListLink } from '../../../../../utils/utils'; import { Monitor } from '../../../../../models/interfaces'; import { DetectorListItem } from '../../../../../models/interfaces'; @@ -259,7 +255,7 @@ export const getNamesAndMonitorsAndStatesGrid = ( export const containsEnabledDetectors = (detectors: DetectorListItem[]) => { const enabledDetectors = detectors.filter( - detector => + (detector) => detector.curState === DETECTOR_STATE.RUNNING || detector.curState === DETECTOR_STATE.INIT ); diff --git a/public/pages/DetectorsList/containers/List/List.tsx b/public/pages/DetectorsList/containers/List/List.tsx index b101bf97..279916ad 100644 --- a/public/pages/DetectorsList/containers/List/List.tsx +++ b/public/pages/DetectorsList/containers/List/List.tsx @@ -22,14 +22,10 @@ import { EuiPageBody, } from '@elastic/eui'; import { debounce, get, isEmpty } from 'lodash'; -import queryString from 'query-string'; +import queryString from 'querystring'; import React, { useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { RouteComponentProps } from 'react-router'; -//@ts-ignore -import chrome from 'ui/chrome'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; import { CatIndex, GetDetectorsQueryParams, @@ -90,6 +86,8 @@ import { NO_PERMISSIONS_KEY_WORD, prettifyErrorMessage, } from '../../../../../server/utils/helpers'; +import { CoreStart } from '../../../../../../../src/core/public'; +import { CoreServicesContext } from '../../../../components/CoreServices/CoreServices'; export interface ListRouterParams { from: string; @@ -121,6 +119,7 @@ interface ListActionsState { } export const DetectorList = (props: ListProps) => { + const core = React.useContext(CoreServicesContext) as CoreStart; const dispatch = useDispatch(); const allDetectors = useSelector((state: AppState) => state.ad.detectorList); const allMonitors = useSelector((state: AppState) => state.alerting.monitors); @@ -187,8 +186,9 @@ export const DetectorList = (props: ListProps) => { errorGettingDetectors !== SINGLE_DETECTOR_ERROR_MSG ) { console.error(errorGettingDetectors); - toastNotifications.addDanger( - errorGettingDetectors.includes(NO_PERMISSIONS_KEY_WORD) + core.notifications.toasts.addDanger( + typeof errorGettingDetectors === 'string' && + errorGettingDetectors.includes(NO_PERMISSIONS_KEY_WORD) ? prettifyErrorMessage(errorGettingDetectors) : 'Unable to get all detectors' ); @@ -210,7 +210,7 @@ export const DetectorList = (props: ListProps) => { // Set breadcrumbs on page initialization useEffect(() => { - chrome.breadcrumbs.set([ + core.chrome.setBreadcrumbs([ BREADCRUMBS.ANOMALY_DETECTOR, BREADCRUMBS.DETECTORS, ]); @@ -404,7 +404,7 @@ export const DetectorList = (props: ListProps) => { affectedMonitors: {}, }); } else { - toastNotifications.addWarning( + core.notifications.toasts.addWarning( 'All selected detectors are unable to start. Make sure selected \ detectors have features and are not already running' ); @@ -427,7 +427,7 @@ export const DetectorList = (props: ListProps) => { affectedMonitors: validMonitors, }); } else { - toastNotifications.addWarning( + core.notifications.toasts.addWarning( 'All selected detectors are unable to stop. Make sure selected \ detectors are already running' ); @@ -450,7 +450,7 @@ export const DetectorList = (props: ListProps) => { affectedMonitors: validMonitors, }); } else { - toastNotifications.addWarning( + core.notifications.toasts.addWarning( 'No detectors selected. Please select detectors to delete' ); } @@ -467,12 +467,12 @@ export const DetectorList = (props: ListProps) => { }); await Promise.all(promises) .then(() => { - toastNotifications.addSuccess( + core.notifications.toasts.addSuccess( 'All selected detectors have been started successfully' ); }) .catch((error) => { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( `Error starting all selected detectors: ${error}` ) @@ -494,13 +494,13 @@ export const DetectorList = (props: ListProps) => { }); await Promise.all(promises) .then(() => { - toastNotifications.addSuccess( + core.notifications.toasts.addSuccess( 'All selected detectors have been stopped successfully' ); if (listener) listener.onSuccess(); }) .catch((error) => { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( `Error stopping all selected detectors: ${error}` ) @@ -526,12 +526,12 @@ export const DetectorList = (props: ListProps) => { }); await Promise.all(promises) .then(() => { - toastNotifications.addSuccess( + core.notifications.toasts.addSuccess( 'All selected detectors have been deleted successfully' ); }) .catch((error) => { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( `Error deleting all selected detectors: ${error}` ) diff --git a/public/pages/DetectorsList/containers/List/__tests__/List.test.tsx b/public/pages/DetectorsList/containers/List/__tests__/List.test.tsx index 052f448e..cb935ef8 100644 --- a/public/pages/DetectorsList/containers/List/__tests__/List.test.tsx +++ b/public/pages/DetectorsList/containers/List/__tests__/List.test.tsx @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -import { render, wait, getByTestId, getByRole } from '@testing-library/react'; +import { render, wait } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import moment from 'moment'; import React from 'react'; @@ -25,7 +25,7 @@ import { RouteComponentProps, Switch, } from 'react-router-dom'; -import { httpClientMock } from '../../../../../../test/mocks'; +import { httpClientMock, coreServicesMock } from '../../../../../../test/mocks'; import configureStore from '../../../../../redux/configureStore'; import { Detectors, @@ -33,6 +33,7 @@ import { } from '../../../../../redux/reducers/ad'; import { DetectorList, ListRouterParams } from '../List'; import { DETECTOR_STATE } from '../../../../../utils/constants'; +import { CoreServicesContext } from '../../../../../components/CoreServices/CoreServices'; const renderWithRouter = ( initialAdState: Detectors = initialDetectorsState @@ -45,7 +46,9 @@ const renderWithRouter = ( exact path="/detectors" render={(props: RouteComponentProps) => ( - + + + )} /> @@ -62,7 +65,8 @@ describe(' spec', () => { describe('Empty results', () => { test('renders in loading state if detectors are being fetched', async () => { httpClientMock.get = jest.fn().mockResolvedValue({ - data: { ok: true, response: { detectorList: [], totalDetectors: 0 } }, + ok: true, + response: { detectorList: [], totalDetectors: 0 }, }); const { getByText } = renderWithRouter({ ...initialDetectorsState, @@ -72,7 +76,8 @@ describe(' spec', () => { }); test('should display empty message when list is empty', async () => { httpClientMock.get = jest.fn().mockResolvedValue({ - data: { ok: true, response: { detectorList: [], totalDetectors: 0 } }, + ok: true, + response: { detectorList: [], totalDetectors: 0 }, }); const { getByText } = renderWithRouter({ ...initialDetectorsState, @@ -97,12 +102,10 @@ describe(' spec', () => { }; }); httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectorList: randomDetectors, + totalDetectors: randomDetectors.length, }, }); @@ -152,12 +155,10 @@ describe(' spec', () => { randomDetectors[0].curState = DETECTOR_STATE.RUNNING; httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectorList: randomDetectors, + totalDetectors: randomDetectors.length, }, }); @@ -242,12 +243,10 @@ describe(' spec', () => { }; }); httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectorList: randomDetectors, + totalDetectors: randomDetectors.length, }, }); @@ -285,12 +284,10 @@ describe(' spec', () => { }; }); httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectorList: randomDetectors, + totalDetectors: randomDetectors.length, }, }); @@ -350,12 +347,10 @@ describe(' spec', () => { }, ]; httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectorList: randomDetectors, + totalDetectors: randomDetectors.length, }, }); const { getByText } = renderWithRouter({ @@ -392,12 +387,10 @@ describe(' spec', () => { }, ]; httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectorList: randomDetectors, + totalDetectors: randomDetectors.length, }, }); const { @@ -427,12 +420,10 @@ describe(' spec', () => { }, ]; httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectorList: randomDetectors, + totalDetectors: randomDetectors.length, }, }); const { getByText, getByTestId, getAllByRole } = renderWithRouter(); @@ -456,12 +447,10 @@ describe(' spec', () => { }, ]; httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectorList: randomDetectors, + totalDetectors: randomDetectors.length, }, }); const { @@ -491,12 +480,10 @@ describe(' spec', () => { }, ]; httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectorList: randomDetectors, + totalDetectors: randomDetectors.length, }, }); const { getByText, getByTestId, getAllByRole } = renderWithRouter(); @@ -566,12 +553,10 @@ describe(' spec', () => { }, ]; httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectorList: randomDetectors, + totalDetectors: randomDetectors.length, }, }); const { getByText, getByTestId, getAllByRole } = renderWithRouter(); diff --git a/public/pages/EditFeatures/components/CategoryField/CategoryField.tsx b/public/pages/EditFeatures/components/CategoryField/CategoryField.tsx index 13c0e206..718fa804 100644 --- a/public/pages/EditFeatures/components/CategoryField/CategoryField.tsx +++ b/public/pages/EditFeatures/components/CategoryField/CategoryField.tsx @@ -32,15 +32,11 @@ import { Field, FieldProps } from 'formik'; import { get, isEmpty } from 'lodash'; import React, { useState, useEffect } from 'react'; import ContentPanel from '../../../../components/ContentPanel/ContentPanel'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; import { isInvalid, getError, validateCategoryField, } from '../../../../utils/utils'; -//@ts-ignore -import chrome from 'ui/chrome'; interface CategoryFieldProps { isHCDetector: boolean; diff --git a/public/pages/EditFeatures/components/ConfirmModal/SaveFeaturesConfirmModal.tsx b/public/pages/EditFeatures/components/ConfirmModal/SaveFeaturesConfirmModal.tsx index e06a49bd..7d3ffff2 100644 --- a/public/pages/EditFeatures/components/ConfirmModal/SaveFeaturesConfirmModal.tsx +++ b/public/pages/EditFeatures/components/ConfirmModal/SaveFeaturesConfirmModal.tsx @@ -20,10 +20,6 @@ import { EuiRadioGroup, } from '@elastic/eui'; import React from 'react'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; -//@ts-ignore -import chrome from 'ui/chrome'; import { ConfirmModal } from '../../../DetectorDetail/components/ConfirmModal/ConfirmModal'; import { SAVE_FEATURE_OPTIONS } from '../../utils/constants'; diff --git a/public/pages/EditFeatures/components/CustomAggregation/__tests__/CustomAggregation.test.tsx b/public/pages/EditFeatures/components/CustomAggregation/__tests__/CustomAggregation.test.tsx index 7ce7109c..4be06f63 100644 --- a/public/pages/EditFeatures/components/CustomAggregation/__tests__/CustomAggregation.test.tsx +++ b/public/pages/EditFeatures/components/CustomAggregation/__tests__/CustomAggregation.test.tsx @@ -21,17 +21,21 @@ import { mockedStore } from '../../../../../redux/utils/testUtils'; import { Formik } from 'formik'; import { FeaturesFormikValues } from '../../../../EditFeatures/containers/utils/formikToFeatures'; import { INITIAL_VALUES } from '../../../../EditFeatures/utils/constants'; +import { CoreServicesContext } from '../../../../../components/CoreServices/CoreServices'; +import { coreServicesMock } from '../../../../../../test/mocks'; const renderWithFormik = (initialValue: FeaturesFormikValues) => ({ ...render( - - {formikProps => ( -
- -
- )} -
+ + + {(formikProps) => ( +
+ +
+ )} +
+
), }); diff --git a/public/pages/EditFeatures/containers/EditFeatures.tsx b/public/pages/EditFeatures/containers/EditFeatures.tsx index 2be235f9..5ec09bb2 100644 --- a/public/pages/EditFeatures/containers/EditFeatures.tsx +++ b/public/pages/EditFeatures/containers/EditFeatures.tsx @@ -45,8 +45,6 @@ import React, { Fragment, useState, useEffect, useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { RouteComponentProps } from 'react-router-dom'; import ContentPanel from '../../../components/ContentPanel/ContentPanel'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; import { AppState } from '../../../redux/reducers'; import { updateDetector, startDetector } from '../../../redux/reducers/ad'; import { getMappings } from '../../../redux/reducers/elasticsearch'; @@ -59,8 +57,6 @@ import { } from '../../../utils/utils'; import { prepareDetector } from './utils/formikToFeatures'; import { useFetchDetectorInfo } from '../../createDetector/hooks/useFetchDetectorInfo'; -//@ts-ignore -import chrome from 'ui/chrome'; import { BREADCRUMBS, MAX_FEATURE_NUM } from '../../../utils/constants'; import { useHideSideNavBar } from '../../main/hooks/useHideSideNavBar'; import { FeatureAccordion } from '../components/FeatureAccordion/FeatureAccordion'; @@ -78,6 +74,8 @@ import { import { SampleAnomalies } from './SampleAnomalies'; import { CategoryField } from '../components/CategoryField/CategoryField'; import { prettifyErrorMessage } from '../../../../server/utils/helpers'; +import { CoreStart } from '../../../../../../src/core/public'; +import { CoreServicesContext } from '../../../components/CoreServices/CoreServices'; interface FeaturesRouterProps { detectorId?: string; @@ -86,6 +84,7 @@ interface FeaturesRouterProps { interface EditFeaturesProps extends RouteComponentProps {} export function EditFeatures(props: EditFeaturesProps) { + const core = React.useContext(CoreServicesContext) as CoreStart; const dispatch = useDispatch(); useHideSideNavBar(true, false); const detectorId = get(props, 'match.params.detectorId', ''); @@ -121,7 +120,7 @@ export function EditFeatures(props: EditFeaturesProps) { }, [detector]); useEffect(() => { - chrome.breadcrumbs.set([ + core.chrome.setBreadcrumbs([ BREADCRUMBS.ANOMALY_DETECTOR, BREADCRUMBS.DETECTORS, { @@ -220,11 +219,11 @@ export function EditFeatures(props: EditFeaturesProps) { const handleStartAdJob = async (detectorId: string) => { try { await dispatch(startDetector(detectorId)); - toastNotifications.addSuccess( + core.notifications.toasts.addSuccess( `Detector job has been started successfully` ); } catch (err) { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( getErrorMessage(err, 'There was a problem starting detector job') ) @@ -246,14 +245,14 @@ export function EditFeatures(props: EditFeaturesProps) { detector ); await dispatch(updateDetector(detector.id, requestBody)); - toastNotifications.addSuccess('Feature updated'); + core.notifications.toasts.addSuccess('Feature updated'); if (saveFeatureOption === 'start_ad_job') { handleStartAdJob(detector.id); } setSubmitting(false); props.history.push(`/detectors/${detectorId}/configurations`); } catch (err) { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( getErrorMessage(err, 'There was a problem updating feature') ) @@ -269,7 +268,7 @@ export function EditFeatures(props: EditFeaturesProps) { setSubmitting: any ) => { if (detector.enabled) { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( "Can't edit feature as the detector is running" ); return; diff --git a/public/pages/EditFeatures/containers/SampleAnomalies.tsx b/public/pages/EditFeatures/containers/SampleAnomalies.tsx index c7e617e2..d6ee0eb9 100644 --- a/public/pages/EditFeatures/containers/SampleAnomalies.tsx +++ b/public/pages/EditFeatures/containers/SampleAnomalies.tsx @@ -35,8 +35,6 @@ import { } from '../../AnomalyCharts/utils/anomalyChartUtils'; import React, { Fragment, useCallback, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; import ContentPanel from '../../../components/ContentPanel/ContentPanel'; import { DateRange, Detector } from '../../../models/interfaces'; import { AppState } from '../../../redux/reducers'; @@ -52,6 +50,8 @@ import { prepareDetector, } from './utils/formikToFeatures'; import { prettifyErrorMessage } from '../../../../server/utils/helpers'; +import { CoreStart } from '../../../../../../src/core/public'; +import { CoreServicesContext } from '../../../components/CoreServices/CoreServices'; interface SampleAnomaliesProps { detector: Detector; @@ -63,6 +63,7 @@ interface SampleAnomaliesProps { } export function SampleAnomalies(props: SampleAnomaliesProps) { + const core = React.useContext(CoreServicesContext) as CoreStart; const dispatch = useDispatch(); useHideSideNavBar(true, false); @@ -144,7 +145,7 @@ export function SampleAnomalies(props: SampleAnomaliesProps) { } catch (err) { console.error(`Fail to preview detector ${detector.id}`, err); setIsLoading(false); - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( getPreviewErrorMessage(err, 'There was a problem previewing detector') ) diff --git a/public/pages/SampleData/containers/SampleData/SampleData.tsx b/public/pages/SampleData/containers/SampleData/SampleData.tsx index 816da231..d2aec241 100644 --- a/public/pages/SampleData/containers/SampleData/SampleData.tsx +++ b/public/pages/SampleData/containers/SampleData/SampleData.tsx @@ -23,10 +23,6 @@ import { } from '@elastic/eui'; import React, { Fragment, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -//@ts-ignore -import chrome from 'ui/chrome'; -//@ts-ignore -import { toastNotifications } from 'ui/notify'; import { BREADCRUMBS, SAMPLE_TYPE } from '../../../../utils/constants'; import { GET_SAMPLE_DETECTORS_QUERY_PARAMS, @@ -54,8 +50,11 @@ import { import { SampleDataBox } from '../../components/SampleDataBox/SampleDataBox'; import { SampleDetailsFlyout } from '../../components/SampleDetailsFlyout/SampleDetailsFlyout'; import { prettifyErrorMessage } from '../../../../../server/utils/helpers'; +import { CoreStart } from '../../../../../../../src/core/public'; +import { CoreServicesContext } from '../../../../components/CoreServices/CoreServices'; export const SampleData = () => { + const core = React.useContext(CoreServicesContext) as CoreStart; const dispatch = useDispatch(); const visibleIndices = useSelector( (state: AppState) => state.elasticsearch.indices @@ -99,7 +98,7 @@ export const SampleData = () => { // Set breadcrumbs on page initialization useEffect(() => { - chrome.breadcrumbs.set([ + core.chrome.setBreadcrumbs([ BREADCRUMBS.ANOMALY_DETECTOR, BREADCRUMBS.SAMPLE_DETECTORS, ]); @@ -136,7 +135,7 @@ export const SampleData = () => { if (!errorDuringAction) { await dispatch(createSampleData(sampleType)).catch((error: any) => { errorDuringAction = true; - errorMessage = prettifyErrorMessage(error); + errorMessage = prettifyErrorMessage(error.message); console.error('Error bulk inserting data: ', errorMessage); }); } @@ -145,17 +144,17 @@ export const SampleData = () => { if (!errorDuringAction) { await dispatch(createDetector(detectorConfig)) .then(function (response: any) { - const detectorId = response.data.response.id; + const detectorId = response.response.id; // Start the detector dispatch(startDetector(detectorId)).catch((error: any) => { errorDuringAction = true; - errorMessage = prettifyErrorMessage(error.data.message); + errorMessage = prettifyErrorMessage(error.message); console.error('Error starting sample detector: ', errorMessage); }); }) .catch((error: any) => { errorDuringAction = true; - errorMessage = prettifyErrorMessage(error); + errorMessage = prettifyErrorMessage(error.message); console.error('Error creating sample detector: ', errorMessage); }); } @@ -164,9 +163,11 @@ export const SampleData = () => { getAllSampleIndices(); setLoadingState(false); if (!errorDuringAction) { - toastNotifications.addSuccess('Successfully loaded sample detector'); + core.notifications.toasts.addSuccess( + 'Successfully loaded sample detector' + ); } else { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( `Unable to load all sample data, please try again. ${errorMessage}` ); } diff --git a/public/pages/SampleData/containers/SampleData/__tests__/SampleData.test.tsx b/public/pages/SampleData/containers/SampleData/__tests__/SampleData.test.tsx index 76da8ef4..337f0f79 100644 --- a/public/pages/SampleData/containers/SampleData/__tests__/SampleData.test.tsx +++ b/public/pages/SampleData/containers/SampleData/__tests__/SampleData.test.tsx @@ -23,13 +23,14 @@ import { Route, Switch, } from 'react-router-dom'; -import { httpClientMock } from '../../../../../../test/mocks'; +import { httpClientMock, coreServicesMock } from '../../../../../../test/mocks'; import configureStore from '../../../../../redux/configureStore'; import { Detectors, initialDetectorsState, } from '../../../../../redux/reducers/ad'; import { sampleHttpResponses } from '../../../utils/constants'; +import { CoreServicesContext } from '../../../../../components/CoreServices/CoreServices'; const renderWithRouter = ( initialAdState: Detectors = initialDetectorsState @@ -38,7 +39,15 @@ const renderWithRouter = ( - } /> + ( + + {' '} + + )} + /> @@ -50,9 +59,12 @@ describe(' spec', () => { jest.clearAllMocks(); describe('No sample detectors created', () => { test('renders component', async () => { - httpClientMock.get = jest.fn().mockResolvedValue({ - data: { ok: true, response: { detectorList: [], totalDetectors: 0 } }, - }); + httpClientMock.get = jest + .fn() + .mockResolvedValue({ + ok: true, + response: { detectorList: [], totalDetectors: 0 }, + }); const { container, getByText, queryByText } = renderWithRouter(); expect(container).toMatchSnapshot(); getByText('Sample detectors'); @@ -69,20 +81,18 @@ describe(' spec', () => { jest.clearAllMocks(); test('renders component with sample detector', async () => { httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: [ - { - id: 'sample-detector-id', - name: sampleHttpResponses.detectorName, - indices: sampleHttpResponses.indexName, - totalAnomalies: 0, - lastActiveAnomaly: 0, - }, - ], - totalDetectors: 1, - }, + ok: true, + response: { + detectorList: [ + { + id: 'sample-detector-id', + name: sampleHttpResponses.detectorName, + indices: sampleHttpResponses.indexName, + totalAnomalies: 0, + lastActiveAnomaly: 0, + }, + ], + totalDetectors: 1, }, }); const { container, getByText, getAllByText } = renderWithRouter(); @@ -98,20 +108,18 @@ describe(' spec', () => { }); test('renders component with non-sample detector', async () => { httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectorList: [ - { - id: 'non-sample-detector-id', - name: 'non-sample-detector', - indices: 'non-sample-index', - totalAnomalies: 0, - lastActiveAnomaly: 0, - }, - ], - totalDetectors: 1, - }, + ok: true, + response: { + detectorList: [ + { + id: 'non-sample-detector-id', + name: 'non-sample-detector', + indices: 'non-sample-index', + totalAnomalies: 0, + lastActiveAnomaly: 0, + }, + ], + totalDetectors: 1, }, }); const { container, getByText, queryByText } = renderWithRouter(); diff --git a/public/pages/SampleData/containers/SampleData/__tests__/__snapshots__/SampleData.test.tsx.snap b/public/pages/SampleData/containers/SampleData/__tests__/__snapshots__/SampleData.test.tsx.snap index 77f3ee13..010627d5 100644 --- a/public/pages/SampleData/containers/SampleData/__tests__/__snapshots__/SampleData.test.tsx.snap +++ b/public/pages/SampleData/containers/SampleData/__tests__/__snapshots__/SampleData.test.tsx.snap @@ -398,6 +398,7 @@ exports[` spec No sample detectors created renders component 1`] = class="euiSpacer euiSpacer--m" />
+
`; @@ -811,6 +812,7 @@ exports[` spec Some detectors created renders component with non-s class="euiSpacer euiSpacer--m" /> + `; @@ -1243,5 +1245,6 @@ exports[` spec Some detectors created renders component with sampl class="euiSpacer euiSpacer--m" /> + `; diff --git a/public/pages/createDetector/components/DataFilters/DataFilter.tsx b/public/pages/createDetector/components/DataFilters/DataFilter.tsx index 0e77b5c7..de4936b8 100644 --- a/public/pages/createDetector/components/DataFilters/DataFilter.tsx +++ b/public/pages/createDetector/components/DataFilters/DataFilter.tsx @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -import { EuiFormRow, EuiHorizontalRule, EuiSelect } from '@elastic/eui'; +import { EuiHorizontalRule, EuiSelect } from '@elastic/eui'; import { Field, FieldProps, FormikProps } from 'formik'; import React, { Fragment } from 'react'; import { getError, isInvalid, required } from '../../../../utils/utils'; @@ -23,6 +23,7 @@ import { SimpleFilter } from './SimpleFilter'; import { QueryDataFilter } from './QueryDataFilter'; import { FILTER_TYPES } from '../../../../models/interfaces'; import { FormattedFormRow } from '../FormattedFormRow/FormattedFormRow'; + interface DataFilterProps { formikProps: FormikProps; } diff --git a/public/pages/createDetector/components/DataFilters/SimpleFilter.tsx b/public/pages/createDetector/components/DataFilters/SimpleFilter.tsx index a8641088..eb2bc370 100644 --- a/public/pages/createDetector/components/DataFilters/SimpleFilter.tsx +++ b/public/pages/createDetector/components/DataFilters/SimpleFilter.tsx @@ -140,7 +140,9 @@ export const SimpleFilter = (props: DataFilterProps) => { {values.filters.map((filter: UIFilter, index: number) => { return ( - {get(props, 'formikProps.values.index.0.label', '').includes(':') ? ( + {get(props, 'formikProps.values.index.0.label', '').includes( + ':' + ) ? (
({ ...render( @@ -40,13 +42,15 @@ const renderDataFilter = (initialValue: ADFormikValues) => ({ }, })} > - - {formikProps => ( -
- -
- )} -
+ + + {(formikProps) => ( +
+ +
+ )} +
+
), }); diff --git a/public/pages/createDetector/containers/CreateDetector.tsx b/public/pages/createDetector/containers/CreateDetector.tsx index 9d138725..f39b6b27 100644 --- a/public/pages/createDetector/containers/CreateDetector.tsx +++ b/public/pages/createDetector/containers/CreateDetector.tsx @@ -31,10 +31,7 @@ import React, { Fragment, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { RouteComponentProps } from 'react-router'; import { Dispatch } from 'redux'; -//@ts-ignore -import chrome from 'ui/chrome'; -//@ts-ignore -import { toastNotifications } from 'ui/notify'; +import { CoreStart } from '../../../../../../src/core/public'; import { APIAction } from '../../../redux/middleware/types'; import { createDetector, @@ -60,6 +57,7 @@ import { SampleDataCallout } from '../../SampleData/components/SampleDataCallout import { containsDetectorsIndex } from '../../SampleData/utils/helpers'; import { clearModelConfiguration } from './utils/helpers'; import { prettifyErrorMessage } from '../../../../server/utils/helpers'; +import { CoreServicesContext } from '../../../components/CoreServices/CoreServices'; interface CreateRouterProps { detectorId?: string; @@ -70,6 +68,7 @@ interface CreateADProps extends RouteComponentProps { } export function CreateDetector(props: CreateADProps) { + const core = React.useContext(CoreServicesContext) as CoreStart; useHideSideNavBar(true, false); const dispatch = useDispatch>(); const detectorId: string = get(props, 'match.params.detectorId', ''); @@ -114,12 +113,12 @@ export function CreateDetector(props: CreateADProps) { href: `#/detectors/${detectorId}`, }); } - chrome.breadcrumbs.set(breadCrumbs); + core.chrome.setBreadcrumbs(breadCrumbs); }); // If no detector found with ID, redirect it to list useEffect(() => { if (props.isEdit && hasError) { - toastNotifications.addDanger('Unable to find detector for edit'); + core.notifications.toasts.addDanger('Unable to find detector for edit'); props.history.push(`/detectors`); } }, [props.isEdit]); @@ -131,12 +130,12 @@ export function CreateDetector(props: CreateADProps) { ? clearModelConfiguration(detectorToBeUpdated) : detectorToBeUpdated; await dispatch(updateDetector(detectorId, preparedDetector)); - toastNotifications.addSuccess( + core.notifications.toasts.addSuccess( `Detector updated: ${preparedDetector.name}` ); props.history.push(`/detectors/${detectorId}/configurations/`); } catch (err) { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( getErrorMessage(err, 'There was a problem updating detector') ) @@ -146,23 +145,23 @@ export function CreateDetector(props: CreateADProps) { const handleCreate = async (detectorToBeCreated: Detector) => { try { const detectorResp = await dispatch(createDetector(detectorToBeCreated)); - toastNotifications.addSuccess( + core.notifications.toasts.addSuccess( `Detector created: ${detectorToBeCreated.name}` ); props.history.push( - `/detectors/${detectorResp.data.response.id}/configurations/` + `/detectors/${detectorResp.response.id}/configurations/` ); } catch (err) { const resp = await dispatch(getDetectorCount()); - const totalDetectors = get(resp, 'data.response.count', 0); + const totalDetectors = get(resp, 'response.count', 0); if (totalDetectors === MAX_DETECTORS) { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( 'Cannot create detector - limit of ' + MAX_DETECTORS + ' detectors reached' ); } else { - toastNotifications.addDanger( + core.notifications.toasts.addDanger( prettifyErrorMessage( getErrorMessage(err, 'There was a problem creating detector') ) @@ -201,7 +200,7 @@ export function CreateDetector(props: CreateADProps) { } //TODO::Avoid making call if value is same const resp = await dispatch(matchDetector(detectorName)); - const match = get(resp, 'data.response.match', false); + const match = get(resp, 'response.match', false); if (!match) { return undefined; } diff --git a/public/pages/createDetector/containers/__tests__/CreateDetector.test.tsx b/public/pages/createDetector/containers/__tests__/CreateDetector.test.tsx index 3a6e76e4..bce6d37e 100644 --- a/public/pages/createDetector/containers/__tests__/CreateDetector.test.tsx +++ b/public/pages/createDetector/containers/__tests__/CreateDetector.test.tsx @@ -22,13 +22,12 @@ import { Switch, } from 'react-router-dom'; import { render, fireEvent, wait } from '@testing-library/react'; -// @ts-ignore -import { toastNotifications } from 'ui/notify'; import { CreateDetector } from '../CreateDetector'; import { getRandomDetector } from '../../../../redux/reducers/__tests__/utils'; import configureStore from '../../../../redux/configureStore'; -import { httpClientMock } from '../../../../../test/mocks'; +import { httpClientMock, coreServicesMock } from '../../../../../test/mocks'; import userEvent from '@testing-library/user-event'; +import { CoreServicesContext } from '../../../../components/CoreServices/CoreServices'; const renderWithRouter = (isEdit: boolean = false) => ({ ...render( @@ -37,7 +36,9 @@ const renderWithRouter = (isEdit: boolean = false) => ({ ( - + + + )} /> @@ -53,14 +54,12 @@ describe(' spec', () => { describe('create detector', () => { test('renders the component', () => { httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - indices: [ - { index: 'hello', health: 'green' }, - { index: 'world', health: 'yellow' }, - ], - }, + ok: true, + response: { + indices: [ + { index: 'hello', health: 'green' }, + { index: 'world', health: 'yellow' }, + ], }, }); const { container } = renderWithRouter(); @@ -69,14 +68,12 @@ describe(' spec', () => { test('validate all required field', async () => { httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - indices: [ - { index: 'hello', health: 'green' }, - { index: 'world', health: 'yellow' }, - ], - }, + ok: true, + response: { + indices: [ + { index: 'hello', health: 'green' }, + { index: 'world', health: 'yellow' }, + ], }, }); const { getByText } = renderWithRouter(); @@ -90,10 +87,8 @@ describe(' spec', () => { test('prevent duplicate detector name', async () => { const randomDetector = getRandomDetector(); httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { count: 0, match: true }, - }, + ok: true, + response: { count: 0, match: true }, }); const { getByPlaceholderText, getByText } = renderWithRouter(); fireEvent.focus(getByPlaceholderText('Enter detector name')); @@ -111,21 +106,17 @@ describe(' spec', () => { const randomDetector = getRandomDetector(); //Mocked name validation search detector httpClientMock.post = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { detectors: [randomDetector], totalDetectors: 1 }, - }, + ok: true, + response: { detectors: [randomDetector], totalDetectors: 1 }, }); //Mocked get indices httpClientMock.get = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - indices: [ - { index: 'hello', health: 'green' }, - { index: 'world', health: 'yellow' }, - ], - }, + ok: true, + response: { + indices: [ + { index: 'hello', health: 'green' }, + { index: 'world', health: 'yellow' }, + ], }, }); const { getByPlaceholderText } = renderWithRouter(); diff --git a/public/pages/main/Main.tsx b/public/pages/main/Main.tsx index 22e71a41..a171ebe7 100644 --- a/public/pages/main/Main.tsx +++ b/public/pages/main/Main.tsx @@ -27,6 +27,8 @@ import { APP_PATH } from '../../utils/constants'; import { DetectorDetail } from '../DetectorDetail'; import { EditFeatures } from '../EditFeatures/containers/EditFeatures'; import { DashboardOverview } from '../Dashboard/Container/DashboardOverview'; +import { CoreServicesConsumer } from '../../components/CoreServices/CoreServices'; +import { CoreStart } from '../../../../../src/core/public'; enum Navigation { AnomalyDetection = 'Anomaly detection', @@ -76,56 +78,64 @@ export function Main(props: MainProps) { ]; return ( - - - - - } - /> - ) => ( - - )} - /> - } - /> - ( - - )} - /> - ( - - )} - /> - } - /> - ( - - )} - /> - - - - + + {(core: CoreStart | null) => + core && ( + + + + + } + /> + ) => ( + + )} + /> + } + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + + + + + ) + } + ); } diff --git a/public/pages/utils/anomalyResultUtils.ts b/public/pages/utils/anomalyResultUtils.ts index 08529618..efbabb9f 100644 --- a/public/pages/utils/anomalyResultUtils.ts +++ b/public/pages/utils/anomalyResultUtils.ts @@ -413,7 +413,7 @@ export const getBucketizedAnomalyResultsQuery = ( export const parseBucketizedAnomalyResults = (result: any): Anomalies => { const rawAnomalies = get( result, - 'data.response.aggregations.bucketized_anomaly_grade.buckets', + 'response.aggregations.bucketized_anomaly_grade.buckets', [] ) as any[]; let anomalies = [] as AnomalyData[]; @@ -460,7 +460,7 @@ export const parseAnomalySummary = ( ): AnomalySummary => { const anomalyCount = get( anomalySummaryResult, - 'data.response.aggregations.count_anomalies.value', + 'response.aggregations.count_anomalies.value', 0 ); return { @@ -469,7 +469,7 @@ export const parseAnomalySummary = ( ? toFixedNumberForAnomaly( get( anomalySummaryResult, - 'data.response.aggregations.min_anomaly_grade.value' + 'response.aggregations.min_anomaly_grade.value' ) ) : 0, @@ -477,7 +477,7 @@ export const parseAnomalySummary = ( ? toFixedNumberForAnomaly( get( anomalySummaryResult, - 'data.response.aggregations.max_anomaly_grade.value' + 'response.aggregations.max_anomaly_grade.value' ) ) : 0, @@ -485,7 +485,7 @@ export const parseAnomalySummary = ( ? toFixedNumberForAnomaly( get( anomalySummaryResult, - 'data.response.aggregations.min_confidence.value' + 'response.aggregations.min_confidence.value' ) ) : 0, @@ -493,7 +493,7 @@ export const parseAnomalySummary = ( ? toFixedNumberForAnomaly( get( anomalySummaryResult, - 'data.response.aggregations.max_confidence.value' + 'response.aggregations.max_confidence.value' ) ) : 0, @@ -501,7 +501,7 @@ export const parseAnomalySummary = ( ? minuteDateFormatter( get( anomalySummaryResult, - 'data.response.aggregations.max_data_end_time.value' + 'response.aggregations.max_data_end_time.value' ) ) : '', @@ -511,11 +511,7 @@ export const parseAnomalySummary = ( export const parsePureAnomalies = ( anomalySummaryResult: any ): AnomalyData[] => { - const anomaliesHits = get( - anomalySummaryResult, - 'data.response.hits.hits', - [] - ); + const anomaliesHits = get(anomalySummaryResult, 'response.hits.hits', []); const anomalies = [] as AnomalyData[]; if (anomaliesHits.length > 0) { anomaliesHits.forEach((item: any) => { diff --git a/public/plugin.ts b/public/plugin.ts new file mode 100644 index 00000000..bb2394d9 --- /dev/null +++ b/public/plugin.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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 { + AppMountParameters, + CoreSetup, + CoreStart, + Plugin, + PluginInitializerContext, + DEFAULT_APP_CATEGORIES, +} from '../../../src/core/public'; +import { + AnomalyDetectionKibanaPluginSetup, + AnomalyDetectionKibanaPluginStart, +} from '.'; + +export class AnomalyDetectionKibanaPlugin + implements + Plugin< + AnomalyDetectionKibanaPluginSetup, + AnomalyDetectionKibanaPluginStart + > { + constructor(private readonly initializerContext: PluginInitializerContext) { + // can retrieve config from initializerContext + } + + public setup(core: CoreSetup): AnomalyDetectionKibanaPluginSetup { + core.application.register({ + id: 'opendistro-anomaly-detection-kibana', + title: 'Anomaly Detection', + category: DEFAULT_APP_CATEGORIES.kibana, + order: 8030, + mount: async (params: AppMountParameters) => { + const { renderApp } = await import('./anomaly_detection_app'); + const [coreStart, depsStart] = await core.getStartServices(); + return renderApp(coreStart, params); + }, + }); + return {}; + } + + public start(core: CoreStart): AnomalyDetectionKibanaPluginStart { + return {}; + } +} diff --git a/public/redux/configureStore.ts b/public/redux/configureStore.ts index 319bbbaf..c3ea9f10 100644 --- a/public/redux/configureStore.ts +++ b/public/redux/configureStore.ts @@ -1,5 +1,5 @@ /* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. @@ -15,13 +15,16 @@ import { createStore, applyMiddleware, compose } from 'redux'; import clientMiddleware from './middleware/clientMiddleware'; -import { IHttpService } from './middleware/types'; +import { HttpSetup } from './middleware/types'; import reducers, { AppState } from './reducers'; -function configureStore(httpClient: IHttpService) { +function configureStore(httpClient: HttpSetup) { const middleWares = [clientMiddleware(httpClient)]; - const composeWithReduxDevTools = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; - const store = composeWithReduxDevTools(applyMiddleware(...middleWares))(createStore); + const composeWithReduxDevTools = + (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; + const store = composeWithReduxDevTools(applyMiddleware(...middleWares))( + createStore + ); //@ts-ignore return store(reducers); } diff --git a/public/redux/middleware/clientMiddleware.ts b/public/redux/middleware/clientMiddleware.ts index d3816037..805e6116 100644 --- a/public/redux/middleware/clientMiddleware.ts +++ b/public/redux/middleware/clientMiddleware.ts @@ -14,7 +14,7 @@ */ import { Dispatch, MiddlewareAPI, AnyAction } from 'redux'; -import { IHttpService, APIAction, ThunkAction } from './types'; +import { HttpSetup, APIAction, ThunkAction } from './types'; import { get } from 'lodash'; /* This a middleware for Redux. To understand this read : http://redux.js.org/docs/advanced/Middleware.html @@ -26,7 +26,7 @@ const isAPIAction = ( //TODO: Find better way to define return type and avoid ANY. -export default function clientMiddleware(client: IHttpService) { +export default function clientMiddleware(client: HttpSetup) { return ({ dispatch, getState }: MiddlewareAPI) => ( next: Dispatch ) => async (action: APIAction | ThunkAction | AnyAction): Promise => { diff --git a/public/redux/middleware/types.ts b/public/redux/middleware/types.ts index 200d5865..7a34cb7a 100644 --- a/public/redux/middleware/types.ts +++ b/public/redux/middleware/types.ts @@ -13,12 +13,13 @@ * permissions and limitations under the License. */ -import { IHttpService, IHttpPromise, IHttpResponse } from 'angular'; +import { HttpSetup, HttpResponse } from '../../../../../src/core/public'; import { Action, Dispatch } from 'redux'; import { AppState } from '../reducers'; interface APIAction extends Action { - request: (client: IHttpService) => IHttpPromise>; + // NOTE: there is no HttpPromise equivalent in core, using TypeScript's default Promise. Will need to confirm this still works as expected + request: (client: HttpSetup) => Promise>; [key: string]: any; } @@ -38,9 +39,8 @@ type ThunkAction = ( ) => void; export { - IHttpPromise, - IHttpResponse, - IHttpService, + HttpSetup, + HttpResponse, APIAction, APIResponseAction, APIErrorAction, diff --git a/public/redux/reducers/__tests__/ad.test.ts b/public/redux/reducers/__tests__/ad.test.ts index 0437c359..71eb43fe 100644 --- a/public/redux/reducers/__tests__/ad.test.ts +++ b/public/redux/reducers/__tests__/ad.test.ts @@ -24,7 +24,7 @@ describe('detector reducer actions', () => { const detectorId = 'randomDetectorID'; httpMockedClient.get = jest .fn() - .mockResolvedValue({ data: { ok: true, response: expectedDetector } }); + .mockResolvedValue({ ok: true, response: expectedDetector }); await store.dispatch(getDetector(detectorId)); const actions = store.getActions(); expect(actions[0].type).toBe('ad/GET_DETECTOR_REQUEST'); @@ -76,7 +76,7 @@ describe('detector reducer actions', () => { const expectedDetector = getRandomDetector(false); httpMockedClient.get = jest .fn() - .mockResolvedValue({ data: { ok: true, response: {} } }); + .mockResolvedValue({ ok: true, response: {} }); await store.dispatch(deleteDetector(expectedDetector.id)); const actions = store.getActions(); expect(actions[0].type).toBe('ad/DELETE_DETECTOR_REQUEST'); @@ -99,7 +99,8 @@ describe('detector reducer actions', () => { test('should invoke [REQUEST, FAILURE]', async () => { const expectedDetector = getRandomDetector(false); httpMockedClient.get = jest.fn().mockRejectedValue({ - data: { ok: false, error: 'Detector is consumed by Monitor' }, + ok: false, + error: 'Detector is consumed by Monitor', }); try { await store.dispatch(deleteDetector(expectedDetector.id)); @@ -128,7 +129,8 @@ describe('detector reducer actions', () => { const expectedDetector = getRandomDetector(); const detectorId = 'randomDetectorID'; httpMockedClient.post = jest.fn().mockResolvedValue({ - data: { ok: true, response: { ...expectedDetector, id: detectorId } }, + ok: true, + response: { ...expectedDetector, id: detectorId }, }); await store.dispatch(createDetector(expectedDetector)); const actions = store.getActions(); @@ -148,10 +150,11 @@ describe('detector reducer actions', () => { }, }, }); - expect(httpMockedClient.post).toHaveBeenCalledWith( - `..${BASE_NODE_API_PATH}/detectors`, - expectedDetector - ); + expect( + httpMockedClient.post + ).toHaveBeenCalledWith(`..${BASE_NODE_API_PATH}/detectors`, { + body: JSON.stringify(expectedDetector), + }); }); test('should invoke [REQUEST, FAILURE]', async () => { @@ -176,7 +179,9 @@ describe('detector reducer actions', () => { }); expect(httpMockedClient.post).toHaveBeenCalledWith( `..${BASE_NODE_API_PATH}/detectors`, - expectedDetector + { + body: JSON.stringify(expectedDetector), + } ); } }); @@ -186,7 +191,8 @@ describe('detector reducer actions', () => { const randomDetector = getRandomDetector(false); const detectorId = randomDetector.id; httpMockedClient.put = jest.fn().mockResolvedValue({ - data: { ok: true, response: { ...randomDetector, id: detectorId } }, + ok: true, + response: { ...randomDetector, id: detectorId }, }); await store.dispatch(updateDetector(detectorId, randomDetector)); const actions = store.getActions(); @@ -211,15 +217,11 @@ describe('detector reducer actions', () => { }, }, }); - expect(httpMockedClient.put).toHaveBeenCalledWith( + expect( + httpMockedClient.put + ).toHaveBeenCalledWith( `..${BASE_NODE_API_PATH}/detectors/${detectorId}`, - randomDetector, - { - params: { - ifPrimaryTerm: randomDetector.primaryTerm, - ifSeqNo: randomDetector.seqNo, - }, - } + { body: JSON.stringify(randomDetector) } ); }); @@ -227,7 +229,8 @@ describe('detector reducer actions', () => { const randomDetector = getRandomDetector(true); const detectorId = randomDetector.id; httpMockedClient.post = jest.fn().mockRejectedValue({ - data: { ok: false, error: 'Invalid primary Term' }, + ok: false, + error: 'Invalid primary Term', }); try { await store.dispatch(updateDetector(detectorId, randomDetector)); @@ -262,12 +265,10 @@ describe('detector reducer actions', () => { const randomDetectors = [getRandomDetector(), getRandomDetector()]; const query = { query: { match: { match_all: {} } } }; httpMockedClient.post = jest.fn().mockResolvedValue({ - data: { - ok: true, - response: { - detectors: randomDetectors, - totalDetectors: randomDetectors.length, - }, + ok: true, + response: { + detectors: randomDetectors, + totalDetectors: randomDetectors.length, }, }); await store.dispatch(searchDetector(query)); @@ -288,7 +289,9 @@ describe('detector reducer actions', () => { }); expect(httpMockedClient.post).toHaveBeenCalledWith( `..${BASE_NODE_API_PATH}/detectors/_search`, - query + { + body: JSON.stringify(query), + } ); }); @@ -296,7 +299,8 @@ describe('detector reducer actions', () => { const randomDetector = getRandomDetector(); const detectorId = randomDetector.id; httpMockedClient.post = jest.fn().mockRejectedValue({ - data: { ok: false, error: 'Invalid primary Term' }, + ok: false, + error: 'Invalid primary Term', }); try { await store.dispatch(updateDetector(detectorId, randomDetector)); diff --git a/public/redux/reducers/__tests__/anomalyResults.test.ts b/public/redux/reducers/__tests__/anomalyResults.test.ts index af14bbeb..ee5d0a19 100644 --- a/public/redux/reducers/__tests__/anomalyResults.test.ts +++ b/public/redux/reducers/__tests__/anomalyResults.test.ts @@ -22,7 +22,7 @@ describe('elasticsearch reducer actions', () => { }; httpMockedClient.get = jest .fn() - .mockResolvedValue({ data: { ok: true, response } }); + .mockResolvedValue({ ok: true, response }); const tempDetectorId = '123'; let queryParams: DetectorResultsQueryParams = { from: 0, @@ -44,16 +44,19 @@ describe('elasticsearch reducer actions', () => { requesting: false, total: response.totalAnomalies, anomalies: response.results, - "featureData": undefined, + featureData: undefined, }); - expect(httpMockedClient.get).toHaveBeenCalledWith( + expect( + httpMockedClient.get + ).toHaveBeenCalledWith( `..${AD_NODE_API.DETECTOR}/${tempDetectorId}/results`, - { params: queryParams } + { query: queryParams } ); }); test('should invoke [REQUEST, FAILURE]', async () => { httpMockedClient.get = jest.fn().mockRejectedValue({ - data: { ok: false, error: 'Something went wrong' }, + ok: false, + error: 'Something went wrong', }); const tempDetectorId = '123'; let queryParams: DetectorResultsQueryParams = { @@ -77,9 +80,11 @@ describe('elasticsearch reducer actions', () => { requesting: false, errorMessage: 'Something went wrong', }); - expect(httpMockedClient.get).toHaveBeenCalledWith( + expect( + httpMockedClient.get + ).toHaveBeenCalledWith( `..${AD_NODE_API.DETECTOR}/${tempDetectorId}/results`, - { params: queryParams } + { query: queryParams } ); } }); diff --git a/public/redux/reducers/__tests__/elasticsearch.test.ts b/public/redux/reducers/__tests__/elasticsearch.test.ts index bd704694..91996f2e 100644 --- a/public/redux/reducers/__tests__/elasticsearch.test.ts +++ b/public/redux/reducers/__tests__/elasticsearch.test.ts @@ -23,7 +23,7 @@ describe('elasticsearch reducer actions', () => { ]; httpMockedClient.get = jest .fn() - .mockResolvedValue({ data: { ok: true, response: { indices } } }); + .mockResolvedValue({ ok: true, response: { indices } }); await store.dispatch(getIndices()); const actions = store.getActions(); @@ -38,13 +38,16 @@ describe('elasticsearch reducer actions', () => { requesting: false, indices, }); - expect(httpMockedClient.get).toHaveBeenCalledWith( - `..${BASE_NODE_API_PATH}/_indices?index=` - ); + expect( + httpMockedClient.get + ).toHaveBeenCalledWith(`..${BASE_NODE_API_PATH}/_indices`, { + query: { index: '' }, + }); }); test('should invoke [REQUEST, FAILURE]', async () => { httpMockedClient.get = jest.fn().mockRejectedValue({ - data: { ok: false, error: 'Something went wrong' }, + ok: false, + error: 'Something went wrong', }); try { await store.dispatch(getIndices()); @@ -62,7 +65,10 @@ describe('elasticsearch reducer actions', () => { errorMessage: 'Something went wrong', }); expect(httpMockedClient.get).toHaveBeenCalledWith( - `..${BASE_NODE_API_PATH}/_indices?index=` + `..${BASE_NODE_API_PATH}/_indices`, + { + query: { index: '' }, + } ); } }); @@ -72,7 +78,7 @@ describe('elasticsearch reducer actions', () => { const aliases = [{ index: 'hello', alias: 'world' }]; httpMockedClient.get = jest .fn() - .mockResolvedValue({ data: { ok: true, response: { aliases } } }); + .mockResolvedValue({ ok: true, response: { aliases } }); await store.dispatch(getAliases()); const actions = store.getActions(); @@ -88,12 +94,16 @@ describe('elasticsearch reducer actions', () => { aliases, }); expect(httpMockedClient.get).toHaveBeenCalledWith( - `..${BASE_NODE_API_PATH}/_aliases?alias=` + `..${BASE_NODE_API_PATH}/_aliases`, + { + query: { alias: '' }, + } ); }); test('should invoke [REQUEST, FAILURE]', async () => { httpMockedClient.get = jest.fn().mockRejectedValue({ - data: { ok: false, error: 'Something went wrong' }, + ok: false, + error: 'Something went wrong', }); try { await store.dispatch(getAliases()); @@ -111,7 +121,10 @@ describe('elasticsearch reducer actions', () => { errorMessage: 'Something went wrong', }); expect(httpMockedClient.get).toHaveBeenCalledWith( - `..${BASE_NODE_API_PATH}/_aliases?alias=` + `..${BASE_NODE_API_PATH}/_aliases`, + { + query: { alias: '' }, + } ); } }); @@ -130,7 +143,7 @@ describe('elasticsearch reducer actions', () => { }; httpMockedClient.get = jest .fn() - .mockResolvedValue({ data: { ok: true, response: { mappings } } }); + .mockResolvedValue({ ok: true, response: { mappings } }); await store.dispatch(getMappings()); const actions = store.getActions(); expect(actions[0].type).toBe('elasticsearch/GET_MAPPINGS_REQUEST'); @@ -148,12 +161,16 @@ describe('elasticsearch reducer actions', () => { }, }); expect(httpMockedClient.get).toHaveBeenCalledWith( - `..${BASE_NODE_API_PATH}/_mappings?index=` + `..${BASE_NODE_API_PATH}/_mappings`, + { + query: { index: '' }, + } ); }); test('should invoke [REQUEST, FAILURE]', async () => { httpMockedClient.get = jest.fn().mockRejectedValue({ - data: { ok: false, error: 'Something went wrong' }, + ok: false, + error: 'Something went wrong', }); try { await store.dispatch(getMappings()); @@ -171,7 +188,10 @@ describe('elasticsearch reducer actions', () => { errorMessage: 'Something went wrong', }); expect(httpMockedClient.get).toHaveBeenCalledWith( - `..${BASE_NODE_API_PATH}/_mappings?index=` + `..${BASE_NODE_API_PATH}/_mappings`, + { + query: { index: '' }, + } ); } }); @@ -186,7 +206,8 @@ describe('elasticsearch reducer actions', () => { index: 'test-index', }; httpMockedClient.post = jest.fn().mockResolvedValue({ - data: { ok: true, response: { hits: { hits: [] } } }, + ok: true, + response: { hits: { hits: [] } }, }); await store.dispatch(searchES(requestData)); const actions = store.getActions(); @@ -205,7 +226,9 @@ describe('elasticsearch reducer actions', () => { }); expect(httpMockedClient.post).toHaveBeenCalledWith( `..${BASE_NODE_API_PATH}/_search`, - requestData + { + body: JSON.stringify(requestData), + } ); }); test('should invoke [REQUEST, FAILURE]', async () => { @@ -216,7 +239,8 @@ describe('elasticsearch reducer actions', () => { index: 'test-index', }; httpMockedClient.post = jest.fn().mockRejectedValue({ - data: { ok: false, error: 'Something went wrong' }, + ok: false, + error: 'Something went wrong', }); try { await store.dispatch(searchES(requestData)); @@ -235,7 +259,9 @@ describe('elasticsearch reducer actions', () => { }); expect(httpMockedClient.post).toHaveBeenCalledWith( `..${BASE_NODE_API_PATH}/_search`, - requestData + { + body: JSON.stringify(requestData), + } ); } }); diff --git a/public/redux/reducers/ad.ts b/public/redux/reducers/ad.ts index ca8ad189..7a734c3f 100644 --- a/public/redux/reducers/ad.ts +++ b/public/redux/reducers/ad.ts @@ -16,7 +16,7 @@ import { APIAction, APIResponseAction, - IHttpService, + HttpSetup, APIErrorAction, } from '../middleware/types'; import handleActions from '../utils/handleActions'; @@ -68,7 +68,7 @@ const reducer = handleActions( requesting: false, detectors: { ...state.detectors, - [action.result.data.response.id]: action.result.data.response, + [action.result.response.id]: action.result.response, }, }), FAILURE: (state: Detectors, action: APIErrorAction): Detectors => ({ @@ -89,7 +89,7 @@ const reducer = handleActions( detectors: { ...state.detectors, [action.detectorId]: { - ...cloneDeep(action.result.data.response), + ...cloneDeep(action.result.response), }, }, }), @@ -162,7 +162,7 @@ const reducer = handleActions( requesting: false, detectors: { ...state.detectors, - ...action.result.data.response.detectors.reduce( + ...action.result.response.detectors.reduce( (acc: any, detector: Detector) => ({ ...acc, [detector.id]: detector, @@ -171,9 +171,10 @@ const reducer = handleActions( ), }, }), - FAILURE: (state: Detectors): Detectors => ({ + FAILURE: (state: Detectors, action: APIErrorAction): Detectors => ({ ...state, requesting: false, + errorMessage: action.error, }), }, [GET_DETECTOR_LIST]: { @@ -185,14 +186,14 @@ const reducer = handleActions( SUCCESS: (state: Detectors, action: APIResponseAction): Detectors => ({ ...state, requesting: false, - detectorList: action.result.data.response.detectorList.reduce( + detectorList: action.result.response.detectorList.reduce( (acc: any, detector: DetectorListItem) => ({ ...acc, [detector.id]: detector, }), {} ), - totalDetectors: action.result.data.response.totalDetectors, + totalDetectors: action.result.response.totalDetectors, }), FAILURE: (state: Detectors, action: APIErrorAction): Detectors => ({ ...state, @@ -212,7 +213,7 @@ const reducer = handleActions( ...state.detectors, [action.detectorId]: { ...state.detectors[action.detectorId], - ...action.result.data.response, + ...action.result.response, lastUpdateTime: moment().valueOf(), }, }, @@ -256,7 +257,7 @@ const reducer = handleActions( ...state.detectorList, [action.detectorId]: { ...state.detectorList[action.detectorId], - curState: action.result.data.response.state, + curState: action.result.response.state, }, }, }), @@ -306,13 +307,15 @@ const reducer = handleActions( export const createDetector = (requestBody: Detector): APIAction => ({ type: CREATE_DETECTOR, - request: (client: IHttpService) => - client.post(`..${AD_NODE_API.DETECTOR}`, requestBody), + request: (client: HttpSetup) => + client.post(`..${AD_NODE_API.DETECTOR}`, { + body: JSON.stringify(requestBody), + }), }); export const getDetector = (detectorId: string): APIAction => ({ type: GET_DETECTOR, - request: (client: IHttpService) => + request: (client: HttpSetup) => client.get(`..${AD_NODE_API.DETECTOR}/${detectorId}`), detectorId, }); @@ -321,14 +324,16 @@ export const getDetectorList = ( queryParams: GetDetectorsQueryParams ): APIAction => ({ type: GET_DETECTOR_LIST, - request: (client: IHttpService) => - client.get(`..${AD_NODE_API.DETECTOR}`, { params: queryParams }), + request: (client: HttpSetup) => + client.get(`..${AD_NODE_API.DETECTOR}`, { query: queryParams }), }); export const searchDetector = (requestBody: any): APIAction => ({ type: SEARCH_DETECTOR, - request: (client: IHttpService) => - client.post(`..${AD_NODE_API.DETECTOR}/_search`, requestBody), + request: (client: HttpSetup) => + client.post(`..${AD_NODE_API.DETECTOR}/_search`, { + body: JSON.stringify(requestBody), + }), }); export const updateDetector = ( @@ -336,62 +341,50 @@ export const updateDetector = ( requestBody: Detector ): APIAction => ({ type: UPDATE_DETECTOR, - request: (client: IHttpService) => - client.put(`..${AD_NODE_API.DETECTOR}/${detectorId}`, requestBody, { - params: { - ifPrimaryTerm: requestBody.primaryTerm, - ifSeqNo: requestBody.seqNo, - }, + request: (client: HttpSetup) => + client.put(`..${AD_NODE_API.DETECTOR}/${detectorId}`, { + body: JSON.stringify(requestBody), }), detectorId, }); export const deleteDetector = (detectorId: string): APIAction => ({ type: DELETE_DETECTOR, - request: (client: IHttpService) => + request: (client: HttpSetup) => client.delete(`..${AD_NODE_API.DETECTOR}/${detectorId}`), detectorId, }); export const startDetector = (detectorId: string): APIAction => ({ type: START_DETECTOR, - request: (client: IHttpService) => - client.post(`..${AD_NODE_API.DETECTOR}/${detectorId}/start`, { - detectorId: detectorId, - }), + request: (client: HttpSetup) => + client.post(`..${AD_NODE_API.DETECTOR}/${detectorId}/start`), detectorId, }); export const stopDetector = (detectorId: string): APIAction => ({ type: STOP_DETECTOR, - request: (client: IHttpService) => - client.post(`..${AD_NODE_API.DETECTOR}/${detectorId}/stop`, { - detectorId: detectorId, - }), + request: (client: HttpSetup) => + client.post(`..${AD_NODE_API.DETECTOR}/${detectorId}/stop`), detectorId, }); export const getDetectorProfile = (detectorId: string): APIAction => ({ type: GET_DETECTOR_PROFILE, - request: (client: IHttpService) => - client.get(`..${AD_NODE_API.DETECTOR}/${detectorId}/_profile`, { - params: detectorId, - }), + request: (client: HttpSetup) => + client.get(`..${AD_NODE_API.DETECTOR}/${detectorId}/_profile`), detectorId, }); export const matchDetector = (detectorName: string): APIAction => ({ type: MATCH_DETECTOR, - request: (client: IHttpService) => - client.get(`..${AD_NODE_API.DETECTOR}/${detectorName}/_match`, { - params: detectorName, - }), - detectorName, + request: (client: HttpSetup) => + client.get(`..${AD_NODE_API.DETECTOR}/${detectorName}/_match`), }); export const getDetectorCount = (): APIAction => ({ type: GET_DETECTOR_COUNT, - request: (client: IHttpService) => + request: (client: HttpSetup) => client.get(`..${AD_NODE_API.DETECTOR}/_count`, {}), }); diff --git a/public/redux/reducers/adAppReducer.ts b/public/redux/reducers/adAppReducer.ts index 9444ad65..fb0277b2 100644 --- a/public/redux/reducers/adAppReducer.ts +++ b/public/redux/reducers/adAppReducer.ts @@ -15,11 +15,10 @@ import { Action } from 'redux'; - export const SET_HIDE_SIDE_NAV_BAR_STATE = 'adApp/SET_HIDE_SIDE_NAV_BAR_STATE'; const initialAdAppState = { - hideSideNavBar: false + hideSideNavBar: false, }; export interface AdAppState { @@ -39,6 +38,6 @@ const reducer = (state = initialAdAppState, action: Action) => { default: return state; } -} +}; export default reducer; diff --git a/public/redux/reducers/alerting.ts b/public/redux/reducers/alerting.ts index 466e816c..3bee9ffc 100644 --- a/public/redux/reducers/alerting.ts +++ b/public/redux/reducers/alerting.ts @@ -13,11 +13,7 @@ * permissions and limitations under the License. */ -import { - APIAction, - APIResponseAction, - IHttpService, -} from '../middleware/types'; +import { APIAction, APIResponseAction, HttpSetup } from '../middleware/types'; import handleActions from '../utils/handleActions'; import { ALERTING_NODE_API } from '../../../utils/constants'; import { Monitor } from '../../../server/models/types'; @@ -57,7 +53,7 @@ const reducer = handleActions( let totalAdMonitors = 0; const monitors = get( action, - 'result.data.response.monitors', + 'result.response.monitors', [] // @ts-ignore ).reduce((map, obj) => { @@ -74,7 +70,7 @@ const reducer = handleActions( return { ...state, requesting: false, - totalMonitors: get(action, 'result.data.response.totalMonitors', 0), + totalMonitors: get(action, 'result.response.totalMonitors', 0), totalAdMonitors: totalAdMonitors, monitors: monitors, }; @@ -104,8 +100,7 @@ const reducer = handleActions( export const searchMonitors = (): APIAction => ({ type: SEARCH_MONITORS, - request: (client: IHttpService) => - client.post(`..${ALERTING_NODE_API._SEARCH}`, {}), + request: (client: HttpSetup) => client.post(`..${ALERTING_NODE_API._SEARCH}`), }); export const searchAlerts = ( @@ -114,9 +109,9 @@ export const searchAlerts = ( endTime: number ): APIAction => ({ type: SEARCH_ALERTS, - request: (client: IHttpService) => + request: (client: HttpSetup) => client.get(`..${ALERTING_NODE_API.ALERTS}`, { - params: { + query: { monitorId: monitorId, startTime: startTime, endTime: endTime, diff --git a/public/redux/reducers/anomalyResults.ts b/public/redux/reducers/anomalyResults.ts index 5b5e7426..941be5a2 100644 --- a/public/redux/reducers/anomalyResults.ts +++ b/public/redux/reducers/anomalyResults.ts @@ -13,14 +13,11 @@ * permissions and limitations under the License. */ -import { - APIAction, - APIResponseAction, - IHttpService, -} from '../middleware/types'; +import { APIAction, APIResponseAction, HttpSetup } from '../middleware/types'; import handleActions from '../utils/handleActions'; import { AD_NODE_API } from '../../../utils/constants'; import { AnomalyData } from '../../models/interfaces'; +import { get } from 'lodash'; const DETECTOR_RESULTS = 'ad/DETECTOR_RESULTS'; const SEARCH_ANOMALY_RESULTS = 'ad/SEARCH_ANOMALY_RESULTS'; @@ -51,14 +48,14 @@ const reducer = handleActions( SUCCESS: (state: Anomalies, action: APIResponseAction): Anomalies => ({ ...state, requesting: false, - total: action.result.data.response.totalAnomalies, - anomalies: action.result.data.response.results, - featureData: action.result.data.response.featureResults, + total: action.result.response.totalAnomalies, + anomalies: action.result.response.results, + featureData: action.result.response.featureResults, }), FAILURE: (state: Anomalies, action: APIResponseAction): Anomalies => ({ ...state, requesting: false, - errorMessage: action.error.data.error, + errorMessage: get(action, 'error.error', action.error), }), }, @@ -83,16 +80,18 @@ export const getDetectorResults = ( queryParams: any ): APIAction => ({ type: DETECTOR_RESULTS, - request: (client: IHttpService) => + request: (client: HttpSetup) => client.get(`..${AD_NODE_API.DETECTOR}/${detectorId}/results`, { - params: queryParams, + query: queryParams, }), }); export const searchResults = (requestBody: any): APIAction => ({ type: SEARCH_ANOMALY_RESULTS, - request: (client: IHttpService) => - client.post(`..${AD_NODE_API.DETECTOR}/results/_search`, requestBody), + request: (client: HttpSetup) => + client.post(`..${AD_NODE_API.DETECTOR}/results/_search`, { + body: JSON.stringify(requestBody), + }), }); export default reducer; diff --git a/public/redux/reducers/elasticsearch.ts b/public/redux/reducers/elasticsearch.ts index a05d40da..093513f7 100644 --- a/public/redux/reducers/elasticsearch.ts +++ b/public/redux/reducers/elasticsearch.ts @@ -16,7 +16,7 @@ import { APIAction, APIResponseAction, - IHttpService, + HttpSetup, APIErrorAction, ThunkAction, } from '../middleware/types'; @@ -88,7 +88,7 @@ const reducer = handleActions( return { ...state, requesting: false, - indices: action.result.data.response.indices, + indices: action.result.response.indices, }; }, FAILURE: ( @@ -97,7 +97,7 @@ const reducer = handleActions( ): ElasticsearchState => ({ ...state, requesting: false, - errorMessage: get(action, 'error.data.error', action.error), + errorMessage: get(action, 'error.error', action.error), }), }, [GET_ALIASES]: { @@ -113,7 +113,7 @@ const reducer = handleActions( return { ...state, requesting: false, - aliases: action.result.data.response.aliases, + aliases: action.result.response.aliases, }; }, FAILURE: ( @@ -122,7 +122,7 @@ const reducer = handleActions( ): ElasticsearchState => ({ ...state, requesting: false, - errorMessage: get(action, 'error.data.error', action.error), + errorMessage: get(action, 'error.error', action.error), }), }, [SEARCH_ES]: { @@ -138,7 +138,7 @@ const reducer = handleActions( return { ...state, requesting: false, - searchResult: { ...action.result.data.response }, + searchResult: { ...action.result.response }, }; }, FAILURE: ( @@ -147,7 +147,7 @@ const reducer = handleActions( ): ElasticsearchState => ({ ...state, requesting: false, - errorMessage: get(action, 'error.data.error', action.error), + errorMessage: get(action, 'error.error', action.error), }), }, [GET_MAPPINGS]: { @@ -163,7 +163,7 @@ const reducer = handleActions( return { ...state, requesting: false, - dataTypes: getPathsPerDataType(action.result.data.response.mappings), + dataTypes: getPathsPerDataType(action.result.response.mappings), }; }, FAILURE: ( @@ -172,7 +172,7 @@ const reducer = handleActions( ): ElasticsearchState => ({ ...state, requesting: false, - errorMessage: get(action, 'error.data.error', action.error), + errorMessage: get(action, 'error.error', action.error), dataTypes: {}, }), }, @@ -187,7 +187,7 @@ const reducer = handleActions( return { ...state, requesting: false, - indices: action.result.data.response.indices, + indices: action.result.response.indices, }; }, FAILURE: ( @@ -232,7 +232,7 @@ const reducer = handleActions( return { ...state, requesting: false, - indices: action.result.data.response.indices, + indices: action.result.response.indices, }; }, FAILURE: ( @@ -250,47 +250,50 @@ const reducer = handleActions( export const getIndices = (searchKey: string = ''): APIAction => ({ type: GET_INDICES, - request: (client: IHttpService) => - client.get(`..${AD_NODE_API._INDICES}?index=${searchKey}`), - searchKey, + request: (client: HttpSetup) => + client.get(`..${AD_NODE_API._INDICES}`, { query: { index: searchKey } }), }); export const getAliases = (searchKey: string = ''): APIAction => ({ type: GET_ALIASES, - request: (client: IHttpService) => - client.get(`..${AD_NODE_API._ALIASES}?alias=${searchKey}`), - searchKey, + request: (client: HttpSetup) => + client.get(`..${AD_NODE_API._ALIASES}`, { query: { alias: searchKey } }), }); export const getMappings = (searchKey: string = ''): APIAction => ({ type: GET_MAPPINGS, - request: (client: IHttpService) => - client.get(`..${AD_NODE_API._MAPPINGS}?index=${searchKey}`), - searchKey, + request: (client: HttpSetup) => + client.get(`..${AD_NODE_API._MAPPINGS}`, { + query: { index: searchKey }, + }), }); export const searchES = (requestData: any): APIAction => ({ type: SEARCH_ES, - request: (client: IHttpService) => - client.post(`..${AD_NODE_API._SEARCH}`, requestData), + request: (client: HttpSetup) => + client.post(`..${AD_NODE_API._SEARCH}`, { + body: JSON.stringify(requestData), + }), }); export const createIndex = (indexConfig: any): APIAction => ({ type: CREATE_INDEX, - request: (client: IHttpService) => - client.put(`..${AD_NODE_API.CREATE_INDEX}`, { indexConfig }), + request: (client: HttpSetup) => + client.put(`..${AD_NODE_API.CREATE_INDEX}`, { + body: JSON.stringify(indexConfig), + }), }); export const bulk = (body: any): APIAction => ({ type: BULK, - request: (client: IHttpService) => - client.post(`..${AD_NODE_API.BULK}`, { body }), + request: (client: HttpSetup) => + client.post(`..${AD_NODE_API.BULK}`, { body: JSON.stringify(body) }), }); export const deleteIndex = (index: string): APIAction => ({ type: DELETE_INDEX, - request: (client: IHttpService) => - client.post(`..${AD_NODE_API.DELETE_INDEX}`, { index }), + request: (client: HttpSetup) => + client.post(`..${AD_NODE_API.DELETE_INDEX}`, { query: { index: index } }), }); export const getPrioritizedIndices = (searchKey: string): ThunkAction => async ( diff --git a/public/redux/reducers/liveAnomalyResults.ts b/public/redux/reducers/liveAnomalyResults.ts index 625e211d..0041d74a 100644 --- a/public/redux/reducers/liveAnomalyResults.ts +++ b/public/redux/reducers/liveAnomalyResults.ts @@ -13,15 +13,12 @@ * permissions and limitations under the License. */ -import { - APIAction, - APIResponseAction, - IHttpService, -} from '../middleware/types'; +import { APIAction, APIResponseAction, HttpSetup } from '../middleware/types'; import handleActions from '../utils/handleActions'; import { AD_NODE_API } from '../../../utils/constants'; import { DetectorResultsQueryParams } from '../../../server/models/types'; import { Anomaly } from '../../../server/models/interfaces'; +import { get } from 'lodash'; const DETECTOR_LIVE_RESULTS = 'ad/DETECTOR_LIVE_RESULTS'; @@ -49,13 +46,13 @@ const reducer = handleActions( SUCCESS: (state: Anomalies, action: APIResponseAction): Anomalies => ({ ...state, requesting: false, - totalLiveAnomalies: action.result.data.response.totalAnomalies, - liveAnomalies: action.result.data.response.results, + totalLiveAnomalies: action.result.response.totalAnomalies, + liveAnomalies: action.result.response.results, }), FAILURE: (state: Anomalies, action: APIResponseAction): Anomalies => ({ ...state, requesting: false, - errorMessage: action.error.data.error, + errorMessage: get(action, 'error.error', action.error), }), }, }, @@ -67,9 +64,9 @@ export const getDetectorLiveResults = ( queryParams: DetectorResultsQueryParams ): APIAction => ({ type: DETECTOR_LIVE_RESULTS, - request: (client: IHttpService) => + request: (client: HttpSetup) => client.get(`..${AD_NODE_API.DETECTOR}/${detectorId}/results`, { - params: queryParams, + query: queryParams, }), }); diff --git a/public/redux/reducers/previewAnomalies.ts b/public/redux/reducers/previewAnomalies.ts index a820e107..6f533c4a 100644 --- a/public/redux/reducers/previewAnomalies.ts +++ b/public/redux/reducers/previewAnomalies.ts @@ -13,11 +13,7 @@ * permissions and limitations under the License. */ -import { - APIAction, - APIResponseAction, - IHttpService, -} from '../middleware/types'; +import { APIAction, APIResponseAction, HttpSetup } from '../middleware/types'; import handleActions from '../utils/handleActions'; import { AD_NODE_API } from '../../../utils/constants'; import { Anomalies } from '../../models/interfaces'; @@ -52,7 +48,7 @@ const reducer = handleActions( ): PreviewAnomalies => ({ ...state, requesting: false, - anomaliesResult: action.result.data.response, + anomaliesResult: action.result.response, }), FAILURE: ( state: PreviewAnomalies, @@ -72,8 +68,10 @@ export const previewDetector = ( requestBody: any ): APIAction => ({ type: PREVIEW_DETECTOR, - request: (client: IHttpService) => - client.post(`..${AD_NODE_API.DETECTOR}/${detectorId}/preview`, requestBody), + request: (client: HttpSetup) => + client.post(`..${AD_NODE_API.DETECTOR}/${detectorId}/preview`, { + body: JSON.stringify(requestBody), + }), }); export default reducer; diff --git a/public/redux/reducers/sampleData.ts b/public/redux/reducers/sampleData.ts index 7cfb6879..6e30e8a4 100644 --- a/public/redux/reducers/sampleData.ts +++ b/public/redux/reducers/sampleData.ts @@ -13,14 +13,11 @@ * permissions and limitations under the License. */ -import { - APIAction, - APIResponseAction, - IHttpService, -} from '../middleware/types'; +import { APIAction, APIResponseAction, HttpSetup } from '../middleware/types'; import handleActions from '../utils/handleActions'; import { AD_NODE_API } from '../../../utils/constants'; import { SAMPLE_TYPE } from '../../utils/constants'; +import { get } from 'lodash'; const CREATE_SAMPLE_DATA = 'ad/CREATE_SAMPLE_DATA'; @@ -54,7 +51,7 @@ const reducer = handleActions( ): SampleDataState => ({ ...state, requesting: false, - errorMessage: action.error.data.error, + errorMessage: get(action, 'error.error', action.error), }), }, }, @@ -63,10 +60,8 @@ const reducer = handleActions( export const createSampleData = (sampleDataType: SAMPLE_TYPE): APIAction => ({ type: CREATE_SAMPLE_DATA, - request: (client: IHttpService) => - client.post(`..${AD_NODE_API.CREATE_SAMPLE_DATA}`, { - type: sampleDataType, - }), + request: (client: HttpSetup) => + client.post(`..${AD_NODE_API.CREATE_SAMPLE_DATA}/${sampleDataType}`), }); export default reducer; diff --git a/public/utils/kibanaUtils.ts b/public/utils/kibanaUtils.ts index 420e0533..e0a54813 100644 --- a/public/utils/kibanaUtils.ts +++ b/public/utils/kibanaUtils.ts @@ -13,9 +13,11 @@ * permissions and limitations under the License. */ -//@ts-ignore -import chrome from 'ui/chrome'; +import React from 'react'; +import { CoreStart } from '../../../../src/core/public'; +import { CoreServicesContext } from '../components/CoreServices/CoreServices'; export const darkModeEnabled = (): boolean => { - return chrome.getUiSettingsClient().get('theme:darkMode') || false; + const core = React.useContext(CoreServicesContext) as CoreStart; + return core.uiSettings.get('theme:darkMode') || false; }; diff --git a/public/utils/utils.tsx b/public/utils/utils.tsx index d95dbe55..1bb57713 100644 --- a/public/utils/utils.tsx +++ b/public/utils/utils.tsx @@ -16,13 +16,11 @@ import { get, isEmpty } from 'lodash'; import React from 'react'; import { EuiTitle } from '@elastic/eui'; -//@ts-ignore -import { isAngularHttpError } from 'ui/notify'; -//@ts-ignore -import { npStart } from 'ui/new_platform'; import { darkModeEnabled } from '../utils/kibanaUtils'; import { ALERTING_PLUGIN_NAME, NAME_REGEX } from './constants'; import { MAX_FEATURE_NAME_SIZE } from './constants'; +import { CoreStart } from '../../../../src/core/public'; +import { CoreServicesContext } from '../components/CoreServices/CoreServices'; export const validateFeatureName = ( featureName: string @@ -102,18 +100,9 @@ export const validateNonNegativeInteger = (value: any) => { export const getErrorMessage = (err: any, defaultMessage: string) => { if (typeof err === 'string') return err; if (err && err.message) return err.message; - if (isAngularHttpError && isAngularHttpError(err)) return err.data.message; return defaultMessage; }; -export const isAlertingInstalled = (): boolean => { - const navLinks = get(npStart, 'core.chrome.navLinks', undefined); - if (navLinks) { - return navLinks.has(ALERTING_PLUGIN_NAME); - } - return false; -}; - const getPluginRootPath = (url: string, pluginName: string) => { return url.slice(0, url.indexOf(pluginName) + pluginName.length); }; @@ -125,7 +114,8 @@ export const getAlertingCreateMonitorLink = ( unit: string ): string => { try { - const navLinks = get(npStart, 'core.chrome.navLinks', undefined); + const core = React.useContext(CoreServicesContext) as CoreStart; + const navLinks = get(core, 'chrome.navLinks', undefined); const url = `${navLinks.get(ALERTING_PLUGIN_NAME).url}`; const alertingRootUrl = getPluginRootPath(url, ALERTING_PLUGIN_NAME); return `${alertingRootUrl}#/create-monitor?searchType=ad&adId=${detectorId}&name=${detectorName}&interval=${ @@ -139,7 +129,8 @@ export const getAlertingCreateMonitorLink = ( export const getAlertingMonitorListLink = (): string => { try { - const navLinks = get(npStart, 'core.chrome.navLinks', undefined); + const core = React.useContext(CoreServicesContext) as CoreStart; + const navLinks = get(core, 'chrome.navLinks', undefined); const url = `${navLinks.get(ALERTING_PLUGIN_NAME).url}`; const alertingRootUrl = getPluginRootPath(url, ALERTING_PLUGIN_NAME); return `${alertingRootUrl}#/monitors`; @@ -154,7 +145,8 @@ export interface Listener { onException(): void; } -const detectorCountFontColor = darkModeEnabled() ? '#98A2B3' : '#535966'; +const detectorCountFontColor = () => + darkModeEnabled() ? '#98A2B3' : '#535966'; export const getTitleWithCount = (title: string, count: number | string) => { return ( @@ -166,7 +158,7 @@ export const getTitleWithCount = (title: string, count: number | string) => { }} >

{title} 

-

{`(${count})`}

+

{`(${count})`}

); diff --git a/server/index.ts b/server/index.ts new file mode 100644 index 00000000..2b4673a8 --- /dev/null +++ b/server/index.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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 { schema, TypeOf } from '@kbn/config-schema'; +import { + PluginConfigDescriptor, + PluginInitializerContext, +} from '../../../src/core/server'; +import { AnomalyDetectionKibanaPlugin } from './plugin'; + +export const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), +}); + +export type AnomalyDetectionKibanaPluginConfigType = TypeOf< + typeof configSchema +>; + +export const config: PluginConfigDescriptor = { + exposeToBrowser: { + enabled: true, + }, + schema: configSchema, +}; + +export interface AnomalyDetectionKibanaPluginSetup {} +export interface AnomalyDetectionKibanaPluginStart {} + +export function plugin(initializerContext: PluginInitializerContext) { + return new AnomalyDetectionKibanaPlugin(initializerContext); +} diff --git a/server/plugin.ts b/server/plugin.ts index 735093b4..4949552a 100644 --- a/server/plugin.ts +++ b/server/plugin.ts @@ -1,5 +1,5 @@ /* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. @@ -12,44 +12,81 @@ * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ - -//@ts-ignore -import { Legacy, Logger, PluginInitializerContext, PluginName } from 'kibana'; import { BASE_NODE_API_PATH } from '../utils/constants'; -import { createAdCluster } from './cluster'; +import { first } from 'rxjs/operators'; import { default as createRouter, Router } from './router'; -import registerADRoutes from './routes/ad'; -import registerAlertingRoutes from './routes/alerting'; -import registerElasticsearchRoute from './routes/elasticsearch'; -import registerSampleDataRoutes from './routes/sampleData'; - -interface CoreSetup { - elasticsearch: Legacy.Plugins.elasticsearch.Plugin; - http: Legacy.Server; - config: Legacy.KibanaConfig; -} +import { + AnomalyDetectionKibanaPluginSetup, + AnomalyDetectionKibanaPluginStart, +} from '.'; +import { + Plugin, + CoreSetup, + CoreStart, + PluginInitializerContext, + Logger, +} from '../../../src/core/server'; +import { ILegacyClusterClient } from '../../../src/core/server/'; +import adPlugin from './cluster/ad/adPlugin'; +import alertingPlugin from './cluster/ad/alertingPlugin'; +import AdService, { registerADRoutes } from './routes/ad'; +import AlertingService, { registerAlertingRoutes } from './routes/alerting'; +import ESService, { registerESRoutes } from './routes/elasticsearch'; +import SampleDataService, { + registerSampleDataRoutes, +} from './routes/sampleData'; +import { DEFAULT_HEADERS } from './utils/constants'; -export class ADPlugin { - private readonly log: Logger; +export class AnomalyDetectionKibanaPlugin + implements + Plugin< + AnomalyDetectionKibanaPluginSetup, + AnomalyDetectionKibanaPluginStart + > { + private readonly logger: Logger; + private readonly globalConfig$: any; constructor(private readonly initializerContext: PluginInitializerContext) { - this.log = this.initializerContext.logger.get(); + this.logger = initializerContext.logger.get(); + this.globalConfig$ = initializerContext.config.legacy.globalConfig$; } + public async setup(core: CoreSetup) { + // Get any custom/overridden headers + const globalConfig = await this.globalConfig$.pipe(first()).toPromise(); + const { customHeaders, ...rest } = globalConfig.elasticsearch; + + // Create ES client w/ relevant plugins and headers + const client: ILegacyClusterClient = core.elasticsearch.legacy.createClient( + 'anomaly_detection', + { + plugins: [adPlugin, alertingPlugin], + customHeaders: { ...customHeaders, ...DEFAULT_HEADERS }, + ...rest, + } + ); - public setup(core: CoreSetup, deps: Record) { - this.log.info(`Setting up AD with core contract`); - createAdCluster(core.elasticsearch, core.config); + // Create router const apiRouter: Router = createRouter( - core.http, - BASE_NODE_API_PATH, - core.elasticsearch + core.http.createRouter(), + BASE_NODE_API_PATH ); - registerElasticsearchRoute(apiRouter); - registerADRoutes(apiRouter); - registerAlertingRoutes(apiRouter); - registerSampleDataRoutes(apiRouter); + + // Create services & register with ES client + const adService = new AdService(client); + const alertingService = new AlertingService(client); + const esService = new ESService(client); + const sampleDataService = new SampleDataService(client); + + // Register server routes with the service + registerADRoutes(apiRouter, adService); + registerAlertingRoutes(apiRouter, alertingService); + registerESRoutes(apiRouter, esService); + registerSampleDataRoutes(apiRouter, sampleDataService); + + return {}; } - public start() {} - public stop() {} + public async start(core: CoreStart) { + return {}; + } } diff --git a/server/router.ts b/server/router.ts index ccd03969..bd85f71d 100644 --- a/server/router.ts +++ b/server/router.ts @@ -1,5 +1,5 @@ /* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. @@ -13,16 +13,20 @@ * permissions and limitations under the License. */ -import { Request, ResponseToolkit } from 'hapi'; -import { CLUSTER } from './utils/constants'; -//TODO: Fix types -// import { CallClusterWithRequest, ElasticsearchPlugin } from '../../../kibana/src/legacy/core_plugins/elasticsearch/index' +import { + IRouter, + RequestHandlerContext, + KibanaRequest, + KibanaResponseFactory, + IKibanaResponse, +} from '../../../src/core/server'; +import { schema } from '@kbn/config-schema'; type RouteHandler = ( - req: Request, - responseToolkit: ResponseToolkit, - callWithRequest: any -) => Promise; + context: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory +) => Promise>; type Route = (path: string, handler: RouteHandler) => Router; @@ -33,19 +37,17 @@ export interface Router { delete: Route; } // Router factory -export default (server: any, basePath: String, elasticsearch: any): Router => { +export default (iRouter: IRouter, basePath: String): Router => { if (basePath == null || basePath == '') { throw new TypeError('Base path is null'); } const requestHandler = (handler: RouteHandler) => async ( - req: Request, - h: ResponseToolkit + context: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory ) => { try { - //TODO :: See, if we need to pass on entire cluster or not. - const callWithRequest = elasticsearch.getCluster(CLUSTER.AES_AD) - .callWithRequest; - return await handler(req, h, callWithRequest); + return await handler(context, request, response); } catch (e) { throw e; } @@ -53,11 +55,67 @@ export default (server: any, basePath: String, elasticsearch: any): Router => { return ['get', 'put', 'post', 'delete'].reduce( (router: any, method: string) => { router[method] = (path: String, handler: RouteHandler) => { - server.route({ - path: `${basePath}${path}`, - method: method.toUpperCase(), - handler: requestHandler(handler), - }); + switch (method) { + case 'get': { + iRouter.get( + { + path: `${basePath}${path}`, + validate: { + params: schema.any(), + query: schema.any(), + body: schema.any(), + }, + }, + requestHandler(handler) + ); + break; + } + case 'put': { + iRouter.put( + { + path: `${basePath}${path}`, + validate: { + params: schema.any(), + query: schema.any(), + body: schema.any(), + }, + }, + requestHandler(handler) + ); + break; + } + case 'post': { + iRouter.post( + { + path: `${basePath}${path}`, + validate: { + params: schema.any(), + query: schema.any(), + body: schema.any(), + }, + }, + requestHandler(handler) + ); + break; + } + case 'delete': { + iRouter.delete( + { + path: `${basePath}${path}`, + validate: { + params: schema.any(), + query: schema.any(), + body: schema.any(), + }, + }, + requestHandler(handler) + ); + break; + } + default: { + break; + } + } }; return router; }, diff --git a/server/routes/ad.ts b/server/routes/ad.ts index 2b8c5585..091bc26d 100644 --- a/server/routes/ad.ts +++ b/server/routes/ad.ts @@ -13,13 +13,10 @@ * permissions and limitations under the License. */ -import { Request, ResponseToolkit } from 'hapi'; //@ts-ignore import get from 'lodash/get'; import orderBy from 'lodash/orderBy'; import pullAll from 'lodash/pullAll'; -//@ts-ignore -import { CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; import { AnomalyResults, SearchResponse } from '../models/interfaces'; import { AnomalyResult, @@ -49,7 +46,13 @@ import { isIndexNotFoundError, getErrorMessage, } from './utils/adHelpers'; -import { isEmpty, set } from 'lodash'; +import { set } from 'lodash'; +import { + RequestHandlerContext, + KibanaRequest, + KibanaResponseFactory, + IKibanaResponse, +} from '../../../../src/core/server'; type PutDetectorParams = { detectorId: string; @@ -58,744 +61,833 @@ type PutDetectorParams = { body: string; }; -export default function (apiRouter: Router) { - apiRouter.post('/detectors', putDetector); - apiRouter.put('/detectors/{detectorId}', putDetector); - apiRouter.post('/detectors/_search', searchDetector); - apiRouter.post('/detectors/results/_search', searchResults); - apiRouter.get('/detectors/{detectorId}', getDetector); - apiRouter.get('/detectors', getDetectors); - apiRouter.post('/detectors/{detectorId}/preview', previewDetector); - apiRouter.get('/detectors/{detectorId}/results', getAnomalyResults); - apiRouter.delete('/detectors/{detectorId}', deleteDetector); - apiRouter.post('/detectors/{detectorId}/start', startDetector); - apiRouter.post('/detectors/{detectorId}/stop', stopDetector); - apiRouter.get('/detectors/{detectorId}/_profile', getDetectorProfile); - apiRouter.get('/detectors/{detectorName}/_match', matchDetector); - apiRouter.get('/detectors/_count', getDetectorCount); +export function registerADRoutes(apiRouter: Router, adService: AdService) { + apiRouter.post('/detectors', adService.putDetector); + apiRouter.put('/detectors/{detectorId}', adService.putDetector); + apiRouter.post('/detectors/_search', adService.searchDetector); + apiRouter.post('/detectors/results/_search', adService.searchResults); + apiRouter.get('/detectors/{detectorId}', adService.getDetector); + apiRouter.get('/detectors', adService.getDetectors); + apiRouter.post('/detectors/{detectorId}/preview', adService.previewDetector); + apiRouter.get('/detectors/{detectorId}/results', adService.getAnomalyResults); + apiRouter.delete('/detectors/{detectorId}', adService.deleteDetector); + apiRouter.post('/detectors/{detectorId}/start', adService.startDetector); + apiRouter.post('/detectors/{detectorId}/stop', adService.stopDetector); + apiRouter.get( + '/detectors/{detectorId}/_profile', + adService.getDetectorProfile + ); + apiRouter.get('/detectors/{detectorName}/_match', adService.matchDetector); + apiRouter.get('/detectors/_count', adService.getDetectorCount); } -const deleteDetector = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { detectorId } = req.params; - const response = await callWithRequest(req, 'ad.deleteDetector', { - detectorId, - }); - return { - ok: true, - response: response, - }; - } catch (err) { - console.log('Anomaly detector - deleteDetector', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; +export default class AdService { + private client: any; -const previewDetector = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { detectorId } = req.params; - //@ts-ignore - const requestBody = JSON.stringify( - convertPreviewInputKeysToSnakeCase(req.payload) - ); - const response = await callWithRequest(req, 'ad.previewDetector', { - detectorId, - body: requestBody, - }); - const transformedKeys = mapKeysDeep(response, toCamel); - return { - ok: true, - //@ts-ignore - response: anomalyResultMapper(transformedKeys.anomalyResult), - }; - } catch (err) { - console.log('Anomaly detector - previewDetector', err); - return { - ok: false, - error: getErrorMessage(err), - }; + constructor(client: any) { + this.client = client; } -}; -const putDetector = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { detectorId } = req.params; - const { ifSeqNo, ifPrimaryTerm } = req.query as { - ifSeqNo?: string; - ifPrimaryTerm?: string; - }; - const requestBody = JSON.stringify( - convertDetectorKeysToSnakeCase(req.payload) - ); - let params: PutDetectorParams = { - detectorId: detectorId, - ifSeqNo: ifSeqNo, - ifPrimaryTerm: ifPrimaryTerm, - body: requestBody, - }; - let response; - if (ifSeqNo && ifPrimaryTerm) { - response = await callWithRequest(req, 'ad.updateDetector', params); - } else { - response = await callWithRequest(req, 'ad.createDetector', { - body: params.body, + deleteDetector = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const { detectorId } = request.params as { detectorId: string }; + const response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.deleteDetector', { + detectorId, + }); + return kibanaResponse.ok({ + body: { + ok: true, + response: response, + }, + }); + } catch (err) { + console.log('Anomaly detector - deleteDetector', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, }); } - const resp = { - ...response.anomaly_detector, - id: response._id, - primaryTerm: response._primary_term, - seqNo: response._seq_no, - }; - return { - ok: true, - response: convertDetectorKeysToCamelCase(resp) as Detector, - }; - } catch (err) { - console.log('Anomaly detector - PutDetector', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + }; -const getDetector = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { detectorId } = req.params; - const response = await callWithRequest(req, 'ad.getDetector', { - detectorId, - }); - let detectorState; + previewDetector = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { try { - const detectorStateResp = await callWithRequest( - req, - 'ad.detectorProfile', - { - detectorId: detectorId, - } - ); - const detectorStates = getFinalDetectorStates( - [detectorStateResp], - [convertDetectorKeysToCamelCase(response.anomaly_detector)] + const { detectorId } = request.params as { detectorId: string }; + const requestBody = JSON.stringify( + convertPreviewInputKeysToSnakeCase(request.body) ); - detectorState = detectorStates[0]; + const response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.previewDetector', { + detectorId, + body: requestBody, + }); + const transformedKeys = mapKeysDeep(response, toCamel); + return kibanaResponse.ok({ + body: { + ok: true, + //@ts-ignore + response: anomalyResultMapper(transformedKeys.anomalyResult), + }, + }); } catch (err) { - console.log('Anomaly detector - Unable to retrieve detector state', err); + console.log('Anomaly detector - previewDetector', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); } - const resp = { - ...response.anomaly_detector, - id: response._id, - primaryTerm: response._primary_term, - seqNo: response._seq_no, - adJob: { ...response.anomaly_detector_job }, - ...(detectorState !== undefined - ? { - curState: detectorState.state, - stateError: detectorState.error, - initProgress: getDetectorInitProgress(detectorState), - } - : {}), - }; - return { - ok: true, - response: convertDetectorKeysToCamelCase(resp) as Detector, - }; - } catch (err) { - console.log('Anomaly detector - Unable to get detector', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + }; -const startDetector = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { detectorId } = req.params; - const response = await callWithRequest(req, 'ad.startDetector', { - detectorId, - }); - return { - ok: true, - response: response, - }; - } catch (err) { - console.log('Anomaly detector - startDetector', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; - -const stopDetector = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { detectorId } = req.params; - const response = await callWithRequest(req, 'ad.stopDetector', { - detectorId, - }); - return { - ok: true, - response: response, - }; - } catch (err) { - console.log('Anomaly detector - stopDetector', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; - -const getDetectorProfile = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { detectorId } = req.params; - const response = await callWithRequest(req, 'ad.detectorProfile', { - detectorId, - }); - return { - ok: true, - response, - }; - } catch (err) { - console.log('Anomaly detector - detectorProfile', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + putDetector = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const { detectorId } = request.params as { detectorId: string }; + //@ts-ignore + const ifSeqNo = request.body.seqNo; + //@ts-ignore + const ifPrimaryTerm = request.body.primaryTerm; -const searchDetector = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - //@ts-ignore - const requestBody = JSON.stringify(req.payload); - const response: SearchResponse = await callWithRequest( - req, - 'ad.searchDetector', - { body: requestBody } - ); - const totalDetectors = get(response, 'hits.total.value', 0); - const detectors = get(response, 'hits.hits', []).map((detector: any) => ({ - ...convertDetectorKeysToCamelCase(detector._source), - id: detector._id, - seqNo: detector._seq_no, - primaryTerm: detector._primary_term, - })); - return { - ok: true, - response: { - totalDetectors, - detectors, - }, - }; - } catch (err) { - console.log('Anomaly detector - Unable to search detectors', err); - if (isIndexNotFoundError(err)) { - return { ok: true, response: { totalDetectors: 0, detectors: [] } }; + const requestBody = JSON.stringify( + convertDetectorKeysToSnakeCase(request.body) + ); + let params: PutDetectorParams = { + detectorId: detectorId, + ifSeqNo: ifSeqNo, + ifPrimaryTerm: ifPrimaryTerm, + body: requestBody, + }; + let response; + if (ifSeqNo && ifPrimaryTerm) { + response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.updateDetector', params); + } else { + response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.createDetector', { + body: params.body, + }); + } + const resp = { + ...response.anomaly_detector, + id: response._id, + primaryTerm: response._primary_term, + seqNo: response._seq_no, + }; + return kibanaResponse.ok({ + body: { + ok: true, + response: convertDetectorKeysToCamelCase(resp) as Detector, + }, + }); + } catch (err) { + console.log('Anomaly detector - PutDetector', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); } - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + }; -const searchResults = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - //@ts-ignore - const requestBody = JSON.stringify(req.payload); - const response = await callWithRequest(req, 'ad.searchResults', { - body: requestBody, - }); - return { - ok: true, - response, - }; - } catch (err) { - console.log('Anomaly detector - Unable to search anomaly result', err); - if (isIndexNotFoundError(err)) { - return { ok: true, response: { totalDetectors: 0, detectors: [] } }; + getDetector = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const { detectorId } = request.params as { detectorId: string }; + const response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.getDetector', { + detectorId, + }); + let detectorState; + try { + const detectorStateResp = await this.client + .asScoped(request) + .callAsCurrentUser('ad.detectorProfile', { + detectorId: detectorId, + }); + const detectorStates = getFinalDetectorStates( + [detectorStateResp], + [convertDetectorKeysToCamelCase(response.anomaly_detector)] + ); + detectorState = detectorStates[0]; + } catch (err) { + console.log( + 'Anomaly detector - Unable to retrieve detector state', + err + ); + } + const resp = { + ...response.anomaly_detector, + id: response._id, + primaryTerm: response._primary_term, + seqNo: response._seq_no, + adJob: { ...response.anomaly_detector_job }, + ...(detectorState !== undefined + ? { + curState: detectorState.state, + stateError: detectorState.error, + initProgress: getDetectorInitProgress(detectorState), + } + : {}), + }; + return kibanaResponse.ok({ + body: { + ok: true, + response: convertDetectorKeysToCamelCase(resp) as Detector, + }, + }); + } catch (err) { + console.log('Anomaly detector - Unable to get detector', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); } - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + }; -const getDetectors = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { - from = 0, - size = 20, - search = '', - indices = '', - sortDirection = SORT_DIRECTION.DESC, - sortField = 'name', - //@ts-ignore - } = req.query as GetDetectorsQueryParams; - const mustQueries = []; - if (search.trim()) { - mustQueries.push({ - query_string: { - fields: ['name', 'description'], - default_operator: 'AND', - query: `*${search.trim().split('-').join('* *')}*`, + startDetector = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const { detectorId } = request.params as { detectorId: string }; + const response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.startDetector', { + detectorId, + }); + return kibanaResponse.ok({ + body: { + ok: true, + response: response, }, }); - } - if (indices.trim()) { - mustQueries.push({ - query_string: { - fields: ['indices'], - default_operator: 'OR', - query: `*${indices.trim().split(' ').join('* *')}*`, + } catch (err) { + console.log('Anomaly detector - startDetector', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), }, }); } - //Allowed sorting columns - const sortQueryMap = { - name: { 'name.keyword': sortDirection }, - indices: { 'indices.keyword': sortDirection }, - lastUpdateTime: { last_update_time: sortDirection }, - } as { [key: string]: object }; - let sort = {}; - const sortQuery = sortQueryMap[sortField]; - if (sortQuery) { - sort = sortQuery; - } - //Preparing search request - const requestBody = { - sort, - size, - from, - query: { - bool: { - must: mustQueries, + }; + + stopDetector = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const { detectorId } = request.params as { detectorId: string }; + const response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.stopDetector', { + detectorId, + }); + return kibanaResponse.ok({ + body: { + ok: true, + response: response, }, - }, - }; - const response: SearchResponse = await callWithRequest( - req, - 'ad.searchDetector', - { body: requestBody } - ); - const totalDetectors = get(response, 'hits.total.value', 0); - //Get all detectors from search detector API - const allDetectors = get(response, 'hits.hits', []).reduce( - (acc: any, detector: any) => ({ - ...acc, - [detector._id]: { - id: detector._id, - description: get(detector, '_source.description', ''), - indices: get(detector, '_source.indices', []), - lastUpdateTime: get(detector, '_source.last_update_time', 0), - ...convertDetectorKeysToCamelCase(get(detector, '_source', {})), + }); + } catch (err) { + console.log('Anomaly detector - stopDetector', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), }, - }), - {} - ); - //Given each detector from previous result, get aggregation to power list - const allDetectorIds = Object.keys(allDetectors); - const aggregationResult = await callWithRequest(req, 'ad.searchResults', { - body: getResultAggregationQuery(allDetectorIds, { - from, - size, - sortField, - sortDirection, - search, - indices, - }), - }); - const aggsDetectors = get( - aggregationResult, - 'aggregations.unique_detectors.buckets', - [] - ).reduce((acc: any, agg: any) => { - return { - ...acc, - [agg.key]: { - ...allDetectors[agg.key], - totalAnomalies: agg.total_anomalies_in_24hr.doc_count, - lastActiveAnomaly: agg.latest_anomaly_time.value, + }); + } + }; + + getDetectorProfile = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const { detectorId } = request.params as { detectorId: string }; + const response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.detectorProfile', { + detectorId, + }); + return kibanaResponse.ok({ + body: { + ok: true, + response, }, - }; - }, {}); - - // Aggregation will not return values where anomalies for detectors are not generated, loop through it and fill values with 0 - const unUsedDetectors = pullAll( - allDetectorIds, - Object.keys(aggsDetectors) - ).reduce((acc: any, unusedDetector: string) => { - return { - ...acc, - [unusedDetector]: { - ...allDetectors[unusedDetector], - totalAnomalies: 0, - lastActiveAnomaly: 0, + }); + } catch (err) { + console.log('Anomaly detector - detectorProfile', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), }, - }; - }, {}); - - // If sorting criteria is from the aggregation manage pagination in memory. - let finalDetectors = orderBy( - { ...aggsDetectors, ...unUsedDetectors }, - [sortField], - [sortDirection] - ); - if (!sortQueryMap[sortField]) { - finalDetectors = Object.values(finalDetectors) - .slice(from, from + size) - .reduce( - (acc, detector: any) => ({ ...acc, [detector.id]: detector }), - {} - ); + }); } + }; - // Get detector state as well: loop through the ids to get each detector's state using profile api - const allIds = finalDetectors.map((detector) => detector.id); + searchDetector = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const requestBody = JSON.stringify(request.body); + const response: SearchResponse = await this.client + .asScoped(request) + .callAsCurrentUser('ad.searchDetector', { body: requestBody }); + const totalDetectors = get(response, 'hits.total.value', 0); + const detectors = get(response, 'hits.hits', []).map((detector: any) => ({ + ...convertDetectorKeysToCamelCase(detector._source), + id: detector._id, + seqNo: detector._seq_no, + primaryTerm: detector._primary_term, + })); + return kibanaResponse.ok({ + body: { + ok: true, + response: { + totalDetectors, + detectors, + }, + }, + }); + } catch (err) { + console.log('Anomaly detector - Unable to search detectors', err); + if (isIndexNotFoundError(err)) { + return kibanaResponse.ok({ + body: { ok: true, response: { totalDetectors: 0, detectors: [] } }, + }); + } + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + }; - const detectorStatePromises = allIds.map(async (id: string) => { - try { - const detectorStateResp = await callWithRequest( - req, - 'ad.detectorProfile', - { - detectorId: id, - } - ); - return detectorStateResp; - } catch (err) { - console.log('Error getting detector profile ', err); - return Promise.reject( - new Error( - 'Error retrieving all detector states: ' + getErrorMessage(err) - ) - ); + searchResults = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const requestBody = JSON.stringify(request.body); + const response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.searchResults', { + body: requestBody, + }); + return kibanaResponse.ok({ + body: { + ok: true, + response, + }, + }); + } catch (err) { + console.log('Anomaly detector - Unable to search anomaly result', err); + if (isIndexNotFoundError(err)) { + return kibanaResponse.ok({ + body: { ok: true, response: { totalDetectors: 0, detectors: [] } }, + }); } - }); - const detectorStateResponses = await Promise.all( - detectorStatePromises - ).catch((err) => { - throw err; - }); - const finalDetectorStates = getFinalDetectorStates( - detectorStateResponses, - finalDetectors - ); - // update the final detectors to include the detector state - finalDetectors.forEach((detector, i) => { - detector.curState = finalDetectorStates[i].state; - }); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + }; - // get ad job - const detectorsWithJobPromises = allIds.map(async (id: string) => { - try { - const detectorResp = await callWithRequest(req, 'ad.getDetector', { - detectorId: id, + getDetectors = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const { + from = 0, + size = 20, + search = '', + indices = '', + sortDirection = SORT_DIRECTION.DESC, + sortField = 'name', + } = request.query as GetDetectorsQueryParams; + const mustQueries = []; + if (search.trim()) { + mustQueries.push({ + query_string: { + fields: ['name', 'description'], + default_operator: 'AND', + query: `*${search.trim().split('-').join('* *')}*`, + }, }); - return detectorResp; - } catch (err) { - console.log('Error getting detector ', err); - return Promise.reject( - new Error('Error retrieving all detectors: ' + getErrorMessage(err)) - ); } - }); - const detectorsWithJobResponses = await Promise.all( - detectorsWithJobPromises - ).catch((err) => { - throw err; - }); - const finalDetectorsWithJob = getDetectorsWithJob( - detectorsWithJobResponses - ); + if (indices.trim()) { + mustQueries.push({ + query_string: { + fields: ['indices'], + default_operator: 'OR', + query: `*${indices.trim().split(' ').join('* *')}*`, + }, + }); + } + //Allowed sorting columns + const sortQueryMap = { + name: { 'name.keyword': sortDirection }, + indices: { 'indices.keyword': sortDirection }, + lastUpdateTime: { last_update_time: sortDirection }, + } as { [key: string]: object }; + let sort = {}; + const sortQuery = sortQueryMap[sortField]; + if (sortQuery) { + sort = sortQuery; + } + //Preparing search request + const requestBody = { + sort, + size, + from, + query: { + bool: { + must: mustQueries, + }, + }, + }; + const response: any = await this.client + .asScoped(request) + .callAsCurrentUser('ad.searchDetector', { body: requestBody }); + + const totalDetectors = get(response, 'hits.total.value', 0); + //Get all detectors from search detector API + const allDetectors = get(response, 'hits.hits', []).reduce( + (acc: any, detector: any) => ({ + ...acc, + [detector._id]: { + id: detector._id, + description: get(detector, '_source.description', ''), + indices: get(detector, '_source.indices', []), + lastUpdateTime: get(detector, '_source.last_update_time', 0), + ...convertDetectorKeysToCamelCase(get(detector, '_source', {})), + }, + }), + {} + ); + //Given each detector from previous result, get aggregation to power list + const allDetectorIds = Object.keys(allDetectors); + const aggregationResult = await this.client + .asScoped(request) + .callAsCurrentUser('ad.searchResults', { + body: getResultAggregationQuery(allDetectorIds, { + from, + size, + sortField, + sortDirection, + search, + indices, + }), + }); + const aggsDetectors = get( + aggregationResult, + 'aggregations.unique_detectors.buckets', + [] + ).reduce((acc: any, agg: any) => { + return { + ...acc, + [agg.key]: { + ...allDetectors[agg.key], + totalAnomalies: agg.total_anomalies_in_24hr.doc_count, + lastActiveAnomaly: agg.latest_anomaly_time.value, + }, + }; + }, {}); + + // Aggregation will not return values where anomalies for detectors are not generated, loop through it and fill values with 0 + const unUsedDetectors = pullAll( + allDetectorIds, + Object.keys(aggsDetectors) + ).reduce((acc: any, unusedDetector: string) => { + return { + ...acc, + [unusedDetector]: { + ...allDetectors[unusedDetector], + totalAnomalies: 0, + lastActiveAnomaly: 0, + }, + }; + }, {}); + + // If sorting criteria is from the aggregation manage pagination in memory. + let finalDetectors = orderBy( + { ...aggsDetectors, ...unUsedDetectors }, + [sortField], + [sortDirection] + ); + if (!sortQueryMap[sortField]) { + finalDetectors = Object.values(finalDetectors) + .slice(from, from + size) + .reduce( + (acc, detector: any) => ({ ...acc, [detector.id]: detector }), + {} + ); + } - // update the final detectors to include the detector enabledTime - finalDetectors.forEach((detector, i) => { - detector.enabledTime = finalDetectorsWithJob[i].enabledTime; - }); + // Get detector state as well: loop through the ids to get each detector's state using profile api + const allIds = finalDetectors.map((detector) => detector.id); + + const detectorStatePromises = allIds.map(async (id: string) => { + try { + const detectorStateResp = await this.client + .asScoped(request) + .callAsCurrentUser('ad.detectorProfile', { + detectorId: id, + }); + return detectorStateResp; + } catch (err) { + console.log('Error getting detector profile ', err); + return Promise.reject( + new Error( + 'Error retrieving all detector states: ' + getErrorMessage(err) + ) + ); + } + }); + const detectorStateResponses = await Promise.all( + detectorStatePromises + ).catch((err) => { + throw err; + }); + const finalDetectorStates = getFinalDetectorStates( + detectorStateResponses, + finalDetectors + ); + // update the final detectors to include the detector state + finalDetectors.forEach((detector, i) => { + detector.curState = finalDetectorStates[i].state; + }); - return { - ok: true, - response: { - totalDetectors, - detectorList: Object.values(finalDetectors), - }, - }; - } catch (err) { - console.log('Anomaly detector - Unable to search detectors', err); - if (isIndexNotFoundError(err)) { - return { ok: true, response: { totalDetectors: 0, detectorList: [] } }; - } - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + // get ad job + const detectorsWithJobPromises = allIds.map(async (id: string) => { + try { + const detectorResp = await this.client + .asScoped(request) + .callAsCurrentUser('ad.getDetector', { + detectorId: id, + }); + return detectorResp; + } catch (err) { + console.log('Error getting detector ', err); + return Promise.reject( + new Error('Error retrieving all detectors: ' + getErrorMessage(err)) + ); + } + }); + const detectorsWithJobResponses = await Promise.all( + detectorsWithJobPromises + ).catch((err) => { + throw err; + }); + const finalDetectorsWithJob = getDetectorsWithJob( + detectorsWithJobResponses + ); -const getAnomalyResults = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { - from = 0, - size = 20, - sortDirection = SORT_DIRECTION.DESC, - sortField = AD_DOC_FIELDS.DATA_START_TIME, - dateRangeFilter = undefined, - anomalyThreshold = -1, - //@ts-ignore - } = req.query as { - from: number; - size: number; - sortDirection: SORT_DIRECTION; - sortField?: string; - dateRangeFilter?: string; - anomalyThreshold: number; - }; - const { detectorId } = req.params; - - //Allowed sorting columns - const sortQueryMap = { - anomalyGrade: { anomaly_grade: sortDirection }, - confidence: { confidence: sortDirection }, - [AD_DOC_FIELDS.DATA_START_TIME]: { - [AD_DOC_FIELDS.DATA_START_TIME]: sortDirection, - }, - [AD_DOC_FIELDS.DATA_END_TIME]: { - [AD_DOC_FIELDS.DATA_END_TIME]: sortDirection, - }, - } as { [key: string]: object }; - let sort = {}; - const sortQuery = sortQueryMap[sortField]; - if (sortQuery) { - sort = sortQuery; + // update the final detectors to include the detector enabledTime + finalDetectors.forEach((detector, i) => { + detector.enabledTime = finalDetectorsWithJob[i].enabledTime; + }); + + return kibanaResponse.ok({ + body: { + ok: true, + response: { + totalDetectors, + detectorList: Object.values(finalDetectors), + }, + }, + }); + } catch (err) { + console.log('Anomaly detector - Unable to search detectors', err); + if (isIndexNotFoundError(err)) { + return kibanaResponse.ok({ + body: { ok: true, response: { totalDetectors: 0, detectorList: [] } }, + }); + } + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); } + }; + + getAnomalyResults = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + const { detectorId } = request.params as { detectorId: string }; + try { + const { + from = 0, + size = 20, + sortDirection = SORT_DIRECTION.DESC, + sortField = AD_DOC_FIELDS.DATA_START_TIME, + dateRangeFilter = undefined, + anomalyThreshold = -1, + } = request.query as { + from: number; + size: number; + sortDirection: SORT_DIRECTION; + sortField?: string; + dateRangeFilter?: string; + anomalyThreshold: number; + }; + + //Allowed sorting columns + const sortQueryMap = { + anomalyGrade: { anomaly_grade: sortDirection }, + confidence: { confidence: sortDirection }, + [AD_DOC_FIELDS.DATA_START_TIME]: { + [AD_DOC_FIELDS.DATA_START_TIME]: sortDirection, + }, + [AD_DOC_FIELDS.DATA_END_TIME]: { + [AD_DOC_FIELDS.DATA_END_TIME]: sortDirection, + }, + } as { [key: string]: object }; + let sort = {}; + const sortQuery = sortQueryMap[sortField]; + if (sortQuery) { + sort = sortQuery; + } - //Preparing search request - const requestBody = { - sort, - size, - from, - query: { - bool: { - filter: [ - { - term: { - detector_id: detectorId, + //Preparing search request + const requestBody = { + sort, + size, + from, + query: { + bool: { + filter: [ + { + term: { + detector_id: detectorId, + }, }, - }, - { - range: { - anomaly_grade: { - gt: anomalyThreshold, + { + range: { + anomaly_grade: { + gt: anomalyThreshold, + }, }, }, - }, - ], + ], + }, }, - }, - }; - - try { - const dateRangeFilterObj = (dateRangeFilter - ? JSON.parse(dateRangeFilter) - : undefined) as DateRangeFilter; - const filterSize = requestBody.query.bool.filter.length; - if (dateRangeFilterObj && dateRangeFilterObj.fieldName) { - (dateRangeFilterObj.startTime || dateRangeFilterObj.endTime) && - set( - requestBody.query.bool.filter, - `${filterSize}.range.${dateRangeFilterObj.fieldName}.format`, - 'epoch_millis' - ); - - dateRangeFilterObj.startTime && - set( - requestBody.query.bool.filter, - `${filterSize}.range.${dateRangeFilterObj.fieldName}.gte`, - dateRangeFilterObj.startTime - ); + }; - dateRangeFilterObj.endTime && - set( - requestBody.query.bool.filter, - `${filterSize}.range.${dateRangeFilterObj.fieldName}.lte`, - dateRangeFilterObj.endTime - ); + try { + const dateRangeFilterObj = (dateRangeFilter + ? JSON.parse(dateRangeFilter) + : undefined) as DateRangeFilter; + const filterSize = requestBody.query.bool.filter.length; + if (dateRangeFilterObj && dateRangeFilterObj.fieldName) { + (dateRangeFilterObj.startTime || dateRangeFilterObj.endTime) && + set( + requestBody.query.bool.filter, + `${filterSize}.range.${dateRangeFilterObj.fieldName}.format`, + 'epoch_millis' + ); + + dateRangeFilterObj.startTime && + set( + requestBody.query.bool.filter, + `${filterSize}.range.${dateRangeFilterObj.fieldName}.gte`, + dateRangeFilterObj.startTime + ); + + dateRangeFilterObj.endTime && + set( + requestBody.query.bool.filter, + `${filterSize}.range.${dateRangeFilterObj.fieldName}.lte`, + dateRangeFilterObj.endTime + ); + } + } catch (error) { + console.log('wrong date range filter', error); } - } catch (error) { - console.log('wrong date range filter', error); - } - const response = await callWithRequest(req, 'ad.searchResults', { - body: requestBody, - }); + const response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.searchResults', { + body: requestBody, + }); - const totalResults: number = get(response, 'hits.total.value', 0); - - const detectorResult: AnomalyResult[] = []; - const featureResult: { [key: string]: FeatureResult[] } = {}; - get(response, 'hits.hits', []).forEach((result: any) => { - detectorResult.push({ - startTime: result._source.data_start_time, - endTime: result._source.data_end_time, - plotTime: result._source.data_end_time, - confidence: - result._source.confidence != null && - result._source.confidence !== 'NaN' && - result._source.confidence > 0 - ? toFixedNumberForAnomaly( - Number.parseFloat(result._source.confidence) - ) - : 0, - anomalyGrade: - result._source.anomaly_grade != null && - result._source.anomaly_grade !== 'NaN' && - result._source.anomaly_grade > 0 - ? toFixedNumberForAnomaly( - Number.parseFloat(result._source.anomaly_grade) - ) - : 0, - ...(result._source.entity != null - ? { entity: result._source.entity } - : {}), - // TODO: we should refactor other places to read feature data from - // AnomalyResult, instead of having separate FeatureData which is hard - // to know feature data belongs to which anomaly result - features: getFeatureData(result), - }); - result._source.feature_data.forEach((featureData: any) => { - if (!featureResult[featureData.feature_id]) { - featureResult[featureData.feature_id] = []; - } - featureResult[featureData.feature_id].push({ + const totalResults: number = get(response, 'hits.total.value', 0); + + const detectorResult: AnomalyResult[] = []; + const featureResult: { [key: string]: FeatureResult[] } = {}; + get(response, 'hits.hits', []).forEach((result: any) => { + detectorResult.push({ startTime: result._source.data_start_time, endTime: result._source.data_end_time, plotTime: result._source.data_end_time, - data: - featureData.data != null && featureData.data !== 'NaN' - ? toFixedNumberForAnomaly(Number.parseFloat(featureData.data)) + confidence: + result._source.confidence != null && + result._source.confidence !== 'NaN' && + result._source.confidence > 0 + ? toFixedNumberForAnomaly( + Number.parseFloat(result._source.confidence) + ) + : 0, + anomalyGrade: + result._source.anomaly_grade != null && + result._source.anomaly_grade !== 'NaN' && + result._source.anomaly_grade > 0 + ? toFixedNumberForAnomaly( + Number.parseFloat(result._source.anomaly_grade) + ) : 0, + ...(result._source.entity != null + ? { entity: result._source.entity } + : {}), + // TODO: we should refactor other places to read feature data from + // AnomalyResult, instead of having separate FeatureData which is hard + // to know feature data belongs to which anomaly result + features: this.getFeatureData(result), + }); + result._source.feature_data.forEach((featureData: any) => { + if (!featureResult[featureData.feature_id]) { + featureResult[featureData.feature_id] = []; + } + featureResult[featureData.feature_id].push({ + startTime: result._source.data_start_time, + endTime: result._source.data_end_time, + plotTime: result._source.data_end_time, + data: + featureData.data != null && featureData.data !== 'NaN' + ? toFixedNumberForAnomaly(Number.parseFloat(featureData.data)) + : 0, + }); }); }); - }); - return { - ok: true, - response: { - totalAnomalies: totalResults, - results: detectorResult, - featureResults: featureResult, - }, - }; - } catch (err) { - console.log('Anomaly detector - Unable to get results', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; - -const matchDetector = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { detectorName } = req.params; - const response = await callWithRequest(req, 'ad.matchDetector', { - detectorName, - }); - return { - ok: true, - response: response, - }; - } catch (err) { - console.log('Anomaly detector - matchDetector', err); - return { ok: false, error: getErrorMessage(err) }; - } -}; + return kibanaResponse.ok({ + body: { + ok: true, + response: { + totalAnomalies: totalResults, + results: detectorResult, + featureResults: featureResult, + }, + }, + }); + } catch (err) { + console.log('Anomaly detector - Unable to get results', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + }; -const getDetectorCount = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const response = await callWithRequest(req, 'ad.detectorCount'); - return { - ok: true, - response: response, - }; - } catch (err) { - console.log('Anomaly detector - getDetectorCount', err); - return { ok: false, error: getErrorMessage(err) }; - } -}; + matchDetector = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const { detectorName } = request.params as { detectorName: string }; + const response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.matchDetector', { + detectorName, + }); + return kibanaResponse.ok({ + body: { + ok: true, + response: response, + }, + }); + } catch (err) { + console.log('Anomaly detector - matchDetector', err); + return kibanaResponse.ok({ + body: { ok: false, error: getErrorMessage(err) }, + }); + } + }; -const getFeatureData = (rawResult: any) => { - const featureResult: { [key: string]: FeatureResult } = {}; - rawResult._source.feature_data.forEach((featureData: any) => { - featureResult[featureData.feature_id] = { - startTime: rawResult._source.data_start_time, - endTime: rawResult._source.data_end_time, - plotTime: rawResult._source.data_end_time, - data: - featureData.data != null && featureData.data !== 'NaN' - ? toFixedNumberForAnomaly(Number.parseFloat(featureData.data)) - : 0, - }; - }); - return featureResult; -}; + getDetectorCount = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const response = await this.client + .asScoped(request) + .callAsCurrentUser('ad.detectorCount'); + return kibanaResponse.ok({ + body: { + ok: true, + response: response, + }, + }); + } catch (err) { + console.log('Anomaly detector - getDetectorCount', err); + return kibanaResponse.ok({ + body: { ok: false, error: getErrorMessage(err) }, + }); + } + }; + + getFeatureData = (rawResult: any) => { + const featureResult: { [key: string]: FeatureResult } = {}; + rawResult._source.feature_data.forEach((featureData: any) => { + featureResult[featureData.feature_id] = { + startTime: rawResult._source.data_start_time, + endTime: rawResult._source.data_end_time, + plotTime: rawResult._source.data_end_time, + data: + featureData.data != null && featureData.data !== 'NaN' + ? toFixedNumberForAnomaly(Number.parseFloat(featureData.data)) + : 0, + }; + }); + return featureResult; + }; +} diff --git a/server/routes/alerting.ts b/server/routes/alerting.ts index 1c596dca..25606a2b 100644 --- a/server/routes/alerting.ts +++ b/server/routes/alerting.ts @@ -13,113 +13,135 @@ * permissions and limitations under the License. */ -import { Request, ResponseToolkit } from 'hapi'; //@ts-ignore import { get, set } from 'lodash'; -//@ts-ignore -import { CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; import { SearchResponse } from '../models/interfaces'; -import { Monitor, ServerResponse } from '../models/types'; +import { Monitor } from '../models/types'; import { Router } from '../router'; import { MAX_MONITORS } from '../utils/constants'; import { getErrorMessage } from './utils/adHelpers'; +import { + RequestHandlerContext, + KibanaRequest, + KibanaResponseFactory, + IKibanaResponse, +} from '../../../../src/core/server'; -export default function (apiRouter: Router) { - apiRouter.post('/monitors/_search', searchMonitors); - apiRouter.get('/monitors/alerts', searchAlerts); +export function registerAlertingRoutes( + apiRouter: Router, + alertingService: AlertingService +) { + apiRouter.post('/monitors/_search', alertingService.searchMonitors); + apiRouter.get('/monitors/alerts', alertingService.searchAlerts); } -const searchMonitors = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const requestBody = { - size: MAX_MONITORS, - query: { - nested: { - path: 'monitor.inputs', - query: { - bool: { - must: [ - { - term: { - 'monitor.inputs.search.indices.keyword': { - value: '.opendistro-anomaly-results*', +export default class AlertingService { + private client: any; + + constructor(client: any) { + this.client = client; + } + + searchMonitors = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const requestBody = { + size: MAX_MONITORS, + query: { + nested: { + path: 'monitor.inputs', + query: { + bool: { + must: [ + { + term: { + 'monitor.inputs.search.indices.keyword': { + value: '.opendistro-anomaly-results*', + }, }, }, - }, - ], + ], + }, }, }, }, - }, - }; - const response: SearchResponse = await callWithRequest( - req, - 'alerting.searchMonitors', - { body: requestBody } - ); - const totalMonitors = get(response, 'hits.total.value', 0); - const allMonitors = get(response, 'hits.hits', []).reduce( - (acc: any, monitor: any) => ({ - ...acc, - [monitor._id]: { - id: monitor._id, - name: get(monitor, '_source.name'), - enabled: get(monitor, '_source.enabled', false), - enabledTime: get(monitor, '_source.enabled_time'), - schedule: get(monitor, '_source.schedule'), - inputs: get(monitor, '_source.inputs'), - triggers: get(monitor, '_source.triggers'), - lastUpdateTime: get(monitor, '_source.last_update_time'), - }, - }), - {} - ); + }; + const response: SearchResponse = await this.client + .asScoped(request) + .callAsCurrentUser('alerting.searchMonitors', { body: requestBody }); + const totalMonitors = get(response, 'hits.total.value', 0); + const allMonitors = get(response, 'hits.hits', []).reduce( + (acc: any, monitor: any) => ({ + ...acc, + [monitor._id]: { + id: monitor._id, + name: get(monitor, '_source.name'), + enabled: get(monitor, '_source.enabled', false), + enabledTime: get(monitor, '_source.enabled_time'), + schedule: get(monitor, '_source.schedule'), + inputs: get(monitor, '_source.inputs'), + triggers: get(monitor, '_source.triggers'), + lastUpdateTime: get(monitor, '_source.last_update_time'), + }, + }), + {} + ); - return { - ok: true, - response: { - totalMonitors, - monitors: Object.values(allMonitors), - }, - }; - } catch (err) { - console.log('Unable to get monitor on top of detector', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + return kibanaResponse.ok({ + body: { + ok: true, + response: { + totalMonitors, + monitors: Object.values(allMonitors), + }, + }, + }); + } catch (err) { + console.log('Unable to get monitor on top of detector', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + }; -const searchAlerts = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - try { - const { monitorId, startTime, endTime } = req.query as { - monitorId?: string; - startTime?: number; - endTime?: number; - }; - const response = await callWithRequest(req, 'alerting.searchAlerts', { - monitorId: monitorId, - startTime: startTime, - endTime: endTime, - }); - return { - ok: true, - response, - }; - } catch (err) { - console.log('Unable to search alerts', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + searchAlerts = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const { monitorId, startTime, endTime } = request.query as { + monitorId?: string; + startTime?: number; + endTime?: number; + }; + const response = await this.client + .asScoped(request) + .callAsCurrentUser('alerting.searchAlerts', { + monitorId: monitorId, + startTime: startTime, + endTime: endTime, + }); + return kibanaResponse.ok({ + body: { + ok: true, + response, + }, + }); + } catch (err) { + console.log('Unable to search alerts', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + }; +} diff --git a/server/routes/elasticsearch.ts b/server/routes/elasticsearch.ts index e89157bb..25723499 100644 --- a/server/routes/elasticsearch.ts +++ b/server/routes/elasticsearch.ts @@ -13,10 +13,7 @@ * permissions and limitations under the License. */ -import { Request, ResponseToolkit } from 'hapi'; import { get } from 'lodash'; -//@ts-ignore -import { CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; import { SearchResponse } from '../models/interfaces'; import { CatIndex, @@ -28,16 +25,12 @@ import { } from '../models/types'; import { Router } from '../router'; import { getErrorMessage, isIndexNotFoundError } from './utils/adHelpers'; - -export default function (apiRouter: Router) { - apiRouter.get('/_indices', getIndices); - apiRouter.get('/_aliases', getAliases); - apiRouter.get('/_mappings', getMapping); - apiRouter.post('/_search', executeSearch); - apiRouter.put('/create_index', createIndex); - apiRouter.post('/bulk', bulk); - apiRouter.post('/delete_index', deleteIndex); -} +import { + RequestHandlerContext, + KibanaRequest, + KibanaResponseFactory, + IKibanaResponse, +} from '../../../../src/core/server'; type SearchParams = { index: string; @@ -45,222 +38,277 @@ type SearchParams = { body: object; }; -const executeSearch = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise>> => { - try { - const { - index, - query, - size = 0, - sort = undefined, - collapse = undefined, - aggs = undefined, - rawQuery = undefined, - } = req.payload as { - index: string; - query?: object; - size?: number; - sort?: object; - collapse?: object; - aggs?: object; - rawQuery: object; - }; - const requestBody = rawQuery - ? rawQuery - : { - query: query, - ...(sort !== undefined && { sort: sort }), - ...(collapse !== undefined && { collapse: collapse }), - ...(aggs !== undefined && { aggs: aggs }), - }; - - const params: SearchParams = { index, size, body: requestBody }; +export function registerESRoutes(apiRouter: Router, esService: ESService) { + apiRouter.get('/_indices', esService.getIndices); + apiRouter.get('/_aliases', esService.getAliases); + apiRouter.get('/_mappings', esService.getMapping); + apiRouter.post('/_search', esService.executeSearch); + apiRouter.put('/create_index', esService.createIndex); + apiRouter.post('/bulk', esService.bulk); + apiRouter.post('/delete_index', esService.deleteIndex); +} - const results: SearchResponse = await callWithRequest( - req, - 'search', - params - ); +export default class ESService { + private client: any; - return { ok: true, response: results }; - } catch (err) { - console.error('Anomaly detector - Unable to execute search', err); - return { - ok: false, - error: getErrorMessage(err), - }; + constructor(client: any) { + this.client = client; } -}; -const getIndices = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - const { index } = req.query as { index: string }; - try { - const response: CatIndex[] = await callWithRequest(req, 'cat.indices', { - index, - format: 'json', - h: 'health,index', - }); - return { ok: true, response: { indices: response } }; - } catch (err) { - // In case no matching indices is found it throws an error. - if ( - err.statusCode === 404 && - get(err, 'body.error.type', '') === 'index_not_found_exception' - ) { - return { ok: true, response: { indices: [] } }; + executeSearch = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + try { + const { + index, + query, + size = 0, + sort = undefined, + collapse = undefined, + aggs = undefined, + rawQuery = undefined, + } = request.body as { + index: string; + query?: object; + size?: number; + sort?: object; + collapse?: object; + aggs?: object; + rawQuery: object; + }; + const requestBody = rawQuery + ? rawQuery + : { + query: query, + ...(sort !== undefined && { sort: sort }), + ...(collapse !== undefined && { collapse: collapse }), + ...(aggs !== undefined && { aggs: aggs }), + }; + + const params: SearchParams = { index, size, body: requestBody }; + + const results: SearchResponse = await this.client + .asScoped(request) + .callAsCurrentUser('search', params); + + return kibanaResponse.ok({ body: { ok: true, response: results } }); + } catch (err) { + console.error('Anomaly detector - Unable to execute search', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); } - console.log('Anomaly detector - Unable to get indices', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + }; -const getAliases = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - const { alias } = req.query as { alias: string }; - try { - const response: IndexAlias[] = await callWithRequest(req, 'cat.aliases', { - alias, - format: 'json', - h: 'alias,index', - }); - return { ok: true, response: { aliases: response } }; - } catch (err) { - console.log('Anomaly detector - Unable to get aliases', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + getIndices = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + const { index } = request.query as { index: string }; + try { + const response: CatIndex[] = await this.client + .asScoped(request) + .callAsCurrentUser('cat.indices', { + index, + format: 'json', + h: 'health,index', + }); + return kibanaResponse.ok({ + body: { ok: true, response: { indices: response } }, + }); + } catch (err) { + // In case no matching indices is found it throws an error. + if ( + err.statusCode === 404 && + get(err, 'body.error.type', '') === 'index_not_found_exception' + ) { + return kibanaResponse.ok({ + body: { ok: true, response: { indices: [] } }, + }); + } + console.log('Anomaly detector - Unable to get indices', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + }; -const createIndex = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - //@ts-ignore - const index = req.payload.indexConfig.index; - //@ts-ignore - const body = req.payload.indexConfig.body; - try { - await callWithRequest(req, 'indices.create', { - index: index, - body: body, - }); - } catch (err) { - console.log('Anomaly detector - Unable to create index', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } - try { - const response: CatIndex[] = await callWithRequest(req, 'cat.indices', { - index, - format: 'json', - h: 'health,index', - }); - return { ok: true, response: { indices: response } }; - } catch (err) { - console.log('Anomaly detector - Unable to get indices', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + getAliases = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + const { alias } = request.query as { alias: string }; + try { + const response: IndexAlias[] = await this.client + .asScoped(request) + .callAsCurrentUser('cat.aliases', { + alias, + format: 'json', + h: 'alias,index', + }); + return kibanaResponse.ok({ + body: { ok: true, response: { aliases: response } }, + }); + } catch (err) { + console.log('Anomaly detector - Unable to get aliases', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + }; -const bulk = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - //@ts-ignore - const body = req.payload.body; - try { - const response: any = await callWithRequest(req, 'bulk', { - body: body, - }); + createIndex = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { //@ts-ignore - return { ok: true, response: { response } }; - } catch (err) { - console.log('Anomaly detector - Unable to perform bulk action', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + const index = request.body.index; + //@ts-ignore + const body = request.body.body; + try { + await this.client.asScoped(request).callAsCurrentUser('indices.create', { + index: index, + body: body, + }); + } catch (err) { + console.log('Anomaly detector - Unable to create index', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + try { + const response: CatIndex[] = await this.client + .asScoped(request) + .callAsCurrentUser('cat.indices', { + index, + format: 'json', + h: 'health,index', + }); + return kibanaResponse.ok({ + body: { ok: true, response: { indices: response } }, + }); + } catch (err) { + console.log('Anomaly detector - Unable to get indices', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + }; -const deleteIndex = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - //@ts-ignore - const index = req.payload.index; - try { - await callWithRequest(req, 'indices.delete', { - index: index, - }); - } catch (err) { - console.log( - 'Anomaly detector - Unable to perform delete index action', - err - ); - // Ignore the error if it's an index_not_found_exception - if (!isIndexNotFoundError(err)) { - return { - ok: false, - error: getErrorMessage(err), - }; + bulk = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + const body = request.body; + try { + const response: any = await this.client + .asScoped(request) + .callAsCurrentUser('bulk', { + body: body, + }); + return kibanaResponse.ok({ body: { ok: true, response: { response } } }); + } catch (err) { + console.log('Anomaly detector - Unable to perform bulk action', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); } - } - try { - const response: CatIndex[] = await callWithRequest(req, 'cat.indices', { - index, - format: 'json', - h: 'health,index', - }); - return { ok: true, response: { indices: response } }; - } catch (err) { - console.log('Anomaly detector - Unable to get indices', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + }; -const getMapping = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - const { index } = req.query as { index: string }; - try { - const response = await callWithRequest(req, 'indices.getMapping', { - index, - }); - return { ok: true, response: { mappings: response } }; - } catch (err) { - console.log('Anomaly detector - Unable to get mappings', err); - return { - ok: false, - error: getErrorMessage(err), - }; - } -}; + deleteIndex = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + const index = request.query as { index: string }; + try { + await this.client.asScoped(request).callAsCurrentUser('indices.delete', { + index: index, + }); + } catch (err) { + console.log( + 'Anomaly detector - Unable to perform delete index action', + err + ); + // Ignore the error if it's an index_not_found_exception + if (!isIndexNotFoundError(err)) { + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + } + try { + const response: CatIndex[] = await this.client + .asScoped(request) + .callAsCurrentUser('cat.indices', { + index, + format: 'json', + h: 'health,index', + }); + return kibanaResponse.ok({ + body: { ok: true, response: { indices: response } }, + }); + } catch (err) { + console.log('Anomaly detector - Unable to get indices', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + }; + + getMapping = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + const { index } = request.query as { index: string }; + try { + const response = await this.client + .asScoped(request) + .callAsCurrentUser('indices.getMapping', { + index, + }); + return kibanaResponse.ok({ + body: { ok: true, response: { mappings: response } }, + }); + } catch (err) { + console.log('Anomaly detector - Unable to get mappings', err); + return kibanaResponse.ok({ + body: { + ok: false, + error: getErrorMessage(err), + }, + }); + } + }; +} diff --git a/server/routes/sampleData.ts b/server/routes/sampleData.ts index 07948b83..9fefa08e 100644 --- a/server/routes/sampleData.ts +++ b/server/routes/sampleData.ts @@ -15,64 +15,80 @@ //@ts-ignore import moment from 'moment'; -import { Request, ResponseToolkit } from 'hapi'; import path from 'path'; -//@ts-ignore -import { CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; import { ServerResponse } from '../models/types'; import { Router } from '../router'; import { SAMPLE_TYPE } from '../../public/utils/constants'; import { loadSampleData } from '../sampleData/utils/helpers'; +import { + RequestHandlerContext, + KibanaRequest, + KibanaResponseFactory, + IKibanaResponse, +} from '../../../../src/core/server'; -export default function (apiRouter: Router) { - apiRouter.post('/create_sample_data', createSampleData); +export function registerSampleDataRoutes( + apiRouter: Router, + sampleDataService: SampleDataService +) { + apiRouter.post( + '/create_sample_data/{type}', + sampleDataService.createSampleData + ); } -// Get the zip file stored in server, unzip it, and bulk insert it -const createSampleData = async ( - req: Request, - h: ResponseToolkit, - callWithRequest: CallClusterWithRequest -): Promise> => { - //@ts-ignore - const type = req.payload.type as SAMPLE_TYPE; - try { - let filePath = ''; - let indexName = ''; +export default class SampleDataService { + private client: any; - switch (type) { - case SAMPLE_TYPE.HTTP_RESPONSES: { - filePath = path.resolve( - __dirname, - '../sampleData/rawData/httpResponses.json.gz' - ); - indexName = 'opendistro-sample-http-responses'; - break; - } - case SAMPLE_TYPE.ECOMMERCE: { - filePath = path.resolve( - __dirname, - '../sampleData/rawData/ecommerce.json.gz' - ); - indexName = 'opendistro-sample-ecommerce'; - break; - } - case SAMPLE_TYPE.HOST_HEALTH: { - filePath = path.resolve( - __dirname, - '../sampleData/rawData/hostHealth.json.gz' - ); - indexName = 'opendistro-sample-host-health'; - break; + constructor(client: any) { + this.client = client; + } + + // Get the zip file stored in server, unzip it, and bulk insert it + createSampleData = async ( + context: RequestHandlerContext, + request: KibanaRequest, + kibanaResponse: KibanaResponseFactory + ): Promise> => { + //@ts-ignore + const type = request.params.type as SAMPLE_TYPE; + try { + let filePath = ''; + let indexName = ''; + + switch (type) { + case SAMPLE_TYPE.HTTP_RESPONSES: { + filePath = path.resolve( + __dirname, + '../sampleData/rawData/httpResponses.json.gz' + ); + indexName = 'opendistro-sample-http-responses'; + break; + } + case SAMPLE_TYPE.ECOMMERCE: { + filePath = path.resolve( + __dirname, + '../sampleData/rawData/ecommerce.json.gz' + ); + indexName = 'opendistro-sample-ecommerce'; + break; + } + case SAMPLE_TYPE.HOST_HEALTH: { + filePath = path.resolve( + __dirname, + '../sampleData/rawData/hostHealth.json.gz' + ); + indexName = 'opendistro-sample-host-health'; + break; + } } - } - await loadSampleData(filePath, indexName, req, callWithRequest); + await loadSampleData(filePath, indexName, this.client, request); - //@ts-ignore - return { ok: true }; - } catch (err) { - console.log('Anomaly detector - Unable to load the sample data', err); - return { ok: false, error: err.message }; - } -}; + return kibanaResponse.ok({ body: { ok: true } }); + } catch (err) { + console.log('Anomaly detector - Unable to load the sample data', err); + return kibanaResponse.ok({ body: { ok: false, error: err.message } }); + } + }; +} diff --git a/server/sampleData/utils/helpers.ts b/server/sampleData/utils/helpers.ts index 7af1b870..3cf4d316 100644 --- a/server/sampleData/utils/helpers.ts +++ b/server/sampleData/utils/helpers.ts @@ -16,12 +16,9 @@ //@ts-ignore import moment from 'moment'; import readline from 'readline'; -import { Request } from 'hapi'; - +import { RequestHandlerContext, KibanaRequest } from '../../../../../src/core/server'; import fs from 'fs'; import { createUnzip } from 'zlib'; -//@ts-ignore -import { CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; import { isEmpty } from 'lodash'; import { prettifyErrorMessage } from '../../utils/helpers'; @@ -30,8 +27,8 @@ const BULK_INSERT_SIZE = 500; export const loadSampleData = ( filePath: string, indexName: string, - req: Request, - callWithRequest: CallClusterWithRequest + client: any, + request: KibanaRequest, ) => { return new Promise((resolve, reject) => { let count: number = 0; @@ -102,9 +99,12 @@ export const loadSampleData = ( const bulkInsert = async (docs: any[]) => { try { const bulkBody = prepareBody(docs, offset); - const resp = await callWithRequest(req, 'bulk', { - body: bulkBody, - }); + const resp = await client.asScoped(request).callAsCurrentUser( + 'bulk', + { + body: bulkBody, + } + ); if (resp.errors) { const errorItems = resp.items; const firstErrorReason = isEmpty(errorItems) diff --git a/server/utils/helpers.ts b/server/utils/helpers.ts index 971bb897..ed1b0f9d 100644 --- a/server/utils/helpers.ts +++ b/server/utils/helpers.ts @@ -69,8 +69,8 @@ const PERMISSIONS_ERROR_PATTERN = /no permissions for \[(.+)\] and User \[name=( export const NO_PERMISSIONS_KEY_WORD = 'no permissions'; export const prettifyErrorMessage = (rawErrorMessage: string) => { - if (isEmpty(rawErrorMessage)) { - return 'Unknow error is returned.'; + if (isEmpty(rawErrorMessage) || rawErrorMessage === 'undefined') { + return 'Unknown error is returned.'; } const match = rawErrorMessage.match(PERMISSIONS_ERROR_PATTERN); if (isEmpty(match)) { diff --git a/test/jest.config.js b/test/jest.config.js index 9c5e302f..d005a376 100644 --- a/test/jest.config.js +++ b/test/jest.config.js @@ -21,7 +21,6 @@ module.exports = { coverageDirectory: './coverage', moduleNameMapper: { '\\.(css|less|scss)$': '/test/mocks/styleMock.ts', - '^ui/(.*)': '', }, coverageReporters: ['lcov', 'text', 'cobertura'], testMatch: ['**/*.test.js', '**/*.test.jsx', '**/*.test.ts', '**/*.test.tsx'], diff --git a/test/mocks/coreServicesMock.ts b/test/mocks/coreServicesMock.ts new file mode 100644 index 00000000..7e4ef974 --- /dev/null +++ b/test/mocks/coreServicesMock.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ + +const coreServicesMock = { + uiSettings: { + get: jest.fn(), + }, + chrome: { + setBreadcrumbs: jest.fn(), + }, + notifications: { + toasts: { + addDanger: jest.fn().mockName('addDanger'), + addSuccess: jest.fn().mockName('addSuccess'), + }, + }, +}; + +export default coreServicesMock; diff --git a/test/mocks/httpClientMock.ts b/test/mocks/httpClientMock.ts index 333b1f1f..dda3bf92 100644 --- a/test/mocks/httpClientMock.ts +++ b/test/mocks/httpClientMock.ts @@ -1,5 +1,5 @@ /* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -import { IHttpService } from 'angular'; +import { HttpSetup } from '../../../../src/core/public'; const httpClientMock = jest.fn() as any; @@ -23,4 +23,4 @@ httpClientMock.head = jest.fn(); httpClientMock.post = jest.fn(); httpClientMock.put = jest.fn(); -export default httpClientMock as IHttpService; +export default httpClientMock as HttpSetup; diff --git a/test/mocks/index.ts b/test/mocks/index.ts index 1e53568a..bbc698f4 100644 --- a/test/mocks/index.ts +++ b/test/mocks/index.ts @@ -15,5 +15,6 @@ import httpClientMock from './httpClientMock'; import styleMock from './styleMock'; +import coreServicesMock from './coreServicesMock'; -export { httpClientMock, styleMock }; +export { httpClientMock, styleMock, coreServicesMock }; diff --git a/test/setup.jest.ts b/test/setup.jest.ts index acfe0ae3..3f11db59 100644 --- a/test/setup.jest.ts +++ b/test/setup.jest.ts @@ -29,35 +29,6 @@ jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ }, })); -jest.mock('ui/notify', () => ({ - toastNotifications: { - addDanger: jest.fn().mockName('addDanger'), - addSuccess: jest.fn().mockName('addSuccess'), - }, -})); - -jest.mock('ui/notify/lib/format_angular_http_error', () => ({ - isAngularHttpError: jest.fn().mockName('isAngularHttpError'), -})); - -jest.mock('ui/chrome', () => { - return { - breadcrumbs: (() => { - const breadcrumbs = () => {}; - // @ts-ignore - breadcrumbs.set = jest.fn(); - // @ts-ignore - breadcrumbs.push = jest.fn(); - return breadcrumbs; - })(), - getUiSettingsClient: () => { - return { - get: jest.fn(), - }; - }, - }; -}); - // for Plotly //@ts-ignore window.URL.createObjectURL = function () {}; diff --git a/yarn.lock b/yarn.lock index 18aa485f..114c04e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,28 +18,24 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" - integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== - dependencies: - browserslist "^4.12.0" - invariant "^2.2.4" - semver "^5.5.0" +"@babel/compat-data@^7.12.1", "@babel/compat-data@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.5.tgz#f56db0c4bb1bbbf221b4e81345aab4141e7cb0e9" + integrity sha512-DTsS7cxrsH3by8nqQSpFSyjSfSYl57D6Cf4q8dW3LK83tBKBDCkfcay1nYkXq1nIHXnpX8WMMb/O25HOy3h1zg== "@babel/core@^7.1.0", "@babel/core@^7.10.2": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.4.tgz#4301dfdfafa01eeb97f1896c5501a3f0655d4229" - integrity sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg== + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8" + integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.4" - "@babel/helper-module-transforms" "^7.11.0" - "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.11.4" + "@babel/generator" "^7.12.1" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.1" + "@babel/parser" "^7.12.3" "@babel/template" "^7.10.4" - "@babel/traverse" "^7.11.0" - "@babel/types" "^7.11.0" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -49,12 +45,12 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.11.0", "@babel/generator@^7.11.4", "@babel/generator@^7.4.0": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.4.tgz#1ec7eec00defba5d6f83e50e3ee72ae2fee482be" - integrity sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g== +"@babel/generator@^7.12.1", "@babel/generator@^7.12.5", "@babel/generator@^7.4.0": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de" + integrity sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A== dependencies: - "@babel/types" "^7.11.0" + "@babel/types" "^7.12.5" jsesc "^2.5.1" source-map "^0.5.0" @@ -73,14 +69,14 @@ "@babel/helper-explode-assignable-expression" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-builder-react-jsx-experimental@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz#f35e956a19955ff08c1258e44a515a6d6248646b" - integrity sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg== +"@babel/helper-builder-react-jsx-experimental@^7.12.1": + version "7.12.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.4.tgz#55fc1ead5242caa0ca2875dcb8eed6d311e50f48" + integrity sha512-AjEa0jrQqNk7eDQOo0pTfUOwQBMF+xVqrausQwT9/rTKy0g04ggFNaJpaE09IQMn9yExluigWMJcj0WC7bq+Og== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-module-imports" "^7.10.4" - "@babel/types" "^7.10.5" + "@babel/helper-module-imports" "^7.12.1" + "@babel/types" "^7.12.1" "@babel/helper-builder-react-jsx@^7.10.4": version "7.10.4" @@ -90,37 +86,35 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" - integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== +"@babel/helper-compilation-targets@^7.12.1": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" + integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== dependencies: - "@babel/compat-data" "^7.10.4" - browserslist "^4.12.0" - invariant "^2.2.4" - levenary "^1.1.1" + "@babel/compat-data" "^7.12.5" + "@babel/helper-validator-option" "^7.12.1" + browserslist "^4.14.5" semver "^5.5.0" -"@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.10.5": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" - integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== +"@babel/helper-create-class-features-plugin@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e" + integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== dependencies: "@babel/helper-function-name" "^7.10.4" - "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-member-expression-to-functions" "^7.12.1" "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" "@babel/helper-split-export-declaration" "^7.10.4" -"@babel/helper-create-regexp-features-plugin@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" - integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== +"@babel/helper-create-regexp-features-plugin@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz#18b1302d4677f9dc4740fe8c9ed96680e29d37e8" + integrity sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-regex" "^7.10.4" - regexpu-core "^4.7.0" + regexpu-core "^4.7.1" "@babel/helper-define-map@^7.10.4": version "7.10.5" @@ -132,11 +126,11 @@ lodash "^4.17.19" "@babel/helper-explode-assignable-expression@^7.10.4": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz#2d8e3470252cc17aba917ede7803d4a7a276a41b" - integrity sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ== + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633" + integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.1" "@babel/helper-function-name@^7.10.4": version "7.10.4" @@ -161,31 +155,33 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" - integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== +"@babel/helper-member-expression-to-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" + integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ== dependencies: - "@babel/types" "^7.11.0" + "@babel/types" "^7.12.1" -"@babel/helper-module-imports@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" - integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== +"@babel/helper-module-imports@^7.12.1": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" + integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.5" -"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" - integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== +"@babel/helper-module-transforms@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-simple-access" "^7.12.1" "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/helper-validator-identifier" "^7.10.4" "@babel/template" "^7.10.4" - "@babel/types" "^7.11.0" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" lodash "^4.17.19" "@babel/helper-optimise-call-expression@^7.10.4": @@ -207,40 +203,38 @@ dependencies: lodash "^4.17.19" -"@babel/helper-remap-async-to-generator@^7.10.4": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz#4474ea9f7438f18575e30b0cac784045b402a12d" - integrity sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA== +"@babel/helper-remap-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" + integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-wrap-function" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.1" -"@babel/helper-replace-supers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" - integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== +"@babel/helper-replace-supers@^7.12.1": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz#f009a17543bbbbce16b06206ae73b63d3fca68d9" + integrity sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA== dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.12.1" "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/traverse" "^7.12.5" + "@babel/types" "^7.12.5" -"@babel/helper-simple-access@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" - integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== +"@babel/helper-simple-access@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== dependencies: - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.1" -"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" - integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== +"@babel/helper-skip-transparent-expression-wrappers@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" + integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== dependencies: - "@babel/types" "^7.11.0" + "@babel/types" "^7.12.1" "@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": version "7.11.0" @@ -254,24 +248,29 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-option@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9" + integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A== + "@babel/helper-wrap-function@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" - integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" + integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow== dependencies: "@babel/helper-function-name" "^7.10.4" "@babel/template" "^7.10.4" "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helpers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" - integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== +"@babel/helpers@^7.12.1": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" + integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== dependencies: "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/traverse" "^7.12.5" + "@babel/types" "^7.12.5" "@babel/highlight@^7.10.4": version "7.10.4" @@ -282,116 +281,116 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.4", "@babel/parser@^7.4.3": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.4.tgz#6fa1a118b8b0d80d0267b719213dc947e88cc0ca" - integrity sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.12.3", "@babel/parser@^7.12.5", "@babel/parser@^7.4.3": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0" + integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ== -"@babel/plugin-proposal-async-generator-functions@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" - integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== +"@babel/plugin-proposal-async-generator-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz#dc6c1170e27d8aca99ff65f4925bd06b1c90550e" + integrity sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@^7.10.4", "@babel/plugin-proposal-class-properties@^7.5.5": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" - integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== +"@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.5.5": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" + integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-dynamic-import@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" - integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== +"@babel/plugin-proposal-dynamic-import@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" + integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-export-namespace-from@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54" - integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg== +"@babel/plugin-proposal-export-namespace-from@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4" + integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" - integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== +"@babel/plugin-proposal-json-strings@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" + integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-logical-assignment-operators@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" - integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q== +"@babel/plugin-proposal-logical-assignment-operators@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" + integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" - integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" + integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" - integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== +"@babel/plugin-proposal-numeric-separator@^7.12.1": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.5.tgz#b1ce757156d40ed79d59d467cb2b154a5c4149ba" + integrity sha512-UiAnkKuOrCyjZ3sYNHlRlfuZJbBHknMQ9VMwVeX97Ofwx7RpD6gS2HfqTCh8KNUQgcOm8IKt103oR4KIjh7Q8g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.11.0", "@babel/plugin-proposal-object-rest-spread@^7.5.5": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" - integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== +"@babel/plugin-proposal-object-rest-spread@^7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.5.5": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" + integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-transform-parameters" "^7.12.1" -"@babel/plugin-proposal-optional-catch-binding@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" - integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== +"@babel/plugin-proposal-optional-catch-binding@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" + integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" - integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== +"@babel/plugin-proposal-optional-chaining@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz#cce122203fc8a32794296fc377c6dedaf4363797" + integrity sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-private-methods@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" - integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== +"@babel/plugin-proposal-private-methods@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" + integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" - integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== +"@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" + integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-async-generators@^7.8.0": @@ -401,10 +400,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" - integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== +"@babel/plugin-syntax-class-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978" + integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -429,10 +428,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" - integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g== +"@babel/plugin-syntax-jsx@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" + integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -478,354 +477,352 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" - integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== +"@babel/plugin-syntax-top-level-await@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" + integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-typescript@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.4.tgz#2f55e770d3501e83af217d782cb7517d7bb34d25" - integrity sha512-oSAEz1YkBCAKr5Yiq8/BNtvSAPwkp/IyUnwZogd8p+F0RuYQQrLeRUzIQhueQTTBy/F+a40uS7OFKxnkRvmvFQ== +"@babel/plugin-syntax-typescript@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.1.tgz#460ba9d77077653803c3dd2e673f76d66b4029e5" + integrity sha512-UZNEcCY+4Dp9yYRCAHrHDU+9ZXLYaY9MgBXSRLkB9WjYFRR6quJBumfVrEkUxrePPBwFcpWfNKXqVRQQtm7mMA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-arrow-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" - integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== +"@babel/plugin-transform-arrow-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" + integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-async-to-generator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" - integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== +"@babel/plugin-transform-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" + integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== dependencies: - "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-module-imports" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" -"@babel/plugin-transform-block-scoped-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" - integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== +"@babel/plugin-transform-block-scoped-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" + integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-block-scoping@^7.10.4": - version "7.11.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" - integrity sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew== +"@babel/plugin-transform-block-scoping@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz#f0ee727874b42a208a48a586b84c3d222c2bbef1" + integrity sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-classes@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" - integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== +"@babel/plugin-transform-classes@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" + integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-define-map" "^7.10.4" "@babel/helper-function-name" "^7.10.4" "@babel/helper-optimise-call-expression" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" - integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== +"@babel/plugin-transform-computed-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" + integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-destructuring@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" - integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== +"@babel/plugin-transform-destructuring@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" + integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" - integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== +"@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" + integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-duplicate-keys@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" - integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== +"@babel/plugin-transform-duplicate-keys@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" + integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-exponentiation-operator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" - integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== +"@babel/plugin-transform-exponentiation-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" + integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-for-of@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" - integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== +"@babel/plugin-transform-for-of@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" + integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-function-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" - integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== +"@babel/plugin-transform-function-name@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" + integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== dependencies: "@babel/helper-function-name" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" - integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== +"@babel/plugin-transform-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" + integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" - integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== +"@babel/plugin-transform-member-expression-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" + integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-modules-amd@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" - integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== +"@babel/plugin-transform-modules-amd@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" + integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== dependencies: - "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-module-transforms" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" - integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== +"@babel/plugin-transform-modules-commonjs@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" + integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== dependencies: - "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-module-transforms" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-simple-access" "^7.12.1" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" - integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== +"@babel/plugin-transform-modules-systemjs@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" + integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== dependencies: "@babel/helper-hoist-variables" "^7.10.4" - "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-module-transforms" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-identifier" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" - integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== +"@babel/plugin-transform-modules-umd@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" + integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== dependencies: - "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-module-transforms" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" - integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== +"@babel/plugin-transform-named-capturing-groups-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" + integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-create-regexp-features-plugin" "^7.12.1" -"@babel/plugin-transform-new-target@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" - integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== +"@babel/plugin-transform-new-target@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" + integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-object-super@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" - integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== +"@babel/plugin-transform-object-super@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" + integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" -"@babel/plugin-transform-parameters@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" - integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== +"@babel/plugin-transform-parameters@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" + integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== dependencies: - "@babel/helper-get-function-arity" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-property-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" - integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== +"@babel/plugin-transform-property-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" + integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-display-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz#b5795f4e3e3140419c3611b7a2a3832b9aef328d" - integrity sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw== +"@babel/plugin-transform-react-display-name@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz#1cbcd0c3b1d6648c55374a22fc9b6b7e5341c00d" + integrity sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-jsx-development@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" - integrity sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ== +"@babel/plugin-transform-react-jsx-development@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.5.tgz#677de5b96da310430d6cfb7fee16a1603afa3d56" + integrity sha512-1JJusg3iPgsZDthyWiCr3KQiGs31ikU/mSf2N2dSYEAO0GEImmVUbWf0VoSDGDFTAn5Dj4DUiR6SdIXHY7tELA== dependencies: - "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.12.1" -"@babel/plugin-transform-react-jsx-self@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" - integrity sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg== +"@babel/plugin-transform-react-jsx-self@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.12.1.tgz#ef43cbca2a14f1bd17807dbe4376ff89d714cf28" + integrity sha512-FbpL0ieNWiiBB5tCldX17EtXgmzeEZjFrix72rQYeq9X6nUK38HCaxexzVQrZWXanxKJPKVVIU37gFjEQYkPkA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx-source@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.5.tgz#34f1779117520a779c054f2cdd9680435b9222b4" - integrity sha512-wTeqHVkN1lfPLubRiZH3o73f4rfon42HpgxUSs86Nc+8QIcm/B9s8NNVXu/gwGcOyd7yDib9ikxoDLxJP0UiDA== +"@babel/plugin-transform-react-jsx-source@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.12.1.tgz#d07de6863f468da0809edcf79a1aa8ce2a82a26b" + integrity sha512-keQ5kBfjJNRc6zZN1/nVHCd6LLIHq4aUKcVnvE/2l+ZZROSbqoiGFRtT5t3Is89XJxBQaP7NLZX2jgGHdZvvFQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2" - integrity sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A== +"@babel/plugin-transform-react-jsx@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.5.tgz#39ede0e30159770561b6963be143e40af3bde00c" + integrity sha512-2xkcPqqrYiOQgSlM/iwto1paPijjsDbUynN13tI6bosDz/jOW3CRzYguIE8wKX32h+msbBM22Dv5fwrFkUOZjQ== dependencies: "@babel/helper-builder-react-jsx" "^7.10.4" - "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.12.1" -"@babel/plugin-transform-react-pure-annotations@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz#3eefbb73db94afbc075f097523e445354a1c6501" - integrity sha512-+njZkqcOuS8RaPakrnR9KvxjoG1ASJWpoIv/doyWngId88JoFlPlISenGXjrVacZUIALGUr6eodRs1vmPnF23A== +"@babel/plugin-transform-react-pure-annotations@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" + integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-regenerator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" - integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== +"@babel/plugin-transform-regenerator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" + integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" - integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== +"@babel/plugin-transform-reserved-words@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" + integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-shorthand-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" - integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== +"@babel/plugin-transform-shorthand-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3" + integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-spread@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" - integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== +"@babel/plugin-transform-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" + integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" -"@babel/plugin-transform-sticky-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" - integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== +"@babel/plugin-transform-sticky-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.1.tgz#5c24cf50de396d30e99afc8d1c700e8bce0f5caf" + integrity sha512-CiUgKQ3AGVk7kveIaPEET1jNDhZZEl1RPMWdTBE1799bdz++SwqDHStmxfCtDfBhQgCl38YRiSnrMuUMZIWSUQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-regex" "^7.10.4" -"@babel/plugin-transform-template-literals@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" - integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== +"@babel/plugin-transform-template-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" + integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-typeof-symbol@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" - integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== +"@babel/plugin-transform-typeof-symbol@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz#9ca6be343d42512fbc2e68236a82ae64bc7af78a" + integrity sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-typescript@^7.10.4": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz#2b4879676af37342ebb278216dd090ac67f13abb" - integrity sha512-edJsNzTtvb3MaXQwj8403B7mZoGu9ElDJQZOKjGUnvilquxBA3IQoEIOvkX/1O8xfAsnHS/oQhe2w/IXrr+w0w== +"@babel/plugin-transform-typescript@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.1.tgz#d92cc0af504d510e26a754a7dbc2e5c8cd9c7ab4" + integrity sha512-VrsBByqAIntM+EYMqSm59SiMEf7qkmI9dqMt6RbD/wlwueWmYcI0FFK5Fj47pP6DRZm+3teXjosKlwcZJ5lIMw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.5" + "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-typescript" "^7.10.4" + "@babel/plugin-syntax-typescript" "^7.12.1" -"@babel/plugin-transform-unicode-escapes@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" - integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== +"@babel/plugin-transform-unicode-escapes@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" + integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-unicode-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" - integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== +"@babel/plugin-transform-unicode-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" + integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" "@babel/preset-env@^7.5.5": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" - integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.1.tgz#9c7e5ca82a19efc865384bb4989148d2ee5d7ac2" + integrity sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg== dependencies: - "@babel/compat-data" "^7.11.0" - "@babel/helper-compilation-targets" "^7.10.4" - "@babel/helper-module-imports" "^7.10.4" + "@babel/compat-data" "^7.12.1" + "@babel/helper-compilation-targets" "^7.12.1" + "@babel/helper-module-imports" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-proposal-async-generator-functions" "^7.10.4" - "@babel/plugin-proposal-class-properties" "^7.10.4" - "@babel/plugin-proposal-dynamic-import" "^7.10.4" - "@babel/plugin-proposal-export-namespace-from" "^7.10.4" - "@babel/plugin-proposal-json-strings" "^7.10.4" - "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" - "@babel/plugin-proposal-numeric-separator" "^7.10.4" - "@babel/plugin-proposal-object-rest-spread" "^7.11.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" - "@babel/plugin-proposal-optional-chaining" "^7.11.0" - "@babel/plugin-proposal-private-methods" "^7.10.4" - "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" + "@babel/helper-validator-option" "^7.12.1" + "@babel/plugin-proposal-async-generator-functions" "^7.12.1" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-dynamic-import" "^7.12.1" + "@babel/plugin-proposal-export-namespace-from" "^7.12.1" + "@babel/plugin-proposal-json-strings" "^7.12.1" + "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-numeric-separator" "^7.12.1" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.1" + "@babel/plugin-proposal-private-methods" "^7.12.1" + "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-class-properties" "^7.10.4" + "@babel/plugin-syntax-class-properties" "^7.12.1" "@babel/plugin-syntax-dynamic-import" "^7.8.0" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.0" @@ -835,51 +832,48 @@ "@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.10.4" - "@babel/plugin-transform-arrow-functions" "^7.10.4" - "@babel/plugin-transform-async-to-generator" "^7.10.4" - "@babel/plugin-transform-block-scoped-functions" "^7.10.4" - "@babel/plugin-transform-block-scoping" "^7.10.4" - "@babel/plugin-transform-classes" "^7.10.4" - "@babel/plugin-transform-computed-properties" "^7.10.4" - "@babel/plugin-transform-destructuring" "^7.10.4" - "@babel/plugin-transform-dotall-regex" "^7.10.4" - "@babel/plugin-transform-duplicate-keys" "^7.10.4" - "@babel/plugin-transform-exponentiation-operator" "^7.10.4" - "@babel/plugin-transform-for-of" "^7.10.4" - "@babel/plugin-transform-function-name" "^7.10.4" - "@babel/plugin-transform-literals" "^7.10.4" - "@babel/plugin-transform-member-expression-literals" "^7.10.4" - "@babel/plugin-transform-modules-amd" "^7.10.4" - "@babel/plugin-transform-modules-commonjs" "^7.10.4" - "@babel/plugin-transform-modules-systemjs" "^7.10.4" - "@babel/plugin-transform-modules-umd" "^7.10.4" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" - "@babel/plugin-transform-new-target" "^7.10.4" - "@babel/plugin-transform-object-super" "^7.10.4" - "@babel/plugin-transform-parameters" "^7.10.4" - "@babel/plugin-transform-property-literals" "^7.10.4" - "@babel/plugin-transform-regenerator" "^7.10.4" - "@babel/plugin-transform-reserved-words" "^7.10.4" - "@babel/plugin-transform-shorthand-properties" "^7.10.4" - "@babel/plugin-transform-spread" "^7.11.0" - "@babel/plugin-transform-sticky-regex" "^7.10.4" - "@babel/plugin-transform-template-literals" "^7.10.4" - "@babel/plugin-transform-typeof-symbol" "^7.10.4" - "@babel/plugin-transform-unicode-escapes" "^7.10.4" - "@babel/plugin-transform-unicode-regex" "^7.10.4" + "@babel/plugin-syntax-top-level-await" "^7.12.1" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-async-to-generator" "^7.12.1" + "@babel/plugin-transform-block-scoped-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.1" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-computed-properties" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-dotall-regex" "^7.12.1" + "@babel/plugin-transform-duplicate-keys" "^7.12.1" + "@babel/plugin-transform-exponentiation-operator" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-function-name" "^7.12.1" + "@babel/plugin-transform-literals" "^7.12.1" + "@babel/plugin-transform-member-expression-literals" "^7.12.1" + "@babel/plugin-transform-modules-amd" "^7.12.1" + "@babel/plugin-transform-modules-commonjs" "^7.12.1" + "@babel/plugin-transform-modules-systemjs" "^7.12.1" + "@babel/plugin-transform-modules-umd" "^7.12.1" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.1" + "@babel/plugin-transform-new-target" "^7.12.1" + "@babel/plugin-transform-object-super" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-property-literals" "^7.12.1" + "@babel/plugin-transform-regenerator" "^7.12.1" + "@babel/plugin-transform-reserved-words" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/plugin-transform-sticky-regex" "^7.12.1" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/plugin-transform-typeof-symbol" "^7.12.1" + "@babel/plugin-transform-unicode-escapes" "^7.12.1" + "@babel/plugin-transform-unicode-regex" "^7.12.1" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.11.0" - browserslist "^4.12.0" + "@babel/types" "^7.12.1" core-js-compat "^3.6.2" - invariant "^2.2.2" - levenary "^1.1.1" semver "^5.5.0" "@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== + version "0.1.4" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -888,38 +882,38 @@ esutils "^2.0.2" "@babel/preset-react@^7.0.0": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.4.tgz#92e8a66d816f9911d11d4cc935be67adfc82dbcf" - integrity sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw== + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.5.tgz#d45625f65d53612078a43867c5c6750e78772c56" + integrity sha512-jcs++VPrgyFehkMezHtezS2BpnUlR7tQFAyesJn1vGTO9aTFZrgIQrA5YydlTwxbcjMwkFY6i04flCigRRr3GA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-react-display-name" "^7.10.4" - "@babel/plugin-transform-react-jsx" "^7.10.4" - "@babel/plugin-transform-react-jsx-development" "^7.10.4" - "@babel/plugin-transform-react-jsx-self" "^7.10.4" - "@babel/plugin-transform-react-jsx-source" "^7.10.4" - "@babel/plugin-transform-react-pure-annotations" "^7.10.4" + "@babel/plugin-transform-react-display-name" "^7.12.1" + "@babel/plugin-transform-react-jsx" "^7.12.5" + "@babel/plugin-transform-react-jsx-development" "^7.12.5" + "@babel/plugin-transform-react-jsx-self" "^7.12.1" + "@babel/plugin-transform-react-jsx-source" "^7.12.1" + "@babel/plugin-transform-react-pure-annotations" "^7.12.1" "@babel/preset-typescript@^7.3.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.10.4.tgz#7d5d052e52a682480d6e2cc5aa31be61c8c25e36" - integrity sha512-SdYnvGPv+bLlwkF2VkJnaX/ni1sMNetcGI1+nThF1gyv6Ph8Qucc4ZZAjM5yZcE/AKRXIOTZz7eSRDWOEjPyRQ== + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.12.1.tgz#86480b483bb97f75036e8864fe404cc782cc311b" + integrity sha512-hNK/DhmoJPsksdHuI/RVrcEws7GN5eamhi28JkO52MqIxU8Z0QpmiSOQxZHWOHV7I3P4UjHV97ay4TcamMA6Kw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-typescript" "^7.10.4" + "@babel/plugin-transform-typescript" "^7.12.1" "@babel/runtime-corejs3@^7.10.2": - version "7.11.2" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz#02c3029743150188edeb66541195f54600278419" - integrity sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A== + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.12.5.tgz#ffee91da0eb4c6dae080774e94ba606368e414f4" + integrity sha512-roGr54CsTmNPPzZoCP1AmDXuBoNao7tnSA83TXTwt+UK5QVyh1DIJnrgYRPWKCF2flqZQXwa7Yr8v7VmLzF0YQ== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4": - version "7.11.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" - integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== dependencies: regenerator-runtime "^0.13.4" @@ -932,25 +926,25 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0", "@babel/traverse@^7.4.3": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" - integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.4.3": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.5.tgz#78a0c68c8e8a35e4cacfd31db8bb303d5606f095" + integrity sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.0" + "@babel/generator" "^7.12.5" "@babel/helper-function-name" "^7.10.4" "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.11.0" - "@babel/types" "^7.11.0" + "@babel/parser" "^7.12.5" + "@babel/types" "^7.12.5" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" - integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4": + version "7.12.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96" + integrity sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA== dependencies: "@babel/helper-validator-identifier" "^7.10.4" lodash "^4.17.19" @@ -1023,27 +1017,10 @@ version "0.0.0" uid "" -"@hapi/address@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@hapi/address/-/address-4.1.0.tgz#d60c5c0d930e77456fdcde2598e77302e2955e1d" - integrity sha512-SkszZf13HVgGmChdHo/PxchnSaCJ6cetVqLzyciudzZRT0jcOouIF/Q93mgjw8cce+D+4F4C1Z/WrfFN+O3VHQ== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@hapi/formula@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@hapi/formula/-/formula-2.0.0.tgz#edade0619ed58c8e4f164f233cda70211e787128" - integrity sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A== - "@hapi/hoek@^9.0.0": - version "9.0.4" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.0.4.tgz#e80ad4e8e8d2adc6c77d985f698447e8628b6010" - integrity sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw== - -"@hapi/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@hapi/pinpoint/-/pinpoint-2.0.0.tgz#805b40d4dbec04fc116a73089494e00f073de8df" - integrity sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw== + version "9.1.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.0.tgz#6c9eafc78c1529248f8f4d92b0799a712b6052c6" + integrity sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw== "@hapi/topo@^5.0.0": version "5.0.0" @@ -1258,6 +1235,23 @@ resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz#5405ee8e444ed212db44e79351f0c70a582aae25" integrity sha512-DetpxZw1fzPD5xUBrIAoplLChO2VB8DlL5Gg+I1IR9b2wPqYIca2WSUxL5g1vLeR4MsQq1NeWriXAVffV+U1Fw== +"@sideway/address@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.0.tgz#0b301ada10ac4e0e3fa525c90615e0b61a72b78d" + integrity sha512-wAH/JYRXeIFQRsxerIuLjgUu2Xszam+O5xKeatJ4oudShOOirfmsQ1D6LL54XOU2tizpCYku+s1wmU0SYdpoSA== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" + integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@testing-library/dom@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-5.6.1.tgz#705a1cb4a039b877c1e69e916824038e837ab637" @@ -1333,15 +1327,10 @@ dependencies: "@turf/helpers" "6.x" -"@types/angular@^1.6.55": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.7.2.tgz#e996f4a5dc184dfe8c076c6ddbbe0d60caab639e" - integrity sha512-UBEgZTFg+tAvGZrJpTfTrRbBHXdcA3GErBs+QfIM1K8Gnzl7WghYc7gsbWRQ7rXvpnxmbffAFLPkKl32XEx8IQ== - "@types/babel__core@^7.1.0": - version "7.1.9" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d" - integrity sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw== + version "7.1.12" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.12.tgz#4d8e9e51eb265552a7e4f1ff2219ab6133bdfb2d" + integrity sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -1350,24 +1339,24 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04" - integrity sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew== + version "7.6.2" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.2.tgz#f3d71178e187858f7c45e30380f8f1b7415a12d8" + integrity sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" - integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== + version "7.0.3" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.3.tgz#b8aaeba0a45caca7b56a5de9459872dde3727214" + integrity sha512-uCoznIPDmnickEi6D0v11SBpW0OuVqHJCa7syXqQHy5uktSCreIlt0iglsCnmvz8yCb38hGcWeseA8cWJSwv5Q== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.0.13" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.13.tgz#1874914be974a492e1b4cb00585cabb274e8ba18" - integrity sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ== + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.15.tgz#db9e4238931eb69ef8aab0ad6523d4d4caa39d03" + integrity sha512-Pzh9O3sTK8V6I1olsXpCfj2k/ygO2q1X0vhhnDrEQyYLHZesWz+zMZMVcwXLCYf0U36EtmyYaFGPfXlTtDHe3A== dependencies: "@babel/types" "^7.3.0" @@ -1386,15 +1375,10 @@ resolved "https://registry.yarnpkg.com/@types/chance/-/chance-1.1.0.tgz#7d8e6bd0506344d94c042f692d59d20f8eb7d66d" integrity sha512-j/9aaLU6JaaN2iFiSZgvD+G0nju1Fi2/f2WM+WwS+8+cpTdzFhXFH3+SHZgfjgum6wNW80sfcawUx+Rx7tH26w== -"@types/color-name@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" - integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== - "@types/d3@^3": - version "3.5.43" - resolved "https://registry.yarnpkg.com/@types/d3/-/d3-3.5.43.tgz#e9b4992817e0b6c5efaa7d6e5bb2cee4d73eab58" - integrity sha512-t9ZmXOcpVxywRw86YtIC54g7M9puRh8hFedRvVfHKf5YyOP6pSxA0TvpXpfseXSCInoW4P7bggTrSDiUOs4g5w== + version "3.5.44" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-3.5.44.tgz#28635f8bb9adf1cef5bbef2b06778174a9d34383" + integrity sha512-hFEcf03YGJ2uQoDYEp3nFD5mXWxly5kf6KOstuOQFEs9sUCN7kNlKhcYkpZ3gK6PiHz4XRLkoHa80NVCJNeLBw== "@types/elasticsearch@^5.0.34": version "5.0.36" @@ -1410,9 +1394,9 @@ "@types/node" "*" "@types/hapi@^18.0.2": - version "18.0.3" - resolved "https://registry.yarnpkg.com/@types/hapi/-/hapi-18.0.3.tgz#e74c019f6a1b1c7f647fe014d3890adec9c0214a" - integrity sha512-UM03myDZ2UWbpqLSZqboK4L98F9r4GCcd9JOr2auhgC3iOd/69mvDggivOHhOYJKWHeCW/dECPHIB7DwQz00dw== + version "18.0.4" + resolved "https://registry.yarnpkg.com/@types/hapi/-/hapi-18.0.4.tgz#3a9d26f7f5a71cc2783f862f8b23aa637b0718f6" + integrity sha512-r2FkDKdAxuczL/9ltfcO5uW/AmdvIHAEUuhfYVdsl1xgJJQu3uXbdAX7GvjfHHct35xw+DpqsC41+q/PHtiVBA== dependencies: "@types/boom" "*" "@types/catbox" "*" @@ -1424,9 +1408,9 @@ "@types/shot" "*" "@types/history@*": - version "4.7.7" - resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.7.tgz#613957d900fab9ff84c8dfb24fa3eef0c2a40896" - integrity sha512-2xtoL22/3Mv6a70i4+4RB7VgbDDORoWwjcqeNysojZA0R7NK17RbY5Gof/2QiFfJgX+KkWghbwJ+d/2SB8Ndzg== + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== "@types/hoist-non-react-statics@^3.3.0": version "3.3.1" @@ -1476,9 +1460,9 @@ integrity sha512-1TQNDJvIKlgYXGNIABfgFp9y0FziDpuGrd799Q5RcnsDu+krD+eeW/0Fs5PHARvWWFelOhIG2OPCo6KbadBM4A== "@types/json-schema@^7.0.3": - version "7.0.5" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" - integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== "@types/json5@^0.0.29": version "0.0.29" @@ -1486,9 +1470,9 @@ integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= "@types/lodash@^4.14.136": - version "4.14.160" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.160.tgz#2f1bba6500bc3cb9a732c6d66a083378fb0b0b29" - integrity sha512-aP03BShJoO+WVndoVj/WNcB/YBPt+CIU1mvaao2GRAHy2yg4pT/XS4XnVHEQBjPJGycWf/9seKEO9vopTJGkvA== + version "4.14.165" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.165.tgz#74d55d947452e2de0742bad65270433b63a8c30f" + integrity sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg== "@types/mime-db@*": version "1.43.0" @@ -1508,19 +1492,19 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.6.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.0.tgz#7d4411bf5157339337d7cff864d9ff45f177b499" - integrity sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA== + version "14.14.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d" + integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg== "@types/node@^12.6.8": - version "12.12.54" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1" - integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w== + version "12.19.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.4.tgz#cdfbb62e26c7435ed9aab9c941393cc3598e9b46" + integrity sha512-o3oj1bETk8kBwzz1WlO6JWL/AfAA3Vm6J1B3C9CsdxHYp7XgPiH7OEXPUbZTndHlRaIElrANkQfe6ZmfJb3H2w== "@types/plotly.js@*": - version "1.50.18" - resolved "https://registry.yarnpkg.com/@types/plotly.js/-/plotly.js-1.50.18.tgz#12b37e3026af9b91a1f93a5e6b936fcaff54e347" - integrity sha512-DMIovwLr/PRRzCJNNdBVToci3G/y1AhuiBJI9HB92Rsql8MRCDdVdwFWgQbcsULaSN2kBJbaZLyWLgYjpt6MFA== + version "1.54.2" + resolved "https://registry.yarnpkg.com/@types/plotly.js/-/plotly.js-1.54.2.tgz#8e5916c83bd07b01fed7f404c3e460ee8197968a" + integrity sha512-p05hxJSlPLYEPsPW1NuQs1v+oM7pit3xMyo/L/iAr+xAH7bc035rTGFheCiYhx/d+kfCp1jrdJe52XPwei1m6g== dependencies: "@types/d3" "^3" @@ -1535,9 +1519,9 @@ integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== "@types/react-dom@^16.8.4": - version "16.9.8" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423" - integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA== + version "16.9.9" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.9.tgz#d2d0a6f720a0206369ccbefff752ba37b9583136" + integrity sha512-jE16FNWO3Logq/Lf+yvEAjKzhpST/Eac8EMd1i4dgZdMczfgqC8EjpxwNgEe3SExHYLliabXDh9DEhhqnlXJhg== dependencies: "@types/react" "*" @@ -1550,9 +1534,9 @@ "@types/react" "*" "@types/react-redux@^7.1.1": - version "7.1.9" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.9.tgz#280c13565c9f13ceb727ec21e767abe0e9b4aec3" - integrity sha512-mpC0jqxhP4mhmOl3P4ipRsgTgbNofMRXJb08Ms6gekViLj61v1hOZEKWDCyWsdONr6EjEA6ZHXC446wdywDe0w== + version "7.1.11" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.11.tgz#a18e8ab3651e8e8cc94798934927937c66021217" + integrity sha512-OjaFlmqy0CRbYKBoaWF84dub3impqnLJUrz4u8PRjDzaa4n1A2cVmjMV81shwXyAD5x767efhA8STFGJz/r1Zg== dependencies: "@types/hoist-non-react-statics" "^3.3.0" "@types/react" "*" @@ -1577,16 +1561,16 @@ "@types/react" "*" "@types/react-vis@^1.11.3": - version "1.11.3" - resolved "https://registry.yarnpkg.com/@types/react-vis/-/react-vis-1.11.3.tgz#b5e4a4b914290fc746724929cb499e2f4d85e937" - integrity sha512-2fbSqnKVaACu0T9o8TrluxuZvVOdyzaqJjDJm5DCrCfPr3eRAqK4LLIddW3NlLiHUW4O/6dI0TbeEOWyZ9QmgA== + version "1.11.5" + resolved "https://registry.yarnpkg.com/@types/react-vis/-/react-vis-1.11.5.tgz#60442aae4dff9022254f48fa1b985678c8e45e74" + integrity sha512-siCSR0RiKdwYmmEYLO2Jy3ejn3tWsUSFFAheyLI2Qevny9cFb/LC0zjsjfu7Nm0dXVrlY+QwRukPmVVZ3CkVOg== dependencies: "@types/react" "*" "@types/react@*", "@types/react@^16.8.23": - version "16.9.47" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.47.tgz#fb092936f0b56425f874d0ff1b08051fdf70c1ba" - integrity sha512-dAJO4VbrjYqTUwFiQqAKjLyHHl4RSTNnRyPdX3p16MPbDKvow51wxATUPxoe2QsiXNMEYrOjc2S6s92VjG+1VQ== + version "16.9.56" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.56.tgz#ea25847b53c5bec064933095fc366b1462e2adf0" + integrity sha512-gIkl4J44G/qxbuC6r2Xh+D3CGZpJ+NdWTItAPmZbR5mUS+JQ8Zvzpl0ea5qT/ZT3ZNTUcDKUVqV3xBE8wv/DyQ== dependencies: "@types/prop-types" "*" csstype "^3.0.2" @@ -1606,9 +1590,9 @@ "@types/node" "*" "@types/sinonjs__fake-timers@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.1.tgz#681df970358c82836b42f989188d133e218c458e" - integrity sha512-yYezQwGWty8ziyYLdZjwxyMb0CZR49h8JALHGrxjQHWlqGgc8kLdHEgWrgL0uZ29DMvEVBDnHU2Wg36zKSIUtA== + version "6.0.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz#3a84cf5ec3249439015e14049bd3161419bf9eae" + integrity sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg== "@types/sizzle@^2.3.2": version "2.3.2" @@ -1626,9 +1610,9 @@ integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== "@types/yargs@^13.0.0": - version "13.0.10" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.10.tgz#e77bf3fc73c781d48c2eb541f87c453e321e5f4b" - integrity sha512-MU10TSgzNABgdzKvQVW1nuuT+sgBMWeXNc3XOs5YXV5SDAK+PPja2eUuBNB9iqElu03xyEDqlnGw0jgl4nbqGQ== + version "13.0.11" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.11.tgz#def2f0c93e4bdf2c61d7e34899b17e34be28d3b1" + integrity sha512-NRqD6T4gktUrDi1o1wLH3EKC1o2caCr7/wR87ODcbVITQF106OM3sFN92ysZ++wqelOd1CTzatnOBRDYYG6wGQ== dependencies: "@types/yargs-parser" "*" @@ -1824,19 +1808,19 @@ abs-svg-path@^0.1.1, abs-svg-path@~0.1.1: integrity sha1-32Acjo0roQ1KdtYl4japo5wnI78= acorn-jsx@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" - integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== acorn@^6.0.7, acorn@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" - integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== acorn@^7.1.1: - version "7.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" - integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== add-line-numbers@^1.0.1: version "1.0.1" @@ -1871,9 +1855,9 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.9.1: - version "6.12.4" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" - integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -1955,12 +1939,11 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.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== +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: - "@types/color-name" "^1.1.1" color-convert "^2.0.1" ansi-wrap@^0.1.0: @@ -2002,9 +1985,9 @@ aproba@^1.0.3, aproba@^1.1.1: integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== arch@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.2.tgz#0c52bbe7344bb4fa260c443d2cbad9c00ff2f0bf" - integrity sha512-NTBIIbAfkJeIletyABbVtdPgeKfDafR+1mZV/AyyfC1UkVkp9iUjV+wwmqtUgphHYajbI86jejBJp5e+jkGTiQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== are-we-there-yet@~1.1.2: version "1.1.5" @@ -2212,6 +2195,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob-lite@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-1.0.0.tgz#b88dca6006922b962094f7556826bab31c4a296b" @@ -2233,14 +2221,14 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.10.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" - integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axe-core@^3.5.4: - version "3.5.5" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.5.tgz#84315073b53fa3c0c51676c588d59da09a192227" - integrity sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q== +axe-core@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.0.2.tgz#c7cf7378378a51fcd272d3c09668002a4990b1cb" + integrity sha512-arU1h31OGFu+LPrOLGZ7nB45v940NMDMEJeNmbutu57P+UFDVnkZg3e+J1I2HJRZ9hT7gO8J91dn/PMrAiKakA== axios@^0.19.2: version "0.19.2" @@ -2249,7 +2237,7 @@ axios@^0.19.2: dependencies: follow-redirects "1.5.10" -axobject-query@^2.1.2: +axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== @@ -2341,9 +2329,9 @@ barycentric@^1.0.1: robust-linear-solve "^1.0.0" base64-js@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== base@^0.11.1: version "0.11.2" @@ -2431,6 +2419,11 @@ bl@^2.2.1: readable-stream "^2.3.5" safe-buffer "^5.1.1" +blob-util@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" + integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== + block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" @@ -2570,15 +2563,16 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.12.0, browserslist@^4.8.5: - version "4.14.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.0.tgz#2908951abfe4ec98737b72f34c3bcedc8d43b000" - integrity sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ== +browserslist@^4.14.5, browserslist@^4.14.6: + version "4.14.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.7.tgz#c071c1b3622c1c2e790799a37bb09473a4351cb6" + integrity sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ== dependencies: - caniuse-lite "^1.0.30001111" - electron-to-chromium "^1.3.523" - escalade "^3.0.2" - node-releases "^1.1.60" + caniuse-lite "^1.0.30001157" + colorette "^1.2.1" + electron-to-chromium "^1.3.591" + escalade "^3.1.1" + node-releases "^1.1.66" bser@2.1.1: version "2.1.1" @@ -2662,6 +2656,14 @@ cachedir@^2.3.0: resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== +call-bind@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" + integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.0" + 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" @@ -2709,10 +2711,10 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@^1.0.30001111: - version "1.0.30001117" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001117.tgz#69a9fae5d480eaa9589f7641a83842ad396d17c4" - integrity sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q== +caniuse-lite@^1.0.30001157: + version "1.0.30001157" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz#2d11aaeb239b340bc1aa730eca18a37fdb07a9ab" + integrity sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA== canvas-fit@^1.5.0: version "1.5.0" @@ -2767,6 +2769,14 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chance@^1.1.0: version "1.1.7" resolved "https://registry.yarnpkg.com/chance/-/chance-1.1.7.tgz#e99dde5ac16681af787b5ba94c8277c090d6cfe8" @@ -2802,9 +2812,9 @@ chokidar@^2.1.8: fsevents "^1.2.7" chokidar@^3.4.1: - version "3.4.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" - integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== + version "3.4.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" + integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -2812,7 +2822,7 @@ chokidar@^3.4.1: is-binary-path "~2.1.0" is-glob "~4.0.1" normalize-path "~3.0.0" - readdirp "~3.4.0" + readdirp "~3.5.0" optionalDependencies: fsevents "~2.1.2" @@ -2903,13 +2913,13 @@ cli-cursor@^2.0.0, cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" -cli-table3@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" - integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== +cli-table3@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.0.tgz#b7b1bc65ca8e7b5cef9124e13dc2b21e2ce4faee" + integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ== dependencies: object-assign "^4.1.0" - string-width "^2.1.1" + string-width "^4.2.0" optionalDependencies: colors "^1.1.2" @@ -2981,13 +2991,20 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-alpha@^1.0.4: +color-alpha@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/color-alpha/-/color-alpha-1.0.4.tgz#c141dc926e95fc3db647d0e14e5bc3651c29e040" integrity sha512-lr8/t5NPozTSqli+duAN+x+no/2WaKTeWvxhHGN+aXT6AJ8vPlzLa7UriyjWak0pSC2jHol9JgjBYnnHsGha9A== dependencies: color-parse "^1.3.8" +color-alpha@^1.0.4: + version "1.1.2" + resolved "https://registry.yarnpkg.com/color-alpha/-/color-alpha-1.1.2.tgz#7148ba1f71915fe872f44eb2e67df581f556aef7" + integrity sha512-FOu95n/SjuQyG9lFqzl18S2cfQ4od1QVrvz3PEJxWnRKjAPWBj7FILNnGSUfIXNgmMx58vaXp24URXeqF5obZQ== + dependencies: + color-parse "^1.4.1" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -3019,7 +3036,7 @@ color-name@^1.0.0, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-normalize@1.5.0, color-normalize@^1.5.0: +color-normalize@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/color-normalize/-/color-normalize-1.5.0.tgz#ee610af9acb15daf73e77a945a847b18e40772da" integrity sha512-rUT/HDXMr6RFffrR53oX3HGWkDOP9goSAQGBkUaAYKjOE2JxozccdGyufageWDlInRAjm/jYPrf/Y38oa+7obw== @@ -3028,7 +3045,15 @@ color-normalize@1.5.0, color-normalize@^1.5.0: color-rgba "^2.1.1" dtype "^2.0.0" -color-parse@^1.3.8: +color-normalize@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/color-normalize/-/color-normalize-1.5.2.tgz#d6c8beb02966849548f91a6ac0274c6f19924509" + integrity sha512-yYMIoyFJmUoKbCK6sBShljBWfkt8DXVfaZJn9/zvRJkF9eQJDbZhcYC6LdOVy40p4tfVwYYb9cXl8oqpu7pzBw== + dependencies: + color-rgba "^2.2.0" + dtype "^2.0.0" + +color-parse@1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/color-parse/-/color-parse-1.3.8.tgz#eaf54cd385cb34c0681f18c218aca38478082fa3" integrity sha512-1Y79qFv0n1xair3lNMTNeoFvmc3nirMVBij24zbs1f13+7fPpQClMg5b4AuKXLt3szj7BRlHMCXHplkce6XlmA== @@ -3037,7 +3062,14 @@ color-parse@^1.3.8: defined "^1.0.0" is-plain-obj "^1.1.0" -color-rgba@^2.1.1: +color-parse@^1.3.8, color-parse@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/color-parse/-/color-parse-1.4.2.tgz#78651f5d34df1a57f997643d86f7f87268ad4eb5" + integrity sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA== + dependencies: + color-name "^1.0.0" + +color-rgba@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/color-rgba/-/color-rgba-2.1.1.tgz#4633b83817c7406c90b3d7bf4d1acfa48dde5c83" integrity sha512-VaX97wsqrMwLSOR6H7rU1Doa2zyVdmShabKrPEIFywLlHoibgD3QW9Dw6fSqM4+H/LfjprDNAUUW31qEQcGzNw== @@ -3046,6 +3078,14 @@ color-rgba@^2.1.1: color-parse "^1.3.8" color-space "^1.14.6" +color-rgba@^2.1.1, color-rgba@^2.2.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/color-rgba/-/color-rgba-2.2.3.tgz#f7f1240de7edc5fcafa79c4acb013a8eb2075aa0" + integrity sha512-C20bgnIy09NoXDzhu3RB/SHVlk0y+2zcnkumpVvGOWCrz3rF2xJLS53Fc2ai2Jebs3X7ILZFswN7vVLD2HLr2g== + dependencies: + color-parse "^1.4.1" + color-space "^1.14.6" + color-space@^1.14.6: version "1.16.0" resolved "https://registry.yarnpkg.com/color-space/-/color-space-1.16.0.tgz#611781bca41cd8582a1466fd9e28a7d3d89772a2" @@ -3054,6 +3094,11 @@ color-space@^1.14.6: hsluv "^0.0.3" mumath "^3.3.4" +colorette@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + colormap@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/colormap/-/colormap-2.3.1.tgz#9f2ab643591c0728d32332d5480b2487a4e0f249" @@ -3078,10 +3123,10 @@ commander@2, commander@^2.11.0, commander@^2.15.1, commander@^2.20.0, commander@ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +commander@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== common-tags@^1.8.0: version "1.8.0" @@ -3222,17 +3267,17 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js-compat@^3.6.2: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" - integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== + version "3.7.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.7.0.tgz#8479c5d3d672d83f1f5ab94cf353e57113e065ed" + integrity sha512-V8yBI3+ZLDVomoWICO6kq/CD28Y4r1M7CWeO4AGpMdMfseu8bkSubBmUPySMGKRTS+su4XQ07zUkAsiu9FCWTg== dependencies: - browserslist "^4.8.5" + browserslist "^4.14.6" semver "7.0.0" core-js-pure@^3.0.0: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" - integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== + version "3.7.0" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.7.0.tgz#28a57c861d5698e053f0ff36905f7a3301b4191e" + integrity sha512-EZD2ckZysv8MMt4J6HSvS9K2GdtlZtdBncKAmF9lr2n0c9dJUaUN88PSTjvgwCgQPWKTkERXITgS6JJRAnljtg== core-js@^1.0.0: version "1.2.7" @@ -3414,9 +3459,9 @@ csscolorparser@~1.0.3: integrity sha1-s085HupNqPPpgjHizNjfnAQfFxs= csstype@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.3.tgz#2b410bbeba38ba9633353aff34b05d9755d065f8" - integrity sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag== + version "3.0.4" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.4.tgz#b156d7be03b84ff425c9a0a4b1e5f4da9c5ca888" + integrity sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA== cubic-hermite@^1.0.0: version "1.0.0" @@ -3442,10 +3487,10 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= -cypress@^4.11.0: - version "4.12.1" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-4.12.1.tgz#0ead1b9f4c0917d69d8b57f996b6e01fe693b6ec" - integrity sha512-9SGIPEmqU8vuRA6xst2CMTYd9sCFCxKSzrHt0wr+w2iAQMCIIsXsQ5Gplns1sT6LDbZcmLv6uehabAOl3fhc9Q== +cypress@^5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-5.6.0.tgz#6781755c3ddfd644ce3179fcd7389176c0c82280" + integrity sha512-cs5vG3E2JLldAc16+5yQxaVRLLqMVya5RlrfPWkC72S5xrlHFdw7ovxPb61s4wYweROKTyH01WQc2PFzwwVvyQ== dependencies: "@cypress/listr-verbose-renderer" "^0.4.1" "@cypress/request" "^2.88.5" @@ -3453,34 +3498,35 @@ cypress@^4.11.0: "@types/sinonjs__fake-timers" "^6.0.1" "@types/sizzle" "^2.3.2" arch "^2.1.2" + blob-util "2.0.2" bluebird "^3.7.2" cachedir "^2.3.0" - chalk "^2.4.2" + chalk "^4.1.0" check-more-types "^2.24.0" - cli-table3 "~0.5.1" - commander "^4.1.1" + cli-table3 "~0.6.0" + commander "^5.1.0" common-tags "^1.8.0" debug "^4.1.1" eventemitter2 "^6.4.2" - execa "^1.0.0" + execa "^4.0.2" executable "^4.1.1" extract-zip "^1.7.0" - fs-extra "^8.1.0" + fs-extra "^9.0.1" getos "^3.2.1" is-ci "^2.0.0" is-installed-globally "^0.3.2" lazy-ass "^1.6.0" listr "^0.14.3" lodash "^4.17.19" - log-symbols "^3.0.0" + log-symbols "^4.0.0" minimist "^1.2.5" moment "^2.27.0" ospath "^1.2.2" - pretty-bytes "^5.3.0" + pretty-bytes "^5.4.1" ramda "~0.26.1" request-progress "^3.0.0" - supports-color "^7.1.0" - tmp "~0.1.0" + supports-color "^7.2.0" + tmp "~0.2.1" untildify "^4.0.0" url "^0.11.0" yauzl "^2.10.0" @@ -3642,12 +3688,12 @@ 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== -debug@4.1.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== +debug@4.2.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== dependencies: - ms "^2.1.1" + ms "2.1.2" debug@=3.1.0: version "3.1.0" @@ -3707,7 +3753,7 @@ deepmerge@^2.1.1: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== -define-properties@^1.1.2, define-properties@^1.1.3: +define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== @@ -3912,10 +3958,10 @@ edges-to-adjacency-list@^1.0.0: dependencies: uniq "^1.0.0" -electron-to-chromium@^1.3.523: - version "1.3.546" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.546.tgz#058c8f2f1a64f71127e7993b60ff4be85aa9bab4" - integrity sha512-AArbawRpcPhhfnm2nhmEonHcaEmmgulPI4c+bhaTbWHGzJRhgSoar1+1NQWC554fMjgxnoYC2Mrshjb3D3zSaQ== +electron-to-chromium@^1.3.591: + version "1.3.593" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.593.tgz#947ccf6dc8e013e2b053d2463ecd1043c164fcef" + integrity sha512-GvO7G1ZxvffnMvPCr4A7+iQPVuvpyqMrx2VWSERAjG+pHK6tmO9XqYdBfMIq9corRyi4bNImSDEiDvIoDb8HrA== elegant-spinner@^1.0.1: version "1.0.1" @@ -3958,9 +4004,9 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emoji-regex@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.0.0.tgz#48a2309cc8a1d2e9d23bc6a67c39b63032e76ea4" - integrity sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w== + version "9.2.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.0.tgz#a26da8e832b16a9753309f25e35e3c0efb9a066a" + integrity sha512-DNc3KFPK18bPdElMJnf/Pkv5TXhxFU3YFDEuGLDRtPmV4rkmCjBkCSEp22u6rBHdSN9Vlp/GK7k98prmE1Jgug== emojis-list@^3.0.0: version "3.0.0" @@ -4014,37 +4060,37 @@ error-ex@^1.2.0, error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5: - version "1.17.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" - integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== + version "1.17.7" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" + integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.2.0" - is-regex "^1.1.0" - object-inspect "^1.7.0" + is-callable "^1.2.2" + is-regex "^1.1.1" + object-inspect "^1.8.0" object-keys "^1.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" -es-abstract@^1.18.0-next.0: - version "1.18.0-next.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.0.tgz#b302834927e624d8e5837ed48224291f2c66e6fc" - integrity sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ== +es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.2.0" + is-callable "^1.2.2" is-negative-zero "^2.0.0" is-regex "^1.1.1" object-inspect "^1.8.0" object-keys "^1.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" @@ -4098,10 +4144,10 @@ es6-weak-map@^2.0.3: es6-iterator "^2.0.3" es6-symbol "^3.1.1" -escalade@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" - integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" @@ -4128,7 +4174,7 @@ eslint-import-resolver-node@0.3.2: debug "^2.6.9" resolve "^1.5.0" -eslint-import-resolver-node@^0.3.3: +eslint-import-resolver-node@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== @@ -4168,23 +4214,23 @@ eslint-plugin-babel@^5.2.0: eslint-rule-composer "^0.3.0" eslint-plugin-cypress@^2.11.1: - version "2.11.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.1.tgz#a945e2774b88211e2c706a059d431e262b5c2862" - integrity sha512-MxMYoReSO5+IZMGgpBZHHSx64zYPSPTpXDwsgW7ChlJTF/sA+obqRbHplxD6sBStE+g4Mi0LCLkG4t9liu//mQ== + version "2.11.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.2.tgz#a8f3fe7ec840f55e4cea37671f93293e6c3e76a0" + integrity sha512-1SergF1sGbVhsf7MYfOLiBhdOg6wqyeV9pXUAIDIffYTGMN3dTBQS9nFAzhLsHhO+Bn0GaVM1Ecm71XUidQ7VA== dependencies: globals "^11.12.0" eslint-plugin-import@^2.14.0: - version "2.22.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz#92f7736fe1fde3e2de77623c838dd992ff5ffb7e" - integrity sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg== + version "2.22.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" + integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== dependencies: array-includes "^3.1.1" array.prototype.flat "^1.2.3" contains-path "^0.1.0" debug "^2.6.9" doctrine "1.5.0" - eslint-import-resolver-node "^0.3.3" + eslint-import-resolver-node "^0.3.4" eslint-module-utils "^2.6.0" has "^1.0.3" minimatch "^3.0.4" @@ -4201,20 +4247,20 @@ eslint-plugin-jest@^22.13.6: "@typescript-eslint/experimental-utils" "^1.13.0" eslint-plugin-jsx-a11y@^6.1.2: - version "6.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz#99ef7e97f567cc6a5b8dd5ab95a94a67058a2660" - integrity sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g== + version "6.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd" + integrity sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg== dependencies: - "@babel/runtime" "^7.10.2" + "@babel/runtime" "^7.11.2" aria-query "^4.2.2" array-includes "^3.1.1" ast-types-flow "^0.0.7" - axe-core "^3.5.4" - axobject-query "^2.1.2" + axe-core "^4.0.2" + axobject-query "^2.2.0" damerau-levenshtein "^1.0.6" emoji-regex "^9.0.0" has "^1.0.3" - jsx-ast-utils "^2.4.1" + jsx-ast-utils "^3.1.0" language-tags "^1.0.5" eslint-plugin-mocha@^5.2.0: @@ -4225,9 +4271,9 @@ eslint-plugin-mocha@^5.2.0: ramda "^0.26.1" eslint-plugin-no-unsanitized@^3.0.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.1.2.tgz#a54724e0b81d43279bb1f8f5e1d82c97da78c858" - integrity sha512-KPShfliA3Uy9qqwQx35P1fwIOeJjZkb0FbMMUFztRYRposzaynsM8JCEb952fqkidROl1kpqY80uSvn+TcWkQQ== + version "3.1.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.1.4.tgz#21d9f3cb5cbed91ac45cb30eec9195c387b918c7" + integrity sha512-WF1+eZo2Sh+bQNjZuVNwT0dA61zuJORsLh+1Sww7+O6GOPw+WPWIIRfTWNqrmaXaDMhM4SXAqYPcNlhRMiH13g== eslint-plugin-prefer-object-spread@^1.2.1: version "1.2.1" @@ -4235,20 +4281,20 @@ eslint-plugin-prefer-object-spread@^1.2.1: integrity sha1-J/uRhTaQzOs65hAdnIrsxqZ6QCw= eslint-plugin-react@^7.11.1: - version "7.20.6" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz#4d7845311a93c463493ccfa0a19c9c5d0fd69f60" - integrity sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg== + version "7.21.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz#50b21a412b9574bfe05b21db176e8b7b3b15bff3" + integrity sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g== dependencies: array-includes "^3.1.1" array.prototype.flatmap "^1.2.3" doctrine "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.4.1" + jsx-ast-utils "^2.4.1 || ^3.0.0" object.entries "^1.1.2" object.fromentries "^2.0.2" object.values "^1.1.1" prop-types "^15.7.2" - resolve "^1.17.0" + resolve "^1.18.1" string.prototype.matchall "^4.0.2" eslint-rule-composer@^0.3.0: @@ -4348,18 +4394,18 @@ esquery@^1.0.1: estraverse "^5.1.0" esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: - estraverse "^4.1.0" + estraverse "^5.2.0" -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.1.0: +estraverse@^5.1.0, estraverse@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== @@ -4455,9 +4501,9 @@ execa@^2.0.3: strip-final-newline "^2.0.0" execa@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2" - integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A== + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== dependencies: cross-spawn "^7.0.0" get-stream "^5.0.0" @@ -4635,9 +4681,9 @@ fast-levenshtein@~2.0.6: integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fastq@^1.6.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" - integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + version "1.9.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.9.0.tgz#e16a72f338eaca48e91b5c23593bcc2ef66b7947" + integrity sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w== dependencies: reusify "^1.0.4" @@ -4890,14 +4936,15 @@ from@~0: resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== +fs-extra@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" + integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== dependencies: + at-least-node "^1.0.0" graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" + jsonfile "^6.0.1" + universalify "^1.0.0" fs-mkdirp-stream@^1.0.0: version "1.0.0" @@ -4982,9 +5029,9 @@ gaze@^1.0.0: globule "^1.0.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== + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== geojson-vt@^3.2.1: version "3.2.1" @@ -5001,6 +5048,15 @@ get-canvas-context@^1.0.1: resolved "https://registry.yarnpkg.com/get-canvas-context/-/get-canvas-context-1.0.2.tgz#d6e7b50bc4e4c86357cd39f22647a84b73601e93" integrity sha1-1ue1C8TkyGNXzTnyJkeoS3NgHpM= +get-intrinsic@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" + integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -5214,9 +5270,9 @@ gl-plot2d@^1.4.5: text-cache "^4.2.2" gl-plot3d@^2.4.6: - version "2.4.6" - resolved "https://registry.yarnpkg.com/gl-plot3d/-/gl-plot3d-2.4.6.tgz#69518759c473e3a8c1c76974472836f6500daf50" - integrity sha512-CkrNvDKu0p74Di2g2Oc9kU+s1Oe+wi4cIfHzXABp8DvfoRl0/bayqJ9q8EcRAqMeQQxQZYGvJkk4hlBwI758Jw== + version "2.4.7" + resolved "https://registry.yarnpkg.com/gl-plot3d/-/gl-plot3d-2.4.7.tgz#b66e18c5affdd664f42c884acf7b82c60b41ee78" + integrity sha512-mLDVWrl4Dj0O0druWyHUK5l7cBQrRIJRn2oROEgrRuOgbbrLAzsREKefwMO0bA0YqkiZMFMnV5VvPA9j57X5Xg== dependencies: "3d-view" "^2.0.0" a-big-triangle "^1.0.3" @@ -5331,10 +5387,10 @@ gl-streamtube3d@^1.4.1: glsl-specular-cook-torrance "^2.0.1" glslify "^7.0.0" -gl-surface3d@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/gl-surface3d/-/gl-surface3d-1.5.2.tgz#a283b98d3473fca4e8552f0f6ac40a6f0dc88b00" - integrity sha512-rWSQwEQDkB0T5CDEDFJwJc4VgwwJaAyFRSJ92NJlrTSwDlsEsWdzG9+APx6FWJMwkOpIoZGWqv+csswK2kMMLQ== +gl-surface3d@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/gl-surface3d/-/gl-surface3d-1.6.0.tgz#5fc915759a91e9962dcfbf3982296c462a032526" + integrity sha512-x15+u4712ysnB85G55RLJEml6mOB4VaDn0VTlXCc9JcjRl5Es10Tk7lhGGyiPtkCfHwvhnkxzYA1/rHHYN7Y0A== dependencies: binary-search-bounds "^2.0.4" bit-twiddle "^1.0.2" @@ -5770,7 +5826,7 @@ has-passive-events@^1.0.0: dependencies: is-browser "^2.0.1" -has-symbols@^1.0.0, has-symbols@^1.0.1: +has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== @@ -5861,7 +5917,7 @@ hoek@4.2.1: resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA== -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -5912,9 +5968,9 @@ iconv-lite@^0.6.2: safer-buffer ">= 2.1.2 < 3.0.0" ieee754@^1.1.12, ieee754@^1.1.4: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== iferr@^0.1.5: version "0.1.5" @@ -5959,9 +6015,9 @@ import-fresh@^2.0.0: resolve-from "^3.0.0" import-fresh@^3.0.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" - integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + version "3.2.2" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e" + integrity sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -6094,7 +6150,7 @@ interval-tree-1d@^1.0.1: dependencies: binary-search-bounds "^1.0.0" -invariant@^2.2.2, invariant@^2.2.4: +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== @@ -6178,19 +6234,14 @@ is-buffer@^1.0.2, is-buffer@^1.1.5: integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-buffer@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== - -is-callable@^1.1.3: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.1.tgz#4d1e21a4f437509d25ce55f8184350771421c96d" - integrity sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg== + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-callable@^1.1.4, is-callable@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" - integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== is-ci@^2.0.0: version "2.0.0" @@ -6199,6 +6250,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-core-module@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946" + integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -6383,7 +6441,7 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-regex@^1.0.4, is-regex@^1.1.0, is-regex@^1.1.1: +is-regex@^1.0.4, is-regex@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== @@ -6638,15 +6696,15 @@ jest-worker@^24.9.0: supports-color "^6.1.0" joi@^17.1.1: - version "17.2.1" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.2.1.tgz#e5140fdf07e8fecf9bc977c2832d1bdb1e3f2a0a" - integrity sha512-YT3/4Ln+5YRpacdmfEfrrKh50/kkgX3LgBltjqnlMPIYiZ4hxXZuVJcxmsvxsdeHg9soZfE3qXxHC2tMpCCBOA== + version "17.3.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.3.0.tgz#f1be4a6ce29bc1716665819ac361dfa139fff5d2" + integrity sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg== dependencies: - "@hapi/address" "^4.1.0" - "@hapi/formula" "^2.0.0" "@hapi/hoek" "^9.0.0" - "@hapi/pinpoint" "^2.0.0" "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.0" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" js-base64@^2.1.8: version "2.6.4" @@ -6720,10 +6778,12 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" @@ -6737,13 +6797,13 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jsx-ast-utils@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" - integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w== +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.1.0.tgz#642f1d7b88aa6d7eb9d8f2210e166478444fa891" + integrity sha512-d4/UOjg+mxAWxCiF0c5UTSwyqbchkbqCvK87aBovhnh8GtysTjWmgC63tY0cJx/HzGgm9qnA147jVBdpOiQ2RA== dependencies: array-includes "^3.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" kdbush@^3.0.0: version "3.0.0" @@ -6775,9 +6835,9 @@ kind-of@^6.0.0, kind-of@^6.0.2: integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== language-subtag-registry@~0.3.2: - version "0.3.20" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.20.tgz#a00a37121894f224f763268e431c55556b0c0755" - integrity sha512-KPMwROklF4tEx283Xw0pNKtfTj1gZ4UByp4EsIFWLgBavJltF4TiYPc39k06zSTsLzxTVXXDSpbwaQXaFB4Qeg== + version "0.3.21" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" + integrity sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg== language-tags@^1.0.5: version "1.0.5" @@ -6810,18 +6870,6 @@ lerp@^1.0.3: resolved "https://registry.yarnpkg.com/lerp/-/lerp-1.0.3.tgz#a18c8968f917896de15ccfcc28d55a6b731e776e" integrity sha1-oYyJaPkXiW3hXM/MKNVaa3Med24= -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" - levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -7001,6 +7049,13 @@ log-symbols@^3.0.0: dependencies: chalk "^2.4.2" +log-symbols@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== + dependencies: + chalk "^4.0.0" + log-update@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" @@ -7287,11 +7342,11 @@ min-indent@^1.0.0: integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== mini-create-react-context@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz#df60501c83151db69e28eac0ef08b4002efab040" - integrity sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA== + version "0.4.1" + resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" + integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== dependencies: - "@babel/runtime" "^7.5.5" + "@babel/runtime" "^7.12.1" tiny-warning "^1.0.3" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: @@ -7355,9 +7410,9 @@ moment-timezone@^0.5.26: moment ">= 2.9.0" "moment@>= 2.9.0", moment@^2.24.0, moment@^2.27.0: - version "2.27.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.27.0.tgz#8bff4e3e26a236220dfe3e36de756b6ebaa0105d" - integrity sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ== + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== monotone-convex-hull-2d@^1.0.1: version "1.0.1" @@ -7409,7 +7464,7 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.1.1: +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -7437,9 +7492,9 @@ mute-stream@0.0.7: integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= nan@^2.12.1, nan@^2.13.2: - version "2.14.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" - integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + version "2.14.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" + integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== nanomatch@^1.2.9: version "1.2.13" @@ -7609,10 +7664,10 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-releases@^1.1.60: - version "1.1.60" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" - integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== +node-releases@^1.1.66: + version "1.1.66" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.66.tgz#609bd0dc069381015cd982300bae51ab4f1b1814" + integrity sha512-JHEQ1iWPGK+38VLB2H9ef2otU4l8s3yAMt9Xf934r6+ojCYDMHPMqvCc9TnzfeFSP1QEOeU6YZEd3+De0LTCgg== node-sass@^4.13.1: version "4.14.1" @@ -7667,9 +7722,9 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== normalize-svg-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/normalize-svg-path/-/normalize-svg-path-1.0.1.tgz#6f729ad6b70bb4ca4eff2fe4b107489efe1d56fe" - integrity sha1-b3Ka1rcLtMpO/y/ksQdInv4dVv4= + version "1.1.0" + resolved "https://registry.yarnpkg.com/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz#0e614eca23c39f0cffe821d6be6cd17e569a766c" + integrity sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg== dependencies: svg-arc-to-cubic-bezier "^3.0.0" @@ -7757,7 +7812,7 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.7.0, object-inspect@^1.8.0: +object-inspect@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== @@ -7768,14 +7823,14 @@ object-inspect@~1.7.0: integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== object-is@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" - integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== + version "1.1.3" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.3.tgz#2e3b9e65560137455ee3bd62aec4d90a2ea1cc81" + integrity sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.0.9, object-keys@^1.1.1: +object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.0.9, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -7787,15 +7842,15 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.0.4, object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== +object.assign@^4.0.4, object.assign@^4.1.0, object.assign@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" object.entries@^1.1.2: version "1.1.2" @@ -8312,9 +8367,9 @@ please-upgrade-node@^3.1.1: semver-compare "^1.0.0" plotly.js@^1.55.2: - version "1.55.2" - resolved "https://registry.yarnpkg.com/plotly.js/-/plotly.js-1.55.2.tgz#65875d3b2b2a53fa9acfa74a3f7764595df46276" - integrity sha512-bphh7nlQOa1j2t7X+4vdGBSz/QME4Puk+Cuj7n/mYThPVxJkPtBFsTForCrgg4tLJWucY5TV+6F3zHNr4hyWZw== + version "1.57.1" + resolved "https://registry.yarnpkg.com/plotly.js/-/plotly.js-1.57.1.tgz#95754814ad57bf9b4ddbc9acc58337582e3bdf6a" + integrity sha512-23GlzClmOGT1lE86Ys0DLuxBM/fgRNzJqH9y7ZylO4VPwstPAlQd12DklXsuqOgCNSxnnWUaP+J7BaUOFplsUg== dependencies: "@plotly/d3-sankey" "0.7.2" "@plotly/d3-sankey-circular" "0.33.1" @@ -8324,8 +8379,10 @@ plotly.js@^1.55.2: "@turf/centroid" "^6.0.2" alpha-shape "^1.0.0" canvas-fit "^1.5.0" - color-normalize "^1.5.0" - color-rgba "^2.1.1" + color-alpha "1.0.4" + color-normalize "1.5.0" + color-parse "1.3.8" + color-rgba "2.1.1" convex-hull "^1.0.3" country-regex "^1.1.0" d3 "^3.5.17" @@ -8350,7 +8407,7 @@ plotly.js@^1.55.2: gl-select-box "^1.0.4" gl-spikes2d "^1.0.2" gl-streamtube3d "^1.4.1" - gl-surface3d "^1.5.2" + gl-surface3d "^1.6.0" gl-text "^1.1.8" glslify "^7.1.1" has-hover "^1.0.1" @@ -8369,7 +8426,7 @@ plotly.js@^1.55.2: regl "^1.6.1" regl-error2d "^2.0.11" regl-line2d "^3.0.18" - regl-scatter2d "3.2.0" + regl-scatter2d "^3.2.1" regl-splom "^1.0.12" right-now "^1.0.0" robust-orientation "^1.1.3" @@ -8377,7 +8434,7 @@ plotly.js@^1.55.2: strongly-connected-components "^1.0.1" superscript-text "^1.0.0" svg-path-sdf "^1.1.3" - tinycolor2 "^1.4.1" + tinycolor2 "^1.4.2" to-px "1.0.1" topojson-client "^3.1.0" webgl-context "^2.2.0" @@ -8430,10 +8487,10 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -pretty-bytes@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" - integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== +pretty-bytes@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.4.1.tgz#cd89f79bbcef21e3d21eb0da68ffe93f803e884b" + integrity sha512-s1Iam6Gwz3JI5Hweaz4GoCD1WUNUIyzePFy5+Js2hjwGVt2Z79wNN+ZKOZ2vB6C+Xs6njyB84Z1IthQg8d9LxA== pretty-format@^24.0.0, pretty-format@^24.8.0, pretty-format@^24.9.0: version "24.9.0" @@ -8589,15 +8646,6 @@ quat-slerp@^1.0.0: dependencies: gl-quat "^1.0.0" -query-string@^6.8.2: - version "6.13.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.1.tgz#d913ccfce3b4b3a713989fe6d39466d92e71ccad" - integrity sha512-RfoButmcK+yCta1+FuU8REvisx1oEzhMKwhLUNcepQTPGcNMp1sIqjnfCtfnvGSQZQEhaBHvccujtWoUV3TTbA== - dependencies: - decode-uri-component "^0.2.0" - split-on-first "^1.0.0" - strict-uri-encode "^2.0.0" - querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -8652,7 +8700,7 @@ react-fast-compare@^2.0.1: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== -react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0: +react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -8667,22 +8715,22 @@ react-motion@^0.5.2: raf "^3.1.0" react-plotly.js@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/react-plotly.js/-/react-plotly.js-2.4.0.tgz#7a8fd89ffa126daa36a5855890282960e2e4eaf0" - integrity sha512-BCkxMe8yWqu3nP/hw9A1KCIuoL67WV5/k68SL9yhEkF6UG+pAuIev9Q3cMKtNkQJZhsYFpOmlqrpPjIdUFACOQ== + version "2.5.0" + resolved "https://registry.yarnpkg.com/react-plotly.js/-/react-plotly.js-2.5.0.tgz#779e489bbbd05deb373a63e918454587236d7c7f" + integrity sha512-nzir3uf+tFO1YXVUH5lFfD2plbDuZJXKrCO88KmRVnha2/zEhZBmZO8yS6GcRnLmSrhJkfmj6GTqWWvrJDBCBQ== dependencies: prop-types "^15.7.2" react-redux@^7.1.0: - version "7.2.1" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.1.tgz#8dedf784901014db2feca1ab633864dee68ad985" - integrity sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg== + version "7.2.2" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.2.tgz#03862e803a30b6b9ef8582dadcc810947f74b736" + integrity sha512-8+CQ1EvIVFkYL/vu6Olo7JFLWop1qRUeb46sGtIMDCSpgwPQq8fPLpirIB0iTqFe9XYEFPHssdX8/UwN6pAkEA== dependencies: - "@babel/runtime" "^7.5.5" - hoist-non-react-statics "^3.3.0" + "@babel/runtime" "^7.12.1" + hoist-non-react-statics "^3.3.2" loose-envify "^1.4.0" prop-types "^15.7.2" - react-is "^16.9.0" + react-is "^16.13.1" react-router-dom@^5.0.1: version "5.2.0" @@ -8829,10 +8877,10 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -readdirp@~3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" - integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== dependencies: picomatch "^2.2.1" @@ -8891,9 +8939,9 @@ regenerate-unicode-properties@^8.2.0: regenerate "^1.4.0" regenerate@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f" - integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A== + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.10.5: version "0.10.5" @@ -8943,10 +8991,10 @@ regexpp@^2.0.1: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== -regexpu-core@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" - integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== +regexpu-core@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== dependencies: regenerate "^1.4.0" regenerate-unicode-properties "^8.2.0" @@ -8997,17 +9045,17 @@ regl-line2d@^3.0.18: pick-by-alias "^1.2.0" to-float32 "^1.0.1" -regl-scatter2d@3.2.0, regl-scatter2d@^3.1.9: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regl-scatter2d/-/regl-scatter2d-3.2.0.tgz#c4733d94bc6352e74c5e5e660a498343d1b7e4cc" - integrity sha512-c0MxiakVW50UBslsHRmnq41w53bhat5oGvugZEpIZGTdKHVeopRAR2FQHeJf8YrEhOsVn7TpOk9tjySoyHXWGA== +regl-scatter2d@^3.1.9, regl-scatter2d@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/regl-scatter2d/-/regl-scatter2d-3.2.1.tgz#2818ba506559e4cd29fb60eacc2d2999be32da8d" + integrity sha512-qxUCK5kXuoVZin2gPLXkgkBfRr3XLobVgEfn5N0fiprsb/ncTCtSNVBqP0EJgNb115R+FXte9LKA9YrFx7uBnA== dependencies: "@plotly/point-cluster" "^3.1.9" array-range "^1.0.1" array-rearrange "^2.2.2" clamp "^1.0.1" color-id "^1.1.0" - color-normalize "1.5.0" + color-normalize "^1.5.0" color-rgba "^2.1.1" flatten-vertex-data "^1.0.2" glslify "^7.0.0" @@ -9034,9 +9082,9 @@ regl-splom@^1.0.12: regl-scatter2d "^3.1.9" regl@^1.3.11, regl@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/regl/-/regl-1.6.1.tgz#6930172cda9b8fb65724abc0d4930d79333f5460" - integrity sha512-7Z9rmpEqmLNwC9kCYCyfyu47eWZaQWeNpwZfwz99QueXN8B/Ow40DB0N+OeUeM/yu9pZAB01+JgJ+XghGveVoA== + version "1.7.0" + resolved "https://registry.yarnpkg.com/regl/-/regl-1.7.0.tgz#0d185431044a356bf80e9b775b11b935ef2746d3" + integrity sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w== remove-bom-buffer@^3.0.0: version "3.0.0" @@ -9169,7 +9217,15 @@ resolve@^0.6.1: resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" integrity sha1-3ZV5gufnNt699TtYpN2RdUV13UY= -resolve@^1.0.0, resolve@^1.1.5, resolve@^1.10.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.7.1, resolve@~1.17.0: +resolve@^1.0.0, resolve@^1.1.5, resolve@^1.10.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.7.1: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + +resolve@~1.17.0: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== @@ -9337,9 +9393,9 @@ run-async@^2.2.0: integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + version "1.1.10" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" + integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" @@ -9359,9 +9415,9 @@ rx@^4.1.0: integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.5.5: - version "6.6.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" - integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== + version "6.6.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" + integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== dependencies: tslib "^1.9.0" @@ -9737,14 +9793,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== - -split-on-first@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" - integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + version "3.0.6" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" + integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== split-polygon@^1.0.0: version "1.0.0" @@ -9811,13 +9862,13 @@ stack-utils@^1.0.1: integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== start-server-and-test@^1.11.0: - version "1.11.3" - resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.11.3.tgz#d293d2cff2c2fa0a46bbcf6b292716dbc8042d01" - integrity sha512-7r2lvcnJPECSG+ydMzk1wLt3MdzsHnYj+kXgKyzbvTXul5XYEmYJJ3K7YUGNgo5w/vnZb8L/AZMyg1C17qBdzg== + version "1.11.5" + resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.11.5.tgz#692cb4c9cf8ba9a992ef8b0010f839041183f687" + integrity sha512-XUGifPzbJcgD6tqWMFvbxnra1KByRuiw6Oc9FHR3tPm7UxB70a4iFDIuXfOAFtMJLvOJuwB3gnMUZxko8gtLow== dependencies: bluebird "3.7.2" check-more-types "2.24.0" - debug "4.1.1" + debug "4.2.0" execa "3.4.0" lazy-ass "1.6.0" ps-tree "1.2.0" @@ -9884,11 +9935,6 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== -strict-uri-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" - integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= - string-argv@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" @@ -9957,29 +10003,28 @@ string.prototype.matchall@^4.0.2: side-channel "^1.0.2" string.prototype.trim@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz#141233dff32c82bfad80684d7e5f0869ee0fb782" - integrity sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw== + version "1.2.2" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz#f538d0bacd98fc4297f0bef645226d5aaebf59f3" + integrity sha512-b5yrbl3BXIjHau9Prk7U0RRYcUYdN4wGSVaqoBQS50CCE3KBuYU0TYRNPFCP7aVoNMX87HKThdMRVIP3giclKg== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" + es-abstract "^1.18.0-next.0" string.prototype.trimend@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" - integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== + version "1.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" + integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" string.prototype.trimstart@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" - integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== + version "1.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" + integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" @@ -10114,10 +10159,10 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== +supports-color@^7.1.0, supports-color@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" @@ -10308,9 +10353,9 @@ through@2, through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.4, through integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= timers-browserify@^2.0.4: - version "2.0.11" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" - integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + version "2.0.12" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== dependencies: setimmediate "^1.0.4" @@ -10324,10 +10369,10 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== -tinycolor2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8" - integrity sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g= +tinycolor2@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803" + integrity sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA== tinyqueue@^2.0.3: version "2.0.3" @@ -10348,12 +10393,12 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -tmp@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" - integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== +tmp@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== dependencies: - rimraf "^2.6.3" + rimraf "^3.0.0" tmpl@1.0.x: version "1.0.4" @@ -10510,9 +10555,9 @@ tsconfig-paths@^3.9.0: strip-bom "^3.0.0" tslib@^1.9.0, tslib@^1.9.3: - version "1.13.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" - integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tty-browserify@0.0.0: version "0.0.0" @@ -10591,9 +10636,9 @@ typescript@3.0.3: integrity sha512-kk80vLW9iGtjMnIv11qyxLqZm20UklzuR2tL0QAnDIygIUIemcZMxlMWudl9OOt76H3ntVzcTiddQ1/pAAJMYg== ua-parser-js@^0.7.18: - version "0.7.21" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" - integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== + version "0.7.22" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.22.tgz#960df60a5f911ea8f1c818f3747b99c6e177eae3" + integrity sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q== unc-path-regex@^0.1.2: version "0.1.2" @@ -10670,10 +10715,15 @@ unique-stream@^2.0.2: json-stable-stringify-without-jsonify "^1.0.1" through2-filter "^3.0.0" -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" + integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== unquote@^1.1.0: version "1.1.1" @@ -10704,9 +10754,9 @@ update-diff@^1.1.0: integrity sha1-9RAYLYHugZ+4LDprIrYrve2ngI8= uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + version "4.4.0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" + integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== dependencies: punycode "^2.1.0" @@ -10956,9 +11006,9 @@ vinyl-sourcemaps-apply@^0.2.0: source-map "^0.5.1" vinyl@^2.0.0, vinyl@^2.1.0, vinyl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" - integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== + version "2.2.1" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974" + integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw== dependencies: clone "^2.1.1" clone-buffer "^1.0.0" @@ -11004,23 +11054,23 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -watchpack-chokidar2@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" - integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== +watchpack-chokidar2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== dependencies: chokidar "^2.1.8" watchpack@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" - integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== + version "1.7.5" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: graceful-fs "^4.1.2" neo-async "^2.5.0" optionalDependencies: chokidar "^3.4.1" - watchpack-chokidar2 "^2.0.0" + watchpack-chokidar2 "^2.0.1" weak-map@^1.0.5: version "1.0.5" @@ -11048,9 +11098,9 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1: source-map "~0.6.1" webpack@^4.41.5: - version "4.44.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21" - integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ== + version "4.44.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" + integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -11077,9 +11127,9 @@ webpack@^4.41.5: webpack-sources "^1.4.1" whatwg-fetch@>=0.10.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.0.tgz#e11de14f4878f773fbebcde8871b2c0699af8b30" - integrity sha512-rsum2ulz2iuZH08mJkT0Yi6JnKhwdw4oeyMjokgxd+mmqYSd9cPpOQf01TIWgjxG/U4+QR+AwKq6lSbXVxkyoQ== + version "3.5.0" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz#605a2cd0a7146e5db141e29d1c62ab84c0c4c868" + integrity sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A== which-module@^2.0.0: version "2.0.0"