From 661e1cd71aae2540280dac2d0eb5362330c5764e Mon Sep 17 00:00:00 2001 From: Andrea Mah <31675041+andreamah@users.noreply.github.com> Date: Mon, 2 Mar 2020 07:54:25 -0800 Subject: [PATCH 1/5] Create Release Version (to staging) (#230) merge to staging for microbit feature flag release --- .gitignore | 3 + .vscode/settings.json | 2 +- README.md | 132 +- gulpfile.js | 275 +- locales/en/out/constants.i18n.json | 4 +- locales/en/package.i18n.json | 29 +- package-lock.json | 12915 ++++++++++------ package.json | 686 +- package.nls.json | 29 +- src/adafruit_circuitplayground/constants.py | 28 +- .../debugger_communication_client.py | 51 - src/adafruit_circuitplayground/express.py | 47 +- src/adafruit_circuitplayground/pixel.py | 23 +- src/adafruit_circuitplayground/telemetry.py | 41 - .../test_debugger_communication_client.py | 63 - .../test/test_utils.py | 2 +- src/adafruit_circuitplayground/utils.py | 35 - src/check_if_venv.py | 11 + src/check_python_dependencies.py | 20 + src/common/__init__.py | 0 src/common/constants.py | 10 + src/common/debugger_communication_client.py | 86 + src/common/telemetry.py | 31 + src/common/telemetry_events.py | 33 + .../test_debugger_communication_client.py | 178 + src/common/utils.py | 49 + src/constants.ts | 185 +- src/debug_user_code.py | 8 +- src/debugger/debugAdapter.ts | 49 + src/debugger/debugAdapterFactory.ts | 33 + src/debuggerCommunicationServer.ts | 80 +- src/extension.ts | 610 +- src/extension_utils/dependencyChecker.ts | 76 - src/extension_utils/utils.ts | 485 +- src/latest_release_note.ts | 67 + src/microbit/__init__.py | 35 + src/microbit/__model/accelerometer.py | 130 + src/microbit/__model/button.py | 59 + src/microbit/__model/constants.py | 167 + src/microbit/__model/display.py | 370 + src/microbit/__model/image.py | 539 + src/microbit/__model/microbit_model.py | 78 + src/microbit/__model/producer_property.py | 3 + src/microbit/test/__init__.py | 0 src/microbit/test/test_accelerometer.py | 104 + src/microbit/test/test_button.py | 46 + src/microbit/test/test_display.py | 185 + src/microbit/test/test_image.py | 283 + src/microbit/test/test_init.py | 45 + src/microbit/test/test_microbit_model.py | 48 + src/process_user_code.py | 28 +- src/python_constants.py | 24 +- src/serialMonitor.ts | 10 +- src/service/PopupService.ts | 16 + src/service/debuggerCommunicationService.ts | 27 + src/service/messagingService.ts | 26 + .../cpx_template.py} | 31 +- src/templates/microbit_template.py | 9 + src/view/App.spec.tsx | 28 + src/view/App.test.tsx | 15 - src/view/App.tsx | 65 +- src/view/__snapshots__/App.spec.tsx.snap | 4720 ++++++ src/view/components/cpx/Cpx.spec.tsx | 29 + src/view/components/cpx/Cpx.tsx | 104 + src/view/components/cpx/CpxImage.tsx | 101 +- .../{Simulator.tsx => cpx/CpxSimulator.tsx} | 66 +- src/view/components/cpx/Svg_utils.tsx | 31 +- .../cpx/__snapshots__/Cpx.spec.tsx.snap | 4710 ++++++ src/view/components/microbit/Microbit.tsx | 84 + .../components/microbit/MicrobitImage.tsx | 176 + .../components/microbit/MicrobitSimulator.tsx | 253 + src/view/components/microbit/Microbit_svg.tsx | 1888 +++ src/view/components/simulator/ActionBar.tsx | 10 +- src/view/components/toolbar/InputSlider.tsx | 62 +- .../components/toolbar/LightSensorBar.tsx | 9 +- .../components/toolbar/MotionSensorBar.tsx | 212 - .../components/toolbar/SensorModalUtils.tsx | 385 +- .../toolbar/TemperatureSensorBar.tsx | 12 +- src/view/components/toolbar/ToolBar.tsx | 59 +- .../toolbar/motion/Accelerometer.tsx | 60 + .../toolbar/motion/MotionSensorBar.tsx | 129 + .../ThreeDimensionSlider.tsx | 87 + src/view/constants.ts | 54 + src/view/container/device/Device.spec.tsx | 30 + src/view/container/device/Device.tsx | 80 +- .../device/__snapshots__/Device.spec.tsx.snap | 2991 ++++ src/view/context.ts | 6 + src/view/index.tsx | 1 - src/view/styles/Microbit.css | 173 + src/view/styles/Simulator.css | 15 +- src/view/translations/en.json | 81 +- src/view/utils/MessageUtils.tsx | 12 + src/view/viewUtils.tsx | 7 +- tslint.json | 62 +- vendor/node-usb-native/.eslintrc | 50 +- vendor/node-usb-native/.gitignore | 28 +- vendor/node-usb-native/.npmignore | 4 +- vendor/node-usb-native/README.md | 8 +- vendor/node-usb-native/binding.gyp | 126 +- vendor/node-usb-native/lib/bindings.js | 88 +- vendor/node-usb-native/lib/detector.js | 190 +- vendor/node-usb-native/lib/index.js | 4 +- vendor/node-usb-native/lib/list-unix.js | 218 +- .../usb-native_Ubuntu14.04_6.1.4_ia32.node | Bin 0 -> 128327 bytes .../usb-native_Ubuntu14.04_6.1.4_x64.node | Bin 0 -> 112915 bytes .../native/usb-native_darwin_6.1.4_x64.node | Bin 0 -> 96696 bytes .../native/usb-native_win32_6.1.4_ia32.node | Bin 0 -> 193536 bytes .../native/usb-native_win32_6.1.4_x64.node | Bin 0 -> 229888 bytes vendor/node-usb-native/lib/native_loader.js | 48 +- vendor/node-usb-native/lib/parsers.js | 128 +- vendor/node-usb-native/lib/serialport.js | 1004 +- vendor/node-usb-native/license | 38 +- vendor/node-usb-native/package.json | 66 +- vendor/node-usb-native/src/combined.cpp | 48 +- vendor/node-usb-native/src/detection.cpp | 442 +- vendor/node-usb-native/src/detection.h | 84 +- .../node-usb-native/src/detection_linux.cpp | 634 +- vendor/node-usb-native/src/detection_mac.cpp | 922 +- vendor/node-usb-native/src/detection_win.cpp | 942 +- vendor/node-usb-native/src/deviceList.cpp | 150 +- vendor/node-usb-native/src/deviceList.h | 126 +- vendor/node-usb-native/src/serialport.cpp | 1434 +- vendor/node-usb-native/src/serialport.h | 390 +- .../node-usb-native/src/serialport_poller.cpp | 256 +- .../node-usb-native/src/serialport_poller.h | 70 +- .../node-usb-native/src/serialport_unix.cpp | 1480 +- vendor/node-usb-native/src/serialport_win.cpp | 1164 +- 127 files changed, 34281 insertions(+), 11307 deletions(-) delete mode 100644 src/adafruit_circuitplayground/debugger_communication_client.py delete mode 100644 src/adafruit_circuitplayground/telemetry.py delete mode 100644 src/adafruit_circuitplayground/test/test_debugger_communication_client.py delete mode 100644 src/adafruit_circuitplayground/utils.py create mode 100644 src/check_if_venv.py create mode 100644 src/check_python_dependencies.py create mode 100644 src/common/__init__.py create mode 100644 src/common/constants.py create mode 100644 src/common/debugger_communication_client.py create mode 100644 src/common/telemetry.py create mode 100644 src/common/telemetry_events.py create mode 100644 src/common/test/test_debugger_communication_client.py create mode 100644 src/common/utils.py create mode 100644 src/debugger/debugAdapter.ts create mode 100644 src/debugger/debugAdapterFactory.ts delete mode 100644 src/extension_utils/dependencyChecker.ts create mode 100644 src/latest_release_note.ts create mode 100644 src/microbit/__init__.py create mode 100644 src/microbit/__model/accelerometer.py create mode 100644 src/microbit/__model/button.py create mode 100644 src/microbit/__model/constants.py create mode 100644 src/microbit/__model/display.py create mode 100644 src/microbit/__model/image.py create mode 100644 src/microbit/__model/microbit_model.py create mode 100644 src/microbit/__model/producer_property.py create mode 100644 src/microbit/test/__init__.py create mode 100644 src/microbit/test/test_accelerometer.py create mode 100644 src/microbit/test/test_button.py create mode 100644 src/microbit/test/test_display.py create mode 100644 src/microbit/test/test_image.py create mode 100644 src/microbit/test/test_init.py create mode 100644 src/microbit/test/test_microbit_model.py create mode 100644 src/service/PopupService.ts create mode 100644 src/service/debuggerCommunicationService.ts create mode 100644 src/service/messagingService.ts rename src/{template.py => templates/cpx_template.py} (81%) create mode 100644 src/templates/microbit_template.py create mode 100644 src/view/App.spec.tsx delete mode 100644 src/view/App.test.tsx create mode 100644 src/view/__snapshots__/App.spec.tsx.snap create mode 100644 src/view/components/cpx/Cpx.spec.tsx create mode 100644 src/view/components/cpx/Cpx.tsx rename src/view/components/{Simulator.tsx => cpx/CpxSimulator.tsx} (91%) create mode 100644 src/view/components/cpx/__snapshots__/Cpx.spec.tsx.snap create mode 100644 src/view/components/microbit/Microbit.tsx create mode 100644 src/view/components/microbit/MicrobitImage.tsx create mode 100644 src/view/components/microbit/MicrobitSimulator.tsx create mode 100644 src/view/components/microbit/Microbit_svg.tsx delete mode 100644 src/view/components/toolbar/MotionSensorBar.tsx create mode 100644 src/view/components/toolbar/motion/Accelerometer.tsx create mode 100644 src/view/components/toolbar/motion/MotionSensorBar.tsx create mode 100644 src/view/components/toolbar/motion/threeDimensionSlider/ThreeDimensionSlider.tsx create mode 100644 src/view/container/device/Device.spec.tsx create mode 100644 src/view/container/device/__snapshots__/Device.spec.tsx.snap create mode 100644 src/view/context.ts create mode 100644 src/view/styles/Microbit.css create mode 100644 src/view/utils/MessageUtils.tsx create mode 100644 vendor/node-usb-native/lib/native/usb-native_Ubuntu14.04_6.1.4_ia32.node create mode 100644 vendor/node-usb-native/lib/native/usb-native_Ubuntu14.04_6.1.4_x64.node create mode 100644 vendor/node-usb-native/lib/native/usb-native_darwin_6.1.4_x64.node create mode 100644 vendor/node-usb-native/lib/native/usb-native_win32_6.1.4_ia32.node create mode 100644 vendor/node-usb-native/lib/native/usb-native_win32_6.1.4_x64.node diff --git a/.gitignore b/.gitignore index 51a3df207..7bc1e7ff6 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ out/ !locales/**/out/ package.nls.*.json +# virtual environment +venv/ + # testing .vscode-test diff --git a/.vscode/settings.json b/.vscode/settings.json index 30bf8c2d3..fa0a10487 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,4 +8,4 @@ }, // Turn off tsc task auto detection since we have the necessary tasks as npm scripts "typescript.tsc.autoDetect": "off" -} \ No newline at end of file +} diff --git a/README.md b/README.md index 9ecc0c8b2..f52084c69 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,39 @@ # Device Simulator Express, a Microsoft Garage project -Make without limit! Device Simulator Express, a Microsoft Garage project, allows you to code in CircuitPython for your awesome -Circuit Playground Express (CPX) projects! Test and debug your code on the device simulator and see the same +Python versions: 3.7+ Project Status: Active – The project has reached a stable, usable state and is being actively developed. License: We are using the MIT License We are welcoming PRS! Platforms Supported: Windows, MacOSX + +Azure DevOps Board Badge + +Make without limit! Device Simulator Express, a Microsoft Garage project, allows you to code microcontrollers without the hardware on hand! You can program your Circuit Playground Express (CPX) or your BBC micro:bit! Test and debug your code on the device simulator and see the same result when you plug in your actual microcontroller. Curious about the output of the device, the serial monitor allows you to observe the device output. CircuitPlayground Express -## Features +## Build Status + +| Branch | Build Status | +| :------ | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| dev | [![Build Status](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_apis/build/status/Adafruit/Pacifica-CI?branchName=dev)](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_build/latest?definitionId=304&branchName=dev) | +| staging | [![Build Status](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_apis/build/status/Adafruit/Pacifica-CI?branchName=staging)](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_build/latest?definitionId=304&branchName=staging) | +| master | [![Build Status](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_apis/build/status/Adafruit/Pacifica-CI?branchName=master)](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_build/latest?definitionId=304&branchName=master) | + + +## Prerequisites -- IntelliSense and syntax highlighting for CircuitPython code (only supports CPX Express library) +The following dependencies are required to install before launching Device Simulator Express. +You will be prompted to install the Python dependencies during the first use. + +- _**[Visual Studio Code](https://code.visualstudio.com/)**_ +- _**[Node](https://nodejs.org/en/download/)**_ +- _**[Python 3.7+](https://www.python.org/downloads/)**_: Make sure you've added python and pip to your PATH in your environment variables. (1) +- _**[Python VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)**_: This will be installed automatically from the marketplace when you install Device Simulator Express. + +## Circuit Playground Express (CPX) Simulator + +### Features + +- IntelliSense and syntax highlighting for CircuitPython code - Template file generation - Integrated Python Debugging for the Simulator - Serial monitor (available on Windows and Mac only) @@ -33,27 +57,10 @@ The simulator supports most of the sensors on CPX except **IR transmitter & Rece The code related to these sensors can still run on the actual CPX board and be deployed using Device Simulator Express. As we only support CPX library now, other libraries (i.e. simpleio) can’t run on the simulator. But they will work on the actual device! -## Prerequisites - -The following dependencies are required to install before launching Device Simulator Express. -You will be prompted to install the Python dependencies during the first use. - -- _**[Visual Studio Code](https://code.visualstudio.com/)**_ -- _**[Node](https://nodejs.org/en/download/)**_ -- _**[Python 3.7.4](https://www.python.org/downloads/)**_: Make sure you've added python and pip to your PATH in your environment variables. (1) -- _**[Python VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)**_: This will be installed automatically from the marketplace when you install Device Simulator Express. -- Python Modules for Simulation - - **Note:** On extension activation, you will be prompted with a popup message asking if you want the modules to be automatically installed for you. The following Python modules should be downloaded when you select "yes" on the prompt message. **If modules are not installed correctly, please use the "pip install" commands listed below.** - - Playsound : `pip install playsound` - - Pywin32 : `pip install pywin32` - - On Windows, you need to use the above command in the console to manually install pywin32. - - Python-Socketio : `pip install python-socketio` - - Requests : `pip install requests` - - Application Insights: `pip install applicationinsights` -## Useful Links +### Useful Links - Tutorials and Example Code for Adafruit CPX: - [Adafruit CPX library tutorial](https://learn.adafruit.com/circuitpython-made-easy-on-circuit-playground-express/circuit-playground-express-library) - [Adafruit CPX Examples on GitHub](https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/tree/master/examples) @@ -62,35 +69,33 @@ You will be prompted to install the Python dependencies during the first use. - [Tutorial for formatting Adafruit CPX for CircuitPython](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython) - [Download Firmware .uf2 file](https://learn.adafruit.com/adafruit-circuit-playground-express/circuitpython-quickstart) - [Download the latest version of the Adafruit CPX library](https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries) -- For developers: - - [Steps to run the extension locally](/docs/developers-setup.md) -## How to use +### How to use To use Device Simulator Express, install the extension from the marketplace and reload VS Code. -### 1. Start with the "New File" Command. +#### 1. Start with the "Device Simulator Express [Circuit Playground Express]: New File" Command. -1. Type in `"Device Simulator Express: New File"` in the command palette (`CTRL+SHIFT+P` to open the command palette). +1. Type in `"Device Simulator Express: [Circuit Playground Express] New File"` in the command palette (`CTRL+SHIFT+P` to open the command palette). "New File" animation 2. Name and save your file somewhere, and we’re good to go! (3) -3. Start with some examples: you can find examples files and tutorials inside the comments, as well as in the notification pop up when you run the `"Device Simulator Express: New File"` Command. +3. Start with some examples: you can find examples files and tutorials inside the comments, as well as in the notification pop up when you run the `"Device Simulator Express: [Circuit Playground Express] New File"` Command. How to find example code screenshot -### 2. Start from an existing python file. +#### 2. Start from an existing python file. 1. Open the folder or your .py file in Visual Studio Code. -2. Run `open Simulator` from the command palette or icon in the editor toolbar. +2. Run `Device Simulator Express: [Circuit Playground Express] Open Simulator` from the command palette or icon in the editor toolbar. -### 3. Run your code on the simulator. +#### 3. Run your code on the simulator. How to run the simulator animation - Run `Run Simulator` from the command palette or icon in the editor toolbar. - You can use the `Play` or `Refresh` button on the simulator webview. -### 4. Deploy your code to the physical device +#### 4. Deploy your code to the physical device Before deploying the python code to your CPX device, you need to format your device following these tutorials: @@ -102,14 +107,14 @@ Then, if you are on Windows, you will also need to install the Python Pywin32 pa Deploy to Device -### 5. Use the Serial Monitor for your Adafruit CPX device (available on Windows and Mac only) +#### 5. Use the Serial Monitor for your Adafruit CPX device (available on Windows and Mac only) 1. Plug in your CPX device (make sure it’s formatted properly already) -2. Run the command `"Device Simulator Express: Open Serial Monitor"` +2. Run the command `"Device Simulator Express: [Circuit Playground Express] Open Serial Monitor"` 3. Select your baud rate for the serial port 4. The print() statements in your code will show in the output console -### 6. Use the sensors in the Device Simulator Express +#### 6. Use the sensors in the Device Simulator Express Generating input for the sensors can be done by interacting directly with device on the webview or by using the toolbar. @@ -118,33 +123,64 @@ or by using the toolbar. - **Temperature sensor, Light sensor, acceleration:** click on the corresponding button in the toolbar and change the value using the slider or the input box attached to it. - **Shake detection:** go to the motion sensor section in the toolbar and click on the shake button. -### 7. Debug your project on the simulator +#### 7. Debug your project on the simulator 1. Add breakpoints in your code 2. Press F5 to enter the debugging mode, and you can start debugging line by line! -## Commands +### Commands Device Simulator Express provides several commands in the Command Palette (F1 or Ctrl + Shift + P/ Cmd + Shift + P for Mac OS) for working with \*.py files: -- `Device Simulator Express: New File`: Opens an unsaved .py file with template code, also opens the simulator. -- `Device Simulator Express: Open Simulator`: Opens the simulator in the webView -- `Device Simulator Express: Run on Simulator`: Runs python code on the simulator -- `Device Simulator Express: Deploy to Device`: Copies & Pastes the code.py or main.py file to CIRCUITPY drive if detected a CPX is plugged in -- `Device Simulator Express: Open Serial Monitor`: Opens the serial monitor in the integrated output window. -- `Device Simulator Express: Close Serial Monitor`: Stops the serial monitor and releases the serial port. -- `Device Simulator Express: Change Baud Rate`: Changes the baud rate of the selected serial port. For Adafruit CPX, the default baud rate is 115200. -- `Device Simulator Express: Select Serial Port`: Changes the current serial port. +- `Device Simulator Express: [Circuit Playground Express] New File`: Opens an unsaved .py file with template code, also opens the simulator. +- `Device Simulator Express: [Circuit Playground Express] Open Simulator`: Opens the simulator in the webView +- `Device Simulator Express: [Circuit Playground Express] Run on Simulator`: Runs python code on the simulator +- `Device Simulator Express: [Circuit Playground Express] Deploy to Device`: Copies & Pastes the code.py or main.py file to CIRCUITPY drive if detected a CPX is plugged in +- `Device Simulator Express: [Circuit Playground Express] Open Serial Monitor`: Opens the serial monitor in the integrated output window. +- `Device Simulator Express: [Circuit Playground Express] Close Serial Monitor`: Stops the serial monitor and releases the serial port. +- `Device Simulator Express: [Circuit Playground Express] Change Baud Rate`: Changes the baud rate of the selected serial port. For Adafruit CPX, the default baud rate is 115200. +- `Device Simulator Express: [Circuit Playground Express] Select Serial Port`: Changes the current serial port. -## Keybindings +### Keybindings In Device Simulator Express, you can use keyboard to interact with the device: -- Push Button `A & B: A B` +- Push Button `A for A, B for B, C for A & B` - Capacitive Touch Sensor `A1 – A7: SHIFT + 1~7` - Slider Switch: `SHIFT + S` - Refresh the simulator: `SHIFT + R` + +## BBC micro:bit Simulator +>**NOTE 1**: this feature is hidden by default. To use it, enable the feature flag in the "deviceSimulatorExpress.previewMode" user setting. + +>**NOTE 2**: micro:bit simulation is still in development. Features may not work as intended. + +### Features +- IntelliSense and syntax highlighting for micro:bit code +- Template file generation +- Integrated Python Debugging for the Simulator +- Simulation of the micro:bit device, including: + - 25 LEDs + - Light sensor + - Motion sensors + - Acceleration detection + - Temperature sensor + +### How to use +Using the simulator for the micro:bit is similar to using the one for the CPX. The only difference is that the commands in the command palette display `Device Simulator Express: [micro:bit] ` instead of `Device Simulator Express: [Circuit Playground Express] `. Currently, we support the following commands for micro:bit: +- `Device Simulator Express: [micro:bit] Open Simulator`: Opens an unsaved .py file with template code, also opens the simulator. +- `Device Simulator Express: [micro:bit] New File`: Opens the simulator in the webView + +Please review the CPX's ["How to use" guide](#How-to-use) for more info. + +### Keybindings +- Push Button `A for A, B for B, C for A & B` +- Refresh the simulator: `SHIFT + R` + +## Contribute +[See here for steps to run the extension locally.](/docs/developers-setup.md) + ## Provide feedback To report issues, provide feedback or requests, please use this link: [Provide Feedback](https://aka.ms/AA5xpxx). @@ -183,7 +219,7 @@ A `ThirdPartyNotices.txt` file is provided in the extension's source code listin - While running a code file, if you get an error saying it can't find the file, make sure you've clicked on a valid Python code file before running it. - To open the output panel again after closing it go to VS Code menu: `View->Output`. - If you try to deploy to the device while it's plugged in but you still get an error saying it cannot find the board, make sure your Circuit Playground Express is formatted correctly and that its name matches `CIRCUITPY`. -- If you can't get the Simulator communication working while debugging, try to open your `Settings` and check the port used under `"Device Simulator Express: Debugger Server Port"`. You can either change it (usually ports above 5000 should work) or try to free it, then start debugging again. +- If you can't get the Simulator communication working while debugging, try to open your `Settings` and check the port used under `"Device Simulator Express: [] Debugger Server Port"`. You can either change it (usually ports above 5000 should work) or try to free it, then start debugging again. - When you are using the serial monitor, if you get some unusual error messages, unplug the device and reload the VS Code windows. ## License diff --git a/gulpfile.js b/gulpfile.js index 3c106798d..e2b15d39b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,135 +1,140 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -const gulp = require("gulp"); - -const ts = require("gulp-typescript"); -const sourcemaps = require("gulp-sourcemaps"); -const typescript = require("typescript"); -const del = require("del"); -const es = require("event-stream"); -const vsce = require("vsce"); -const nls = require("vscode-nls-dev"); - -const tsProject = ts.createProject("./tsconfig.json", { typescript }); - -const inlineMap = true; -const inlineSource = false; -const outDest = "out"; - -// A list of all locales supported by VSCode can be found here: https://code.visualstudio.com/docs/getstarted/locales -const languages = [{ folderName: "en", id: "en" }]; - -gulp.task("clean", () => { - return del( - [ - "out/*", - "package.nls.*.json", - "../../dist/*0.0.0-UNTRACKEDVERSION.vsix" - ], - { force: true } - ); -}); - -const pythonToMove = [ - "./src/adafruit_circuitplayground/*.*", - "./src/*.py", - "./src/requirements.txt", -]; - -gulp.task("python-compile", () => { - // the base option sets the relative root for the set of files, - // preserving the folder structure - return gulp.src(pythonToMove, { base: "./src/" }).pipe(gulp.dest("out")); -}); - -gulp.task("internal-compile", () => { - return compile(false); -}); - -gulp.task("internal-nls-compile", () => { - return compile(true); -}); - -gulp.task("add-locales", () => { - return gulp - .src(["package.nls.json"]) - .pipe(nls.createAdditionalLanguageFiles(languages, "locales")) - .pipe(gulp.dest(".")); -}); - -gulp.task("vsce:publish", () => { - return vsce.publish(); -}); - -gulp.task("vsce:package", () => { - return vsce.createVSIX({ - packagePath: "../../dist/deviceSimulatorExpress-0.0.0-UNTRACKEDVERSION.vsix" - }); -}); - -gulp.task( - "compile", - gulp.series("clean", "internal-compile", "python-compile", callback => { - callback(); - }) -); - -gulp.task( - "build", - gulp.series( - "clean", - "internal-nls-compile", - "python-compile", - "add-locales", - callback => { - callback(); - } - ) -); - -gulp.task( - "publish", - gulp.series("compile", "vsce:publish", callback => { - callback(); - }) -); - -gulp.task( - "package", - gulp.series("compile", "vsce:package", callback => { - callback(); - }) -); - -//---- internal - -function compile(buildNls) { - var r = tsProject - .src() - .pipe(sourcemaps.init()) - .pipe(tsProject()) - .js.pipe(buildNls ? nls.rewriteLocalizeCalls() : es.through()) - .pipe( - buildNls - ? nls.createAdditionalLanguageFiles(languages, "locales", "out") - : es.through() - ); - - if (inlineMap && inlineSource) { - r = r.pipe(sourcemaps.write()); - } else { - r = r.pipe( - sourcemaps.write("../out", { - // no inlined source - includeContent: inlineSource, - // Return relative source map root directories per file. - sourceRoot: "../src" - }) - ); - } - - return r.pipe(gulp.dest(outDest)); -} +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const gulp = require("gulp"); + +const ts = require("gulp-typescript"); +const sourcemaps = require("gulp-sourcemaps"); +const typescript = require("typescript"); +const del = require("del"); +const es = require("event-stream"); +const vsce = require("vsce"); +const nls = require("vscode-nls-dev"); + +const tsProject = ts.createProject("./tsconfig.json", { typescript }); + +const inlineMap = true; +const inlineSource = false; +const outDest = "out"; + +// A list of all locales supported by VSCode can be found here: https://code.visualstudio.com/docs/getstarted/locales +const languages = [{ folderName: "en", id: "en" }]; + +gulp.task("clean", () => { + return del( + [ + "out/*", + "package.nls.*.json", + "../../dist/*0.0.0-UNTRACKEDVERSION.vsix", + ], + { force: true } + ); +}); + +const pythonToMove = [ + "./src/adafruit_circuitplayground/*.*", + "./src/microbit/*.*", + "./src/microbit/!(test)/**/*", + "./src/*.py", + "./src/common/*.py", + "./src/requirements.txt", + "./src/templates/*.*" +]; + +gulp.task("python-compile", () => { + // the base option sets the relative root for the set of files, + // preserving the folder structure + return gulp.src(pythonToMove, { base: "./src/" }).pipe(gulp.dest("out")); +}); + +gulp.task("internal-compile", () => { + return compile(false); +}); + +gulp.task("internal-nls-compile", () => { + return compile(true); +}); + +gulp.task("add-locales", () => { + return gulp + .src(["package.nls.json"]) + .pipe(nls.createAdditionalLanguageFiles(languages, "locales")) + .pipe(gulp.dest(".")); +}); + +gulp.task("vsce:publish", () => { + return vsce.publish(); +}); + +gulp.task("vsce:package", () => { + return vsce.createVSIX({ + packagePath: + "../../dist/deviceSimulatorExpress-0.0.0-UNTRACKEDVERSION.vsix", + }); +}); + +gulp.task( + "compile", + gulp.series("clean", "internal-compile", "python-compile", callback => { + callback(); + }) +); + +gulp.task( + "build", + gulp.series( + "clean", + "internal-nls-compile", + "python-compile", + "add-locales", + callback => { + callback(); + } + ) +); + +gulp.task( + "publish", + gulp.series("compile", "vsce:publish", callback => { + callback(); + }) +); + +gulp.task( + "package", + gulp.series("compile", "vsce:package", callback => { + callback(); + }) +); + +//---- internal + +function compile(buildNls) { + var r = tsProject + .src() + .pipe(sourcemaps.init()) + .pipe(tsProject()) + .js.pipe(buildNls ? nls.rewriteLocalizeCalls() : es.through()) + .pipe( + buildNls + ? nls.createAdditionalLanguageFiles(languages, "locales", "out") + : es.through() + ); + + if (inlineMap && inlineSource) { + r = r.pipe(sourcemaps.write()); + } else { + r = r.pipe( + sourcemaps.write("../out", { + // no inlined source + includeContent: inlineSource, + // Return relative source map root directories per file. + sourceRoot: "../src", + }) + ); + } + + return r.pipe(gulp.dest(outDest)); +} diff --git a/locales/en/out/constants.i18n.json b/locales/en/out/constants.i18n.json index d805009c8..333d9bf47 100644 --- a/locales/en/out/constants.i18n.json +++ b/locales/en/out/constants.i18n.json @@ -27,7 +27,7 @@ "info.deploySimulator": "\n[INFO] Deploying code to the simulator...\n", "info.deploySuccess": "\n[INFO] Code successfully deployed\n", "info.extensionActivated": "Congratulations, your extension Adafruit_Simulator is now active!", - "info.firstTimeWebview": "To reopen the simulator click on the \"Open Simulator\" button on the upper right corner of the text editor, or select the command \"Open Simulator\" from command palette.", + "info.firstTimeWebview": "To reopen the simulator select the command \"Open Simulator\" from command palette.", "info.installPythonDependencies": "Do you want us to try and install this extensions dependencies for you?", "error.invalidFileExtensionDebug": "The file you tried to run isn\\'t a Python file.", "info.newFile": "New to Python or the Circuit Playground Express? We are here to help!", @@ -36,7 +36,7 @@ "info.privacyStatement": "Privacy Statement", "info.successfulInstall": "Successfully installed Python dependencies.", "info.thirdPartyWebsite": "By clicking \"Agree and Proceed\" you will be redirected to adafruit.com, a third party website not managed by Microsoft. Please note that your activity on adafruit.com is subject to Adafruit's privacy policy", - "info.welcomeOutputTab": "Welcome to the Adafruit Simulator output tab!\n\n", + "info.welcomeOutputTab": "Welcome to the Device Simulator Express output tab!\n\n", "label.webviewPanel": "Device Simulator Express", "name": "Device Simulator Express", diff --git a/locales/en/package.i18n.json b/locales/en/package.i18n.json index 49d2906a0..9afd1a72c 100644 --- a/locales/en/package.i18n.json +++ b/locales/en/package.i18n.json @@ -1,16 +1,19 @@ { - "deviceSimulatorExpressExtension.commands.changeBaudRate": "Change Baud Rate", - "deviceSimulatorExpressExtension.commands.closeSerialMonitor": "Close Serial Monitor", - "deviceSimulatorExpressExtension.commands.label": "Device Simulator Express", - "deviceSimulatorExpressExtension.commands.openSerialMonitor": "Open Serial Monitor", - "deviceSimulatorExpressExtension.commands.openSimulator": "Open Simulator", - "deviceSimulatorExpressExtension.commands.runSimulator": "Run Simulator", - "deviceSimulatorExpressExtension.commands.newFile": "New File", - "deviceSimulatorExpressExtension.commands.runDevice": "Deploy to Device", - "deviceSimulatorExpressExtension.commands.selectSerialPort": "Select Serial Port", + "deviceSimulatorExpressExtension.commands.common.installDependencies": "Install Extension Dependencies", + "deviceSimulatorExpressExtension.commands.common.label": "Device Simulator Express", + "deviceSimulatorExpressExtension.commands.common.runSimulator": "Run Simulator", + "deviceSimulatorExpressExtension.commands.cpx.changeBaudRate": "[Circuit Playground Express] Change Baud Rate", + "deviceSimulatorExpressExtension.commands.cpx.closeSerialMonitor": "[Circuit Playground Express] Close Serial Monitor", + "deviceSimulatorExpressExtension.commands.cpx.openSerialMonitor": "[Circuit Playground Express] Open Serial Monitor", + "deviceSimulatorExpressExtension.commands.cpx.openSimulator": "[Circuit Playground Express] Open Simulator", + "deviceSimulatorExpressExtension.commands.cpx.newFile": "[Circuit Playground Express] New File", + "deviceSimulatorExpressExtension.commands.cpx.deployToDevice": "[Circuit Playground Express] Deploy to Device", + "deviceSimulatorExpressExtension.commands.cpx.selectSerialPort": "[Circuit Playground Express] Select Serial Port", + "deviceSimulatorExpressExtension.commands.microbit.openSimulator": "[micro:bit] Open Simulator", + "deviceSimulatorExpressExtension.commands.microbit.newFile": "[micro:bit] New File", "deviceSimulatorExpressExtension.configuration.title": "Device Simulator Express configuration", - "deviceSimulatorExpressExtension.configuration.properties.open": "Whether to show 'Open Simulator' icon in editor title menu.", - "deviceSimulatorExpressExtension.configuration.properties.device": "Whether to show 'Run Device' icon in editor title menu.", - "deviceSimulatorExpressExtension.configuration.properties.simulator": "Whether to show 'Run Simulator' icon in editor title menu.", - "deviceSimulatorExpressExtension.configuration.properties.debuggerPort": "The port the Server will listen on for communication with the debugger." + "deviceSimulatorExpressExtension.configuration.properties.configEnvOnChange": "When you change the Python interpreter, the Device Simulator Express will automatically configure itself for the required dependencies.", + "deviceSimulatorExpressExtension.configuration.properties.debuggerPort": "The port the Server will listen on for communication with the debugger.", + "deviceSimulatorExpressExtension.configuration.properties.dependencyChecker": "Whether or not to ask if we can download dependencies. If unchecked, the extension will default to never download dependencies, except when automatically creating a virtual environment in the extension files." + "deviceSimulatorExpressExtension.configuration.properties.previewMode": "Enable this to test out and play with the new micro:bit simulator!" } diff --git a/package-lock.json b/package-lock.json index 87a51978c..7b8613ef0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,17 @@ "@babel/highlight": "^7.0.0" } }, + "@babel/compat-data": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.8.5.tgz", + "integrity": "sha512-jWYUqQX/ObOhG1UiEkbH5SANsE/8oKXiQWjj7p7xgj9Zmnt//aUvyz4dBkK0HNsS8/cbyC5NmmH87VekW+mXFg==", + "dev": true, + "requires": { + "browserslist": "^4.8.5", + "invariant": "^2.2.4", + "semver": "^5.5.0" + } + }, "@babel/core": { "version": "7.4.3", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.3.tgz", @@ -73,351 +84,392 @@ } }, "@babel/helper-annotate-as-pure": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", + "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", + "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-explode-assignable-expression": "^7.8.3", + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-builder-react-jsx": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.3.0.tgz", - "integrity": "sha512-MjA9KgwCuPEkQd9ncSXvSyJ5y+j2sICHyrI0M3L+6fnS4wMSNDc1ARXsbTfbb2cXHn17VisSnU/sHFTCxVxSMw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz", + "integrity": "sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ==", "dev": true, "requires": { - "@babel/types": "^7.3.0", + "@babel/types": "^7.8.3", "esutils": "^2.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-call-delegate": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", - "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.4.4.tgz", - "integrity": "sha512-UbBHIa2qeAGgyiNR9RszVF7bUHEdgS4JAUNT8SiqrAN6YJVxlOxeLr5pBzb5kan302dejJ9nla4RyKcR1XT6XA==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.4", - "@babel/helper-split-export-declaration": "^7.4.4" - } - }, - "@babel/helper-define-map": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", - "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", - "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", - "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/template": "^7.4.4", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==" - }, - "@babel/helper-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", - "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-replace-supers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", - "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - } - }, - "@babel/helper-simple-access": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", - "dev": true, - "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/helper-wrap-function": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", - "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz", + "integrity": "sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.2.0" - } - }, - "@babel/helpers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", - "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", - "requires": { - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - } - }, - "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, "requires": { - "color-convert": "^1.9.0" + "@babel/highlight": "^7.8.3" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" } }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, "requires": { - "has-flag": "^3.0.0" + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" } - } - } - }, - "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==" - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", - "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.2.0" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.0.tgz", - "integrity": "sha512-t2ECPNOXsIeK1JxJNKmgbzQtoG27KIlVE61vTqX0DKR9E9sZlVVxWUtEW9D5FlZ8b8j7SBNCHY47GgPKCKlpPg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.4.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-proposal-decorators": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.4.0.tgz", - "integrity": "sha512-d08TLmXeK/XbgCo7ZeZ+JaeZDtDai/2ctapTRsWWkkmy7G/cqz8DQN/HlWG7RR4YmfXxmExsbU3SuCjlM7AtUg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.4.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-decorators": "^7.2.0" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", - "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.2.0" + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", - "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", + "@babel/helper-compilation-targets": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz", + "integrity": "sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + "@babel/compat-data": "^7.8.4", + "browserslist": "^4.8.5", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" } }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "@babel/helper-create-class-features-plugin": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", + "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", - "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", + "@babel/helper-create-regexp-features-plugin": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz", + "integrity": "sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" + "@babel/helper-regex": "^7.8.3", + "regexpu-core": "^4.6.0" }, "dependencies": { "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", + "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", "dev": true, "requires": { "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", + "regenerate-unicode-properties": "^8.1.0", "regjsgen": "^0.5.0", "regjsparser": "^0.6.0", "unicode-match-property-ecmascript": "^1.0.4", @@ -425,15 +477,15 @@ } }, "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", + "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", "dev": true }, "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.3.tgz", + "integrity": "sha512-8uZvYbnfAtEm9Ab8NTb3hdLwL4g/LQzEYP7Xs27T96abJCCE2d6r3cPZPQEsLKy0vRSGVNG+/zVGtLr86HQduA==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -441,526 +493,140 @@ } } }, - "@babel/plugin-syntax-async-generators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-bigint": { + "@babel/helper-define-map": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "dependencies": { - "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" - } - } - }, - "@babel/plugin-syntax-decorators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.2.0.tgz", - "integrity": "sha512-38QdqVoXdHUQfTpZo3rQwqQdWtCn5tMv4uV6r2RMfTqNBuv4ZBhz79SfaQWKTVmxHjeFv/DnXVC/+agHCklYWA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-flow": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.2.0.tgz", - "integrity": "sha512-r6YMuZDWLtLlu0kqIim5o/3TNRAlWb073HwT3e2nKf9I8IIvOggPrnILYPsrrKilmn/mYEMCf/Z07w3yQJF6dg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", - "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz", - "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", + "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz", - "integrity": "sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-function-name": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" }, "dependencies": { - "@babel/helper-plugin-utils": { + "@babel/code-frame": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" - } - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", - "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", - "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.11" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", - "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.4", - "@babel/helper-split-export-declaration": "^7.4.4", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", - "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", - "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" - }, - "dependencies": { - "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", "dev": true, "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" + "@babel/highlight": "^7.8.3" } }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", "dev": true }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", "dev": true, "requires": { - "jsesc": "~0.5.0" + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" } } } }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", - "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-flow-strip-types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.0.tgz", - "integrity": "sha512-C4ZVNejHnfB22vI2TYN4RUp2oCmq6cSEAg4RygSvYZUECRqUu9O4PMEMNJ4wsemaRGg27BbgYctG4BZh+AgIHw==", + "@babel/helper-explode-assignable-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", + "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.2.0" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", - "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", - "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", - "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", - "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", - "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", - "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", - "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", - "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", - "dev": true, - "requires": { - "regexp-tree": "^0.1.6" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", - "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", - "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", - "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", - "dev": true, - "requires": { - "@babel/helper-call-delegate": "^7.4.4", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", - "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-react-constant-elements": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.2.0.tgz", - "integrity": "sha512-YYQFg6giRFMsZPKUM9v+VcHOdfSQdz9jHCx3akAi3UYgyjndmdYGSXylQ/V+HswQt4fL8IklchD9HTsaOCrWQQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-react-display-name": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz", - "integrity": "sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-react-jsx": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.3.0.tgz", - "integrity": "sha512-a/+aRb7R06WcKvQLOu4/TpjKOdvVEKRLWFpKcNuHhiREPgGRB4TQJxq07+EZLS8LFVYpfq1a5lDUnuMdcCpBKg==", - "dev": true, - "requires": { - "@babel/helper-builder-react-jsx": "^7.3.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@babel/plugin-transform-react-jsx-self": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.2.0.tgz", - "integrity": "sha512-v6S5L/myicZEy+jr6ielB0OR8h+EH/1QFx/YJ7c7Ua+7lqsjj/vW6fD5FR9hB/6y7mGbfT4vAURn3xqBxsUcdg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@babel/plugin-transform-react-jsx-source": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.2.0.tgz", - "integrity": "sha512-A32OkKTp4i5U6aE88GwwcuV4HAprUgHcTq0sSafLxjr6AW0QahrCRCjxogkbbcdtpbXkuTOlgpjophCxb6sh5g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", - "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.0" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", - "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.4.3.tgz", - "integrity": "sha512-7Q61bU+uEI7bCUFReT1NKn7/X6sDQsZ7wL1sJ9IYMAO7cI+eg6x9re1cEw2fCRMbbTVyoeUKWSV1M6azEfKCfg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "resolve": "^1.8.1", - "semver": "^5.5.1" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", - "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", - "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-typescript": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.3.tgz", - "integrity": "sha512-Ebj230AxcrKGZPKIp4g4TdQLrqX95TobLUWKd/CwG7X1XHUH1ZpkpFvXuXqWbtGRWb7uuEWNlrl681wsOArAdQ==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-typescript": "^7.8.3" + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" }, "dependencies": { "@babel/code-frame": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, "requires": { "@babel/highlight": "^7.8.3" } }, "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, "requires": { "@babel/types": "^7.8.3", "jsesc": "^2.5.1", @@ -968,23 +634,11 @@ "source-map": "^0.5.0" } }, - "@babel/helper-create-class-features-plugin": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", - "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==", - "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3" - } - }, "@babel/helper-function-name": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.8.3", "@babel/template": "^7.8.3", @@ -995,46 +649,16 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, "requires": { "@babel/types": "^7.8.3" } }, - "@babel/helper-member-expression-to-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", - "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", - "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" - }, - "@babel/helper-replace-supers": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", - "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", - "requires": { - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, "@babel/helper-split-export-declaration": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, "requires": { "@babel/types": "^7.8.3" } @@ -1043,6 +667,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, "requires": { "chalk": "^2.0.0", "esutils": "^2.0.2", @@ -1050,14 +675,16 @@ } }, "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==" + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true }, "@babel/template": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, "requires": { "@babel/code-frame": "^7.8.3", "@babel/parser": "^7.8.3", @@ -1065,15 +692,16 @@ } }, "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", + "@babel/generator": "^7.8.4", "@babel/helper-function-name": "^7.8.3", "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", + "@babel/parser": "^7.8.4", "@babel/types": "^7.8.3", "debug": "^4.1.0", "globals": "^11.1.0", @@ -1084,6 +712,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, "requires": { "esutils": "^2.0.2", "lodash": "^4.17.13", @@ -1094,6 +723,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -1102,6 +732,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -1111,208 +742,2583 @@ "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } } } }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", - "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", + "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" + "@babel/types": "^7.8.3" }, "dependencies": { - "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", "dev": true, "requires": { - "jsesc": "~0.5.0" + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" } } } }, - "@babel/preset-env": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", - "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", + "@babel/helper-member-expression-to-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", + "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.4.4", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.4.4", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.4.4", - "@babel/plugin-transform-classes": "^7.4.4", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.2.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.4", - "@babel/plugin-transform-function-name": "^7.4.4", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.4.4", - "@babel/plugin-transform-modules-systemjs": "^7.4.4", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", - "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.2.0", - "@babel/plugin-transform-parameters": "^7.4.4", - "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.5", - "@babel/plugin-transform-reserved-words": "^7.2.0", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.2.0", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.4.4", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "browserslist": "^4.6.0", - "core-js-compat": "^3.1.1", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.5.0" + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, - "@babel/preset-react": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.0.0.tgz", - "integrity": "sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==", + "@babel/helper-module-imports": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", + "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0" + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, - "@babel/preset-typescript": { + "@babel/helper-module-transforms": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.8.3.tgz", - "integrity": "sha512-qee5LgPGui9zQ0jR1TeU5/fP9L+ovoArklEqY12ek8P/wV5ZeM/VYSQYwICeoT6FfpJTekG9Ilay5PhwsOpMHA==", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz", + "integrity": "sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-transform-typescript": "^7.8.3" + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" }, "dependencies": { - "@babel/helper-plugin-utils": { + "@babel/code-frame": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, - "@babel/runtime": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.3.tgz", - "integrity": "sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==", + "@babel/helper-optimise-call-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", + "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", "dev": true, "requires": { - "regenerator-runtime": "^0.13.2" - } - }, - "@babel/template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", - "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.4", - "@babel/types": "^7.4.4" + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, - "@babel/traverse": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", - "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/types": "^7.4.4", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.11" - } + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==" }, - "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "@babel/helper-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", + "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==", + "dev": true, "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" + "lodash": "^4.17.13" } }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" - }, - "@cnakazawa/watch": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", - "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "@babel/helper-remap-async-to-generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", + "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==", + "dev": true, "requires": { - "exec-sh": "^0.3.2", - "minimist": "^1.2.0" - } + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-wrap-function": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/helper-replace-supers": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", + "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/helper-simple-access": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", + "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-wrap-function": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", + "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/helpers": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", + "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==" + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz", + "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz", + "integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.8.3.tgz", + "integrity": "sha512-e3RvdvS4qPJVTe288DlXjwKflpfy1hr0j5dz5WpIYYeP7vQZg2WfAEIp8k5/Lwis/m5REXEteIz6rrcDtXXG7w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-decorators": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", + "integrity": "sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz", + "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz", + "integrity": "sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + } + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz", + "integrity": "sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz", + "integrity": "sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" + } + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.8.3.tgz", + "integrity": "sha512-8Hg4dNNT9/LcA1zQlfwuKR8BUc/if7Q7NkTam9sGTcJphLwpf2g4S42uhspQrIrR+dpzE0dtTqBVFoHl8GtnnQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-flow": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.8.3.tgz", + "integrity": "sha512-innAx3bUbA0KSYj2E2MNFSn9hiCeowOFLxlsuhXzw8hMQnzkDomUr9QCD7E9VF60NmnG1sNTuuv6Qf4f8INYsg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", + "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz", + "integrity": "sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz", + "integrity": "sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz", + "integrity": "sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" + } + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", + "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", + "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", + "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", + "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-classes": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz", + "integrity": "sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-define-map": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", + "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz", + "integrity": "sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz", + "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz", + "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", + "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz", + "integrity": "sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-flow": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz", + "integrity": "sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz", + "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/plugin-transform-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", + "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz", + "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz", + "integrity": "sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz", + "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz", + "integrity": "sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz", + "integrity": "sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", + "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz", + "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", + "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz", + "integrity": "sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.8.3", + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz", + "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-react-constant-elements": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.8.3.tgz", + "integrity": "sha512-glrzN2U+egwRfkNFtL34xIBYTxbbUF2qJTP8HD3qETBBqzAWSeNB821X0GjU06+dNpq/UyCIjI72FmGE5NNkQQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz", + "integrity": "sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz", + "integrity": "sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g==", + "dev": true, + "requires": { + "@babel/helper-builder-react-jsx": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.8.3.tgz", + "integrity": "sha512-01OT7s5oa0XTLf2I8XGsL8+KqV9lx3EZV+jxn/L2LQ97CGKila2YMroTkCEIE0HV/FF7CMSRsIAybopdN9NTdg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz", + "integrity": "sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz", + "integrity": "sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz", + "integrity": "sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz", + "integrity": "sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "resolve": "^1.8.1", + "semver": "^5.5.1" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", + "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", + "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", + "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-regex": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", + "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz", + "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.3.tgz", + "integrity": "sha512-Ebj230AxcrKGZPKIp4g4TdQLrqX95TobLUWKd/CwG7X1XHUH1ZpkpFvXuXqWbtGRWb7uuEWNlrl681wsOArAdQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-typescript": "^7.8.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", + "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", + "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==", + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", + "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", + "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" + }, + "@babel/helper-replace-supers": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", + "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", + "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==" + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", + "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", + "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/preset-env": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.8.4.tgz", + "integrity": "sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.8.4", + "@babel/helper-compilation-targets": "^7.8.4", + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-proposal-async-generator-functions": "^7.8.3", + "@babel/plugin-proposal-dynamic-import": "^7.8.3", + "@babel/plugin-proposal-json-strings": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.8.3", + "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.8.3", + "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.8.3", + "@babel/plugin-transform-async-to-generator": "^7.8.3", + "@babel/plugin-transform-block-scoped-functions": "^7.8.3", + "@babel/plugin-transform-block-scoping": "^7.8.3", + "@babel/plugin-transform-classes": "^7.8.3", + "@babel/plugin-transform-computed-properties": "^7.8.3", + "@babel/plugin-transform-destructuring": "^7.8.3", + "@babel/plugin-transform-dotall-regex": "^7.8.3", + "@babel/plugin-transform-duplicate-keys": "^7.8.3", + "@babel/plugin-transform-exponentiation-operator": "^7.8.3", + "@babel/plugin-transform-for-of": "^7.8.4", + "@babel/plugin-transform-function-name": "^7.8.3", + "@babel/plugin-transform-literals": "^7.8.3", + "@babel/plugin-transform-member-expression-literals": "^7.8.3", + "@babel/plugin-transform-modules-amd": "^7.8.3", + "@babel/plugin-transform-modules-commonjs": "^7.8.3", + "@babel/plugin-transform-modules-systemjs": "^7.8.3", + "@babel/plugin-transform-modules-umd": "^7.8.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", + "@babel/plugin-transform-new-target": "^7.8.3", + "@babel/plugin-transform-object-super": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.8.4", + "@babel/plugin-transform-property-literals": "^7.8.3", + "@babel/plugin-transform-regenerator": "^7.8.3", + "@babel/plugin-transform-reserved-words": "^7.8.3", + "@babel/plugin-transform-shorthand-properties": "^7.8.3", + "@babel/plugin-transform-spread": "^7.8.3", + "@babel/plugin-transform-sticky-regex": "^7.8.3", + "@babel/plugin-transform-template-literals": "^7.8.3", + "@babel/plugin-transform-typeof-symbol": "^7.8.4", + "@babel/plugin-transform-unicode-regex": "^7.8.3", + "@babel/types": "^7.8.3", + "browserslist": "^4.8.5", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/preset-react": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.8.3.tgz", + "integrity": "sha512-9hx0CwZg92jGb7iHYQVgi0tOEHP/kM60CtWJQnmbATSPIQQ2xYzfoCI3EdqAhFBeeJwYMdWQuDUHMsuDbH9hyQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-react-display-name": "^7.8.3", + "@babel/plugin-transform-react-jsx": "^7.8.3", + "@babel/plugin-transform-react-jsx-self": "^7.8.3", + "@babel/plugin-transform-react-jsx-source": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + } + } + }, + "@babel/preset-typescript": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.8.3.tgz", + "integrity": "sha512-qee5LgPGui9zQ0jR1TeU5/fP9L+ovoArklEqY12ek8P/wV5ZeM/VYSQYwICeoT6FfpJTekG9Ilay5PhwsOpMHA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-typescript": "^7.8.3" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" + } + } + }, + "@babel/runtime": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", + "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/traverse": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + } + }, + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } }, "@csstools/convert-colors": { "version": "1.4.0", @@ -1321,209 +3327,884 @@ "dev": true }, "@csstools/normalize.css": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-9.0.1.tgz", - "integrity": "sha512-6It2EVfGskxZCQhuykrfnALg7oVeiI6KclWSmGDqB0AiInVrTGB9Jp9i4/Ad21u9Jde/voVQz6eFX/eSg/UsPA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz", + "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==", + "dev": true + }, + "@formatjs/intl-relativetimeformat": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-2.8.0.tgz", + "integrity": "sha512-5T3m5hJSxXrbwtnFHyYBSbTjOXPXu+4NJ0MUu1LAf4fPEdd+pJZfWKuMJSWgFQPVMbLYq9NLvDWQda3hVe99sg==" + }, + "@gulp-sourcemaps/identity-map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", + "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "dev": true, + "requires": { + "acorn": "^5.0.3", + "css": "^2.2.1", + "normalize-path": "^2.1.1", + "source-map": "^0.6.0", + "through2": "^2.0.3" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + } + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "requires": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + } + }, + "@hapi/address": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", + "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==", + "dev": true + }, + "@hapi/bourne": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-1.3.2.tgz", + "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==", + "dev": true + }, + "@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", + "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==", "dev": true }, - "@formatjs/intl-relativetimeformat": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-2.8.0.tgz", - "integrity": "sha512-5T3m5hJSxXrbwtnFHyYBSbTjOXPXu+4NJ0MUu1LAf4fPEdd+pJZfWKuMJSWgFQPVMbLYq9NLvDWQda3hVe99sg==" + "@hapi/joi": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.1.tgz", + "integrity": "sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==", + "dev": true, + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "@hapi/topo": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz", + "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==", + "dev": true, + "requires": { + "@hapi/hoek": "^8.3.0" + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", + "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==" + }, + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/core": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-25.1.0.tgz", + "integrity": "sha512-iz05+NmwCmZRzMXvMo6KFipW7nzhbpEawrKrkkdJzgytavPse0biEnCNr2wRlyCsp3SmKaEY+SGv7YWYQnIdig==", + "requires": { + "@jest/console": "^25.1.0", + "@jest/reporters": "^25.1.0", + "@jest/test-result": "^25.1.0", + "@jest/transform": "^25.1.0", + "@jest/types": "^25.1.0", + "ansi-escapes": "^4.2.1", + "chalk": "^3.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.3", + "jest-changed-files": "^25.1.0", + "jest-config": "^25.1.0", + "jest-haste-map": "^25.1.0", + "jest-message-util": "^25.1.0", + "jest-regex-util": "^25.1.0", + "jest-resolve": "^25.1.0", + "jest-resolve-dependencies": "^25.1.0", + "jest-runner": "^25.1.0", + "jest-runtime": "^25.1.0", + "jest-snapshot": "^25.1.0", + "jest-util": "^25.1.0", + "jest-validate": "^25.1.0", + "jest-watcher": "^25.1.0", + "micromatch": "^4.0.2", + "p-each-series": "^2.1.0", + "realpath-native": "^1.1.0", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "@jest/console": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.1.0.tgz", + "integrity": "sha512-3P1DpqAMK/L07ag/Y9/Jup5iDEG9P4pRAuZiMQnU0JB3UOvCyYCjCoxr7sIA80SeyUCUKrr24fKAxVpmBgQonA==", + "requires": { + "@jest/source-map": "^25.1.0", + "chalk": "^3.0.0", + "jest-util": "^25.1.0", + "slash": "^3.0.0" + } + }, + "@jest/source-map": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.1.0.tgz", + "integrity": "sha512-ohf2iKT0xnLWcIUhL6U6QN+CwFWf9XnrM2a6ybL9NXxJjgYijjLSitkYHIdzkd8wFliH73qj/+epIpTiWjRtAA==", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.3", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.1.0.tgz", + "integrity": "sha512-FZzSo36h++U93vNWZ0KgvlNuZ9pnDnztvaM7P/UcTx87aPDotG18bXifkf1Ji44B7k/eIatmMzkBapnAzjkJkg==", + "requires": { + "@jest/console": "^25.1.0", + "@jest/transform": "^25.1.0", + "@jest/types": "^25.1.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "ansi-escapes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", + "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "requires": { + "type-fest": "^0.8.1" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "jest-message-util": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.1.0.tgz", + "integrity": "sha512-Nr/Iwar2COfN22aCqX0kCVbXgn8IBm9nWf4xwGr5Olv/KZh0CZ32RKgZWMVDXGdOahicM10/fgjdimGNX/ttCQ==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^25.1.0", + "@jest/types": "^25.1.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^3.0.0", + "micromatch": "^4.0.2", + "slash": "^3.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-resolve": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.1.0.tgz", + "integrity": "sha512-XkBQaU1SRCHj2Evz2Lu4Czs+uIgJXWypfO57L7JYccmAXv4slXA6hzNblmcRmf7P3cQ1mE7fL3ABV6jAwk4foQ==", + "requires": { + "@jest/types": "^25.1.0", + "browser-resolve": "^1.11.3", + "chalk": "^3.0.0", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + } + }, + "jest-util": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.1.0.tgz", + "integrity": "sha512-7did6pLQ++87Qsj26Fs/TIwZMUFBXQ+4XXSodRNy3luch2DnRXsSnmpVtxxQ0Yd6WTipGpbhh2IFP1mq6/fQGw==", + "requires": { + "@jest/types": "^25.1.0", + "chalk": "^3.0.0", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1" + } + }, + "jest-watcher": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-25.1.0.tgz", + "integrity": "sha512-Q9eZ7pyaIr6xfU24OeTg4z1fUqBF/4MP6J801lyQfg7CsnZ/TCzAPvCfckKdL5dlBBEKBeHV0AdyjFZ5eWj4ig==", + "requires": { + "@jest/test-result": "^25.1.0", + "@jest/types": "^25.1.0", + "ansi-escapes": "^4.2.1", + "chalk": "^3.0.0", + "jest-util": "^25.1.0", + "string-length": "^3.1.0" + } + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "string-length": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", + "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==", + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^5.2.0" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + } + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "@jest/environment": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-25.1.0.tgz", + "integrity": "sha512-cTpUtsjU4cum53VqBDlcW0E4KbQF03Cn0jckGPW/5rrE9tb+porD3+hhLtHAwhthsqfyF+bizyodTlsRA++sHg==", + "requires": { + "@jest/fake-timers": "^25.1.0", + "@jest/types": "^25.1.0", + "jest-mock": "^25.1.0" + }, + "dependencies": { + "@jest/console": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.1.0.tgz", + "integrity": "sha512-3P1DpqAMK/L07ag/Y9/Jup5iDEG9P4pRAuZiMQnU0JB3UOvCyYCjCoxr7sIA80SeyUCUKrr24fKAxVpmBgQonA==", + "requires": { + "@jest/source-map": "^25.1.0", + "chalk": "^3.0.0", + "jest-util": "^25.1.0", + "slash": "^3.0.0" + } + }, + "@jest/fake-timers": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-25.1.0.tgz", + "integrity": "sha512-Eu3dysBzSAO1lD7cylZd/CVKdZZ1/43SF35iYBNV1Lvvn2Undp3Grwsv8PrzvbLhqwRzDd4zxrY4gsiHc+wygQ==", + "requires": { + "@jest/types": "^25.1.0", + "jest-message-util": "^25.1.0", + "jest-mock": "^25.1.0", + "jest-util": "^25.1.0", + "lolex": "^5.0.0" + } + }, + "@jest/source-map": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.1.0.tgz", + "integrity": "sha512-ohf2iKT0xnLWcIUhL6U6QN+CwFWf9XnrM2a6ybL9NXxJjgYijjLSitkYHIdzkd8wFliH73qj/+epIpTiWjRtAA==", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.3", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.1.0.tgz", + "integrity": "sha512-FZzSo36h++U93vNWZ0KgvlNuZ9pnDnztvaM7P/UcTx87aPDotG18bXifkf1Ji44B7k/eIatmMzkBapnAzjkJkg==", + "requires": { + "@jest/console": "^25.1.0", + "@jest/transform": "^25.1.0", + "@jest/types": "^25.1.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "jest-message-util": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.1.0.tgz", + "integrity": "sha512-Nr/Iwar2COfN22aCqX0kCVbXgn8IBm9nWf4xwGr5Olv/KZh0CZ32RKgZWMVDXGdOahicM10/fgjdimGNX/ttCQ==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^25.1.0", + "@jest/types": "^25.1.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^3.0.0", + "micromatch": "^4.0.2", + "slash": "^3.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-mock": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.1.0.tgz", + "integrity": "sha512-28/u0sqS+42vIfcd1mlcg4ZVDmSUYuNvImP4X2lX5hRMLW+CN0BeiKVD4p+ujKKbSPKd3rg/zuhCF+QBLJ4vag==", + "requires": { + "@jest/types": "^25.1.0" + } + }, + "jest-util": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.1.0.tgz", + "integrity": "sha512-7did6pLQ++87Qsj26Fs/TIwZMUFBXQ+4XXSodRNy3luch2DnRXsSnmpVtxxQ0Yd6WTipGpbhh2IFP1mq6/fQGw==", + "requires": { + "@jest/types": "^25.1.0", + "chalk": "^3.0.0", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1" + } + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + } + } }, - "@gulp-sourcemaps/identity-map": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", - "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", "dev": true, "requires": { - "acorn": "^5.0.3", - "css": "^2.2.1", - "normalize-path": "^2.1.1", - "source-map": "^0.6.0", - "through2": "^2.0.3" + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" }, "dependencies": { - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } } } }, - "@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "dev": true, - "requires": { - "normalize-path": "^2.0.1", - "through2": "^2.0.3" - } - }, - "@hapi/address": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.0.0.tgz", - "integrity": "sha512-mV6T0IYqb0xL1UALPFplXYQmR0twnXG0M6jUswpquqT2sD12BOiCiLy3EvMp/Fy7s3DZElC4/aPjEjo2jeZpvw==", - "dev": true - }, - "@hapi/hoek": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-6.2.4.tgz", - "integrity": "sha512-HOJ20Kc93DkDVvjwHyHawPwPkX44sIrbXazAUDiUXaY2R9JwQGo2PhFfnQtdrsIe4igjG2fPgMra7NYw7qhy0A==", - "dev": true - }, - "@hapi/joi": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.0.3.tgz", - "integrity": "sha512-z6CesJ2YBwgVCi+ci8SI8zixoj8bGFn/vZb9MBPbSyoxsS2PnWYjHcyTM17VLK6tx64YVK38SDIh10hJypB+ig==", - "dev": true, - "requires": { - "@hapi/address": "2.x.x", - "@hapi/hoek": "6.x.x", - "@hapi/topo": "3.x.x" - } - }, - "@hapi/topo": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.0.tgz", - "integrity": "sha512-gZDI/eXOIk8kP2PkUKjWu9RW8GGVd2Hkgjxyr/S7Z+JF+0mr7bAlbw+DkTRxnD580o8Kqxlnba9wvqp5aOHBww==", - "dev": true, - "requires": { - "@hapi/hoek": "6.x.x" - } - }, - "@istanbuljs/load-nyc-config": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", - "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", + "@jest/reporters": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-25.1.0.tgz", + "integrity": "sha512-ORLT7hq2acJQa8N+NKfs68ZtHFnJPxsGqmofxW7v7urVhzJvpKZG9M7FAcgh9Ee1ZbCteMrirHA3m5JfBtAaDg==", "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^25.1.0", + "@jest/environment": "^25.1.0", + "@jest/test-result": "^25.1.0", + "@jest/transform": "^25.1.0", + "@jest/types": "^25.1.0", + "chalk": "^3.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.0", + "jest-haste-map": "^25.1.0", + "jest-resolve": "^25.1.0", + "jest-runtime": "^25.1.0", + "jest-util": "^25.1.0", + "jest-worker": "^25.1.0", + "node-notifier": "^6.0.0", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^3.1.0", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^4.0.1" }, "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/core": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.3.tgz", + "integrity": "sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helpers": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@babel/generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", + "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", "requires": { - "p-locate": "^4.1.0" + "@babel/types": "^7.8.3" } }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", "requires": { - "p-limit": "^2.2.0" + "@babel/types": "^7.8.3" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "@babel/helpers": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.3.tgz", + "integrity": "sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==", + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==" - }, - "@jest/console": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz", - "integrity": "sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg==", - "dev": true, - "requires": { - "@jest/source-map": "^24.3.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", "requires": { - "color-convert": "^1.9.0" + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, + "@babel/parser": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", + "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==" + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" } }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "@babel/traverse": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", + "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", "requires": { - "has-flag": "^3.0.0" + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" } - } - } - }, - "@jest/core": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-25.1.0.tgz", - "integrity": "sha512-iz05+NmwCmZRzMXvMo6KFipW7nzhbpEawrKrkkdJzgytavPse0biEnCNr2wRlyCsp3SmKaEY+SGv7YWYQnIdig==", - "requires": { - "@jest/console": "^25.1.0", - "@jest/reporters": "^25.1.0", - "@jest/test-result": "^25.1.0", - "@jest/transform": "^25.1.0", - "@jest/types": "^25.1.0", - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.3", - "jest-changed-files": "^25.1.0", - "jest-config": "^25.1.0", - "jest-haste-map": "^25.1.0", - "jest-message-util": "^25.1.0", - "jest-regex-util": "^25.1.0", - "jest-resolve": "^25.1.0", - "jest-resolve-dependencies": "^25.1.0", - "jest-runner": "^25.1.0", - "jest-runtime": "^25.1.0", - "jest-snapshot": "^25.1.0", - "jest-util": "^25.1.0", - "jest-validate": "^25.1.0", - "jest-watcher": "^25.1.0", - "micromatch": "^4.0.2", - "p-each-series": "^2.1.0", - "realpath-native": "^1.1.0", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, "@jest/console": { "version": "25.1.0", "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.1.0.tgz", @@ -1557,14 +4238,6 @@ "collect-v8-coverage": "^1.0.0" } }, - "ansi-escapes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", - "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", - "requires": { - "type-fest": "^0.8.1" - } - }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -1579,14 +4252,6 @@ "color-convert": "^2.0.1" } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1614,12 +4279,12 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "requires": { - "to-regex-range": "^5.0.1" + "safe-buffer": "~5.1.1" } }, "graceful-fs": { @@ -1632,24 +4297,23 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "jest-message-util": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.1.0.tgz", - "integrity": "sha512-Nr/Iwar2COfN22aCqX0kCVbXgn8IBm9nWf4xwGr5Olv/KZh0CZ32RKgZWMVDXGdOahicM10/fgjdimGNX/ttCQ==", + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==" + }, + "istanbul-lib-instrument": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.0.tgz", + "integrity": "sha512-Nm4wVHdo7ZXSG30KjZ2Wl5SU/Bw7bDx1PdaiIFzEStdjs0H12mOTncn1GVYuqQSaZxpg87VGBRsVRPGD2cD1AQ==", "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^25.1.0", - "@jest/types": "^25.1.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^3.0.0", - "micromatch": "^4.0.2", - "slash": "^3.0.0", - "stack-utils": "^1.0.1" + "@babel/core": "^7.7.5", + "@babel/parser": "^7.7.5", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" } }, "jest-resolve": { @@ -1675,28 +4339,24 @@ "mkdirp": "^0.5.1" } }, - "jest-watcher": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-25.1.0.tgz", - "integrity": "sha512-Q9eZ7pyaIr6xfU24OeTg4z1fUqBF/4MP6J801lyQfg7CsnZ/TCzAPvCfckKdL5dlBBEKBeHV0AdyjFZ5eWj4ig==", - "requires": { - "@jest/test-result": "^25.1.0", - "@jest/types": "^25.1.0", - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "jest-util": "^25.1.0", - "string-length": "^3.1.0" - } + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" + "minimist": "^1.2.0" } }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -1709,31 +4369,14 @@ "requires": { "astral-regex": "^1.0.0", "strip-ansi": "^5.2.0" - }, - "dependencies": { - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "requires": { - "ansi-regex": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - } + "ansi-regex": "^4.1.0" } }, "supports-color": { @@ -1743,25 +4386,61 @@ "requires": { "has-flag": "^4.0.0" } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + } + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, "requires": { - "is-number": "^7.0.0" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" } } } }, - "@jest/environment": { + "@jest/test-sequencer": { "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-25.1.0.tgz", - "integrity": "sha512-cTpUtsjU4cum53VqBDlcW0E4KbQF03Cn0jckGPW/5rrE9tb+porD3+hhLtHAwhthsqfyF+bizyodTlsRA++sHg==", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-25.1.0.tgz", + "integrity": "sha512-WgZLRgVr2b4l/7ED1J1RJQBOharxS11EFhmwDqknpknE0Pm87HLZVS2Asuuw+HQdfQvm2aXL2FvvBLxOD1D0iw==", "requires": { - "@jest/fake-timers": "^25.1.0", - "@jest/types": "^25.1.0", - "jest-mock": "^25.1.0" + "@jest/test-result": "^25.1.0", + "jest-haste-map": "^25.1.0", + "jest-runner": "^25.1.0", + "jest-runtime": "^25.1.0" }, "dependencies": { "@jest/console": { @@ -1775,18 +4454,6 @@ "slash": "^3.0.0" } }, - "@jest/fake-timers": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-25.1.0.tgz", - "integrity": "sha512-Eu3dysBzSAO1lD7cylZd/CVKdZZ1/43SF35iYBNV1Lvvn2Undp3Grwsv8PrzvbLhqwRzDd4zxrY4gsiHc+wygQ==", - "requires": { - "@jest/types": "^25.1.0", - "jest-message-util": "^25.1.0", - "jest-mock": "^25.1.0", - "jest-util": "^25.1.0", - "lolex": "^5.0.0" - } - }, "@jest/source-map": { "version": "25.1.0", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.1.0.tgz", @@ -1818,14 +4485,6 @@ "color-convert": "^2.0.1" } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1853,14 +4512,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", @@ -1871,34 +4522,6 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "jest-message-util": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.1.0.tgz", - "integrity": "sha512-Nr/Iwar2COfN22aCqX0kCVbXgn8IBm9nWf4xwGr5Olv/KZh0CZ32RKgZWMVDXGdOahicM10/fgjdimGNX/ttCQ==", - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^25.1.0", - "@jest/types": "^25.1.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^3.0.0", - "micromatch": "^4.0.2", - "slash": "^3.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.1.0.tgz", - "integrity": "sha512-28/u0sqS+42vIfcd1mlcg4ZVDmSUYuNvImP4X2lX5hRMLW+CN0BeiKVD4p+ujKKbSPKd3rg/zuhCF+QBLJ4vag==", - "requires": { - "@jest/types": "^25.1.0" - } - }, "jest-util": { "version": "25.1.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.1.0.tgz", @@ -1910,15 +4533,6 @@ "mkdirp": "^0.5.1" } }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -1931,81 +4545,30 @@ "requires": { "has-flag": "^4.0.0" } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "@jest/fake-timers": { - "version": "24.8.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.8.0.tgz", - "integrity": "sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw==", - "dev": true, - "requires": { - "@jest/types": "^24.8.0", - "jest-message-util": "^24.8.0", - "jest-mock": "^24.8.0" - }, - "dependencies": { - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } - }, - "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } } } }, - "@jest/reporters": { + "@jest/transform": { "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-25.1.0.tgz", - "integrity": "sha512-ORLT7hq2acJQa8N+NKfs68ZtHFnJPxsGqmofxW7v7urVhzJvpKZG9M7FAcgh9Ee1ZbCteMrirHA3m5JfBtAaDg==", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.1.0.tgz", + "integrity": "sha512-4ktrQ2TPREVeM+KxB4zskAT84SnmG1vaz4S+51aTefyqn3zocZUnliLLm5Fsl85I3p/kFPN4CRp1RElIfXGegQ==", "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^25.1.0", - "@jest/environment": "^25.1.0", - "@jest/test-result": "^25.1.0", - "@jest/transform": "^25.1.0", - "@jest/types": "^25.1.0", - "chalk": "^3.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.0", + "@babel/core": "^7.1.0", + "@jest/types": "^25.1.0", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^3.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.3", "jest-haste-map": "^25.1.0", - "jest-resolve": "^25.1.0", - "jest-runtime": "^25.1.0", + "jest-regex-util": "^25.1.0", "jest-util": "^25.1.0", - "jest-worker": "^25.1.0", - "node-notifier": "^6.0.0", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^3.1.0", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^4.0.1" + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" }, "dependencies": { "@babel/code-frame": { @@ -2016,40 +4579,6 @@ "@babel/highlight": "^7.8.3" } }, - "@babel/core": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.3.tgz", - "integrity": "sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==", - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helpers": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.0", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } - } - }, "@babel/generator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", @@ -2114,14 +4643,6 @@ "js-tokens": "^4.0.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -2131,32 +4652,6 @@ "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } } } }, @@ -2201,58 +4696,34 @@ "to-fast-properties": "^2.0.0" } }, - "@jest/console": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.1.0.tgz", - "integrity": "sha512-3P1DpqAMK/L07ag/Y9/Jup5iDEG9P4pRAuZiMQnU0JB3UOvCyYCjCoxr7sIA80SeyUCUKrr24fKAxVpmBgQonA==", - "requires": { - "@jest/source-map": "^25.1.0", - "chalk": "^3.0.0", - "jest-util": "^25.1.0", - "slash": "^3.0.0" - } - }, - "@jest/source-map": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.1.0.tgz", - "integrity": "sha512-ohf2iKT0xnLWcIUhL6U6QN+CwFWf9XnrM2a6ybL9NXxJjgYijjLSitkYHIdzkd8wFliH73qj/+epIpTiWjRtAA==", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.3", - "source-map": "^0.6.0" + "color-convert": "^1.9.0" } }, - "@jest/test-result": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.1.0.tgz", - "integrity": "sha512-FZzSo36h++U93vNWZ0KgvlNuZ9pnDnztvaM7P/UcTx87aPDotG18bXifkf1Ji44B7k/eIatmMzkBapnAzjkJkg==", + "babel-plugin-istanbul": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", + "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", "requires": { - "@jest/console": "^25.1.0", - "@jest/transform": "^25.1.0", - "@jest/types": "^25.1.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^4.0.0", + "test-exclude": "^6.0.0" } }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" + "fill-range": "^7.0.1" } }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" - }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -2260,14 +4731,38 @@ "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } } }, "color-name": { @@ -2275,12 +4770,12 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "requires": { - "safe-buffer": "~5.1.1" + "to-regex-range": "^5.0.1" } }, "graceful-fs": { @@ -2288,10 +4783,10 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "istanbul-lib-coverage": { "version": "3.0.0", @@ -2310,18 +4805,50 @@ "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.0.0", "semver": "^6.3.0" - } - }, - "jest-resolve": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.1.0.tgz", - "integrity": "sha512-XkBQaU1SRCHj2Evz2Lu4Czs+uIgJXWypfO57L7JYccmAXv4slXA6hzNblmcRmf7P3cQ1mE7fL3ABV6jAwk4foQ==", - "requires": { - "@jest/types": "^25.1.0", - "browser-resolve": "^1.11.3", - "chalk": "^3.0.0", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" + }, + "dependencies": { + "@babel/core": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.3.tgz", + "integrity": "sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helpers": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } } }, "jest-util": { @@ -2348,6 +4875,15 @@ "minimist": "^1.2.0" } }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -2358,127 +4894,62 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, - "string-length": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", - "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==", + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "requires": { - "astral-regex": "^1.0.0", - "strip-ansi": "^5.2.0" + "has-flag": "^3.0.0" } }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "requires": { - "ansi-regex": "^4.1.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" } }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/source-map": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.3.0.tgz", - "integrity": "sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - }, - "dependencies": { - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - } - } - }, - "@jest/test-result": { - "version": "24.8.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.8.0.tgz", - "integrity": "sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng==", - "dev": true, - "requires": { - "@jest/console": "^24.7.1", - "@jest/types": "^24.8.0", - "@types/istanbul-lib-coverage": "^2.0.0" - }, - "dependencies": { - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "is-number": "^7.0.0" } }, - "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", - "dev": true, + "write-file-atomic": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz", + "integrity": "sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw==", "requires": { - "@types/yargs-parser": "*" + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } } } }, - "@jest/test-sequencer": { + "@jest/types": { "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-25.1.0.tgz", - "integrity": "sha512-WgZLRgVr2b4l/7ED1J1RJQBOharxS11EFhmwDqknpknE0Pm87HLZVS2Asuuw+HQdfQvm2aXL2FvvBLxOD1D0iw==", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.1.0.tgz", + "integrity": "sha512-VpOtt7tCrgvamWZh1reVsGADujKigBUFTi19mlRjqEGsE8qH4r3s+skY33dNdXOwyZIvuftZ5tqdF1IgsMejMA==", "requires": { - "@jest/test-result": "^25.1.0", - "jest-haste-map": "^25.1.0", - "jest-runner": "^25.1.0", - "jest-runtime": "^25.1.0" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" }, "dependencies": { - "@jest/console": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.1.0.tgz", - "integrity": "sha512-3P1DpqAMK/L07ag/Y9/Jup5iDEG9P4pRAuZiMQnU0JB3UOvCyYCjCoxr7sIA80SeyUCUKrr24fKAxVpmBgQonA==", - "requires": { - "@jest/source-map": "^25.1.0", - "chalk": "^3.0.0", - "jest-util": "^25.1.0", - "slash": "^3.0.0" - } - }, - "@jest/source-map": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.1.0.tgz", - "integrity": "sha512-ohf2iKT0xnLWcIUhL6U6QN+CwFWf9XnrM2a6ybL9NXxJjgYijjLSitkYHIdzkd8wFliH73qj/+epIpTiWjRtAA==", - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.3", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.1.0.tgz", - "integrity": "sha512-FZzSo36h++U93vNWZ0KgvlNuZ9pnDnztvaM7P/UcTx87aPDotG18bXifkf1Ji44B7k/eIatmMzkBapnAzjkJkg==", + "@types/yargs": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.1.tgz", + "integrity": "sha512-sYlwNU7zYi6eZbMzFvG6eHD7VsEvFdoDtlD7eI1JTg7YNnuguzmiGsc6MPSq5l8n+h21AsNof0je+9sgOe4+dg==", "requires": { - "@jest/console": "^25.1.0", - "@jest/transform": "^25.1.0", - "@jest/types": "^25.1.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@types/yargs-parser": "*" } }, "ansi-styles": { @@ -2490,11 +4961,6 @@ "color-convert": "^2.0.1" } }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" - }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -2517,32 +4983,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "jest-util": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.1.0.tgz", - "integrity": "sha512-7did6pLQ++87Qsj26Fs/TIwZMUFBXQ+4XXSodRNy3luch2DnRXsSnmpVtxxQ0Yd6WTipGpbhh2IFP1mq6/fQGw==", - "requires": { - "@jest/types": "^25.1.0", - "chalk": "^3.0.0", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1" - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" - }, "supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", @@ -2553,59 +4998,185 @@ } } }, - "@jest/transform": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.1.0.tgz", - "integrity": "sha512-4ktrQ2TPREVeM+KxB4zskAT84SnmG1vaz4S+51aTefyqn3zocZUnliLLm5Fsl85I3p/kFPN4CRp1RElIfXGegQ==", + "@microsoft/load-themed-styles": { + "version": "1.10.36", + "resolved": "https://registry.npmjs.org/@microsoft/load-themed-styles/-/load-themed-styles-1.10.36.tgz", + "integrity": "sha512-xsBSgHhUbivT6cHqw5UP567fa+yJ1gM/L9CDnYftTmeruxpDUsLiK1sPrWeyMc+5VSaxcd+lsY10vqDVEptxoA==" + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "@sheerun/mutationobserver-shim": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz", + "integrity": "sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==" + }, + "@sinonjs/commons": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", + "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz", + "integrity": "sha512-j7KnilGyZzYr/jhcrSYS3FGWMZVaqyCG0vzMCwzvei0coIkczuYMcniK07nI0aHJINciujjH11T72ICW5eL5Ig==", + "dev": true + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-4.2.0.tgz", + "integrity": "sha512-3XHLtJ+HbRCH4n28S7y/yZoEQnRpl0tvTZQsHqvaeNXPra+6vE5tbRliH3ox1yZYPCxrlqaJT/Mg+75GpDKlvQ==", + "dev": true + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-4.2.0.tgz", + "integrity": "sha512-yTr2iLdf6oEuUE9MsRdvt0NmdpMBAkgK8Bjhl6epb+eQWk6abBaX3d65UZ3E3FWaOwePyUgNyNCMVG61gGCQ7w==", + "dev": true + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-4.2.0.tgz", + "integrity": "sha512-U9m870Kqm0ko8beHawRXLGLvSi/ZMrl89gJ5BNcT452fAjtF2p4uRzXkdzvGJJJYBgx7BmqlDjBN/eCp5AAX2w==", + "dev": true + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.3.3.tgz", + "integrity": "sha512-w3Be6xUNdwgParsvxkkeZb545VhXEwjGMwExMVBIdPQJeyMQHqm9Msnb2a1teHBqUYL66qtwfhNkbj1iarCG7w==", + "dev": true + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-4.2.0.tgz", + "integrity": "sha512-C0Uy+BHolCHGOZ8Dnr1zXy/KgpBOkEUYY9kI/HseHVPeMbluaX3CijJr7D4C5uR8zrc1T64nnq/k63ydQuGt4w==", + "dev": true + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-4.2.0.tgz", + "integrity": "sha512-7YvynOpZDpCOUoIVlaaOUU87J4Z6RdD6spYN4eUb5tfPoKGSF9OG2NuhgYnq4jSkAxcpMaXWPf1cePkzmqTPNw==", + "dev": true + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-4.2.0.tgz", + "integrity": "sha512-hYfYuZhQPCBVotABsXKSCfel2slf/yvJY8heTVX1PCTaq/IgASq1IyxPPKJ0chWREEKewIU/JMSsIGBtK1KKxw==", + "dev": true + }, + "@svgr/babel-preset": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-4.3.3.tgz", + "integrity": "sha512-6PG80tdz4eAlYUN3g5GZiUjg2FMcp+Wn6rtnz5WJG9ITGEF1pmFdzq02597Hn0OmnQuCVaBYQE1OVFAnwOl+0A==", + "dev": true, + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^4.2.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^4.2.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^4.2.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^4.2.0", + "@svgr/babel-plugin-svg-dynamic-title": "^4.3.3", + "@svgr/babel-plugin-svg-em-dimensions": "^4.2.0", + "@svgr/babel-plugin-transform-react-native-svg": "^4.2.0", + "@svgr/babel-plugin-transform-svg-component": "^4.2.0" + } + }, + "@svgr/core": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-4.3.3.tgz", + "integrity": "sha512-qNuGF1QON1626UCaZamWt5yedpgOytvLj5BQZe2j1k1B8DUG4OyugZyfEwBeXozCUwhLEpsrgPrE+eCu4fY17w==", + "dev": true, "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^25.1.0", - "babel-plugin-istanbul": "^6.0.0", - "chalk": "^3.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.3", - "jest-haste-map": "^25.1.0", - "jest-regex-util": "^25.1.0", - "jest-util": "^25.1.0", - "micromatch": "^4.0.2", - "pirates": "^4.0.1", - "realpath-native": "^1.1.0", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" + "@svgr/plugin-jsx": "^4.3.3", + "camelcase": "^5.3.1", + "cosmiconfig": "^5.2.1" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-4.3.2.tgz", + "integrity": "sha512-JioXclZGhFIDL3ddn4Kiq8qEqYM2PyDKV0aYno8+IXTLuYt6TOgHUbUAAFvqtb0Xn37NwP0BTHglejFoYr8RZg==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@svgr/plugin-jsx": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-4.3.3.tgz", + "integrity": "sha512-cLOCSpNWQnDB1/v+SUENHH7a0XY09bfuMKdq9+gYvtuwzC2rU4I0wKGFEp1i24holdQdwodCtDQdFtJiTCWc+w==", + "dev": true, + "requires": { + "@babel/core": "^7.4.5", + "@svgr/babel-preset": "^4.3.3", + "@svgr/hast-util-to-babel-ast": "^4.3.2", + "svg-parser": "^2.0.0" }, "dependencies": { "@babel/code-frame": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, "requires": { "@babel/highlight": "^7.8.3" } }, + "@babel/core": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", + "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helpers": "^7.8.4", + "@babel/parser": "^7.8.4", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, "requires": { "@babel/types": "^7.8.3", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } } }, "@babel/helper-function-name": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.8.3", "@babel/template": "^7.8.3", @@ -2616,6 +5187,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, "requires": { "@babel/types": "^7.8.3" } @@ -2624,17 +5196,19 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, "requires": { "@babel/types": "^7.8.3" } }, "@babel/helpers": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.3.tgz", - "integrity": "sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", + "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", + "dev": true, "requires": { "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", + "@babel/traverse": "^7.8.4", "@babel/types": "^7.8.3" } }, @@ -2642,33 +5216,24 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, "requires": { "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } } }, "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==" + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true }, "@babel/template": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, "requires": { "@babel/code-frame": "^7.8.3", "@babel/parser": "^7.8.3", @@ -2676,15 +5241,16 @@ } }, "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", + "@babel/generator": "^7.8.4", "@babel/helper-function-name": "^7.8.3", "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", + "@babel/parser": "^7.8.4", "@babel/types": "^7.8.3", "debug": "^4.1.0", "globals": "^11.1.0", @@ -2695,6 +5261,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, "requires": { "esutils": "^2.0.2", "lodash": "^4.17.13", @@ -2705,458 +5272,291 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } }, - "babel-plugin-istanbul": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", - "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^4.0.0", - "test-exclude": "^6.0.0" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==" - }, - "istanbul-lib-instrument": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.0.tgz", - "integrity": "sha512-Nm4wVHdo7ZXSG30KjZ2Wl5SU/Bw7bDx1PdaiIFzEStdjs0H12mOTncn1GVYuqQSaZxpg87VGBRsVRPGD2cD1AQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { - "@babel/core": "^7.7.5", - "@babel/parser": "^7.7.5", - "@babel/template": "^7.7.4", - "@babel/traverse": "^7.7.4", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "dependencies": { - "@babel/core": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.3.tgz", - "integrity": "sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==", - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helpers": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.0", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "jest-util": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.1.0.tgz", - "integrity": "sha512-7did6pLQ++87Qsj26Fs/TIwZMUFBXQ+4XXSodRNy3luch2DnRXsSnmpVtxxQ0Yd6WTipGpbhh2IFP1mq6/fQGw==", + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, "requires": { - "@jest/types": "^25.1.0", - "chalk": "^3.0.0", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1" + "safe-buffer": "~5.1.1" } }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true }, "json5": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, "requires": { "minimist": "^1.2.0" } }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } + } + } + }, + "@svgr/plugin-svgo": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-4.3.1.tgz", + "integrity": "sha512-PrMtEDUWjX3Ea65JsVCwTIXuSqa3CG9px+DluF1/eo9mlDrgrtFE7NE/DjdhjJgSM9wenlVBzkzneSIUgfUI/w==", + "dev": true, + "requires": { + "cosmiconfig": "^5.2.1", + "merge-deep": "^3.0.2", + "svgo": "^1.2.2" + } + }, + "@svgr/webpack": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-4.3.3.tgz", + "integrity": "sha512-bjnWolZ6KVsHhgyCoYRFmbd26p8XVbulCzSG53BDQqAr+JOAderYK7CuYrB3bDjHJuF6LJ7Wrr42+goLRV9qIg==", + "dev": true, + "requires": { + "@babel/core": "^7.4.5", + "@babel/plugin-transform-react-constant-elements": "^7.0.0", + "@babel/preset-env": "^7.4.5", + "@babel/preset-react": "^7.0.0", + "@svgr/core": "^4.3.3", + "@svgr/plugin-jsx": "^4.3.3", + "@svgr/plugin-svgo": "^4.3.1", + "loader-utils": "^1.2.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "@babel/core": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", + "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", + "dev": true, "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helpers": "^7.8.4", + "@babel/parser": "^7.8.4", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" } }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, "requires": { - "is-number": "^7.0.0" + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" } }, - "write-file-atomic": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz", - "integrity": "sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw==", + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" } - } - } - }, - "@jest/types": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.1.0.tgz", - "integrity": "sha512-VpOtt7tCrgvamWZh1reVsGADujKigBUFTi19mlRjqEGsE8qH4r3s+skY33dNdXOwyZIvuftZ5tqdF1IgsMejMA==", - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - }, - "dependencies": { - "@types/yargs": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.1.tgz", - "integrity": "sha512-sYlwNU7zYi6eZbMzFvG6eHD7VsEvFdoDtlD7eI1JTg7YNnuguzmiGsc6MPSq5l8n+h21AsNof0je+9sgOe4+dg==", + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, "requires": { - "@types/yargs-parser": "*" + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helpers": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", + "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" } }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" + "color-convert": "^1.9.0" } }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, "requires": { - "color-name": "~1.1.4" + "safe-buffer": "~5.1.1" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" } } } }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - } - }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true - }, - "@sheerun/mutationobserver-shim": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz", - "integrity": "sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==" - }, - "@sinonjs/commons": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", - "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", - "requires": { - "type-detect": "4.0.8" - } - }, - "@svgr/babel-plugin-add-jsx-attribute": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz", - "integrity": "sha512-j7KnilGyZzYr/jhcrSYS3FGWMZVaqyCG0vzMCwzvei0coIkczuYMcniK07nI0aHJINciujjH11T72ICW5eL5Ig==", - "dev": true - }, - "@svgr/babel-plugin-remove-jsx-attribute": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-4.2.0.tgz", - "integrity": "sha512-3XHLtJ+HbRCH4n28S7y/yZoEQnRpl0tvTZQsHqvaeNXPra+6vE5tbRliH3ox1yZYPCxrlqaJT/Mg+75GpDKlvQ==", - "dev": true - }, - "@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-4.2.0.tgz", - "integrity": "sha512-yTr2iLdf6oEuUE9MsRdvt0NmdpMBAkgK8Bjhl6epb+eQWk6abBaX3d65UZ3E3FWaOwePyUgNyNCMVG61gGCQ7w==", - "dev": true - }, - "@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-4.2.0.tgz", - "integrity": "sha512-U9m870Kqm0ko8beHawRXLGLvSi/ZMrl89gJ5BNcT452fAjtF2p4uRzXkdzvGJJJYBgx7BmqlDjBN/eCp5AAX2w==", - "dev": true - }, - "@svgr/babel-plugin-svg-dynamic-title": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.3.0.tgz", - "integrity": "sha512-3eI17Pb3jlg3oqV4Tie069n1SelYKBUpI90txDcnBWk4EGFW+YQGyQjy6iuJAReH0RnpUJ9jUExrt/xniGvhqw==", - "dev": true - }, - "@svgr/babel-plugin-svg-em-dimensions": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-4.2.0.tgz", - "integrity": "sha512-C0Uy+BHolCHGOZ8Dnr1zXy/KgpBOkEUYY9kI/HseHVPeMbluaX3CijJr7D4C5uR8zrc1T64nnq/k63ydQuGt4w==", - "dev": true - }, - "@svgr/babel-plugin-transform-react-native-svg": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-4.2.0.tgz", - "integrity": "sha512-7YvynOpZDpCOUoIVlaaOUU87J4Z6RdD6spYN4eUb5tfPoKGSF9OG2NuhgYnq4jSkAxcpMaXWPf1cePkzmqTPNw==", - "dev": true - }, - "@svgr/babel-plugin-transform-svg-component": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-4.2.0.tgz", - "integrity": "sha512-hYfYuZhQPCBVotABsXKSCfel2slf/yvJY8heTVX1PCTaq/IgASq1IyxPPKJ0chWREEKewIU/JMSsIGBtK1KKxw==", - "dev": true - }, - "@svgr/babel-preset": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-4.3.0.tgz", - "integrity": "sha512-Lgy1RJiZumGtv6yJroOxzFuL64kG/eIcivJQ7y9ljVWL+0QXvFz4ix1xMrmjMD+rpJWwj50ayCIcFelevG/XXg==", - "dev": true, - "requires": { - "@svgr/babel-plugin-add-jsx-attribute": "^4.2.0", - "@svgr/babel-plugin-remove-jsx-attribute": "^4.2.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "^4.2.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^4.2.0", - "@svgr/babel-plugin-svg-dynamic-title": "^4.3.0", - "@svgr/babel-plugin-svg-em-dimensions": "^4.2.0", - "@svgr/babel-plugin-transform-react-native-svg": "^4.2.0", - "@svgr/babel-plugin-transform-svg-component": "^4.2.0" - } - }, - "@svgr/core": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-4.3.0.tgz", - "integrity": "sha512-Ycu1qrF5opBgKXI0eQg3ROzupalCZnSDETKCK/3MKN4/9IEmt3jPX/bbBjftklnRW+qqsCEpO0y/X9BTRw2WBg==", - "dev": true, - "requires": { - "@svgr/plugin-jsx": "^4.3.0", - "camelcase": "^5.3.1", - "cosmiconfig": "^5.2.0" - } - }, - "@svgr/hast-util-to-babel-ast": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-4.2.0.tgz", - "integrity": "sha512-IvAeb7gqrGB5TH9EGyBsPrMRH/QCzIuAkLySKvH2TLfLb2uqk98qtJamordRQTpHH3e6TORfBXoTo7L7Opo/Ow==", - "dev": true, - "requires": { - "@babel/types": "^7.4.0" - } - }, - "@svgr/plugin-jsx": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-4.3.0.tgz", - "integrity": "sha512-0ab8zJdSOTqPfjZtl89cjq2IOmXXUYV3Fs7grLT9ur1Al3+x3DSp2+/obrYKUGbQUnLq96RMjSZ7Icd+13vwlQ==", - "dev": true, - "requires": { - "@babel/core": "^7.4.3", - "@svgr/babel-preset": "^4.3.0", - "@svgr/hast-util-to-babel-ast": "^4.2.0", - "rehype-parse": "^6.0.0", - "unified": "^7.1.0", - "vfile": "^4.0.0" - } - }, - "@svgr/plugin-svgo": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-4.2.0.tgz", - "integrity": "sha512-zUEKgkT172YzHh3mb2B2q92xCnOAMVjRx+o0waZ1U50XqKLrVQ/8dDqTAtnmapdLsGurv8PSwenjLCUpj6hcvw==", - "dev": true, - "requires": { - "cosmiconfig": "^5.2.0", - "merge-deep": "^3.0.2", - "svgo": "^1.2.1" - } - }, - "@svgr/webpack": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-4.1.0.tgz", - "integrity": "sha512-d09ehQWqLMywP/PT/5JvXwPskPK9QCXUjiSkAHehreB381qExXf5JFCBWhfEyNonRbkIneCeYM99w+Ud48YIQQ==", - "dev": true, - "requires": { - "@babel/core": "^7.1.6", - "@babel/plugin-transform-react-constant-elements": "^7.0.0", - "@babel/preset-env": "^7.1.6", - "@babel/preset-react": "^7.0.0", - "@svgr/core": "^4.1.0", - "@svgr/plugin-jsx": "^4.1.0", - "@svgr/plugin-svgo": "^4.0.3", - "loader-utils": "^1.1.0" - } - }, "@testing-library/dom": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-6.11.0.tgz", @@ -3295,6 +5695,12 @@ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", @@ -3356,6 +5762,12 @@ "jest-diff": "^24.3.0" } }, + "@types/json-schema": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -3375,10 +5787,16 @@ "@types/node": "*" } }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, "@types/prop-types": { - "version": "15.7.1", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", - "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==" + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "@types/q": { "version": "1.5.2", @@ -3387,9 +5805,9 @@ "dev": true }, "@types/react": { - "version": "16.8.18", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.18.tgz", - "integrity": "sha512-lUXdKzRqWR4FebR5tGHkLCqnvQJS4fdXKCBrNGGbglqZg2gpU+J82pMONevQODUotATs9fc9k66bx3/St8vReg==", + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.6.tgz", + "integrity": "sha512-bN9qDjEMltmHrl0PZRI4IF2AbB7V5UlRfG+OOduckVnRQ4VzXVSzy/1eLAh778IEqhTnW0mmgL9yShfinNverA==", "requires": { "@types/prop-types": "*", "csstype": "^2.2.0" @@ -3403,6 +5821,14 @@ "@types/react": "*" } }, + "@types/react-test-renderer": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.2.tgz", + "integrity": "sha512-4eJr1JFLIAlWhzDkBCkhrOIWOvOxcCAfQh+jiKg7l/nNZcCIL2MHl2dZhogIFKyHzedVWHaVP1Yydq/Ruu4agw==", + "requires": { + "@types/react": "*" + } + }, "@types/socket.io": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.2.tgz", @@ -3441,33 +5867,6 @@ "@types/testing-library__dom": "*" } }, - "@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", - "dev": true - }, - "@types/vfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", - "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/unist": "*", - "@types/vfile-message": "*" - } - }, - "@types/vfile-message": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz", - "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/unist": "*" - } - }, "@types/vscode": { "version": "1.36.0", "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.36.0.tgz", @@ -3475,10 +5874,13 @@ "dev": true }, "@types/yargs": { - "version": "12.0.12", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.12.tgz", - "integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==", - "dev": true + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } }, "@types/yargs-parser": { "version": "15.0.0", @@ -3486,43 +5888,208 @@ "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==" }, "@typescript-eslint/eslint-plugin": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.6.0.tgz", - "integrity": "sha512-U224c29E2lo861TQZs6GSmyC0OYeRNg6bE9UVIiFBxN2MlA0nq2dCrgIVyyRbC05UOcrgf2Wk/CF2gGOPQKUSQ==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.20.0.tgz", + "integrity": "sha512-cimIdVDV3MakiGJqMXw51Xci6oEDEoPkvh8ggJe2IIzcc0fYqAxOXN6Vbeanahz6dLZq64W+40iUEc9g32FLDQ==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "2.20.0", + "eslint-utils": "^1.4.3", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.20.0.tgz", + "integrity": "sha512-fEBy9xYrwG9hfBLFEwGW2lKwDRTmYzH3DwTmYbT+SMycmxAoPl0eGretnBFj/s+NfYBG63w/5c3lsvqqz5mYag==", "dev": true, "requires": { - "@typescript-eslint/parser": "1.6.0", - "@typescript-eslint/typescript-estree": "1.6.0", - "requireindex": "^1.2.0", - "tsutils": "^3.7.0" + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.20.0", + "eslint-scope": "^5.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } } }, "@typescript-eslint/parser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.6.0.tgz", - "integrity": "sha512-VB9xmSbfafI+/kI4gUK3PfrkGmrJQfh0N4EScT1gZXSZyUxpsBirPL99EWZg9MmPG0pzq/gMtgkk7/rAHj4aQw==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.20.0.tgz", + "integrity": "sha512-o8qsKaosLh2qhMZiHNtaHKTHyCHc3Triq6aMnwnWj7budm3xAY9owSZzV1uon5T9cWmJRJGzTFa90aex4m77Lw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "1.6.0", - "eslint-scope": "^4.0.0", - "eslint-visitor-keys": "^1.0.0" + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "2.20.0", + "@typescript-eslint/typescript-estree": "2.20.0", + "eslint-visitor-keys": "^1.1.0" } }, "@typescript-eslint/typescript-estree": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.6.0.tgz", - "integrity": "sha512-A4CanUwfaG4oXobD5y7EXbsOHjCwn8tj1RDd820etpPAjH+Icjc2K9e/DQM1Hac5zH2BSy+u6bjvvF2wwREvYA==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.20.0.tgz", + "integrity": "sha512-WlFk8QtI8pPaE7JGQGxU7nGcnk1ccKAJkhbVookv94ZcAef3m6oCE/jEDL6dGte3JcD7reKrA0o55XhBRiVT3A==", "dev": true, "requires": { - "lodash.unescape": "4.0.1", - "semver": "5.5.0" + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^6.3.0", + "tsutils": "^3.17.1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@uifabric/foundation": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@uifabric/foundation/-/foundation-7.5.3.tgz", + "integrity": "sha512-LCUETWPkTOjJ0LeP7/fyfpVt8MTzdb41LgV+n3rmKo809R1NjDyG62xX/f7DOLaEvJIO10f8h8I8vilYmUoCRg==", + "requires": { + "@uifabric/merge-styles": "^7.8.3", + "@uifabric/set-version": "^7.0.3", + "@uifabric/styling": "^7.10.2", + "@uifabric/utilities": "^7.11.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@uifabric/icons": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.3.2.tgz", + "integrity": "sha512-ZqlRBkFporJWHusvAzXI3ye99B/pKN/mGmHbMZtAPoGSFSge3ahv3GzQA8IvamrrHdf5j2OwCZR7db9BJvOOzA==", + "requires": { + "@uifabric/set-version": "^7.0.3", + "@uifabric/styling": "^7.10.2", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@uifabric/merge-styles": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.8.3.tgz", + "integrity": "sha512-mMLXIKmB7NH2ss6k7I4o7kE7Dy9+vcgubkxNVsgzBdV9vlDtnMDMc6/nZjOxgmBAr1UCRxCxERaKSB1oNFxtAg==", + "requires": { + "@uifabric/set-version": "^7.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@uifabric/react-hooks": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@uifabric/react-hooks/-/react-hooks-7.0.3.tgz", + "integrity": "sha512-ANkdK7ckRfljl4CKHDoW4H2DfTqRJ4QqTM7VD3IddcbZwBlvyhbRJO3sxnBigdBW5An7qdsJeZuOEoRjhm9e+Q==", + "requires": { + "@uifabric/set-version": "^7.0.3", + "@uifabric/utilities": "^7.11.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@uifabric/set-version": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.3.tgz", + "integrity": "sha512-03A68Fyfx3y75dUW9rjQ2fZv/9zmGgMeovVLAQa0wc/oVjQ++eVDlAEK0AjfgnOaujYmhk79lXbYAuW3n+YUXw==", + "requires": { + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@uifabric/styling": { + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.10.2.tgz", + "integrity": "sha512-a4BCtbm273s2997wZwBkOeWNm2lzUr6eVzE+CmShUVxXWAMPXI5ZZS6SZ4LpZkDkhdItLnNq+VODSJ7M/VM0aw==", + "requires": { + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/merge-styles": "^7.8.3", + "@uifabric/set-version": "^7.0.3", + "@uifabric/utilities": "^7.11.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@uifabric/utilities": { + "version": "7.11.3", + "resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.11.3.tgz", + "integrity": "sha512-y/2H65F41Q3DU4GQJFWj6x09qfjMYcwutHkU7sm2r0h82K01u5qeCPkPV9RqGGsJOrqllvsR5BoaRP77a1ot8A==", + "requires": { + "@uifabric/merge-styles": "^7.8.3", + "@uifabric/set-version": "^7.0.3", + "prop-types": "^15.5.10", + "tslib": "^1.10.0" }, "dependencies": { - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" } } }, @@ -3749,9 +6316,9 @@ } }, "acorn-jsx": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", - "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", "dev": true }, "acorn-walk": { @@ -3760,11 +6327,56 @@ "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==" }, "address": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz", - "integrity": "sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", + "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", "dev": true }, + "adjust-sourcemap-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-2.0.0.tgz", + "integrity": "sha512-4hFsTsn58+YjrU9qKzML2JSSDqKvN8mUGQ0nNIrfPi8hmIONT4L3uUaT6MKdMsZ9AjsU6D2xDkZxCkbQPxChrA==", + "dev": true, + "requires": { + "assert": "1.4.1", + "camelcase": "5.0.0", + "loader-utils": "1.2.3", + "object-path": "0.11.4", + "regex-parser": "2.2.10" + }, + "dependencies": { + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", @@ -3779,6 +6391,16 @@ "es6-promisify": "^5.0.0" } }, + "aggregate-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", + "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", @@ -3824,10 +6446,13 @@ } }, "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", + "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } }, "ansi-gray": { "version": "0.1.1", @@ -3926,6 +6551,12 @@ "commander": "^2.11.0" } }, + "arity-n": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz", + "integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=", + "dev": true + }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -3989,13 +6620,67 @@ "dev": true }, "array-includes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", - "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + } } }, "array-initial": { @@ -4090,6 +6775,69 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + } + } + }, "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", @@ -4174,10 +6922,13 @@ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" }, "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } }, "async-done": { "version": "1.3.2", @@ -4222,17 +6973,18 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "autoprefixer": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.5.1.tgz", - "integrity": "sha512-KJSzkStUl3wP0D5sdMlP82Q52JLy5+atf2MHAre48+ckWkXgixmfHyWmA77wFDy6jTHU6mIgXv6hAQ2mf1PjJQ==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.4.tgz", + "integrity": "sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g==", "dev": true, "requires": { - "browserslist": "^4.5.4", - "caniuse-lite": "^1.0.30000957", + "browserslist": "^4.8.3", + "caniuse-lite": "^1.0.30001020", + "chalk": "^2.4.2", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^7.0.14", - "postcss-value-parser": "^3.3.1" + "postcss": "^7.0.26", + "postcss-value-parser": "^4.0.2" }, "dependencies": { "ansi-styles": { @@ -4253,12 +7005,23 @@ "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + } + }, + "postcss": { + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" }, "dependencies": { "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4266,21 +7029,16 @@ } } }, - "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } + "postcss-value-parser": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", + "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", + "dev": true }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4299,13 +7057,10 @@ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "axobject-query": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", - "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", - "dev": true, - "requires": { - "ast-types-flow": "0.0.7" - } + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.1.2.tgz", + "integrity": "sha512-ICt34ZmrVt8UQnvPl6TVyDTkmhXmAyAT4Jh5ugfGUX4MOrZ+U/ZY6/sdylRw3qGNr9Ub5AJsaHeDMzNLehRdOQ==", + "dev": true }, "azure-devops-node-api": { "version": "7.2.0", @@ -4339,27 +7094,26 @@ } }, "babel-eslint": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.1.tgz", - "integrity": "sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz", + "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "@babel/parser": "^7.0.0", "@babel/traverse": "^7.0.0", "@babel/types": "^7.0.0", - "eslint-scope": "3.7.1", - "eslint-visitor-keys": "^1.0.0" + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" }, "dependencies": { - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "path-parse": "^1.0.6" } } } @@ -4850,32 +7604,41 @@ } }, "babel-loader": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.5.tgz", - "integrity": "sha512-NTnHnVRd2JnRqPC0vW+iOQWU5pchDbYXsG2E6DMXEpMfUcQKclF9gmf3G3ZMhzG7IG9ji4coL0cm+FxeWxDpnw==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", + "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", "dev": true, "requires": { "find-cache-dir": "^2.0.0", "loader-utils": "^1.0.2", "mkdirp": "^0.5.1", - "util.promisify": "^1.0.0" + "pify": "^4.0.1" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } } }, "babel-plugin-dynamic-import-node": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.2.0.tgz", - "integrity": "sha512-fP899ELUnTaBcIzmrW7nniyqqdYWrWuJUyPWHxFa/c7r7hS6KC8FscNfLlBNIoPSc55kYMGEEKjPjJGCLbE1qA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", "dev": true, "requires": { "object.assign": "^4.1.0" } }, "babel-plugin-istanbul": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.4.tgz", - "integrity": "sha512-dySz4VJMH+dpndj0wjJ8JPs/7i1TdSPb1nRrn56/92pKOF9VKC1FMFJmMXjzlGGusnCAqujP6PBCiKq0sVA+YQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", "dev": true, "requires": { + "@babel/helper-plugin-utils": "^7.0.0", "find-up": "^3.0.0", "istanbul-lib-instrument": "^3.3.0", "test-exclude": "^5.2.3" @@ -4890,20 +7653,78 @@ } }, "babel-plugin-macros": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.5.1.tgz", - "integrity": "sha512-xN3KhAxPzsJ6OQTktCanNpIFnnMsCV+t8OloKxIL72D6+SUZYFn9qfklPgef5HyyDtzYZqqb+fs1S12+gQY82Q==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", "dev": true, "requires": { - "@babel/runtime": "^7.4.2", - "cosmiconfig": "^5.2.0", - "resolve": "^1.10.0" + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } } }, "babel-plugin-named-asset-import": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.2.tgz", - "integrity": "sha512-CxwvxrZ9OirpXQ201Ec57OmGhmI8/ui/GwTDy0hSp6CmRvgRC0pSair6Z04Ck+JStA0sMPZzSJ3uE4n17EXpPQ==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.6.tgz", + "integrity": "sha512-1aGDUfL1qOOIoqk9QKGIo2lANk+C7ko/fqH0uIyC71x3PEGz0uVP8ISgfEsFuG+FKmjHTvFK/nNM8dowpmUxLA==", "dev": true }, "babel-plugin-syntax-object-rest-spread": { @@ -4939,130 +7760,223 @@ } }, "babel-preset-react-app": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-9.0.0.tgz", - "integrity": "sha512-YVsDA8HpAKklhFLJtl9+AgaxrDaor8gGvDFlsg1ByOS0IPGUovumdv4/gJiAnLcDmZmKlH6+9sVOz4NVW7emAg==", - "dev": true, - "requires": { - "@babel/core": "7.4.3", - "@babel/plugin-proposal-class-properties": "7.4.0", - "@babel/plugin-proposal-decorators": "7.4.0", - "@babel/plugin-proposal-object-rest-spread": "7.4.3", - "@babel/plugin-syntax-dynamic-import": "7.2.0", - "@babel/plugin-transform-classes": "7.4.3", - "@babel/plugin-transform-destructuring": "7.4.3", - "@babel/plugin-transform-flow-strip-types": "7.4.0", - "@babel/plugin-transform-react-constant-elements": "7.2.0", - "@babel/plugin-transform-react-display-name": "7.2.0", - "@babel/plugin-transform-runtime": "7.4.3", - "@babel/preset-env": "7.4.3", - "@babel/preset-react": "7.0.0", - "@babel/preset-typescript": "7.3.3", - "@babel/runtime": "7.4.3", - "babel-plugin-dynamic-import-node": "2.2.0", - "babel-plugin-macros": "2.5.1", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-9.1.1.tgz", + "integrity": "sha512-YkWP2UwY//TLltNlEBRngDOrYhvSLb+CA330G7T9M5UhGEMWe+JK/8IXJc5p2fDTSfSiETf+PY0+PYXFMix81Q==", + "dev": true, + "requires": { + "@babel/core": "7.8.4", + "@babel/plugin-proposal-class-properties": "7.8.3", + "@babel/plugin-proposal-decorators": "7.8.3", + "@babel/plugin-proposal-numeric-separator": "7.8.3", + "@babel/plugin-transform-flow-strip-types": "7.8.3", + "@babel/plugin-transform-react-display-name": "7.8.3", + "@babel/plugin-transform-runtime": "7.8.3", + "@babel/preset-env": "7.8.4", + "@babel/preset-react": "7.8.3", + "@babel/preset-typescript": "7.8.3", + "@babel/runtime": "7.8.4", + "babel-plugin-macros": "2.8.0", "babel-plugin-transform-react-remove-prop-types": "0.4.24" }, "dependencies": { - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.3.tgz", - "integrity": "sha512-xC//6DNSSHVjq8O2ge0dyYlhshsH4T7XdCVoxbi5HzLYWfsC5ooFlJjrXk8RcAT+hjHAK9UjBXdylzSoDK3t4g==", + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/core": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", + "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helpers": "^7.8.4", + "@babel/parser": "^7.8.4", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + "@babel/types": "^7.8.3" } }, - "@babel/plugin-transform-classes": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.3.tgz", - "integrity": "sha512-PUaIKyFUDtG6jF5DUJOfkBdwAS/kFFV3XFk7Nn0a6vR7ZT8jYw5cGtIlat77wcnd0C6ViGqo/wyNf4ZHytF/nQ==", + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.4.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.0", - "@babel/helper-split-export-declaration": "^7.4.0", - "globals": "^11.1.0" + "@babel/types": "^7.8.3" } }, - "@babel/plugin-transform-destructuring": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.3.tgz", - "integrity": "sha512-rVTLLZpydDFDyN4qnXdzwoVpk1oaXHIvPEOkOLyr88o7oHxVc/LyrnDx+amuBWGOwUb7D1s/uLsKBNTx08htZg==", + "@babel/helpers": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", + "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3" } }, - "@babel/preset-env": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.3.tgz", - "integrity": "sha512-FYbZdV12yHdJU5Z70cEg0f6lvtpZ8jFSDakTm7WXeJbLXh4R0ztGEu/SW7G1nJ2ZvKwDhz8YrbA84eYyprmGqw==", + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.4.3", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.0", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.4.0", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.4.0", - "@babel/plugin-transform-classes": "^7.4.3", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.4.3", - "@babel/plugin-transform-dotall-regex": "^7.4.3", - "@babel/plugin-transform-duplicate-keys": "^7.2.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.3", - "@babel/plugin-transform-function-name": "^7.4.3", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.4.3", - "@babel/plugin-transform-modules-systemjs": "^7.4.0", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.2", - "@babel/plugin-transform-new-target": "^7.4.0", - "@babel/plugin-transform-object-super": "^7.2.0", - "@babel/plugin-transform-parameters": "^7.4.3", - "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.3", - "@babel/plugin-transform-reserved-words": "^7.2.0", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.2.0", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.2.0", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.3", - "@babel/types": "^7.4.0", - "browserslist": "^4.5.2", - "core-js-compat": "^3.0.0", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.5.0" - } - }, - "@babel/preset-typescript": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.3.3.tgz", - "integrity": "sha512-mzMVuIP4lqtn4du2ynEfdO0+RYcslwrZiJHXu4MGaC1ctJiW2fyaeDrtjJGs7R/KebZ1sgowcIoWf4uRpEfKEg==", + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.3.2" + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" } } } @@ -5078,9 +7992,9 @@ }, "dependencies": { "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", "dev": true }, "regenerator-runtime": { @@ -5119,12 +8033,6 @@ "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" }, - "bail": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.4.tgz", - "integrity": "sha512-S8vuDB4w6YpRhICUDET3guPlQpaJl7od94tpZ0Fvnyp+MKW/HyDTcRDck+29C9g+d/qQHnddRH3+94kZdrW0Ww==", - "dev": true - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -5469,14 +8377,14 @@ } }, "browserslist": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.1.tgz", - "integrity": "sha512-1MC18ooMPRG2UuVFJTHFIAkk6mpByJfxCrnUyvSlu/hyQSFHMrlhM02SzNuCV+quTP4CKmqtOMAIjrifrpBJXQ==", + "version": "4.8.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.7.tgz", + "integrity": "sha512-gFOnZNYBHrEyUML0xr5NJ6edFaaKbTFX9S9kQHlYfCP0Rit/boRIz4G+Avq6/4haEKJXdGGUnoolx+5MWW2BoA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000971", - "electron-to-chromium": "^1.3.137", - "node-releases": "^1.1.21" + "caniuse-lite": "^1.0.30001027", + "electron-to-chromium": "^1.3.349", + "node-releases": "^1.1.49" } }, "bs-logger": { @@ -5554,27 +8462,52 @@ "dev": true }, "cacache": { - "version": "11.3.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", - "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", + "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", "dev": true, "requires": { - "bluebird": "^3.5.3", - "chownr": "^1.1.1", + "chownr": "^1.1.2", "figgy-pudding": "^3.5.1", - "glob": "^7.1.3", - "graceful-fs": "^4.1.15", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "infer-owner": "^1.0.4", "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", + "minipass": "^3.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" + "rimraf": "^2.7.1", + "ssri": "^7.0.0", + "unique-filename": "^1.1.1" }, "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -5583,6 +8516,16 @@ "requires": { "glob": "^7.1.3" } + }, + "ssri": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz", + "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "minipass": "^3.1.1" + } } } }, @@ -5638,13 +8581,21 @@ "dev": true }, "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz", + "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==", "dev": true, "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" + "pascal-case": "^3.1.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz", + "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==", + "dev": true + } } }, "camelcase": { @@ -5665,9 +8616,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000971", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000971.tgz", - "integrity": "sha512-TQFYFhRS0O5rdsmSbF1Wn+16latXYsQJat66f7S7lizXW1PVpWJeZw9wqqVLIjuxDRz7s7xRUj13QCfd8hKn6g==", + "version": "1.0.30001028", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001028.tgz", + "integrity": "sha512-Vnrq+XMSHpT7E+LWoIYhs3Sne8h9lx9YJV3acH3THNCwU/9zV93/ta4xVfzTtnqd3rvnuVpVjE3DFqf56tr3aQ==", "dev": true }, "capture-exit": { @@ -5679,9 +8630,9 @@ } }, "case-sensitive-paths-webpack-plugin": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.2.0.tgz", - "integrity": "sha512-u5ElzokS8A1pm9vM3/iDgTcI3xqHxuCao94Oz8etI3cf0Tio0p8izkDYbTIn09uP3yUUr6+veaE6IkjnTYS46g==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.3.0.tgz", + "integrity": "sha512-/4YgnZS8y1UXXmC02xD5rRrBEu6T5ub+mQHLNRj0fzTRbgdBYhsNo2V5EqwgqrExjxsjtF/OpAKAMkKsxbD5XQ==", "dev": true }, "caseless": { @@ -5689,12 +8640,6 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, - "ccount": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.4.tgz", - "integrity": "sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w==", - "dev": true - }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -5840,21 +8785,27 @@ } }, "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", "dev": true, "requires": { "source-map": "~0.6.0" } }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "restore-cursor": "^3.1.0" } }, "cli-width": { @@ -6023,9 +8974,9 @@ } }, "color": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.1.tgz", - "integrity": "sha512-PvUltIXRjehRKPSy89VnDWFKY58xyhTLyxIg21vwQBI6qLwZNPmC8k3C1uytIgFKEpOIzN4y32iPm8231zFHIg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", + "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", "dev": true, "requires": { "color-convert": "^1.9.1", @@ -6069,12 +9020,6 @@ "delayed-stream": "~1.0.0" } }, - "comma-separated-tokens": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.7.tgz", - "integrity": "sha512-Jrx3xsP4pPv4AwJUDWY9wOXGtwPXARej6Xd99h4TUGotmf8APuquKMpK+dnD3UgyxK7OEWaisjZz+3b5jtL6xQ==", - "dev": true - }, "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", @@ -6111,13 +9056,30 @@ "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" }, + "compose-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz", + "integrity": "sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=", + "dev": true, + "requires": { + "arity-n": "^1.0.4" + } + }, "compressible": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", - "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, "requires": { - "mime-db": ">= 1.40.0 < 2" + "mime-db": ">= 1.43.0 < 2" + }, + "dependencies": { + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "dev": true + } } }, "compression": { @@ -6170,9 +9132,9 @@ } }, "confusing-browser-globals": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.7.tgz", - "integrity": "sha512-cgHI1azax5ATrZ8rJ+ODDML9Fvu67PimB6aNxBrc/QwSaDaM9eTfIEUHx3bBLJJ82ioSb+/5zfsMCCEJax3ByQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", + "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", "dev": true }, "connect-history-api-fallback": { @@ -6278,36 +9240,29 @@ } }, "core-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", - "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", "dev": true }, "core-js-compat": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.3.tgz", - "integrity": "sha512-EP018pVhgwsKHz3YoN1hTq49aRe+h017Kjz0NQz3nXV0cCRMvH3fLQl+vEPGr4r4J5sk4sU3tUC7U1aqTCeJeA==", + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz", + "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==", "dev": true, "requires": { - "browserslist": "^4.6.0", - "core-js-pure": "3.1.3", - "semver": "^6.1.0" + "browserslist": "^4.8.3", + "semver": "7.0.0" }, "dependencies": { "semver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", - "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", "dev": true } } }, - "core-js-pure": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.1.3.tgz", - "integrity": "sha512-k3JWTrcQBKqjkjI0bkfXS0lbpWPxYuHWfMMjC1VDmzU4Q58IwSbuXSo99YO/hUHlw/EB4AlfA2PVxOGkrIq6dA==", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -6445,9 +9400,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -6514,9 +9469,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -6583,9 +9538,9 @@ "dev": true }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -6727,9 +9682,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -6749,15 +9704,23 @@ } }, "css-select": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz", - "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", "dev": true, "requires": { "boolbase": "^1.0.0", - "css-what": "^2.1.2", + "css-what": "^3.2.1", "domutils": "^1.7.0", "nth-check": "^1.0.2" + }, + "dependencies": { + "css-what": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", + "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==", + "dev": true + } } }, "css-select-base-adapter": { @@ -6777,35 +9740,15 @@ } }, "css-tree": { - "version": "1.0.0-alpha.28", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz", - "integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==", + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", "dev": true, "requires": { - "mdn-data": "~1.1.0", - "source-map": "^0.5.3" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "mdn-data": "2.0.4", + "source-map": "^0.6.1" } }, - "css-unit-converter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", - "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=", - "dev": true - }, - "css-url-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz", - "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=", - "dev": true - }, "css-what": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", @@ -6872,9 +9815,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -6963,9 +9906,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -7037,9 +9980,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -7065,51 +10008,33 @@ "dev": true }, "csso": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz", - "integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.2.tgz", + "integrity": "sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg==", "dev": true, "requires": { - "css-tree": "1.0.0-alpha.29" - }, - "dependencies": { - "css-tree": { - "version": "1.0.0-alpha.29", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz", - "integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==", - "dev": true, - "requires": { - "mdn-data": "~1.1.0", - "source-map": "^0.5.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "css-tree": "1.0.0-alpha.37" } }, "cssom": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", - "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, "cssstyle": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.2.tgz", - "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", "dev": true, "requires": { "cssom": "0.3.x" } }, "csstype": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.5.tgz", - "integrity": "sha512-JsTaiksRsel5n7XwqPAfB0l3TFKdpjW/kgAELf9vrb5adGA7UCPLajKK5s3nFrcFm3Rkyp/Qkgl73ENc1UY3cA==" + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.8.tgz", + "integrity": "sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA==" }, "cyclist": { "version": "0.2.2", @@ -7128,9 +10053,9 @@ } }, "damerau-levenshtein": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz", - "integrity": "sha512-CBCRqFnpu715iPmw1KrdOrzRqbdFwQTwAWyyyYS42+iAgHCuXZ+/TdMgQkUENPomxEz9z1BEzuQU2Xw0kUuAgA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", + "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", "dev": true }, "dashdash": { @@ -7210,10 +10135,18 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } }, "deep-is": { "version": "0.1.3", @@ -7571,25 +10504,43 @@ "domelementtype": "1" } }, + "dot-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.3.tgz", + "integrity": "sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA==", + "dev": true, + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz", + "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==", + "dev": true + } + } + }, "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", + "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", "dev": true, "requires": { - "is-obj": "^1.0.0" + "is-obj": "^2.0.0" } }, "dotenv": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", - "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", "dev": true }, "dotenv-expand": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.2.0.tgz", - "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "dev": true }, "duplexer": { @@ -7636,9 +10587,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.137", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.137.tgz", - "integrity": "sha512-kGi32g42a8vS/WnYE7ELJyejRT7hbr3UeOOu0WeuYuQ29gCpg9Lrf6RdcTQVXSt/v0bjCfnlb/EWOOsiKpTmkw==", + "version": "1.3.355", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.355.tgz", + "integrity": "sha512-zKO/wS+2ChI/jz9WAo647xSW8t2RmgRLFdbUb/77cORkUTargO+SCj4ctTHjBn2VeNFrsLgDT7IuDVrd3F8mLQ==", "dev": true }, "elliptic": { @@ -7927,53 +10878,54 @@ } }, "eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", + "ajv": "^6.10.0", "chalk": "^2.1.0", "cross-spawn": "^6.0.5", "debug": "^4.0.1", "doctrine": "^3.0.0", - "eslint-scope": "^4.0.3", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.17.11", + "lodash": "^4.17.14", "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", + "optionator": "^0.8.3", "progress": "^2.0.0", "regexpp": "^2.0.1", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", "table": "^5.2.3", - "text-table": "^0.2.0" + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { @@ -7996,31 +10948,91 @@ "supports-color": "^5.3.0" } }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", + "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, "import-fresh": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", - "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" } }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -8033,22 +11045,22 @@ } }, "eslint-config-react-app": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-4.0.1.tgz", - "integrity": "sha512-ZsaoXUIGsK8FCi/x4lT2bZR5mMkL/Kgj+Lnw690rbvvUr/uiwgFiD8FcfAhkCycm7Xte6O5lYz4EqMx2vX7jgw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-5.2.0.tgz", + "integrity": "sha512-WrHjoGpKr1kLLiWDD81tme9jMM0hk5cMxasLSdyno6DdPt+IfLOrDJBVo6jN7tn4y1nzhs43TmUaZWO6Sf0blw==", "dev": true, "requires": { - "confusing-browser-globals": "^1.0.7" + "confusing-browser-globals": "^1.0.9" } }, "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", + "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", "dev": true, "requires": { "debug": "^2.6.9", - "resolve": "^1.5.0" + "resolve": "^1.13.1" }, "dependencies": { "debug": { @@ -8065,40 +11077,74 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, "eslint-loader": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.1.2.tgz", - "integrity": "sha512-rA9XiXEOilLYPOIInvVH5S/hYfyTPyxag6DZhoQOduM+3TkghAEQ3VcFO8VnX4J4qg/UIBzp72aOf/xvYmpmsg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-3.0.3.tgz", + "integrity": "sha512-+YRqB95PnNvxNp1HEjQmvf9KNvCin5HXYYseOXVC2U0KEcw4IkQ2IQEBG46j7+gW39bMzeu0GsUhVbBY3Votpw==", "dev": true, "requires": { - "loader-fs-cache": "^1.0.0", - "loader-utils": "^1.0.2", - "object-assign": "^4.0.1", - "object-hash": "^1.1.4", - "rimraf": "^2.6.1" + "fs-extra": "^8.1.0", + "loader-fs-cache": "^1.0.2", + "loader-utils": "^1.2.3", + "object-hash": "^2.0.1", + "schema-utils": "^2.6.1" }, "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", "dev": true, "requires": { - "glob": "^7.1.3" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "schema-utils": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.4.tgz", + "integrity": "sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" } } } }, "eslint-module-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz", - "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", + "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", "dev": true, "requires": { - "debug": "^2.6.8", + "debug": "^2.6.9", "pkg-dir": "^2.0.0" }, "dependencies": { @@ -8172,30 +11218,32 @@ } }, "eslint-plugin-flowtype": { - "version": "2.50.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.50.1.tgz", - "integrity": "sha512-9kRxF9hfM/O6WGZcZPszOVPd2W0TLHBtceulLTsGfwMPtiCCLnCW0ssRiOOiXyqrCA20pm1iXdXm7gQeN306zQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-4.6.0.tgz", + "integrity": "sha512-W5hLjpFfZyZsXfo5anlu7HM970JBDqbEshAJUkeczP6BFCIfJXuiIBQXyberLRtOStT0OGPF8efeTbxlHk4LpQ==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.15" } }, "eslint-plugin-import": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", - "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.0.tgz", + "integrity": "sha512-NK42oA0mUc8Ngn4kONOPsPB1XhbUvNHqF+g307dPV28aknPoiNnKLFd9em4nkswwepdF5ouieqv5Th/63U7YJQ==", "dev": true, "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.3.0", + "eslint-module-utils": "^2.4.1", "has": "^1.0.3", - "lodash": "^4.17.11", "minimatch": "^3.0.4", + "object.values": "^1.1.0", "read-pkg-up": "^2.0.0", - "resolve": "^1.9.0" + "resolve": "^1.12.0" }, "dependencies": { "debug": { @@ -8322,15 +11370,25 @@ "find-up": "^2.0.0", "read-pkg": "^2.0.0" } + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, "eslint-plugin-jsx-a11y": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.1.tgz", - "integrity": "sha512-cjN2ObWrRz0TTw7vEcGQrx+YltMvZoOEx4hWU8eEERDnBIU00OTq7Vr+jA7DFKxiwLNv4tTh5Pq2GUNEa8b6+w==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.3.tgz", + "integrity": "sha512-CawzfGt9w83tyuVekn0GDPU9ytYtxyxyFZ3aSWROmnRRFQFT2BiPJd7jvRdzNDi6oLWaS2asMeYSNMjWTV4eNg==", "dev": true, "requires": { + "@babel/runtime": "^7.4.5", "aria-query": "^3.0.0", "array-includes": "^3.0.3", "ast-types-flow": "^0.0.7", @@ -8338,22 +11396,24 @@ "damerau-levenshtein": "^1.0.4", "emoji-regex": "^7.0.2", "has": "^1.0.3", - "jsx-ast-utils": "^2.0.1" + "jsx-ast-utils": "^2.2.1" } }, "eslint-plugin-react": { - "version": "7.12.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz", - "integrity": "sha512-1puHJkXJY+oS1t467MjbqjvX53uQ05HXwjqDgdbGBqf5j9eeydI54G3KwiJmWciQ0HTBacIKw2jgwSBSH3yfgQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.18.0.tgz", + "integrity": "sha512-p+PGoGeV4SaZRDsXqdj9OWcOrOpZn8gXoGPcIQTzo2IDMbAKhNDnME9myZWqO3Ic4R3YmwAZ1lDjWl2R2hMUVQ==", "dev": true, "requires": { - "array-includes": "^3.0.3", + "array-includes": "^3.1.1", "doctrine": "^2.1.0", "has": "^1.0.3", - "jsx-ast-utils": "^2.0.1", - "object.fromentries": "^2.0.0", - "prop-types": "^15.6.2", - "resolve": "^1.9.0" + "jsx-ast-utils": "^2.2.3", + "object.entries": "^1.1.1", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.14.2" }, "dependencies": { "doctrine": { @@ -8364,13 +11424,85 @@ "requires": { "esutils": "^2.0.2" } + }, + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "object.entries": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, "eslint-plugin-react-hooks": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.6.0.tgz", - "integrity": "sha512-lHBVRIaz5ibnIgNG07JNiAuBUeKhEf8l4etNx5vfAEwqQ5tcuK3jV9yjmopPgQDagQb7HwIuQVsE3IVcGrRnag==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz", + "integrity": "sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA==", "dev": true }, "eslint-scope": { @@ -8390,31 +11522,31 @@ "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true - } } }, "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", "dev": true }, "espree": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", "dev": true, "requires": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + } } }, "esprima": { @@ -8423,9 +11555,9 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz", + "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==", "dev": true, "requires": { "estraverse": "^4.0.0" @@ -8487,9 +11619,9 @@ "integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI=" }, "eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", + "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", "dev": true }, "events": { @@ -8911,9 +12043,9 @@ } }, "external-editor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", - "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, "requires": { "chardet": "^0.7.0", @@ -9037,9 +12169,9 @@ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==" }, "faye-websocket": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", - "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { "websocket-driver": ">=0.5.1" @@ -9069,9 +12201,9 @@ "dev": true }, "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" @@ -9087,13 +12219,49 @@ } }, "file-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", - "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.3.0.tgz", + "integrity": "sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA==", "dev": true, "requires": { - "loader-utils": "^1.0.2", - "schema-utils": "^1.0.0" + "loader-utils": "^1.2.3", + "schema-utils": "^2.5.0" + }, + "dependencies": { + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "schema-utils": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.4.tgz", + "integrity": "sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } + } } }, "file-uri-to-path": { @@ -9104,9 +12272,9 @@ "optional": true }, "filesize": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", - "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.0.1.tgz", + "integrity": "sha512-u4AYWPgbI5GBhs6id1KdImZWn5yfyFrrQ8OWZdN7ZMfA8Bf4HcO0BGo9bmUIEV8yrp8I1xVfJ/dn90GtFNNJcg==", "dev": true }, "fill-range": { @@ -9256,15 +12424,15 @@ } }, "flatted": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", "dev": true }, "flush-write-stream": { @@ -9278,12 +12446,12 @@ } }, "follow-redirects": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", - "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.10.0.tgz", + "integrity": "sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ==", "dev": true, "requires": { - "debug": "^3.2.6" + "debug": "^3.0.0" }, "dependencies": { "debug": { @@ -9317,14 +12485,14 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "fork-ts-checker-webpack-plugin": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.1.1.tgz", - "integrity": "sha512-gqWAEMLlae/oeVnN6RWCAhesOJMswAN1MaKNqhhjXHV5O0/rTUjWI4UbgQHdlrVbCnb+xLotXmJbBlC66QmpFw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-3.1.1.tgz", + "integrity": "sha512-DuVkPNrM12jR41KM2e+N+styka0EgLkTnXmNcXdgOM37vtGeY+oCBK/Jx0hzSeEU6memFCtWb4htrHPMDfwwUQ==", "dev": true, "requires": { "babel-code-frame": "^6.22.0", "chalk": "^2.4.1", - "chokidar": "^2.0.4", + "chokidar": "^3.3.0", "micromatch": "^3.1.10", "minimatch": "^3.0.4", "semver": "^5.6.0", @@ -9341,6 +12509,31 @@ "color-convert": "^1.9.0" } }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -9352,13 +12545,93 @@ "supports-color": "^5.3.0" } }, + "chokidar": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", + "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.3.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "readdirp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", + "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.7" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^3.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" } } } @@ -9410,14 +12683,31 @@ } }, "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", + "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + } + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" } }, "fs-mkdirp-stream": { @@ -10049,9 +13339,9 @@ "dev": true }, "get-own-enumerable-property-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", - "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", "dev": true }, "get-stream": { @@ -10187,9 +13477,9 @@ }, "dependencies": { "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true } } @@ -10602,13 +13892,21 @@ } }, "gzip-size": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.0.0.tgz", - "integrity": "sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", + "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", "dev": true, "requires": { "duplexer": "^0.1.1", - "pify": "^3.0.0" + "pify": "^4.0.1" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } } }, "handle-thing": { @@ -10737,37 +14035,6 @@ "minimalistic-assert": "^1.0.1" } }, - "hast-util-from-parse5": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.1.tgz", - "integrity": "sha512-UfPzdl6fbxGAxqGYNThRUhRlDYY7sXu6XU9nQeX4fFZtV+IHbyEJtd+DUuwOqNV4z3K05E/1rIkoVr/JHmeWWA==", - "dev": true, - "requires": { - "ccount": "^1.0.3", - "hastscript": "^5.0.0", - "property-information": "^5.0.0", - "web-namespaces": "^1.1.2", - "xtend": "^4.0.1" - } - }, - "hast-util-parse-selector": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.2.tgz", - "integrity": "sha512-jIMtnzrLTjzqgVEQqPEmwEZV+ea4zHRFTP8Z2Utw0I5HuBOXHzUPPQWr6ouJdJqDKLbFU/OEiYwZ79LalZkmmw==", - "dev": true - }, - "hastscript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.0.1.tgz", - "integrity": "sha512-i9nc9NRtVIKlvVfVJ/Tnonk5PXO3BOqaqwfxHw53CWZEETpLCFIjvu0jej/DzT/xlXFOVDpB7KRUFpUrgU8Tow==", - "dev": true, - "requires": { - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.2.0", - "property-information": "^5.0.1", - "space-separated-tokens": "^1.0.0" - } - }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -10863,40 +14130,40 @@ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==" }, - "html-minifier": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", - "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "html-minifier-terser": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.0.4.tgz", + "integrity": "sha512-fHwmKQ+GzhlqdxEtwrqLT7MSuheiA+rif5/dZgbz3GjoMXJzcRzy1L9NXoiiyxrnap+q5guSiv8Tz5lrh9g42g==", "dev": true, "requires": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" }, "dependencies": { "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true } } }, "html-webpack-plugin": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.5.tgz", - "integrity": "sha512-y5l4lGxOW3pz3xBTFdfB9rnnrWRPVxlAhX6nrBYIcW+2k2zC3mSp/3DxlWVCMBfnO6UAnoF8OcFn0IMy6kaKAQ==", + "version": "4.0.0-beta.11", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz", + "integrity": "sha512-4Xzepf0qWxf8CGg7/WQM5qBB2Lc/NFI7MhU59eUDTkuQp3skZczH4UA1d6oQyDEIoMDgERVhRyTdtUPZ5s5HBg==", "dev": true, "requires": { - "html-minifier": "^3.5.20", - "loader-utils": "^1.1.0", - "lodash": "^4.17.11", + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.15", "pretty-error": "^2.1.1", - "tapable": "^1.1.0", + "tapable": "^1.1.3", "util.promisify": "1.0.0" } }, @@ -10947,18 +14214,18 @@ } }, "http-parser-js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", - "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", + "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", "dev": true }, "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", + "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", "dev": true, "requires": { - "eventemitter3": "^3.0.0", + "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } @@ -11019,9 +14286,9 @@ "dev": true }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "requires": { "agent-base": "^4.3.0", @@ -11163,6 +14430,12 @@ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -11184,30 +14457,30 @@ "dev": true }, "inquirer": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", - "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz", + "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==", "dev": true, "requires": { - "ansi-escapes": "^3.2.0", + "ansi-escapes": "^4.2.1", "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", + "cli-cursor": "^3.1.0", "cli-width": "^2.0.0", "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.11", - "mute-stream": "0.0.7", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", "strip-ansi": "^5.1.0", "through": "^2.3.6" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { @@ -11230,6 +14503,46 @@ "supports-color": "^5.3.0" } }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -11237,6 +14550,14 @@ "dev": true, "requires": { "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } } }, "supports-color": { @@ -11438,6 +14759,12 @@ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" }, + "is-docker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", + "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", + "dev": true + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -11489,9 +14816,9 @@ } }, "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true }, "is-path-cwd": { @@ -11568,9 +14895,9 @@ "dev": true }, "is-root": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.0.0.tgz", - "integrity": "sha512-F/pJIk8QD6OX5DNhRB7hWamLsUilmkDGho48KbgZ6xg/lmAZXHxzXQ91jzB3yRSw5kdQGGGc4yz8HYhTYIMWPg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", "dev": true }, "is-stream": { @@ -11578,6 +14905,12 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, "is-svg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", @@ -11673,9 +15006,9 @@ }, "dependencies": { "semver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", - "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -12631,16 +15964,139 @@ } }, "jest-environment-jsdom-fourteen": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom-fourteen/-/jest-environment-jsdom-fourteen-0.1.0.tgz", - "integrity": "sha512-4vtoRMg7jAstitRzL4nbw83VmGH8Rs13wrND3Ud2o1fczDhMUF32iIrNKwYGgeOPUdfvZU4oy8Bbv+ni1fgVCA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom-fourteen/-/jest-environment-jsdom-fourteen-1.0.1.tgz", + "integrity": "sha512-DojMX1sY+at5Ep+O9yME34CdidZnO3/zfPh8UW+918C5fIZET5vCjfkegixmsi7AtdYfkr4bPlIzmWnlvQkP7Q==", "dev": true, "requires": { - "jest-mock": "^24.5.0", - "jest-util": "^24.5.0", - "jsdom": "^14.0.0" + "@jest/environment": "^24.3.0", + "@jest/fake-timers": "^24.3.0", + "@jest/types": "^24.3.0", + "jest-mock": "^24.0.0", + "jest-util": "^24.0.0", + "jsdom": "^14.1.0" }, "dependencies": { + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true + }, + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "jsdom": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-14.1.0.tgz", @@ -12675,6 +16131,15 @@ "xml-name-validator": "^3.0.0" } }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", @@ -12682,18 +16147,7 @@ "dev": true, "requires": { "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "whatwg-url": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", - "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + "punycode": "^2.1.1" } }, "ws": { @@ -13374,14 +16828,14 @@ } }, "jest-message-util": { - "version": "24.8.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.8.0.tgz", - "integrity": "sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.8.0", - "@jest/types": "^24.8.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", "@types/stack-utils": "^1.0.1", "chalk": "^2.0.1", "micromatch": "^3.1.10", @@ -13400,15 +16854,6 @@ "@types/yargs": "^13.0.0" } }, - "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -13441,12 +16886,12 @@ } }, "jest-mock": { - "version": "24.8.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.8.0.tgz", - "integrity": "sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", "dev": true, "requires": { - "@jest/types": "^24.8.0" + "@jest/types": "^24.9.0" }, "dependencies": { "@jest/types": { @@ -13459,15 +16904,6 @@ "@types/istanbul-reports": "^1.1.1", "@types/yargs": "^13.0.0" } - }, - "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } } } }, @@ -13482,12 +16918,12 @@ "integrity": "sha512-9lShaDmDpqwg+xAd73zHydKrBbbrIi08Kk9YryBEBybQFg/lBWR/2BDjjiSE7KIppM9C5+c03XiDaZ+m4Pgs1w==" }, "jest-resolve": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.7.1.tgz", - "integrity": "sha512-Bgrc+/UUZpGJ4323sQyj85hV9d+ANyPNu6XfRDUcyFNX1QrZpSoM0kE4Mb2vZMAYTJZsBFzYe8X1UaOkOELSbw==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", "dev": true, "requires": { - "@jest/types": "^24.7.0", + "@jest/types": "^24.9.0", "browser-resolve": "^1.11.3", "chalk": "^2.0.1", "jest-pnp-resolver": "^1.2.1", @@ -13505,15 +16941,6 @@ "@types/yargs": "^13.0.0" } }, - "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -14368,16 +17795,16 @@ } }, "jest-util": { - "version": "24.8.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.8.0.tgz", - "integrity": "sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", "dev": true, "requires": { - "@jest/console": "^24.7.1", - "@jest/fake-timers": "^24.8.0", - "@jest/source-map": "^24.3.0", - "@jest/test-result": "^24.8.0", - "@jest/types": "^24.8.0", + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", "callsites": "^3.0.0", "chalk": "^2.0.1", "graceful-fs": "^4.1.15", @@ -14398,15 +17825,6 @@ "@types/yargs": "^13.0.0" } }, - "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -14530,16 +17948,17 @@ } }, "jest-watch-typeahead": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-0.3.0.tgz", - "integrity": "sha512-+uOtlppt9ysST6k6ZTqsPI0WNz2HLa8bowiZylZoQCQaAVn7XsVmHhZREkz73FhKelrFrpne4hQQjdq42nFEmA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-0.4.2.tgz", + "integrity": "sha512-f7VpLebTdaXs81rg/oj4Vg/ObZy2QtGzAmGLNsqUS5G5KtSN68tFcIsbvNODfNyQxU78g7D8x77o3bgfBTR+2Q==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", + "ansi-escapes": "^4.2.1", "chalk": "^2.4.1", + "jest-regex-util": "^24.9.0", "jest-watcher": "^24.3.0", - "slash": "^2.0.0", - "string-length": "^2.0.0", + "slash": "^3.0.0", + "string-length": "^3.1.0", "strip-ansi": "^5.0.0" }, "dependencies": { @@ -14569,6 +17988,28 @@ "supports-color": "^5.3.0" } }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "string-length": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", + "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^5.2.0" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -14590,17 +18031,17 @@ } }, "jest-watcher": { - "version": "24.8.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.8.0.tgz", - "integrity": "sha512-SBjwHt5NedQoVu54M5GEx7cl7IGEFFznvd/HNT8ier7cCAx/Qgu9ZMlaTQkvK22G1YOpcWBLQPFSImmxdn3DAw==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", + "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", "dev": true, "requires": { - "@jest/test-result": "^24.8.0", - "@jest/types": "^24.8.0", - "@types/yargs": "^12.0.9", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", "ansi-escapes": "^3.0.0", "chalk": "^2.0.1", - "jest-util": "^24.8.0", + "jest-util": "^24.9.0", "string-length": "^2.0.0" }, "dependencies": { @@ -14613,19 +18054,14 @@ "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^1.1.1", "@types/yargs": "^13.0.0" - }, - "dependencies": { - "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - } } }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -14681,12 +18117,6 @@ } } }, - "js-levenshtein": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", - "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", - "dev": true - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -14863,12 +18293,13 @@ } }, "jsx-ast-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.1.0.tgz", - "integrity": "sha512-yDGDG2DS4JcqhA6blsuYbtsT09xL8AoLuUR2Gb5exrw7UEM19sBcOTq+YBBhrNbl0PUC4R4LnFu+dHg2HKeVvA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz", + "integrity": "sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==", "dev": true, "requires": { - "array-includes": "^3.0.3" + "array-includes": "^3.0.3", + "object.assign": "^4.1.0" } }, "just-debounce": { @@ -14995,6 +18426,15 @@ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", + "dev": true, + "requires": { + "leven": "^3.1.0" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -15034,6 +18474,12 @@ } } }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, "linkify-it": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.1.0.tgz", @@ -15159,12 +18605,6 @@ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, - "lodash.tail": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", - "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", - "dev": true - }, "lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -15176,20 +18616,14 @@ } }, "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", "dev": true, "requires": { - "lodash._reinterpolate": "~3.0.0" + "lodash._reinterpolate": "^3.0.0" } }, - "lodash.unescape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", - "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", - "dev": true - }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -15237,9 +18671,9 @@ } }, "loglevel": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", - "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.7.tgz", + "integrity": "sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A==", "dev": true }, "lolex": { @@ -15259,10 +18693,21 @@ } }, "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.1.tgz", + "integrity": "sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==", + "dev": true, + "requires": { + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz", + "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==", + "dev": true + } + } }, "lru-cache": { "version": "5.1.1", @@ -15401,9 +18846,9 @@ } }, "mdn-data": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz", - "integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", "dev": true }, "mdurl": { @@ -15492,9 +18937,9 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "merge2": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", - "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", + "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", "dev": true }, "methods": { @@ -15566,9 +19011,9 @@ } }, "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "min-indent": { @@ -15577,12 +19022,13 @@ "integrity": "sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY=" }, "mini-css-extract-plugin": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz", - "integrity": "sha512-IuaLjruM0vMKhUUT51fQdQzBYTX49dLj8w68ALEAe2A4iYNpIC4eMac67mt3NzycvjOlf07/kYxJDc0RTl1Wqw==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", + "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==", "dev": true, "requires": { "loader-utils": "^1.1.0", + "normalize-url": "1.9.1", "schema-utils": "^1.0.0", "webpack-sources": "^1.1.0" } @@ -15612,6 +19058,50 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, + "minipass": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.1.tgz", + "integrity": "sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.2.tgz", + "integrity": "sha512-3JS5A2DKhD2g0Gg8x3yamO0pj7YeKGwVlDS90pF++kxptwx/F+B//roxf9SqYil5tQo65bijy+dAuAFZmYOouA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", @@ -15944,12 +19434,21 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.3.tgz", + "integrity": "sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw==", "dev": true, "requires": { - "lower-case": "^1.1.1" + "lower-case": "^2.0.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz", + "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==", + "dev": true + } } }, "node-environment-flags": { @@ -15963,9 +19462,9 @@ } }, "node-forge": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", - "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", + "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==", "dev": true }, "node-int64": { @@ -16054,12 +19553,20 @@ } }, "node-releases": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.21.tgz", - "integrity": "sha512-TwnURTCjc8a+ElJUjmDqU6+12jhli1Q61xOQmdZ7ECZVBZuQpN/1UnembiIHDM1wCcfLvh5wrWXUF5H6ufX64Q==", + "version": "1.1.49", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.49.tgz", + "integrity": "sha512-xH8t0LS0disN0mtRCh+eByxFPie+msJUBL/lJDBuap53QGiYPa9joh83K4pCZgWJ+2L4b9h88vCVdXQ60NO2bg==", "dev": true, "requires": { - "semver": "^5.3.0" + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "normalize-package-data": { @@ -16089,10 +19596,16 @@ "dev": true }, "normalize-url": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", - "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", - "dev": true + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } }, "now-and-later": { "version": "2.0.1", @@ -16181,9 +19694,9 @@ "dev": true }, "nwsapi": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", - "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, "oauth-sign": { @@ -16222,9 +19735,21 @@ } }, "object-hash": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", - "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz", + "integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==", + "dev": true + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", + "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==", "dev": true }, "object-keys": { @@ -16232,6 +19757,12 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, + "object-path": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", + "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=", + "dev": true + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -16287,15 +19818,68 @@ } }, "object.fromentries": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz", - "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.11.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", - "has": "^1.0.1" + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + } } }, "object.getownpropertydescriptors": { @@ -16358,15 +19942,68 @@ } }, "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + } } }, "obuf": { @@ -16375,6 +20012,30 @@ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, + "office-ui-fabric-react": { + "version": "7.85.0", + "resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.85.0.tgz", + "integrity": "sha512-lWE300YX1GM8r3CHDVL+tT9tfr6XeOL6lMaO8uhoTWyepR+ot2pKlMrPYLyhhuytqEB5qRgmG/RCvvB/09jn0Q==", + "requires": { + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/foundation": "^7.5.3", + "@uifabric/icons": "^7.3.2", + "@uifabric/merge-styles": "^7.8.3", + "@uifabric/react-hooks": "^7.0.3", + "@uifabric/set-version": "^7.0.3", + "@uifabric/styling": "^7.10.2", + "@uifabric/utilities": "^7.11.3", + "prop-types": "^15.5.10", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, "on-error-resume-next": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/on-error-resume-next/-/on-error-resume-next-1.1.0.tgz", @@ -16405,12 +20066,12 @@ } }, "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "^2.1.0" } }, "open": { @@ -16421,13 +20082,22 @@ "is-wsl": "^1.1.0" } }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, "optimize-css-assets-webpack-plugin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.1.tgz", - "integrity": "sha512-Rqm6sSjWtx9FchdP0uzTQDc7GXDKnwVEGoSxjezPkzMewx7gEWE9IMUYKmigTRC4U3RaNSwYVnUDLuIdtTpm0A==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz", + "integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==", "dev": true, "requires": { - "cssnano": "^4.1.0", + "cssnano": "^4.1.10", "last-call-webpack-plugin": "^3.0.0" } }, @@ -16557,6 +20227,15 @@ "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", "dev": true }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -16580,12 +20259,21 @@ } }, "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.3.tgz", + "integrity": "sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA==", "dev": true, "requires": { - "no-case": "^2.2.0" + "dot-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz", + "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==", + "dev": true + } } }, "parent-module": { @@ -16687,6 +20375,24 @@ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, + "pascal-case": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.1.tgz", + "integrity": "sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA==", + "dev": true, + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz", + "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==", + "dev": true + } + } + }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -16844,57 +20550,12 @@ } }, "pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", "dev": true, "requires": { - "find-up": "^2.1.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - } + "find-up": "^3.0.0" } }, "plugin-error": { @@ -16955,39 +20616,33 @@ "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" }, "pnp-webpack-plugin": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.2.1.tgz", - "integrity": "sha512-W6GctK7K2qQiVR+gYSv/Gyt6jwwIH4vwdviFqx+Y2jAtVf5eZyYIDf5Ac2NCDMBiX5yWscBLZElPTsyA1UtVVA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.0.tgz", + "integrity": "sha512-ZcMGn/xF/fCOq+9kWMP9vVVxjIkMCja72oy3lziR7UHy0hHFZ57iVpQ71OtveVbmzeCmphBg8pxNdk/hlK99aQ==", "dev": true, "requires": { - "ts-pnp": "^1.0.0" + "ts-pnp": "^1.1.2" } }, "portfinder": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz", - "integrity": "sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==", + "version": "1.0.25", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", + "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==", "dev": true, "requires": { - "async": "^1.5.2", - "debug": "^2.2.0", - "mkdirp": "0.5.x" + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.1" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, @@ -17035,13 +20690,13 @@ } }, "postcss-attribute-case-insensitive": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.1.tgz", - "integrity": "sha512-L2YKB3vF4PetdTIthQVeT+7YiSzMoNMLLYxPXXppOOP7NoazEAy45sh2LvJ8leCQjfBcfkYQs8TtCcQjeZTp8A==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", + "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", "dev": true, "requires": { "postcss": "^7.0.2", - "postcss-selector-parser": "^5.0.0" + "postcss-selector-parser": "^6.0.2" }, "dependencies": { "ansi-styles": { @@ -17075,16 +20730,10 @@ } } }, - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", - "dev": true - }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17092,17 +20741,6 @@ "supports-color": "^6.1.0" } }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "dev": true, - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, "supports-color": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", @@ -17115,12 +20753,12 @@ } }, "postcss-browser-comments": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-2.0.0.tgz", - "integrity": "sha512-xGG0UvoxwBc4Yx4JX3gc0RuDl1kc4bVihCzzk6UC72YPfq5fu3c717Nu8Un3nvnq1BJ31gBnFXIG/OaUTnpHgA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-3.0.0.tgz", + "integrity": "sha512-qfVjLfq7HFd2e0HW4s1dvU8X080OZdG46fFbIBFjW7US7YPDcWfRvdElvwMJr2LI6hMmD+7LnH2HcmXTs+uOig==", "dev": true, "requires": { - "postcss": "^7.0.2" + "postcss": "^7" }, "dependencies": { "ansi-styles": { @@ -17155,9 +20793,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17177,15 +20815,14 @@ } }, "postcss-calc": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz", - "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz", + "integrity": "sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ==", "dev": true, "requires": { - "css-unit-converter": "^1.1.1", - "postcss": "^7.0.5", - "postcss-selector-parser": "^5.0.0-rc.4", - "postcss-value-parser": "^3.3.1" + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" }, "dependencies": { "ansi-styles": { @@ -17219,16 +20856,10 @@ } } }, - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", - "dev": true - }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17236,16 +20867,11 @@ "supports-color": "^6.1.0" } }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "dev": true, - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } + "postcss-value-parser": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", + "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", + "dev": true }, "supports-color": { "version": "6.1.0", @@ -17300,9 +20926,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17364,9 +20990,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17427,9 +21053,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17491,9 +21117,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17554,9 +21180,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17620,9 +21246,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17683,9 +21309,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17745,9 +21371,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17767,12 +21393,12 @@ } }, "postcss-custom-properties": { - "version": "8.0.10", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.10.tgz", - "integrity": "sha512-GDL0dyd7++goDR4SSasYdRNNvp4Gqy1XMzcCnTijiph7VB27XXpJ8bW/AI0i2VSBZ55TpdGhMr37kMSpRfYD0Q==", + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", + "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", "dev": true, "requires": { - "postcss": "^7.0.14", + "postcss": "^7.0.17", "postcss-values-parser": "^2.0.1" }, "dependencies": { @@ -17808,9 +21434,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17877,9 +21503,9 @@ "dev": true }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17957,9 +21583,9 @@ "dev": true }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18030,9 +21656,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18092,9 +21718,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18154,9 +21780,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18216,9 +21842,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18279,9 +21905,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18342,9 +21968,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18404,9 +22030,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18466,9 +22092,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18528,9 +22154,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18590,9 +22216,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18652,9 +22278,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18715,9 +22341,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18737,12 +22363,12 @@ } }, "postcss-initial": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.0.tgz", - "integrity": "sha512-WzrqZ5nG9R9fUtrA+we92R4jhVvEB32IIRTzfIG/PLL8UV4CvbF1ugTEHEFX6vWxl41Xt5RTCJPEZkuWzrOM+Q==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz", + "integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==", "dev": true, "requires": { - "lodash.template": "^4.2.4", + "lodash.template": "^4.5.0", "postcss": "^7.0.2" }, "dependencies": { @@ -18778,9 +22404,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18842,9 +22468,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18929,9 +22555,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -18991,9 +22617,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19053,9 +22679,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19118,9 +22744,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19185,9 +22811,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19196,12 +22822,12 @@ } }, "postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", "dev": true, "requires": { - "dot-prop": "^4.1.1", + "dot-prop": "^5.2.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } @@ -19259,9 +22885,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19324,9 +22950,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19391,9 +23017,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19456,9 +23082,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19467,12 +23093,12 @@ } }, "postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", "dev": true, "requires": { - "dot-prop": "^4.1.1", + "dot-prop": "^5.2.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } @@ -19585,9 +23211,9 @@ } }, "postcss-nesting": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.0.tgz", - "integrity": "sha512-WSsbVd5Ampi3Y0nk/SKr5+K34n52PqMqEfswu6RtU4r7wA8vSD+gM8/D9qq4aJkHImwn1+9iEFTbjoWsQeqtaQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", + "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", "dev": true, "requires": { "postcss": "^7.0.2" @@ -19625,9 +23251,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19647,15 +23273,16 @@ } }, "postcss-normalize": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-7.0.1.tgz", - "integrity": "sha512-NOp1fwrG+6kVXWo7P9SizCHX6QvioxFD/hZcI2MLxPmVnFJFC0j0DDpIuNw2tUDeCFMni59gCVgeJ1/hYhj2OQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-8.0.1.tgz", + "integrity": "sha512-rt9JMS/m9FHIRroDDBGSMsyW1c0fkvOJPy62ggxSHUldJO7B195TqFMqIf+lY5ezpDcYOV4j86aUp3/XbxzCCQ==", "dev": true, "requires": { - "@csstools/normalize.css": "^9.0.1", - "browserslist": "^4.1.1", - "postcss": "^7.0.2", - "postcss-browser-comments": "^2.0.0" + "@csstools/normalize.css": "^10.1.0", + "browserslist": "^4.6.2", + "postcss": "^7.0.17", + "postcss-browser-comments": "^3.0.0", + "sanitize.css": "^10.0.0" }, "dependencies": { "ansi-styles": { @@ -19690,9 +23317,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19752,9 +23379,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19816,9 +23443,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19881,9 +23508,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -19946,9 +23573,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20010,9 +23637,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20074,9 +23701,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20138,9 +23765,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20202,10 +23829,16 @@ } } }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20266,9 +23899,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20330,9 +23963,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20392,9 +24025,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20454,9 +24087,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20517,9 +24150,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20539,27 +24172,27 @@ } }, "postcss-preset-env": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.6.0.tgz", - "integrity": "sha512-I3zAiycfqXpPIFD6HXhLfWXIewAWO8emOKz+QSsxaUZb9Dp8HbF5kUf+4Wy/AxR33o+LRoO8blEWCHth0ZsCLA==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz", + "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", "dev": true, "requires": { - "autoprefixer": "^9.4.9", - "browserslist": "^4.4.2", - "caniuse-lite": "^1.0.30000939", + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", "css-blank-pseudo": "^0.1.4", "css-has-pseudo": "^0.10.0", "css-prefers-color-scheme": "^3.1.1", - "cssdb": "^4.3.0", - "postcss": "^7.0.14", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", "postcss-attribute-case-insensitive": "^4.0.1", "postcss-color-functional-notation": "^2.0.1", "postcss-color-gray": "^5.0.0", - "postcss-color-hex-alpha": "^5.0.2", + "postcss-color-hex-alpha": "^5.0.3", "postcss-color-mod-function": "^3.0.3", "postcss-color-rebeccapurple": "^4.0.1", - "postcss-custom-media": "^7.0.7", - "postcss-custom-properties": "^8.0.9", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", "postcss-custom-selectors": "^5.1.2", "postcss-dir-pseudo-class": "^5.0.0", "postcss-double-position-gradients": "^1.0.0", @@ -20615,9 +24248,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20684,9 +24317,9 @@ "dev": true }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20760,9 +24393,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20825,9 +24458,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20887,9 +24520,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20949,9 +24582,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -21012,9 +24645,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -21075,9 +24708,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -21159,9 +24792,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -21223,9 +24856,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -21266,6 +24899,12 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, "prettier": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", @@ -21273,9 +24912,9 @@ "dev": true }, "pretty-bytes": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.2.0.tgz", - "integrity": "sha512-ujANBhiUsl9AhREUDUEY1GPOharMGm8x8juS7qOHybcLi7XsKfrYQ88hSly1l2i0klXHTDYrlL8ihMCG55Dc3w==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz", + "integrity": "sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==", "dev": true }, "pretty-error": { @@ -21397,15 +25036,6 @@ "react-is": "^16.8.1" } }, - "property-information": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.1.0.tgz", - "integrity": "sha512-tODH6R3+SwTkAQckSp2S9xyYX8dEKYkeXw+4TmJzTxnNzd6mQPu1OD4f9zPrvw/Rm4wpPgI+Zp63mNSGNzUgHg==", - "dev": true, - "requires": { - "xtend": "^4.0.1" - } - }, "proxy-addr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", @@ -21422,12 +25052,6 @@ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, "psl": { "version": "1.1.32", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", @@ -21495,6 +25119,16 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -21568,78 +25202,102 @@ } }, "react": { - "version": "16.8.6", - "resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz", - "integrity": "sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==", + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz", + "integrity": "sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.13.6" + "prop-types": "^15.6.2" } }, "react-app-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-1.0.1.tgz", - "integrity": "sha512-LbVpT1NdzTdDDs7xEZdebjDrqsvKi5UyVKUQqtTYYNyC1JJYVAwNQWe4ybWvoT2V2WW9PGVO2u5Y6aVj4ER/Ow==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz", + "integrity": "sha512-OfBnObtnGgLGfweORmdZbyEz+3dgVePQBb3zipiaDsMHV1NpWm0rDFYIVXFV/AK+x4VIIfWHhrdMIeoTLyRr2g==", "dev": true, "requires": { - "core-js": "3.0.1", - "object-assign": "4.1.1", - "promise": "8.0.2", - "raf": "3.4.1", - "regenerator-runtime": "0.13.2", - "whatwg-fetch": "3.0.0" + "core-js": "^3.5.0", + "object-assign": "^4.1.1", + "promise": "^8.0.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.3", + "whatwg-fetch": "^3.0.0" }, "dependencies": { "promise": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.0.2.tgz", - "integrity": "sha512-EIyzM39FpVOMbqgzEHhxdrEhtOSDOtjMZQ0M6iVfCE+kWNgCkAyOdnuCWqfmflylftfadU6FkiMgHZA2kUzwRw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.0.3.tgz", + "integrity": "sha512-HeRDUL1RJiLhyA0/grn+PTShlBAcLuh/1BJGtrvjwbvRDCTLLMEz9rOGCV+R3vHY4MixIuoMEd9Yq/XvsTPcjw==", "dev": true, "requires": { "asap": "~2.0.6" } + }, + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "dev": true } } }, "react-dev-utils": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-9.0.1.tgz", - "integrity": "sha512-pnaeMo/Pxel8aZpxk1WwxT3uXxM3tEwYvsjCYn5R7gNxjhN1auowdcLDzFB8kr7rafAj2rxmvfic/fbac5CzwQ==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.2.0.tgz", + "integrity": "sha512-MwrvQW2TFjLblhqpDNeqCXHBkz3G5vc7k4wntgutAJZX4ia3o07eGKo6uYGhUOeJ0hfOxcpJFNFk7+4XCc1S8g==", "dev": true, "requires": { - "@babel/code-frame": "7.0.0", - "address": "1.0.3", - "browserslist": "4.5.4", + "@babel/code-frame": "7.8.3", + "address": "1.1.2", + "browserslist": "4.8.6", "chalk": "2.4.2", - "cross-spawn": "6.0.5", + "cross-spawn": "7.0.1", "detect-port-alt": "1.1.6", - "escape-string-regexp": "1.0.5", - "filesize": "3.6.1", - "find-up": "3.0.0", - "fork-ts-checker-webpack-plugin": "1.1.1", + "escape-string-regexp": "2.0.0", + "filesize": "6.0.1", + "find-up": "4.1.0", + "fork-ts-checker-webpack-plugin": "3.1.1", "global-modules": "2.0.0", "globby": "8.0.2", - "gzip-size": "5.0.0", + "gzip-size": "5.1.1", "immer": "1.10.0", - "inquirer": "6.2.2", - "is-root": "2.0.0", + "inquirer": "7.0.4", + "is-root": "2.1.0", "loader-utils": "1.2.3", - "opn": "5.4.0", - "pkg-up": "2.0.0", - "react-error-overlay": "^5.1.6", + "open": "^7.0.2", + "pkg-up": "3.1.0", + "react-error-overlay": "^6.0.6", "recursive-readdir": "2.2.2", - "shell-quote": "1.6.1", - "sockjs-client": "1.3.0", - "strip-ansi": "5.2.0", + "shell-quote": "1.7.2", + "strip-ansi": "6.0.0", "text-table": "0.2.0" }, "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { @@ -21652,14 +25310,14 @@ } }, "browserslist": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.4.tgz", - "integrity": "sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag==", + "version": "4.8.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.6.tgz", + "integrity": "sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000955", - "electron-to-chromium": "^1.3.122", - "node-releases": "^1.1.13" + "caniuse-lite": "^1.0.30001023", + "electron-to-chromium": "^1.3.341", + "node-releases": "^1.1.47" } }, "chalk": { @@ -21671,45 +25329,117 @@ "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + } } }, - "inquirer": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", - "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", "dev": true, "requires": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.11", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.0.0", - "through": "^2.3.6" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-wsl": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", + "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "open": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.0.2.tgz", + "integrity": "sha512-70E/pFTPr7nZ9nLDPNTcj3IVqnNvKuP4VsBmoKV9YGTnChe0mlS3C4qM7qKarhZ8rGaHKLfo+vBTHXDp6ZSyLQ==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" } }, - "opn": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "is-wsl": "^1.1.0" + "shebang-regex": "^3.0.0" } }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true + }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } }, "supports-color": { @@ -21720,24 +25450,33 @@ "requires": { "has-flag": "^3.0.0" } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, "react-dom": { - "version": "16.8.6", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz", - "integrity": "sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==", + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.12.0.tgz", + "integrity": "sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.13.6" + "scheduler": "^0.18.0" } }, "react-error-overlay": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-5.1.6.tgz", - "integrity": "sha512-X1Y+0jR47ImDVr54Ab6V9eGk0Hnu7fVWGeHQSOXHf/C2pF9c6uy3gef8QUeuUiWlNb0i08InPSE5a/KJzNzw1Q==", + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.6.tgz", + "integrity": "sha512-Yzpno3enVzSrSCnnljmr4b/2KUQSMZaPuqmS26t9k4nW7uwJk6STWmH9heNjPuvqUTO3jOSPkHoKgO4+Dw7uIw==", "dev": true }, "react-intl": { @@ -21763,75 +25502,212 @@ "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" }, "react-scripts": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.0.1.tgz", - "integrity": "sha512-LKEjBhVpEB+c312NeJhzF+NATxF7JkHNr5GhtwMeRS1cMeLElMeIu8Ye7WGHtDP7iz7ra4ryy48Zpo6G/cwWUw==", - "dev": true, - "requires": { - "@babel/core": "7.4.3", - "@svgr/webpack": "4.1.0", - "@typescript-eslint/eslint-plugin": "1.6.0", - "@typescript-eslint/parser": "1.6.0", - "babel-eslint": "10.0.1", - "babel-jest": "^24.8.0", - "babel-loader": "8.0.5", - "babel-plugin-named-asset-import": "^0.3.2", - "babel-preset-react-app": "^9.0.0", - "camelcase": "^5.2.0", - "case-sensitive-paths-webpack-plugin": "2.2.0", - "css-loader": "2.1.1", - "dotenv": "6.2.0", - "dotenv-expand": "4.2.0", - "eslint": "^5.16.0", - "eslint-config-react-app": "^4.0.1", - "eslint-loader": "2.1.2", - "eslint-plugin-flowtype": "2.50.1", - "eslint-plugin-import": "2.16.0", - "eslint-plugin-jsx-a11y": "6.2.1", - "eslint-plugin-react": "7.12.4", - "eslint-plugin-react-hooks": "^1.5.0", - "file-loader": "3.0.1", - "fs-extra": "7.0.1", - "fsevents": "2.0.6", - "html-webpack-plugin": "4.0.0-beta.5", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.0.tgz", + "integrity": "sha512-pBqaAroFoHnFAkuX+uSK9Th1uEh2GYdGY2IG1I9/7HmuEf+ls3lLCk1p2GFYRSrLMz6ieQR/SyN6TLIGK3hKRg==", + "dev": true, + "requires": { + "@babel/core": "7.8.4", + "@svgr/webpack": "4.3.3", + "@typescript-eslint/eslint-plugin": "^2.10.0", + "@typescript-eslint/parser": "^2.10.0", + "babel-eslint": "10.0.3", + "babel-jest": "^24.9.0", + "babel-loader": "8.0.6", + "babel-plugin-named-asset-import": "^0.3.6", + "babel-preset-react-app": "^9.1.1", + "camelcase": "^5.3.1", + "case-sensitive-paths-webpack-plugin": "2.3.0", + "css-loader": "3.4.2", + "dotenv": "8.2.0", + "dotenv-expand": "5.1.0", + "eslint": "^6.6.0", + "eslint-config-react-app": "^5.2.0", + "eslint-loader": "3.0.3", + "eslint-plugin-flowtype": "4.6.0", + "eslint-plugin-import": "2.20.0", + "eslint-plugin-jsx-a11y": "6.2.3", + "eslint-plugin-react": "7.18.0", + "eslint-plugin-react-hooks": "^1.6.1", + "file-loader": "4.3.0", + "fs-extra": "^8.1.0", + "fsevents": "2.1.2", + "html-webpack-plugin": "4.0.0-beta.11", "identity-obj-proxy": "3.0.0", - "is-wsl": "^1.1.0", - "jest": "24.7.1", - "jest-environment-jsdom-fourteen": "0.1.0", - "jest-resolve": "24.7.1", - "jest-watch-typeahead": "0.3.0", - "mini-css-extract-plugin": "0.5.0", - "optimize-css-assets-webpack-plugin": "5.0.1", - "pnp-webpack-plugin": "1.2.1", + "jest": "24.9.0", + "jest-environment-jsdom-fourteen": "1.0.1", + "jest-resolve": "24.9.0", + "jest-watch-typeahead": "0.4.2", + "mini-css-extract-plugin": "0.9.0", + "optimize-css-assets-webpack-plugin": "5.0.3", + "pnp-webpack-plugin": "1.6.0", "postcss-flexbugs-fixes": "4.1.0", "postcss-loader": "3.0.0", - "postcss-normalize": "7.0.1", - "postcss-preset-env": "6.6.0", + "postcss-normalize": "8.0.1", + "postcss-preset-env": "6.7.0", "postcss-safe-parser": "4.0.1", - "react-app-polyfill": "^1.0.1", - "react-dev-utils": "^9.0.1", - "resolve": "1.10.0", - "sass-loader": "7.1.0", - "semver": "6.0.0", + "react-app-polyfill": "^1.0.6", + "react-dev-utils": "^10.2.0", + "resolve": "1.15.0", + "resolve-url-loader": "3.1.1", + "sass-loader": "8.0.2", + "semver": "6.3.0", "style-loader": "0.23.1", - "terser-webpack-plugin": "1.2.3", - "ts-pnp": "1.1.2", - "url-loader": "1.1.2", - "webpack": "4.29.6", - "webpack-dev-server": "3.2.1", - "webpack-manifest-plugin": "2.0.4", - "workbox-webpack-plugin": "4.2.0" + "terser-webpack-plugin": "2.3.4", + "ts-pnp": "1.1.5", + "url-loader": "2.3.0", + "webpack": "4.41.5", + "webpack-dev-server": "3.10.2", + "webpack-manifest-plugin": "2.2.0", + "workbox-webpack-plugin": "4.3.1" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", "dev": true, "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" + "@babel/highlight": "^7.8.3" + } + }, + "@babel/core": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", + "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helpers": "^7.8.4", + "@babel/parser": "^7.8.4", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helpers": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", + "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" } }, "@jest/core": { @@ -21868,21 +25744,6 @@ "rimraf": "^2.5.4", "slash": "^2.0.0", "strip-ansi": "^5.0.0" - }, - "dependencies": { - "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" - } - } } }, "@jest/environment": { @@ -21897,17 +25758,6 @@ "jest-mock": "^24.9.0" } }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" - } - }, "@jest/reporters": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", @@ -21937,43 +25787,14 @@ "string-length": "^2.0.0" }, "dependencies": { - "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" - } + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - } - }, "@jest/test-sequencer": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", @@ -22008,6 +25829,14 @@ "slash": "^2.0.0", "source-map": "^0.6.1", "write-file-atomic": "2.4.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "@jest/types": { @@ -22021,15 +25850,36 @@ "@types/yargs": "^13.0.0" } }, - "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -22079,12 +25929,6 @@ "babel-plugin-jest-hoist": "^24.9.0" } }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -22094,17 +25938,6 @@ "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "cliui": { @@ -22118,25 +25951,41 @@ "wrap-ansi": "^5.1.0" } }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, "css-loader": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", - "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.4.2.tgz", + "integrity": "sha512-jYq4zdZT0oS0Iykt+fqnzVLRIeiPWhka+7BqPn+oSIpWJAHak5tmB/WZrJ2a21JhCeFyNnnlroSl8c+MtVndzA==", "dev": true, "requires": { - "camelcase": "^5.2.0", - "icss-utils": "^4.1.0", + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", "loader-utils": "^1.2.3", "normalize-path": "^3.0.0", - "postcss": "^7.0.14", + "postcss": "^7.0.23", "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^2.0.6", - "postcss-modules-scope": "^2.1.0", - "postcss-modules-values": "^2.0.0", - "postcss-value-parser": "^3.3.0", - "schema-utils": "^1.0.0" + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.1.1", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.0.2", + "schema-utils": "^2.6.0" } }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, "expect": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", @@ -22151,10 +26000,38 @@ "jest-regex-util": "^24.9.0" } }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "find-cache-dir": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.2.0.tgz", + "integrity": "sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.0", + "pkg-dir": "^4.1.0" + }, + "dependencies": { + "make-dir": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", + "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + } + } + }, "fsevents": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.6.tgz", - "integrity": "sha512-vfmKZp3XPM36DNF0qhW+Cdxk7xm7gTEHY1clv1Xq1arwRQuKZgAhw+NZNWbJBtuaNxzNXwhfdPYRrvIbjfS33A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", "dev": true, "optional": true }, @@ -22165,9 +26042,9 @@ "dev": true }, "icss-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.0.tgz", - "integrity": "sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", "dev": true, "requires": { "postcss": "^7.0.14" @@ -22182,6 +26059,17 @@ "istanbul-lib-coverage": "^2.0.5", "make-dir": "^2.1.0", "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "istanbul-lib-source-maps": { @@ -22195,6 +26083,14 @@ "make-dir": "^2.1.0", "rimraf": "^2.6.3", "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "istanbul-reports": { @@ -22207,13 +26103,13 @@ } }, "jest": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-24.7.1.tgz", - "integrity": "sha512-AbvRar5r++izmqo5gdbAjTeA6uNRGoNRuj5vHB0OnDXo2DXWZJVuaObiGgtlvhKb+cWy2oYbQSfxv7Q7GjnAtA==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", + "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", "dev": true, "requires": { "import-local": "^2.0.0", - "jest-cli": "^24.7.1" + "jest-cli": "^24.9.0" }, "dependencies": { "jest-cli": { @@ -22273,21 +26169,6 @@ "micromatch": "^3.1.10", "pretty-format": "^24.9.0", "realpath-native": "^1.1.0" - }, - "dependencies": { - "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" - } - } } }, "jest-docblock": { @@ -22953,31 +26834,6 @@ "pretty-format": "^24.9.0" } }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, "jest-regex-util": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", @@ -23020,21 +26876,6 @@ "jest-worker": "^24.6.0", "source-map-support": "^0.5.6", "throat": "^4.0.0" - }, - "dependencies": { - "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" - } - } } }, "jest-runtime": { @@ -23066,21 +26907,6 @@ "slash": "^2.0.0", "strip-bom": "^3.0.0", "yargs": "^13.3.0" - }, - "dependencies": { - "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" - } - } } }, "jest-serializer": { @@ -23108,47 +26934,6 @@ "natural-compare": "^1.4.0", "pretty-format": "^24.9.0", "semver": "^6.2.0" - }, - "dependencies": { - "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" } }, "jest-validate": { @@ -23165,21 +26950,6 @@ "pretty-format": "^24.9.0" } }, - "jest-watcher": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", - "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", - "dev": true, - "requires": { - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/yargs": "^13.0.0", - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "jest-util": "^24.9.0", - "string-length": "^2.0.0" - } - }, "jest-worker": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", @@ -23188,6 +26958,17 @@ "requires": { "merge-stream": "^2.0.0", "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "jsdom": { @@ -23222,22 +27003,63 @@ "whatwg-url": "^6.4.1", "ws": "^5.2.0", "xml-name-validator": "^3.0.0" - }, - "dependencies": { - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - } } }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + } + }, "node-notifier": { "version": "5.4.3", "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", @@ -23274,21 +27096,89 @@ "p-reduce": "^1.0.0" } }, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", "dev": true }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss-modules-extract-imports": { @@ -23301,20 +27191,21 @@ } }, "postcss-modules-local-by-default": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", - "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz", + "integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==", "dev": true, "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0", - "postcss-value-parser": "^3.3.1" + "icss-utils": "^4.1.1", + "postcss": "^7.0.16", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.0" } }, "postcss-modules-scope": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", - "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.1.tgz", + "integrity": "sha512-OXRUPecnHCg8b9xWvldG/jUpRIGPNRka0r4D4j0ESUU2/5IOnpsjfPPmDprM3Ih8CgZ8FXjWqaniK5v4rWt3oQ==", "dev": true, "requires": { "postcss": "^7.0.6", @@ -23322,19 +27213,31 @@ } }, "postcss-modules-values": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", - "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", "dev": true, "requires": { - "icss-replace-symbols": "^1.1.0", + "icss-utils": "^4.0.0", "postcss": "^7.0.6" } }, + "postcss-value-parser": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", + "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, "resolve": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", - "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", + "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -23349,10 +27252,26 @@ "glob": "^7.1.3" } }, + "schema-utils": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.4.tgz", + "integrity": "sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } + }, "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "string-width": { @@ -23381,17 +27300,80 @@ "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^1.0.0" + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" } }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "terser-webpack-plugin": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.4.tgz", + "integrity": "sha512-Nv96Nws2R2nrFOpbzF6IxRDpIkkIfmhvOws+IqMvYdFLO7o6wAILWFKONFgaYy8+T4LVz77DQW0f7wOeDEAjrg==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "cacache": "^13.0.1", + "find-cache-dir": "^3.2.0", + "jest-worker": "^25.1.0", + "p-limit": "^2.2.2", + "schema-utils": "^2.6.4", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.4.3", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-worker": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.1.0.tgz", + "integrity": "sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "throat": { @@ -23400,36 +27382,153 @@ "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", "dev": true }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, "webpack": { - "version": "4.29.6", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.6.tgz", - "integrity": "sha512-MwBwpiE1BQpMDkbnUUaW6K8RFZjljJHArC6tWQJoFm0oQtfoSebtg4Y7/QHnJ/SddtjYLHaKGX64CFjG5rehJw==", + "version": "4.41.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.5.tgz", + "integrity": "sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", "@webassemblyjs/helper-module-context": "1.8.5", "@webassemblyjs/wasm-edit": "1.8.5", "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.0.5", - "acorn-dynamic-import": "^4.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", + "eslint-scope": "^4.0.3", "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", "schema-utils": "^1.0.0", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "dev": true + }, + "cacache": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "terser-webpack-plugin": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "whatwg-url": { @@ -23493,6 +27592,28 @@ } } }, + "react-test-renderer": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.12.0.tgz", + "integrity": "sha512-Vj/teSqt2oayaWxkbhQ6gKis+t5JrknXfPVo+aIJ8QwYAqMPH77uptOdrlphyxl8eQI/rtkOYg86i/UWkpFu0w==", + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "react-is": "^16.8.6", + "scheduler": "^0.18.0" + }, + "dependencies": { + "scheduler": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", + "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -23604,9 +27725,9 @@ "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" }, "regenerator-transform": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", - "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", "dev": true, "requires": { "private": "^0.1.6" @@ -23621,16 +27742,79 @@ "safe-regex": "^1.1.0" } }, - "regexp-tree": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", - "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", + "regex-parser": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.10.tgz", + "integrity": "sha512-8t6074A68gHfU8Neftl0Le6KTDwfGAj7IyjPIMSfikI2wJUTHDMaIq42bUsfVnj8mhx0R+45rdUXHGpN164avA==", "dev": true }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + } + } + }, "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", + "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", "dev": true }, "regexpu-core": { @@ -23656,17 +27840,6 @@ "jsesc": "~0.5.0" } }, - "rehype-parse": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.0.tgz", - "integrity": "sha512-V2OjMD0xcSt39G4uRdMTqDXXm6HwkUbLMDayYKA/d037j8/OtVSQ+tqKwYWOuyBeoCs/3clXRe30VUjeMDTBSA==", - "dev": true, - "requires": { - "hast-util-from-parse5": "^5.0.0", - "parse5": "^5.0.0", - "xtend": "^4.0.1" - } - }, "relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -23831,12 +28004,6 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, - "requireindex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", - "dev": true - }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -23915,13 +28082,93 @@ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, + "resolve-url-loader": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.1.tgz", + "integrity": "sha512-K1N5xUjj7v0l2j/3Sgs5b8CjrrgtC70SmdCuZiJ8tSyb5J+uk3FoeZ4b7yTnH6j7ngI+Bc5bldHJIa8hYdu2gQ==", + "dev": true, + "requires": { + "adjust-sourcemap-loader": "2.0.0", + "camelcase": "5.3.1", + "compose-function": "3.0.3", + "convert-source-map": "1.7.0", + "es6-iterator": "2.0.3", + "loader-utils": "1.2.3", + "postcss": "7.0.21", + "rework": "1.0.1", + "rework-visit": "1.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "postcss": { + "version": "7.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", + "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "requires": { - "onetime": "^2.0.0", + "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, @@ -23930,6 +28177,36 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "rework": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", + "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", + "dev": true, + "requires": { + "convert-source-map": "^0.3.3", + "css": "^2.0.0" + }, + "dependencies": { + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + } + } + }, + "rework-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", + "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", + "dev": true + }, "rgb-regex": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", @@ -23984,9 +28261,9 @@ } }, "rxjs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", - "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -24026,64 +28303,89 @@ "walker": "~1.0.5" } }, + "sanitize.css": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-10.0.0.tgz", + "integrity": "sha512-vTxrZz4dX5W86M6oVWVdOVe72ZiPs41Oi7Z6Km4W5Turyz28mrXSJhhEBZoRtzJWIv3833WKVwLSDWWkEfupMg==", + "dev": true + }, "sass-loader": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz", - "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", + "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", "dev": true, "requires": { - "clone-deep": "^2.0.1", - "loader-utils": "^1.0.1", - "lodash.tail": "^4.1.1", - "neo-async": "^2.5.0", - "pify": "^3.0.0", - "semver": "^5.5.0" + "clone-deep": "^4.0.1", + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.6.1", + "semver": "^6.3.0" }, "dependencies": { + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, "clone-deep": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", - "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, "requires": { - "for-own": "^1.0.0", "is-plain-object": "^2.0.4", - "kind-of": "^6.0.0", - "shallow-clone": "^1.0.0" + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" } }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "schema-utils": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.4.tgz", + "integrity": "sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==", "dev": true, "requires": { - "for-in": "^1.0.1" + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" } }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "shallow-clone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", - "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "requires": { - "is-extendable": "^0.1.1", - "kind-of": "^5.0.0", - "mixin-object": "^2.0.1" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "kind-of": "^6.0.2" } } } @@ -24103,9 +28405,9 @@ } }, "scheduler": { - "version": "0.13.6", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", - "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", + "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -24129,12 +28431,12 @@ "dev": true }, "selfsigned": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", - "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz", + "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==", "dev": true, "requires": { - "node-forge": "0.7.5" + "node-forge": "0.9.0" } }, "semver": { @@ -24192,9 +28494,9 @@ } }, "serialize-javascript": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", "dev": true }, "serve-index": { @@ -24655,23 +28957,12 @@ "requires": { "faye-websocket": "^0.10.0", "uuid": "^3.0.1" - }, - "dependencies": { - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - } } }, "sockjs-client": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", - "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", + "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", "dev": true, "requires": { "debug": "^3.2.5", @@ -24690,9 +28981,27 @@ "requires": { "ms": "^2.1.1" } + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } } } }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, "source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", @@ -24730,12 +29039,6 @@ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, - "space-separated-tokens": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.4.tgz", - "integrity": "sha512-UyhMSmeIqZrQn2UdjYpxEkwY9JUrn8pP+7L4f91zRzOQuI8MF1FGLfYU9DKCYeLdo7LXMxwrX5zKFy7eeeVHuA==", - "dev": true - }, "sparkles": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", @@ -24775,9 +29078,9 @@ "dev": true }, "spdy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", - "integrity": "sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.1.tgz", + "integrity": "sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==", "dev": true, "requires": { "debug": "^4.1.0", @@ -24802,9 +29105,9 @@ }, "dependencies": { "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -24972,6 +29275,12 @@ "readable-stream": "^2.0.2" } }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, "string-hash": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", @@ -25042,6 +29351,26 @@ "function-bind": "^1.0.2" } }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -25060,6 +29389,14 @@ "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + } } }, "strip-ansi": { @@ -25186,9 +29523,9 @@ } }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -25197,12 +29534,12 @@ } }, "postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", "dev": true, "requires": { - "dot-prop": "^4.1.1", + "dot-prop": "^5.2.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } @@ -25265,19 +29602,24 @@ "prop-types": "^15.5.0" } }, + "svg-parser": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.3.tgz", + "integrity": "sha512-fnCWiifNhK8i2Z7b9R5tbNahpxrRdAaQbnoxKlT2KrSCj9Kq/yBSgulCRgBJRhy1dPnSY5slg5ehPUnzpEcHlg==", + "dev": true + }, "svgo": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.2.2.tgz", - "integrity": "sha512-rAfulcwp2D9jjdGu+0CuqlrAUin6bBWrpoqXWwKDZZZJfXcUXQSxLJOFJCQCSA0x0pP2U0TxSlJu2ROq5Bq6qA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", "dev": true, "requires": { "chalk": "^2.4.1", "coa": "^2.0.2", "css-select": "^2.0.0", "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.28", - "css-url-regex": "^1.1.0", - "csso": "^3.5.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", "js-yaml": "^3.13.1", "mkdirp": "~0.5.1", "object.values": "^1.1.0", @@ -25324,23 +29666,41 @@ "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" }, "table": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.0.tgz", - "integrity": "sha512-nHFDrxmbrkU7JAFKqKbDJXfzrX2UBsWmrieXFTGxiI5e4ncg3VqsZeI4EzNmX0ncp4XNGVeoxIWJXfCIXwrsvw==", + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", "dev": true, "requires": { - "ajv": "^6.9.1", - "lodash": "^4.17.11", + "ajv": "^6.10.2", + "lodash": "^4.17.14", "slice-ansi": "^2.1.0", "string-width": "^3.0.0" }, "dependencies": { + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -25389,30 +29749,92 @@ } }, "terser": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", - "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz", + "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==", "dev": true, "requires": { - "commander": "^2.19.0", + "commander": "^2.20.0", "source-map": "~0.6.1", - "source-map-support": "~0.5.10" + "source-map-support": "~0.5.12" } }, "terser-webpack-plugin": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz", - "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", "dev": true, "requires": { - "cacache": "^11.0.2", - "find-cache-dir": "^2.0.0", + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", "schema-utils": "^1.0.0", - "serialize-javascript": "^1.4.0", + "serialize-javascript": "^2.1.2", "source-map": "^0.6.1", - "terser": "^3.16.1", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "cacache": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", + "dev": true + }, + "terser": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz", + "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } } }, "test-exclude": { @@ -25465,9 +29887,9 @@ } }, "thunky": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", - "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, "time-stamp": { @@ -25613,12 +30035,6 @@ "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" }, - "trough": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.4.tgz", - "integrity": "sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==", - "dev": true - }, "ts-import-plugin": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/ts-import-plugin/-/ts-import-plugin-1.5.5.tgz", @@ -25713,9 +30129,9 @@ } }, "ts-pnp": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.2.tgz", - "integrity": "sha512-f5Knjh7XCyRIzoC/z1Su1yLLRrPrFCgtUAh/9fCSP6NKbATwpOL1+idQVXQokK9GRFURn/jYPGPfegIctwunoA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.5.tgz", + "integrity": "sha512-ti7OGMOUOzo66wLF3liskw6YQIaSsBgc4GOAlWRnIEj8htCxJUxskanMUoJOD6MDCRAXo36goXJZch+nOS0VMA==", "dev": true }, "tslib": { @@ -25838,9 +30254,9 @@ "dev": true }, "tsutils": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.11.0.tgz", - "integrity": "sha512-RRtGX1FVfHm1+P9XVqN+RxqUa8ZCZ2LjaPyaRUQH7Wvn9cYAkpz/cZKy+BWU/+fncFqjW/+PVgRWF4Ky5IGbjQ==", + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", "dev": true, "requires": { "tslib": "^1.8.1" @@ -25958,24 +30374,6 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", "dev": true }, - "uglify-js": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", - "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", - "dev": true, - "requires": { - "commander": "~2.19.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - } - } - }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -26039,36 +30437,6 @@ "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", "dev": true }, - "unified": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", - "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "@types/vfile": "^3.0.0", - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^3.0.0", - "x-is-string": "^0.1.0" - }, - "dependencies": { - "vfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", - "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", - "dev": true, - "requires": { - "is-buffer": "^2.0.0", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - } - } - } - }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -26120,12 +30488,6 @@ "through2-filter": "^3.0.0" } }, - "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -26186,12 +30548,6 @@ "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", "dev": true }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -26230,21 +30586,55 @@ "dev": true }, "url-loader": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", - "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.3.0.tgz", + "integrity": "sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog==", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "mime": "^2.0.3", - "schema-utils": "^1.0.0" + "loader-utils": "^1.2.3", + "mime": "^2.4.4", + "schema-utils": "^2.5.0" }, "dependencies": { + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, "mime": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz", - "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true + }, + "schema-utils": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.4.tgz", + "integrity": "sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } } } }, @@ -26362,9 +30752,9 @@ "dev": true }, "vendors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz", - "integrity": "sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", "dev": true }, "verror": { @@ -26422,57 +30812,6 @@ } } }, - "vfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.0.0.tgz", - "integrity": "sha512-WMNeHy5djSl895BqE86D7WqA0Ie5fAIeGCa7V1EqiXyJg5LaGch2SUaZueok5abYQGH6mXEAsZ45jkoILIOlyA==", - "dev": true, - "requires": { - "@types/unist": "^2.0.2", - "is-buffer": "^2.0.0", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^2.0.0", - "vfile-message": "^2.0.0" - }, - "dependencies": { - "unist-util-stringify-position": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.1.tgz", - "integrity": "sha512-Zqlf6+FRI39Bah8Q6ZnNGrEHUhwJOkHde2MHVk96lLyftfJJckaPslKgzhVcviXj8KcE9UJM9F+a4JEiBUTYgA==", - "dev": true, - "requires": { - "@types/unist": "^2.0.2" - } - }, - "vfile-message": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.0.tgz", - "integrity": "sha512-YS6qg6UpBfIeiO+6XlhPOuJaoLvt1Y9g2cmlwqhBOOU0XRV8j5RLeoz72t6PWLvNXq3EBG1fQ05wNPrUoz0deQ==", - "dev": true, - "requires": { - "@types/unist": "^2.0.2", - "unist-util-stringify-position": "^1.1.1" - }, - "dependencies": { - "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true - } - } - } - } - }, - "vfile-message": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", - "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } - }, "vinyl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", @@ -26617,9 +30956,9 @@ "integrity": "sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A==" }, "vscode-nls-dev": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/vscode-nls-dev/-/vscode-nls-dev-3.2.6.tgz", - "integrity": "sha512-PsL6k363fp5vHZEVJX0ywT7Uem1WvqnFG/eRGxsjOIPYAXQQl8bhJSxm+kNofM8nchZOAnScbtFRz70z9evkqw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/vscode-nls-dev/-/vscode-nls-dev-3.3.1.tgz", + "integrity": "sha512-fug18D7CXb8pv8JoQ0D0JmZaIYDQoKLiyZxkAy5P8Cln/FwlNsdzwQILDph62EdGY5pvsJ2Jd1T5qgHAExe/tg==", "dev": true, "requires": { "ansi-colors": "^3.2.3", @@ -26633,201 +30972,119 @@ "typescript": "^2.6.2", "vinyl": "^2.1.0", "xml2js": "^0.4.19", - "yargs": "^10.1.1" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "event-stream": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.5.tgz", - "integrity": "sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g==", - "dev": true, - "requires": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } + "yargs": "^13.2.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "color-convert": "^1.9.0" } }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" } }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "event-stream": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.5.tgz", + "integrity": "sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "duplexer": "^0.1.1", + "from": "^0.1.7", + "map-stream": "0.0.7", + "pause-stream": "^0.0.11", + "split": "^1.0.1", + "stream-combiner": "^0.2.2", + "through": "^2.3.8" } }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "p-try": "^1.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "p-limit": "^1.1.0" + "ansi-regex": "^4.1.0" } }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, "typescript": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", "dev": true }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } }, "yargs": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz", - "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^3.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^8.1.0" + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" } }, "yargs-parser": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", - "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -26893,12 +31150,6 @@ "minimalistic-assert": "^1.0.0" } }, - "web-namespaces": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.3.tgz", - "integrity": "sha512-r8sAtNmgR0WKOKOxzuSgk09JsHlpKlB+uHi937qypOu3PZ17UxPrierFKDye/uNHjNTTEshu5PId8rojIPj/tA==", - "dev": true - }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -27011,167 +31262,103 @@ } }, "webpack-dev-middleware": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz", - "integrity": "sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", "dev": true, "requires": { "memory-fs": "^0.4.1", - "mime": "^2.4.2", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", "range-parser": "^1.2.1", "webpack-log": "^2.0.0" }, "dependencies": { "mime": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz", - "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true } } }, "webpack-dev-server": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.2.1.tgz", - "integrity": "sha512-sjuE4mnmx6JOh9kvSbPYw3u/6uxCLHNWfhWaIPwcXWsvWOPN+nc5baq4i9jui3oOBRXGonK9+OI0jVkaz6/rCw==", + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.10.2.tgz", + "integrity": "sha512-pxZKPYb+n77UN8u9YxXT4IaIrGcNtijh/mi8TXbErHmczw0DtPnMTTjHj+eNjkqLOaAZM/qD7V59j/qJsEiaZA==", "dev": true, "requires": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", - "chokidar": "^2.0.0", - "compression": "^1.5.2", - "connect-history-api-fallback": "^1.3.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", "debug": "^4.1.1", - "del": "^3.0.0", - "express": "^4.16.2", - "html-entities": "^1.2.0", - "http-proxy-middleware": "^0.19.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.2.1", + "http-proxy-middleware": "0.19.1", "import-local": "^2.0.0", - "internal-ip": "^4.2.0", + "internal-ip": "^4.3.0", "ip": "^1.1.5", - "killable": "^1.0.0", - "loglevel": "^1.4.1", - "opn": "^5.1.0", - "portfinder": "^1.0.9", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.6", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.25", "schema-utils": "^1.0.0", - "selfsigned": "^1.9.1", - "semver": "^5.6.0", - "serve-index": "^1.7.2", + "selfsigned": "^1.10.7", + "semver": "^6.3.0", + "serve-index": "^1.9.1", "sockjs": "0.3.19", - "sockjs-client": "1.3.0", - "spdy": "^4.0.0", - "strip-ansi": "^3.0.0", + "sockjs-client": "1.4.0", + "spdy": "^4.0.1", + "strip-ansi": "^3.0.1", "supports-color": "^6.1.0", "url": "^0.11.0", - "webpack-dev-middleware": "^3.5.1", + "webpack-dev-middleware": "^3.7.2", "webpack-log": "^2.0.0", - "yargs": "12.0.2" + "ws": "^6.2.1", + "yargs": "12.0.5" }, "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "dev": true, - "requires": { - "xregexp": "4.0.0" - } - }, - "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", - "dev": true, - "requires": { - "globby": "^6.1.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "p-map": "^1.1.1", - "pify": "^3.0.0", - "rimraf": "^2.2.8" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", "dev": true, "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" } }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", "dev": true }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true, - "requires": { - "is-path-inside": "^1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } - }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "supports-color": { @@ -27183,33 +31370,13 @@ "has-flag": "^3.0.0" } }, - "yargs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", - "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^2.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" - } - }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "async-limiter": "~1.0.0" } } } @@ -27225,14 +31392,28 @@ } }, "webpack-manifest-plugin": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-2.0.4.tgz", - "integrity": "sha512-nejhOHexXDBKQOj/5v5IZSfCeTO3x1Dt1RZEcGfBSul891X/eLIcIVH31gwxPDdsi2Z8LKKFGpM4w9+oTBOSCg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-2.2.0.tgz", + "integrity": "sha512-9S6YyKKKh/Oz/eryM1RyLVDVmy3NSPV0JXMRhZ18fJsq+AwGxUY34X54VNwkzYcEmEkDwNxuEOboCZEebJXBAQ==", "dev": true, "requires": { "fs-extra": "^7.0.0", "lodash": ">=3.5 <5", + "object.entries": "^1.1.0", "tapable": "^1.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } } }, "webpack-sources": { @@ -27246,12 +31427,13 @@ } }, "websocket-driver": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", + "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", "dev": true, "requires": { - "http-parser-js": ">=0.4.0", + "http-parser-js": ">=0.4.0 <0.4.11", + "safe-buffer": ">=5.1.0", "websocket-extensions": ">=0.1.1" } }, @@ -27312,6 +31494,12 @@ "string-width": "^1.0.2 || 2" } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -27476,14 +31664,14 @@ "dev": true }, "workbox-webpack-plugin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-4.2.0.tgz", - "integrity": "sha512-YZsiA+y/ns/GdWRaBsfYv8dln1ebWtGnJcTOg1ppO0pO1tScAHX0yGtHIjndxz3L/UUhE8b0NQE9KeLNwJwA5A==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-4.3.1.tgz", + "integrity": "sha512-gJ9jd8Mb8wHLbRz9ZvGN57IAmknOipD3W4XNE/Lk/4lqs5Htw4WOQgakQy/o/4CoXQlMCYldaqUg+EJ35l9MEQ==", "dev": true, "requires": { "@babel/runtime": "^7.0.0", "json-stable-stringify": "^1.0.1", - "workbox-build": "^4.2.0" + "workbox-build": "^4.3.1" } }, "workbox-window": { @@ -27575,31 +31763,25 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.1.tgz", "integrity": "sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A==" }, - "x-is-string": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", - "dev": true - }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" }, "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", "dev": true, "requires": { "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" + "xmlbuilder": "~11.0.0" } }, "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "dev": true }, "xmlchars": { @@ -27612,12 +31794,6 @@ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true - }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", @@ -27635,6 +31811,15 @@ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true }, + "yaml": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.7.2.tgz", + "integrity": "sha512-qXROVp90sb83XtAoqE8bP9RwAkTTZbugRUTm5YeFCBfNRPEp2YzTeqWiz7m5OORHzEvrA/qcGS8hp/E+MMROYw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.6.3" + } + }, "yargs": { "version": "12.0.5", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", diff --git a/package.json b/package.json index 730019a8e..0c716c8f6 100644 --- a/package.json +++ b/package.json @@ -1,362 +1,354 @@ { - "name": "__EXTENSIONNAME__", - "displayName": "__DISPLAYNAME__", - "description": "__DESCRIPTION__", - "version": "0.0.0-UNTRACKEDVERSION", - "publisher": "__PUBLISHER__", - "instrumentationKey": "__AIKEY__", - "icon": "assets/icon.png", - "engines": { - "vscode": "^1.34.0" - }, - "categories": [ - "Other" - ], - "preview": true, - "license": "MIT", - "homepage": "https://github.com/microsoft/vscode-python-devicesimulator", - "repository": { - "type": "git", - "url": "https://github.com/microsoft/vscode-python-devicesimulator" - }, - "bugs": { - "url": "https://github.com/microsoft/vscode-python-devicesimulator/issues" - }, - "keywords": [ - "python", - "CircuitPython", - "Adafruit" - ], - "activationEvents": [ - "onCommand:deviceSimulatorExpress.openSerialMonitor", - "onCommand:deviceSimulatorExpress.openSimulator", - "onCommand:deviceSimulatorExpress.runSimulator", - "onCommand:deviceSimulatorExpress.newFile", - "onCommand:deviceSimulatorExpress.runDevice", - "onCommand:deviceSimulatorExpress.runSimulatorEditorButton", - "onCommand:deviceSimulatorExpress.selectSerialPort", - "onDebug" - ], - "main": "./out/extension.js", - "contributes": { - "commands": [ - { - "command": "deviceSimulatorExpress.changeBaudRate", - "title": "%deviceSimulatorExpressExtension.commands.changeBaudRate%", - "category": "%deviceSimulatorExpressExtension.commands.label%" - }, - { - "command": "deviceSimulatorExpress.closeSerialMonitor", - "title": "%deviceSimulatorExpressExtension.commands.closeSerialMonitor%", - "category": "%deviceSimulatorExpressExtension.commands.label%" - }, - { - "command": "deviceSimulatorExpress.openSerialMonitor", - "title": "%deviceSimulatorExpressExtension.commands.openSerialMonitor%", - "category": "%deviceSimulatorExpressExtension.commands.label%" - }, - { - "command": "deviceSimulatorExpress.openSimulator", - "title": "%deviceSimulatorExpressExtension.commands.openSimulator%", - "category": "%deviceSimulatorExpressExtension.commands.label%", - "icon": { - "light": "./assets/light-theme/open-simulator.svg", - "dark": "./assets/dark-theme/open-simulator.svg" - } - }, - { - "command": "deviceSimulatorExpress.runSimulator", - "title": "%deviceSimulatorExpressExtension.commands.runSimulator%", - "category": "%deviceSimulatorExpressExtension.commands.label%" - }, - { - "command": "deviceSimulatorExpress.runSimulatorEditorButton", - "title": "%deviceSimulatorExpressExtension.commands.runSimulator%", - "category": "%deviceSimulatorExpressExtension.commands.label%", - "icon": { - "light": "./assets/light-theme/run-on-simulator.svg", - "dark": "./assets/dark-theme/run-on-simulator.svg" - } - }, - { - "command": "deviceSimulatorExpress.newFile", - "title": "%deviceSimulatorExpressExtension.commands.newFile%", - "category": "%deviceSimulatorExpressExtension.commands.label%" - }, - { - "command": "deviceSimulatorExpress.runDevice", - "title": "%deviceSimulatorExpressExtension.commands.runDevice%", - "category": "%deviceSimulatorExpressExtension.commands.label%", - "icon": { - "light": "./assets/light-theme/save-to-board.svg", - "dark": "./assets/dark-theme/save-to-board.svg" - } - }, - { - "command": "deviceSimulatorExpress.selectSerialPort", - "title": "%deviceSimulatorExpressExtension.commands.selectSerialPort%", - "category": "%deviceSimulatorExpressExtension.commands.label%" - } - ], - "colors": [ - { - "id": "highContrastButtonBorderOverride.color", - "description": "Color for the high contrast border updated", - "defaults": { - "dark": "debugToolBar.background", - "light": "debugToolBar.background", - "highContrast": "#6FC3DF" - } - }, - { - "id": "badgeForegroundOverride", - "description": "Color that fixes the issue with midnight blue ", - "defaults": { - "dark": "#FFFFFF", - "light": "badge.foreground", - "highContrast": "#FFFFFF" - } - } + "name": "__EXTENSIONNAME__", + "displayName": "__DISPLAYNAME__", + "description": "__DESCRIPTION__", + "version": "0.0.0-UNTRACKEDVERSION", + "publisher": "__PUBLISHER__", + "instrumentationKey": "__AIKEY__", + "icon": "assets/icon.png", + "engines": { + "vscode": "^1.34.0" + }, + "categories": [ + "Other" ], - "menus": { - "commandPalette": [ - { - "command": "deviceSimulatorExpress.runSimulatorEditorButton", - "when": "false" - } - ], - "editor/title": [ - { - "when": "editorLangId==python && config.deviceSimulatorExpress.showOpenIconInEditorTitleMenu", - "command": "deviceSimulatorExpress.openSimulator", - "group": "navigation@1" - }, - { - "when": "editorLangId==python && config.deviceSimulatorExpress.showSimulatorIconInEditorTitleMenu", - "command": "deviceSimulatorExpress.runSimulatorEditorButton", - "group": "navigation@2" - }, - { - "when": "editorLangId==python && config.deviceSimulatorExpress.showDeviceIconInEditorTitleMenu", - "command": "deviceSimulatorExpress.runDevice", - "group": "navigation@3" - } - ] + "preview": true, + "license": "MIT", + "homepage": "https://github.com/microsoft/vscode-python-devicesimulator", + "repository": { + "type": "git", + "url": "https://github.com/microsoft/vscode-python-devicesimulator" }, - "configuration": { - "type": "object", - "title": "%deviceSimulatorExpressExtension.configuration.title%", - "properties": { - "deviceSimulatorExpress.enableUSBDetection": { - "type": "boolean", - "default": true - }, - "deviceSimulatorExpress.showOpenIconInEditorTitleMenu": { - "type": "boolean", - "default": true, - "description": "%deviceSimulatorExpressExtension.configuration.properties.open%", - "scope": "resource" - }, - "deviceSimulatorExpress.showSimulatorIconInEditorTitleMenu": { - "type": "boolean", - "default": true, - "description": "%deviceSimulatorExpressExtension.configuration.properties.simulator%", - "scope": "resource" - }, - "deviceSimulatorExpress.showDeviceIconInEditorTitleMenu": { - "type": "boolean", - "default": true, - "description": "%deviceSimulatorExpressExtension.configuration.properties.device%", - "scope": "resource" - }, - "deviceSimulatorExpress.showDependencyInstall": { - "type": "boolean", - "default": true, - "scope": "resource" - }, - "deviceSimulatorExpress.showNewFilePopup": { - "type": "boolean", - "default": true, - "scope": "resource" - }, - "deviceSimulatorExpress.debuggerServerPort": { - "type": "number", - "default": 5577, - "description": "%deviceSimulatorExpressExtension.configuration.properties.debuggerPort%", - "scope": "resource" - } - } + "bugs": { + "url": "https://github.com/microsoft/vscode-python-devicesimulator/issues" }, - "breakpoints": [ - { - "language": "python" - } + "keywords": [ + "python", + "CircuitPython", + "Adafruit", + "microbit", + "MicroPython" + ], + "activationEvents": [ + "onCommand:deviceSimulatorExpress.common.installDependencies", + "onCommand:deviceSimulatorExpress.common.runSimulator", + "onCommand:deviceSimulatorExpress.cpx.deployToDevice", + "onCommand:deviceSimulatorExpress.cpx.newFile", + "onCommand:deviceSimulatorExpress.cpx.openSerialMonitor", + "onCommand:deviceSimulatorExpress.cpx.openSimulator", + "onCommand:deviceSimulatorExpress.cpx.selectSerialPort", + "onCommand:deviceSimulatorExpress.microbit.newFile", + "onCommand:deviceSimulatorExpress.microbit.openSimulator", + "onDebug" ], - "debuggers": [ - { - "type": "deviceSimulatorExpress", - "label": "Device Simulator Express Debugger", - "languages": [ - "python" + "main": "./out/extension.js", + "contributes": { + "commands": [ + { + "command": "deviceSimulatorExpress.common.installDependencies", + "title": "%deviceSimulatorExpressExtension.commands.common.installDependencies%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + }, + { + "command": "deviceSimulatorExpress.common.runSimulator", + "title": "%deviceSimulatorExpressExtension.commands.common.runSimulator%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + }, + { + "command": "deviceSimulatorExpress.cpx.changeBaudRate", + "title": "%deviceSimulatorExpressExtension.commands.cpx.changeBaudRate%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + }, + { + "command": "deviceSimulatorExpress.cpx.closeSerialMonitor", + "title": "%deviceSimulatorExpressExtension.commands.cpx.closeSerialMonitor%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + }, + { + "command": "deviceSimulatorExpress.cpx.deployToDevice", + "title": "%deviceSimulatorExpressExtension.commands.cpx.deployToDevice%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + }, + { + "command": "deviceSimulatorExpress.cpx.newFile", + "title": "%deviceSimulatorExpressExtension.commands.cpx.newFile%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + }, + { + "command": "deviceSimulatorExpress.cpx.openSerialMonitor", + "title": "%deviceSimulatorExpressExtension.commands.cpx.openSerialMonitor%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + }, + { + "command": "deviceSimulatorExpress.cpx.openSimulator", + "title": "%deviceSimulatorExpressExtension.commands.cpx.openSimulator%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + }, + { + "command": "deviceSimulatorExpress.cpx.selectSerialPort", + "title": "%deviceSimulatorExpressExtension.commands.cpx.selectSerialPort%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + }, + { + "command": "deviceSimulatorExpress.microbit.openSimulator", + "title": "%deviceSimulatorExpressExtension.commands.microbit.openSimulator%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + }, + { + "command": "deviceSimulatorExpress.microbit.newFile", + "title": "%deviceSimulatorExpressExtension.commands.microbit.newFile%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%" + } ], - "configurationAttributes": { - "launch": { - "properties": { - "program": { - "type": "string", - "description": "Absolute path to the code file.", - "default": "${file}" - }, - "stopOnEntry": { - "type": "boolean", - "description": "Automatically stop after launch.", - "default": true - }, - "console": { - "enum": [ - "internalConsole", - "integratedTerminal", - "externalTerminal" - ], - "description": "Where to launch the debug target: internal console, integrated terminal, or external terminal.", - "default": "integratedTerminal" - }, - "args": { - "type": "array", - "description": "Command line arguments passed to the program.", - "default": [], - "items": { - "filePath": "string", - "serverPort": "string" + "menus": { + "commandPalette": [ + { + "command": "deviceSimulatorExpress.microbit.openSimulator", + "title": "%deviceSimulatorExpressExtension.commands.microbit.openSimulator%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%", + "when": "config.deviceSimulatorExpress.previewMode" + }, + { + "command": "deviceSimulatorExpress.microbit.newFile", + "title": "%deviceSimulatorExpressExtension.commands.microbit.newFile%", + "category": "%deviceSimulatorExpressExtension.commands.common.label%", + "when": "config.deviceSimulatorExpress.previewMode" } - }, - "rules": { - "type": "array", - "description": "Debugger rules.", - "default": [], - "items": { - "path": "string", - "include": "boolean" + ] + }, + "colors": [ + { + "id": "highContrastButtonBorderOverride.color", + "description": "Color for the high contrast border updated", + "defaults": { + "dark": "debugToolBar.background", + "light": "debugToolBar.background", + "highContrast": "#6FC3DF" + } + }, + { + "id": "badgeForegroundOverride", + "description": "Color that fixes the issue with midnight blue ", + "defaults": { + "dark": "#FFFFFF", + "light": "badge.foreground", + "highContrast": "#FFFFFF" + } + } + ], + "configuration": { + "type": "object", + "title": "%deviceSimulatorExpressExtension.configuration.title%", + "properties": { + "deviceSimulatorExpress.configNewEnvironmentUponSwitch": { + "type": "boolean", + "default": false, + "description": "%deviceSimulatorExpressExtension.configuration.properties.configEnvOnChange%", + "scope": "resource" + }, + "deviceSimulatorExpress.enableUSBDetection": { + "type": "boolean", + "default": true + }, + "deviceSimulatorExpress.showDependencyInstall": { + "type": "boolean", + "default": true, + "description": "%deviceSimulatorExpressExtension.configuration.properties.dependencyChecker%", + "scope": "resource" + }, + "deviceSimulatorExpress.showNewFilePopup": { + "type": "boolean", + "default": true, + "scope": "resource" + }, + "deviceSimulatorExpress.debuggerServerPort": { + "type": "number", + "default": 5577, + "description": "%deviceSimulatorExpressExtension.configuration.properties.debuggerPort%", + "scope": "resource" + }, + "deviceSimulatorExpress.previewMode": { + "type": "boolean", + "default": false, + "description": "%deviceSimulatorExpressExtension.configuration.properties.previewMode%", + "scope": "resource" } - } } - } }, - "initialConfigurations": [ - { - "type": "deviceSimulatorExpress", - "request": "launch", - "name": "Device Simulator Express Debugger", - "console": "integratedTerminal" - } + "breakpoints": [ + { + "language": "python" + } ], - "configurationSnippets": [ - { - "label": "Device Simulator Express Debugger : Launch", - "description": "Device Simulator Express Debugger - A configuration for debugging a python code file for the Device Simulator Express simulator.", - "body": { - "type": "deviceSimulatorExpress", - "request": "launch", - "name": "Device Simulator Express Debugger", - "console": "integratedTerminal" + "debuggers": [ + { + "type": "deviceSimulatorExpress", + "label": "Device Simulator Express Debugger", + "languages": [ + "python" + ], + "configurationAttributes": { + "launch": { + "properties": { + "program": { + "type": "string", + "description": "Absolute path to the code file.", + "default": "${file}" + }, + "stopOnEntry": { + "type": "boolean", + "description": "Automatically stop after launch.", + "default": true + }, + "console": { + "enum": [ + "internalConsole", + "integratedTerminal", + "externalTerminal" + ], + "description": "Where to launch the debug target: internal console, integrated terminal, or external terminal.", + "default": "integratedTerminal" + }, + "args": { + "type": "array", + "description": "Command line arguments passed to the program.", + "default": [], + "items": { + "filePath": "string", + "serverPort": "string" + } + }, + "rules": { + "type": "array", + "description": "Debugger rules.", + "default": [], + "items": { + "path": "string", + "include": "boolean" + } + } + } + } + }, + "initialConfigurations": [ + { + "type": "deviceSimulatorExpress", + "request": "launch", + "name": "Device Simulator Express Debugger", + "console": "integratedTerminal" + } + ], + "configurationSnippets": [ + { + "label": "Device Simulator Express Debugger : Launch", + "description": "Device Simulator Express Debugger - A configuration for debugging a python code file for the Device Simulator Express simulator.", + "body": { + "type": "deviceSimulatorExpress", + "request": "launch", + "name": "Device Simulator Express Debugger", + "console": "integratedTerminal" + } + } + ] } - } ] - } + }, + "scripts": { + "start": "webpack-dev-server", + "vscode:prepublish": "npm run compile", + "build": "gulp build", + "clean": "gulp clean", + "compile": "npm-run-all compile:*", + "compile:extension": "gulp compile", + "compile:views": "webpack --mode development", + "watch": "npm-run-all -p watch:*", + "watch:extension": "tsc --watch", + "watch:views": "webpack --watch --mode development", + "pretest": "npm run compile", + "test": "npm-run-all test:*", + "test:extension-tests": "node ./out/test/runTest.js", + "test:ts": "jest", + "test:api-tests": "pytest src", + "lint": "npm-run-all lint:*", + "lint:ts": "tslint -c tslint.json src/**/*.{ts,tsx}", + "lint:python": "pylint src", + "format": "npm-run-all format:*", + "format:ts": "prettier --config .prettierrc.yaml --write src/**/*.{css,ts,tsx}", + "format:python": "black src", + "check": "npm-run-all check:*", + "check:ts": "prettier --config .prettierrc.yaml --check src/**/*.{css,ts,tsx}", + "check:python": "black src --check", + "package": "vsce package" + }, + "devDependencies": { + "@types/glob": "^7.1.1", + "@types/node": "^10.12.21", + "@types/react": "16.8.6", + "@types/react-dom": "16.8.4", + "@types/vscode": "^1.34.0", + "css-loader": "^1.0.0", + "del": "^4.0.0", + "event-stream": "^4.0.1", + "gulp": "^4.0.2", + "gulp-cli": "^2.1.0", + "gulp-filter": "^5.1.0", + "gulp-sourcemaps": "^2.6.5", + "gulp-typescript": "^5.0.1", + "less": "^3.7.0", + "less-loader": "^4.1.0", + "mocha": "^6.1.4", + "npm-run-all": "^4.1.3", + "prettier": "^1.19.1", + "react-scripts": "^3.4.0", + "style-loader": "^0.21.0", + "ts-import-plugin": "^1.5.4", + "ts-loader": "^4.4.2", + "tslint": "^5.12.1", + "tslint-config-prettier": "^1.18.0", + "tslint-microsoft-contrib": "^6.1.0", + "tslint-react": "^3.6.0", + "tslint-react-hooks": "^2.0.0", + "typescript": "^3.3.1", + "typescript-react-intl": "^0.4.0", + "version-from-git": "^1.1.1", + "vsce": "^1.47.0", + "vscode-nls-dev": "^3.2.6", + "vscode-test": "^1.0.0", + "webpack": "^4.15.1", + "webpack-cli": "^3.0.8" + }, + "dependencies": { + "@babel/preset-typescript": "^7.8.3", + "@testing-library/jest-dom": "^5.0.2", + "@testing-library/react": "^9.4.0", + "@types/jest": "^24.9.0", + "@types/open": "^6.1.0", + "@types/react-test-renderer": "^16.9.0", + "@types/socket.io": "^2.1.2", + "babel-jest": "^25.1.0", + "compare-versions": "^3.5.1", + "eventemitter2": "^5.0.1", + "glob": "^7.1.4", + "jest": "^25.1.0", + "jest-transform-css": "^2.0.0", + "office-ui-fabric-react": "^7.85.0", + "open": "^6.4.0", + "os": "^0.1.1", + "react": "^16.9.0", + "react-dom": "^16.9.0", + "react-intl": "^3.1.9", + "react-test-renderer": "^16.9.0", + "socket.io": "^2.2.0", + "svg-inline-react": "^3.1.0", + "ts-jest": "^25.0.0", + "util": "^0.12.1", + "vscode-extension-telemetry": "^0.1.1", + "vscode-nls": "^4.1.0" + }, + "eslintConfig": { + "extends": "react-app" + }, + "extensionDependencies": [ + "ms-python.python" ] - }, - "scripts": { - "vscode:prepublish": "npm run compile", - "build": "gulp build", - "clean": "gulp clean", - "compile": "npm-run-all compile:*", - "compile:extension": "gulp compile", - "compile:views": "webpack --mode development", - "watch": "npm-run-all -p watch:*", - "watch:extension": "tsc --watch", - "watch:views": "webpack --watch --mode development", - "pretest": "npm run compile", - "test": "npm-run-all test:*", - "test:extension-tests": "node ./out/test/runTest.js", - "test:react": "jest", - "test:api-tests": "pytest src", - "lint": "npm-run-all lint:*", - "lint:ts": "tslint -c tslint.json src/**/*.{ts,tsx}", - "lint:python": "pylint src", - "format": "npm-run-all format:*", - "format:ts": "prettier --config .prettierrc.yaml --write src/**/*.{css,ts,tsx}", - "format:python": "black src", - "check": "npm-run-all check:*", - "check:ts": "prettier --config .prettierrc.yaml --check src/**/*.{css,ts,tsx}", - "check:python": "black src --check", - "package": "vsce package" - }, - "devDependencies": { - "@types/glob": "^7.1.1", - "@types/node": "^10.12.21", - "@types/react": "16.8.18", - "@types/react-dom": "16.8.4", - "@types/vscode": "^1.34.0", - "css-loader": "^1.0.0", - "del": "^4.0.0", - "event-stream": "^4.0.1", - "gulp": "^4.0.2", - "gulp-cli": "^2.1.0", - "gulp-filter": "^5.1.0", - "gulp-sourcemaps": "^2.6.5", - "gulp-typescript": "^5.0.1", - "less": "^3.7.0", - "less-loader": "^4.1.0", - "mocha": "^6.1.4", - "npm-run-all": "^4.1.3", - "prettier": "^1.19.1", - "react-scripts": "3.0.1", - "style-loader": "^0.21.0", - "ts-import-plugin": "^1.5.4", - "ts-loader": "^4.4.2", - "tslint": "^5.12.1", - "tslint-config-prettier": "^1.18.0", - "tslint-microsoft-contrib": "^6.1.0", - "tslint-react": "^3.6.0", - "tslint-react-hooks": "^2.0.0", - "typescript": "^3.3.1", - "typescript-react-intl": "^0.4.0", - "version-from-git": "^1.1.1", - "vsce": "^1.47.0", - "vscode-nls-dev": "^3.2.6", - "vscode-test": "^1.0.0", - "webpack": "^4.15.1", - "webpack-cli": "^3.0.8" - }, - "dependencies": { - "@babel/preset-typescript": "^7.8.3", - "@testing-library/jest-dom": "^5.0.2", - "@testing-library/react": "^9.4.0", - "@types/jest": "^24.9.0", - "@types/open": "^6.1.0", - "@types/socket.io": "^2.1.2", - "babel-jest": "^25.1.0", - "compare-versions": "^3.5.1", - "eventemitter2": "^5.0.1", - "glob": "^7.1.4", - "jest": "^25.1.0", - "jest-transform-css": "^2.0.0", - "open": "^6.4.0", - "os": "^0.1.1", - "react": "^16.8.6", - "react-dom": "^16.8.6", - "react-intl": "^3.1.9", - "socket.io": "^2.2.0", - "svg-inline-react": "^3.1.0", - "ts-jest": "^25.0.0", - "util": "^0.12.1", - "vscode-extension-telemetry": "^0.1.1", - "vscode-nls": "^4.1.0" - }, - "eslintConfig": { - "extends": "react-app" - }, - "extensionDependencies": [ - "ms-python.python" - ] } diff --git a/package.nls.json b/package.nls.json index 49d2906a0..1092a8d4a 100644 --- a/package.nls.json +++ b/package.nls.json @@ -1,16 +1,19 @@ { - "deviceSimulatorExpressExtension.commands.changeBaudRate": "Change Baud Rate", - "deviceSimulatorExpressExtension.commands.closeSerialMonitor": "Close Serial Monitor", - "deviceSimulatorExpressExtension.commands.label": "Device Simulator Express", - "deviceSimulatorExpressExtension.commands.openSerialMonitor": "Open Serial Monitor", - "deviceSimulatorExpressExtension.commands.openSimulator": "Open Simulator", - "deviceSimulatorExpressExtension.commands.runSimulator": "Run Simulator", - "deviceSimulatorExpressExtension.commands.newFile": "New File", - "deviceSimulatorExpressExtension.commands.runDevice": "Deploy to Device", - "deviceSimulatorExpressExtension.commands.selectSerialPort": "Select Serial Port", + "deviceSimulatorExpressExtension.commands.common.installDependencies": "Install Extension Dependencies", + "deviceSimulatorExpressExtension.commands.common.label": "Device Simulator Express", + "deviceSimulatorExpressExtension.commands.common.runSimulator": "Run Simulator", + "deviceSimulatorExpressExtension.commands.cpx.changeBaudRate": "[Circuit Playground Express] Change Baud Rate", + "deviceSimulatorExpressExtension.commands.cpx.closeSerialMonitor": "[Circuit Playground Express] Close Serial Monitor", + "deviceSimulatorExpressExtension.commands.cpx.openSerialMonitor": "[Circuit Playground Express] Open Serial Monitor", + "deviceSimulatorExpressExtension.commands.cpx.openSimulator": "[Circuit Playground Express] Open Simulator", + "deviceSimulatorExpressExtension.commands.cpx.newFile": "[Circuit Playground Express] New File", + "deviceSimulatorExpressExtension.commands.cpx.deployToDevice": "[Circuit Playground Express] Deploy to Device", + "deviceSimulatorExpressExtension.commands.cpx.selectSerialPort": "[Circuit Playground Express] Select Serial Port", + "deviceSimulatorExpressExtension.commands.microbit.openSimulator": "[micro:bit] Open Simulator", + "deviceSimulatorExpressExtension.commands.microbit.newFile": "[micro:bit] New File", "deviceSimulatorExpressExtension.configuration.title": "Device Simulator Express configuration", - "deviceSimulatorExpressExtension.configuration.properties.open": "Whether to show 'Open Simulator' icon in editor title menu.", - "deviceSimulatorExpressExtension.configuration.properties.device": "Whether to show 'Run Device' icon in editor title menu.", - "deviceSimulatorExpressExtension.configuration.properties.simulator": "Whether to show 'Run Simulator' icon in editor title menu.", - "deviceSimulatorExpressExtension.configuration.properties.debuggerPort": "The port the Server will listen on for communication with the debugger." + "deviceSimulatorExpressExtension.configuration.properties.configEnvOnChange": "When you change the Python interpreter, the Device Simulator Express will automatically configure itself for the required dependencies.", + "deviceSimulatorExpressExtension.configuration.properties.debuggerPort": "The port the Server will listen on for communication with the debugger.", + "deviceSimulatorExpressExtension.configuration.properties.dependencyChecker": "Whether or not to ask for dependency downloads. If unchecked, the extension will default to never download dependencies, except when automatically creating a virtual environment in the extension files.", + "deviceSimulatorExpressExtension.configuration.properties.previewMode": "Enable this to test out and play with the new micro:bit simulator!" } diff --git a/src/adafruit_circuitplayground/constants.py b/src/adafruit_circuitplayground/constants.py index 26642a710..a96083795 100644 --- a/src/adafruit_circuitplayground/constants.py +++ b/src/adafruit_circuitplayground/constants.py @@ -7,6 +7,8 @@ BRIGHTNESS_RANGE_ERROR = "The brightness value should be a number between 0 and 1." +CPX = "CPX" + INDEX_ERROR = ( "The index is not a valid number, you can access the Neopixels from 0 to 9." ) @@ -25,23 +27,23 @@ VALID_PIXEL_ASSIGN_ERROR = "The pixel color value should be a tuple with three values between 0 and 255 or a hexadecimal color between 0x000000 and 0xFFFFFF." -TELEMETRY_EVENT_NAMES = { - "TAPPED": "API.TAPPED", - "PLAY_FILE": "API.PLAY.FILE", - "PLAY_TONE": "API.PLAY.TONE", - "START_TONE": "API.START.TONE", - "STOP_TONE": "API.STOP.TONE", - "DETECT_TAPS": "API.DETECT.TAPS", - "ADJUST_THRESHOLD": "API.ADJUST.THRESHOLD", - "RED_LED": "API.RED.LED", - "PIXELS": "API.PIXELS", -} ERROR_SENDING_EVENT = "Error trying to send event to the process : " TIME_DELAY = 0.03 -DEFAULT_PORT = "5577" - EVENTS_BUTTON_PRESS = ["button_a", "button_b", "switch"] EVENTS_SENSOR_CHANGED = ["temperature", "light", "motion_x", "motion_y", "motion_z"] + +ALL_EXPECTED_INPUT_EVENTS = [ + "button_a", + "button_b", + "switch", + "temperature", + "light", + "shake", + "motion_x", + "motion_y", + "motion_z", + "touch", +] diff --git a/src/adafruit_circuitplayground/debugger_communication_client.py b/src/adafruit_circuitplayground/debugger_communication_client.py deleted file mode 100644 index 0536550ea..000000000 --- a/src/adafruit_circuitplayground/debugger_communication_client.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT license. - -import sys -import json -import socketio -from . import express -from . import constants as CONSTANTS - - -# Create Socket Client -sio = socketio.Client(reconnection_attempts=2) - -# TODO: Get port from process_user_code.py via childprocess communication - - -# Initialize connection -def init_connection(port=CONSTANTS.DEFAULT_PORT): - sio.connect("http://localhost:{}".format(port)) - - -# Transfer the user's inputs to the API -def __update_api_state(data, expected_events): - try: - event_state = json.loads(data) - for event in expected_events: - express.cpx._Express__state[event] = event_state.get( - event, express.cpx._Express__state[event] - ) - except Exception as e: - print(CONSTANTS.ERROR_SENDING_EVENT, e, file=sys.stderr, flush=True) - - -# Method : Update State -def update_state(state): - sio.emit("updateState", state) - - -## Events Handlers ## - - -# Event : Button pressed (A, B, A+B, Switch) -@sio.on("button_press") -def button_press(data): - __update_api_state(data, CONSTANTS.EVENTS_BUTTON_PRESS) - - -# Event : Sensor changed (Temperature, light, Motion) -@sio.on("sensor_changed") -def sensor_changed(data): - __update_api_state(data, CONSTANTS.EVENTS_SENSOR_CHANGED) diff --git a/src/adafruit_circuitplayground/express.py b/src/adafruit_circuitplayground/express.py index f08e1b65c..884f4a723 100644 --- a/src/adafruit_circuitplayground/express.py +++ b/src/adafruit_circuitplayground/express.py @@ -5,12 +5,15 @@ import sys import os import playsound + +from common import utils +from common.telemetry import telemetry_py +from common.telemetry_events import TelemetryEvent from .pixel import Pixel -from . import utils from . import constants as CONSTANTS from collections import namedtuple from applicationinsights import TelemetryClient -from .telemetry import telemetry_py +import common Acceleration = namedtuple("acceleration", ["x", "y", "z"]) @@ -50,25 +53,29 @@ def __init__(self): @property def acceleration(self): + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_ACCELERATION) return Acceleration( self.__state["motion_x"], self.__state["motion_y"], self.__state["motion_z"] ) @property def button_a(self): + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_BUTTON_A) return self.__state["button_a"] @property def button_b(self): + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_BUTTON_B) return self.__state["button_b"] @property def detect_taps(self): - telemetry_py.send_telemetry("DETECT_TAPS") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_DETECT_TAPS) return self.__state["detect_taps"] @detect_taps.setter def detect_taps(self, value): + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_DETECT_TAPS) value_int = int(value) self.__state["detect_taps"] = ( value_int if (value_int == 1 or value_int == 2) else 1 @@ -78,36 +85,45 @@ def detect_taps(self, value): def tapped(self): """ Not Implemented! """ - telemetry_py.send_telemetry("TAPPED") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_TAPPED) raise NotImplementedError(CONSTANTS.NOT_IMPLEMENTED_ERROR) @property def red_led(self): - telemetry_py.send_telemetry("RED_LED") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_RED_LED) return self.__state["red_led"] @red_led.setter def red_led(self, value): - telemetry_py.send_telemetry("RED_LED") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_RED_LED) self.__state["red_led"] = bool(value) self.__show() @property def switch(self): + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_SWITCH) return self.__state["switch"] @property def temperature(self): + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_TEMPERATURE) return self.__state["temperature"] @property def light(self): + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_LIGHT) return self.__state["light"] def __show(self): - utils.show(self.__state, self.__debug_mode) + if self.__debug_mode: + common.debugger_communication_client.debug_send_to_simulator( + self.__state, CONSTANTS.CPX + ) + else: + utils.send_to_simulator(self.__state, CONSTANTS.CPX) def __touch(self, i): + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_TOUCH) return self.__state["touch"][i - 1] @property @@ -142,14 +158,15 @@ def adjust_touch_threshold(self, adjustement): """Not implemented! The CPX Simulator doesn't use capacitive touch threshold. """ - telemetry_py.send_telemetry("ADJUST_THRESHOLD") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_ADJUST_THRESHOLD) raise NotImplementedError(CONSTANTS.NOT_IMPLEMENTED_ERROR) def shake(self, shake_threshold=30): + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_SHAKE) return self.__state["shake"] def play_file(self, file_name): - telemetry_py.send_telemetry("PLAY_FILE") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_PLAY_FILE) file_name = utils.remove_leading_slashes(file_name) abs_path_parent_dir = os.path.abspath( os.path.join(self.__abs_path_to_code_file, os.pardir) @@ -174,20 +191,26 @@ def play_file(self, file_name): def play_tone(self, frequency, duration): """ Not Implemented! """ - telemetry_py.send_telemetry("PLAY_TONE") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_PLAY_TONE) raise NotImplementedError(CONSTANTS.NOT_IMPLEMENTED_ERROR) def start_tone(self, frequency): """ Not Implemented! """ - telemetry_py.send_telemetry("START_TONE") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_START_TONE) raise NotImplementedError(CONSTANTS.NOT_IMPLEMENTED_ERROR) def stop_tone(self): """ Not Implemented! """ - telemetry_py.send_telemetry("STOP_TONE") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_STOP_TONE) raise NotImplementedError(CONSTANTS.NOT_IMPLEMENTED_ERROR) + def update_state(self, new_state): + for event in CONSTANTS.ALL_EXPECTED_INPUT_EVENTS: + self._Express__state[event] = new_state.get( + event, self._Express__state[event] + ) + cpx = Express() diff --git a/src/adafruit_circuitplayground/pixel.py b/src/adafruit_circuitplayground/pixel.py index 3833de2f7..18e0028fc 100644 --- a/src/adafruit_circuitplayground/pixel.py +++ b/src/adafruit_circuitplayground/pixel.py @@ -3,11 +3,12 @@ import json import sys +import common + +from common import utils +from common.telemetry import telemetry_py +from common.telemetry_events import TelemetryEvent from . import constants as CONSTANTS -from . import utils -from applicationinsights import TelemetryClient -from . import constants as CONSTANTS -from .telemetry import telemetry_py class Pixel: @@ -19,7 +20,13 @@ def __init__(self, state, debug_mode=False): def show(self): # Send the state to the extension so that React re-renders the Webview - utils.show(self.__state, self.__debug_mode) + # or send the state to the debugger (within this library) + if self.__debug_mode: + common.debugger_communication_client.debug_send_to_simulator( + self.__state, CONSTANTS.CPX + ) + else: + common.utils.send_to_simulator(self.__state, CONSTANTS.CPX) def __show_if_auto_write(self): if self.auto_write: @@ -32,11 +39,11 @@ def __getitem__(self, index): if type(index) is not slice: if not self.__valid_index(index): raise IndexError(CONSTANTS.INDEX_ERROR) - telemetry_py.send_telemetry("PIXELS") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_PIXELS) return self.__state["pixels"][index] def __setitem__(self, index, val): - telemetry_py.send_telemetry("PIXELS") + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_PIXELS) is_slice = False if type(index) is slice: is_slice = True @@ -109,12 +116,14 @@ def __valid_rgb_value(self, pixValue): @property def brightness(self): + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_BRIGHTNESS) return self.__state["brightness"] @brightness.setter def brightness(self, brightness): if not self.__valid_brightness(brightness): raise ValueError(CONSTANTS.BRIGHTNESS_RANGE_ERROR) + telemetry_py.send_telemetry(TelemetryEvent.CPX_API_BRIGHTNESS) self.__state["brightness"] = brightness self.__show_if_auto_write() diff --git a/src/adafruit_circuitplayground/telemetry.py b/src/adafruit_circuitplayground/telemetry.py deleted file mode 100644 index 9fd1edb1c..000000000 --- a/src/adafruit_circuitplayground/telemetry.py +++ /dev/null @@ -1,41 +0,0 @@ -from . import constants as CONSTANTS -from applicationinsights import TelemetryClient - - -class Telemetry: - def __init__(self): - # State of the telemetry - self.__enable_telemetry = True - self.telemetry_state = { - "DETECT_TAPS": False, - "TAPPED": False, - "RED_LED": False, - "ADJUST_THRESHOLD": False, - "PLAY_FILE": False, - "PLAY_TONE": False, - "START_TONE": False, - "STOP_TONE": False, - "PIXELS": False, - } - self.telemetry_client = TelemetryClient("__AIKEY__") - self.extension_name = "__EXTENSIONNAME__" - - def send_telemetry(self, event_name): - if ( - self.__enable_telemetry - and self.telemetry_available() - and not self.telemetry_state[event_name] - ): - self.telemetry_client.track_event( - "{}/{}".format( - self.extension_name, CONSTANTS.TELEMETRY_EVENT_NAMES[event_name] - ) - ) - self.telemetry_client.flush() - self.telemetry_state[event_name] = True - - def telemetry_available(self): - return self.telemetry_client.context.instrumentation_key != "__AIKEY__" - - -telemetry_py = Telemetry() diff --git a/src/adafruit_circuitplayground/test/test_debugger_communication_client.py b/src/adafruit_circuitplayground/test/test_debugger_communication_client.py deleted file mode 100644 index b25e27eb8..000000000 --- a/src/adafruit_circuitplayground/test/test_debugger_communication_client.py +++ /dev/null @@ -1,63 +0,0 @@ -import pytest -import json # Remove -from unittest import mock -import socketio - -from .. import express -from .. import debugger_communication_client - - -class TestDebuggerCommunicationClient(object): - @mock.patch("socketio.Client.connect") - def test_init_connection(self, mock_connect): - mock_connect.return_value = None - debugger_communication_client.init_connection() - mock_connect.assert_called_once() - - def test_init_connection1(self): - socketio.Client.connect = mock.Mock() - socketio.Client.connect.return_value = None - debugger_communication_client.init_connection() - socketio.Client.connect.assert_called_once() - - def test_update_state(self): - socketio.Client.emit = mock.Mock() - socketio.Client.emit.return_value = None - debugger_communication_client.update_state({}) - socketio.Client.emit.assert_called_once() - - @mock.patch.dict( - express.cpx._Express__state, - {"button_a": False, "button_b": False, "switch": True}, - clear=True, - ) - def test_button_press(self): - data = {"button_a": True, "button_b": True, "switch": True} - serialized_data = json.dumps(data) - debugger_communication_client.button_press(serialized_data) - assert data == express.cpx._Express__state - - @mock.patch.dict( - express.cpx._Express__state, - {"temperature": 0, "light": 0, "motion_x": 0, "motion_y": 0, "motion_z": 0}, - clear=True, - ) - def test_sensor_changed(self): - data = { - "temperature": 1, - "light": 2, - "motion_x": 3, - "motion_y": 4, - "motion_z": 5, - } - serialized_data = json.dumps(data) - debugger_communication_client.sensor_changed(serialized_data) - assert data == express.cpx._Express__state - - @mock.patch("builtins.print") - @mock.patch.dict(express.cpx._Express__state, {}, clear=True) - def test_update_api_state_fail(self, mocked_print): - data = [] - debugger_communication_client.sensor_changed(data) - # Exception is caught and a print is stated to stderr - mocked_print.assert_called_once() diff --git a/src/adafruit_circuitplayground/test/test_utils.py b/src/adafruit_circuitplayground/test/test_utils.py index 3c25128e6..a3c38e1b1 100644 --- a/src/adafruit_circuitplayground/test/test_utils.py +++ b/src/adafruit_circuitplayground/test/test_utils.py @@ -3,7 +3,7 @@ from unittest import mock from .. import constants as CONSTANTS -from .. import utils +from common import utils class TestUtils(object): diff --git a/src/adafruit_circuitplayground/utils.py b/src/adafruit_circuitplayground/utils.py deleted file mode 100644 index 14fddf227..000000000 --- a/src/adafruit_circuitplayground/utils.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT license. - -import sys -import json -import copy -import time -from . import constants as CONSTANTS -from . import debugger_communication_client -from applicationinsights import TelemetryClient - -previous_state = {} - - -def show(state, debug_mode=False): - global previous_state - if state != previous_state: - previous_state = copy.deepcopy(state) - message = {"type": "state", "data": json.dumps(state)} - if debug_mode: - debugger_communication_client.update_state(json.dumps(message)) - else: - print(json.dumps(message) + "\0", end="", file=sys.__stdout__, flush=True) - time.sleep(CONSTANTS.TIME_DELAY) - - -def remove_leading_slashes(string): - string = string.lstrip("\\/") - return string - - -def escape_if_OSX(file_name): - if sys.platform.startswith(CONSTANTS.MAC_OS): - file_name = file_name.replace(" ", "%20") - return file_name diff --git a/src/check_if_venv.py b/src/check_if_venv.py new file mode 100644 index 000000000..45fd3dd2b --- /dev/null +++ b/src/check_if_venv.py @@ -0,0 +1,11 @@ +# from https://stackoverflow.com/questions/1871549/determine-if-python-is-running-inside-virtualenv +import sys + +isVenv = hasattr(sys, "real_prefix") or ( + hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix +) + +# prints result for frontend to read +# 1 -> is a venv +# 0 -> is NOT a venv +print(int(isVenv)) diff --git a/src/check_python_dependencies.py b/src/check_python_dependencies.py new file mode 100644 index 000000000..2e8f5ba13 --- /dev/null +++ b/src/check_python_dependencies.py @@ -0,0 +1,20 @@ +# from https://stackoverflow.com/questions/16294819/check-if-my-python-has-all-required-packages +import sys +import pkg_resources +import python_constants as CONSTANTS + + +def check_for_dependencies(): + with open(f"{sys.path[0]}/requirements.txt") as f: + dependencies = [x.strip() for x in f.readlines()] + + # here, if a dependency is not met, a DistributionNotFound or VersionConflict + # exception is caught and replaced with a new exception with a clearer description. + try: + pkg_resources.require(dependencies) + except (pkg_resources.DistributionNotFound, pkg_resources.VersionConflict) as e: + raise Exception(CONSTANTS.DEPEND_ERR) + + +if __name__ == "__main__": + check_for_dependencies() diff --git a/src/common/__init__.py b/src/common/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/common/constants.py b/src/common/constants.py new file mode 100644 index 000000000..73984933a --- /dev/null +++ b/src/common/constants.py @@ -0,0 +1,10 @@ +MAC_OS = "darwin" + +ERROR_SENDING_EVENT = "Error trying to send event to the process : " + +ACTIVE_DEVICE_FIELD = "active_device" +STATE_FIELD = "state" + +CONNECTION_ATTEMPTS = 10 +TIME_DELAY = 0.03 +DEFAULT_PORT = "5577" diff --git a/src/common/debugger_communication_client.py b/src/common/debugger_communication_client.py new file mode 100644 index 000000000..23035c6f9 --- /dev/null +++ b/src/common/debugger_communication_client.py @@ -0,0 +1,86 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +import sys +import json +import socketio +import copy + +from . import constants as CONSTANTS +from . import utils +import threading + + +from adafruit_circuitplayground.express import cpx +from adafruit_circuitplayground.constants import CPX + +from microbit.__model.microbit_model import __mb as mb +from microbit.__model.constants import MICROBIT + + +device_dict = {CPX: cpx, MICROBIT: mb} +processing_state_event = threading.Event() +previous_state = {} + +# similar to utils.send_to_simulator, but for debugging +# (needs handle to device-specific debugger) +def debug_send_to_simulator(state, active_device): + global previous_state + if state != previous_state: + previous_state = copy.deepcopy(state) + + updated_state = utils.update_state_with_device_name(state, active_device) + message = utils.create_message(updated_state) + + update_state(json.dumps(message)) + + +# Create Socket Client +sio = socketio.Client(reconnection_attempts=CONSTANTS.CONNECTION_ATTEMPTS) + +# TODO: Get port from process_user_code.py via childprocess communication + + +# Initialize connection +def init_connection(port=CONSTANTS.DEFAULT_PORT): + sio.connect("http://localhost:{}".format(port)) + + +# Transfer the user's inputs to the API +def __update_api_state(data): + try: + event_state = json.loads(data) + active_device_string = event_state.get(CONSTANTS.ACTIVE_DEVICE_FIELD) + + if active_device_string is not None: + active_device = device_dict.get(active_device_string) + if active_device is not None: + active_device.update_state(event_state.get(CONSTANTS.STATE_FIELD)) + + except Exception as e: + print(CONSTANTS.ERROR_SENDING_EVENT, e, file=sys.stderr, flush=True) + + +# Method : Update State +def update_state(state): + processing_state_event.clear() + sio.emit("updateState", state) + processing_state_event.wait() + + +# Event : Button pressed (A, B, A+B, Switch) +# or Sensor changed (Temperature, light, Motion) +@sio.on("input_changed") +def input_changed(data): + sio.emit("receivedState", data) + __update_api_state(data) + + +@sio.on("received_state") +def received_state(data): + processing_state_event.set() + + +@sio.on("process_disconnect") +def process_disconnect(data): + sio.disconnect() diff --git a/src/common/telemetry.py b/src/common/telemetry.py new file mode 100644 index 000000000..44a22d058 --- /dev/null +++ b/src/common/telemetry.py @@ -0,0 +1,31 @@ +from applicationinsights import TelemetryClient +from .telemetry_events import TelemetryEvent + + +class Telemetry: + def __init__(self): + # State of the telemetry + self.__enable_telemetry = True + self.telemetry_client = TelemetryClient("__AIKEY__") + self.telemetry_state = dict.fromkeys( + [name for name, _ in TelemetryEvent.__members__.items()], False + ) + self.extension_name = "Device Simulator Express" + + def send_telemetry(self, event_name: TelemetryEvent): + if ( + self.__enable_telemetry + and self.telemetry_available() + and not self.telemetry_state[event_name.name] + ): + self.telemetry_client.track_event( + f"{self.extension_name}/{event_name.value}" + ) + self.telemetry_client.flush() + self.telemetry_state[event_name.name] = True + + def telemetry_available(self): + return self.telemetry_client.context.instrumentation_key == "__AIKEY__" + + +telemetry_py = Telemetry() diff --git a/src/common/telemetry_events.py b/src/common/telemetry_events.py new file mode 100644 index 000000000..d150076d0 --- /dev/null +++ b/src/common/telemetry_events.py @@ -0,0 +1,33 @@ +import enum + + +class TelemetryEvent(enum.Enum): + CPX_API_ACCELERATION = "CPX.API.ACCELERATION" + CPX_API_BUTTON_A = "CPX.API.BUTTON.A" + CPX_API_BUTTON_B = "CPX.API.BUTTON.B" + CPX_API_SWITCH = "CPX.API.SWITCH" + CPX_API_TEMPERATURE = "CPX.API.TEMPERATURE" + CPX_API_BRIGHTNESS = "CPX.API.BRIGHTNESS" + CPX_API_LIGHT = "CPX.API.LIGHT" + CPX_API_TOUCH = "CPX.API.TOUCH" + CPX_API_SHAKE = "CPX.API.SHAKE" + CPX_API_TAPPED = "CPX.API.TAPPED" + CPX_API_PLAY_FILE = "CPX.API.PLAY.FILE" + CPX_API_PLAY_TONE = "CPX.API.PLAY.TONE" + CPX_API_START_TONE = "CPX.API.START.TONE" + CPX_API_STOP_TONE = "CPX.API.STOP.TONE" + CPX_API_DETECT_TAPS = "CPX.API.DETECT.TAPS" + CPX_API_ADJUST_THRESHOLD = "CPX.API.ADJUST.THRESHOLD" + CPX_API_RED_LED = "CPX.API.RED.LED" + CPX_API_PIXELS = "CPX.API.PIXELS" + MICROBIT_API_TEMPERATURE = "MICROBIT.API.TEMPERATURE" + MICROBIT_API_ACCELEROMETER = "MICROBIT.API.ACCELEROMETER" + MICROBIT_API_GESTURE = "MICROBIT.API.GESTURE" + MICROBIT_API_DISPLAY_SCROLL = "MICROBIT.API.DISPLAY.SCROLL" + MICROBIT_API_DISPLAY_SHOW = "MICROBIT.API.DISPLAY.SHOW" + MICROBIT_API_DISPLAY_OTHER = "MICROBIT.API.DISPLAY_OTHER" + MICROBIT_API_LIGHT_LEVEL = "MICROBIT.API.LIGHT.LEVEL" + MICROBIT_API_IMAGE_CREATION = "MICROBIT.API.IMAGE.CREATION" + MICROBIT_API_IMAGE_OTHER = "MICROBIT.API.IMAGE.OTHER" + MICROBIT_API_IMAGE_STATIC = "MICROBIT.API.IMAGE.STATIC" + MICROBIT_API_BUTTON = "MICROBIT.API.BUTTON" diff --git a/src/common/test/test_debugger_communication_client.py b/src/common/test/test_debugger_communication_client.py new file mode 100644 index 000000000..0706ad149 --- /dev/null +++ b/src/common/test/test_debugger_communication_client.py @@ -0,0 +1,178 @@ +import pytest +import json # Remove +from unittest import mock +import socketio +import threading + +from adafruit_circuitplayground import express +from common import debugger_communication_client +from common import constants as CONSTANTS +from adafruit_circuitplayground.constants import CPX + + +class TestDebuggerCommunicationClient(object): + @mock.patch("socketio.Client.connect") + def test_init_connection(self, mock_connect): + mock_connect.return_value = None + debugger_communication_client.init_connection() + mock_connect.assert_called_once() + + def test_init_connection1(self): + socketio.Client.connect = mock.Mock() + socketio.Client.connect.return_value = None + debugger_communication_client.init_connection() + socketio.Client.connect.assert_called_once() + + def test_update_state(self): + threading.Event.clear = mock.Mock() + threading.Event.wait = mock.Mock() + socketio.Client.emit = mock.Mock() + socketio.Client.emit.return_value = None + debugger_communication_client.update_state( + {CONSTANTS.ACTIVE_DEVICE_FIELD: CPX, CONSTANTS.STATE_FIELD: {}} + ) + socketio.Client.emit.assert_called_once() + + @mock.patch.dict( + express.cpx._Express__state, + { + "brightness": 1.0, + "button_a": False, + "button_b": False, + "pixels": [ + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + ], + "red_led": False, + "switch": False, + "temperature": 0, + "light": 0, + "motion_x": 0, + "motion_y": 0, + "motion_z": 0, + "touch": [False] * 7, + "shake": False, + }, + clear=True, + ) + def test_button_press(self): + data = { + CONSTANTS.ACTIVE_DEVICE_FIELD: CPX, + CONSTANTS.STATE_FIELD: {"button_a": True, "button_b": True, "switch": True}, + } + expected_data = { + "brightness": 1.0, + "button_a": True, + "button_b": True, + "pixels": [ + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + ], + "red_led": False, + "switch": True, + "temperature": 0, + "light": 0, + "motion_x": 0, + "motion_y": 0, + "motion_z": 0, + "touch": [False] * 7, + "shake": False, + } + serialized_data = json.dumps(data) + debugger_communication_client.input_changed(serialized_data) + assert expected_data == express.cpx._Express__state + + @mock.patch.dict( + express.cpx._Express__state, + { + "brightness": 1.0, + "button_a": False, + "button_b": False, + "pixels": [ + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + ], + "red_led": False, + "switch": False, + "temperature": 0, + "light": 0, + "motion_x": 0, + "motion_y": 0, + "motion_z": 0, + "touch": [False] * 7, + "shake": False, + }, + clear=True, + ) + def test_input_changed(self): + data = { + CONSTANTS.ACTIVE_DEVICE_FIELD: CPX, + CONSTANTS.STATE_FIELD: { + "temperature": 1, + "light": 2, + "motion_x": 3, + "motion_y": 4, + "motion_z": 5, + }, + } + expected_data = { + "brightness": 1.0, + "button_a": False, + "button_b": False, + "pixels": [ + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + (0, 0, 0), + ], + "red_led": False, + "switch": False, + "temperature": 1, + "light": 2, + "motion_x": 3, + "motion_y": 4, + "motion_z": 5, + "touch": [False] * 7, + "shake": False, + } + serialized_data = json.dumps(data) + debugger_communication_client.input_changed(serialized_data) + assert expected_data == express.cpx._Express__state + + @mock.patch("builtins.print") + @mock.patch.dict(express.cpx._Express__state, {}, clear=True) + def test_update_api_state_fail(self, mocked_print): + data = [] + debugger_communication_client.input_changed(data) + # Exception is caught and a print is stated to stderr + mocked_print.assert_called_once() diff --git a/src/common/utils.py b/src/common/utils.py new file mode 100644 index 000000000..a468044f7 --- /dev/null +++ b/src/common/utils.py @@ -0,0 +1,49 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +from . import constants as CONSTANTS +import json +import copy +import time +import sys + +previous_state = {} + + +def update_state_with_device_name(state, device_name): + updated_state = dict(state) + + state_ext = { + "device_name": device_name, + } + updated_state.update(state_ext) + + return updated_state + + +def create_message(state): + message = {"type": "state", "data": json.dumps(state)} + return message + + +def send_to_simulator(state, device_name): + global previous_state + + updated_state = update_state_with_device_name(state, device_name) + message = create_message(updated_state) + + if updated_state != previous_state: + previous_state = copy.deepcopy(updated_state) + print(json.dumps(message) + "\0", end="", file=sys.__stdout__, flush=True) + time.sleep(CONSTANTS.TIME_DELAY) + + +def remove_leading_slashes(string): + string = string.lstrip("\\/") + return string + + +def escape_if_OSX(file_name): + if sys.platform.startswith(CONSTANTS.MAC_OS): + file_name = file_name.replace(" ", "%20") + return file_name diff --git a/src/constants.ts b/src/constants.ts index 0a2db62dc..7c537c122 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -17,18 +17,23 @@ const localize: nls.LocalizeFunc = nls.config({ })(); export const CONFIG = { + CONFIG_ENV_ON_SWITCH: + "deviceSimulatorExpress.configNewEnvironmentUponSwitch", + PYTHON_PATH: "python.pythonPath", + ENABLE_PREVIEW_MODE: "deviceSimulatorExpress.previewMode", SHOW_DEPENDENCY_INSTALL: "deviceSimulatorExpress.showDependencyInstall", SHOW_NEW_FILE_POPUP: "deviceSimulatorExpress.showNewFilePopup", }; export const CONSTANTS = { DEBUG_CONFIGURATION_TYPE: "deviceSimulatorExpress", - DEPENDENCY_CHECKER: { - PIP3: "pip3", - PYTHON: "python", - PYTHON3: "python3.7", + DEVICE_NAME: { + CPX: "CPX", + MICROBIT: "micro:bit", }, ERROR: { + BAD_PYTHON_PATH: + 'Your interpreter is not pointing to a valid Python executable. Please select a different interpreter (CTRL+SHIFT+P and type "python.selectInterpreter") and restart the application', COMPORT_UNKNOWN_ERROR: "Writing to COM port (GetOverlappedResult): Unknown error code 121", CPX_FILE_ERROR: localize( @@ -46,7 +51,8 @@ export const CONSTANTS = { "[ERROR] A debugging session is currently in progress, please stop it before running your code. \n" ), DEPENDENCY_DOWNLOAD_ERROR: - "Package downloads failed. Some functionalities may not work. Try restarting the simulator or review the installation docs.", + "Dependency download could not be completed. Functionality may be limited. Please review the installation docs.", + FAILED_TO_OPEN_SERIAL_PORT: (port: string): string => { return localize( "error.failedToOpenSerialPort", @@ -67,10 +73,18 @@ export const CONSTANTS = { "error.incorrectFileNameForDevicePopup", 'Seems like you have a different file name than what CPX requires, please rename it to "code.py" or "main.py".' ), + INSTALLATION_ERROR: localize( + "error.installationError", + "Installation Error" + ), INVALID_FILE_EXTENSION_DEBUG: localize( "error.invalidFileExtensionDebug", "The file you tried to run isn't a Python file." ), + INVALID_PYTHON_PATH: localize( + "error.invalidPythonPath", + 'We found that your selected Python interpreter version is too low to run the extension. Please upgrade to version 3.7+ or select a different interpreter (CTRL+SHIFT+P and type "python.selectInterpreter") and restart the application.' + ), NO_DEVICE: localize( "error.noDevice", "No plugged in boards detected. Please double check if your board is connected and/or properly formatted" @@ -87,6 +101,10 @@ export const CONSTANTS = { "error.noProgramFoundDebug", "Cannot find a program to debug." ), + NO_PIP: localize( + "error.noPip", + "We found that you don't have Pip installed on your computer, please install it and try again." + ), NO_PYTHON_PATH: localize( "error.noPythonPath", "We found that you don't have Python 3 installed on your computer, please install the latest version, add it to your PATH and try again." @@ -105,12 +123,16 @@ export const CONSTANTS = { }, FILESYSTEM: { OUTPUT_DIRECTORY: "out", - PYTHON_LIBS_DIR: "python_libs", + PYTHON_VENV_DIR: "venv", }, INFO: { + ALREADY_SUCCESSFUL_INSTALL: localize( + "info.successfulInstall", + "Your current configuration is already successfully set up for the Device Simulator Expresss." + ), ARE_YOU_SURE: localize( "info.areYouSure", - "Are you sure you don't want to install the dependencies? The extension can't run without installing it" + "Are you sure you don't want to install the dependencies? The extension can't run without installing them." ), CLOSED_SERIAL_PORT: (port: string) => { return localize( @@ -147,19 +169,23 @@ export const CONSTANTS = { }, FIRST_TIME_WEBVIEW: localize( "info.firstTimeWebview", - 'To reopen the simulator click on the "Open Simulator" button on the upper right corner of the text editor, or select the command "Open Simulator" from command palette.' + 'To reopen the simulator select the command "Open Simulator" from command palette.' ), INCORRECT_FILE_NAME_FOR_SIMULATOR_POPUP: localize( "info.incorrectFileNameForSimulatorPopup", 'We want your code to work on your actual board as well. Make sure you name your file "code.py" or "main.py" to be able to run your code on an actual physical device' ), - INSTALLING_PYTHON_DEPENDENCIES: localize( - "info.installingPythonDependencies", - "The Python packages are currently being installed. You will be prompt a message telling you when the installation is done." + INSTALLING_PYTHON_VENV: localize( + "info.installingPythonVenv", + "A virtual environment is currently being created. The required Python packages will be installed. You will be prompted a message telling you when the installation is done." ), - INSTALL_PYTHON_DEPENDENCIES: localize( + INSTALL_PYTHON_DEPS: localize( "info.installPythonDependencies", - "Do you want us to try and install this extensions dependencies for you?" + "Do you want us to try and install this extension's dependencies on your selected Python interpreter for you?" + ), + INSTALL_PYTHON_VENV: localize( + "info.installPythonVenv", + "Do you want us to try and install this extension's dependencies via virtual environment for you?" ), INVALID_FILE_NAME_DEBUG: localize( "info.invalidFileNameDebug", @@ -189,15 +215,27 @@ export const CONSTANTS = { RUNNING_CODE: localize("info.runningCode", "Running user code"), SUCCESSFUL_INSTALL: localize( "info.successfulInstall", - "Successfully installed Python dependencies." + "Successfully set up the Python environment." ), - THIRD_PARTY_WEBSITE: localize( - "info.thirdPartyWebsite", + THIRD_PARTY_WEBSITE_ADAFRUIT: localize( + "info.thirdPartyWebsiteAdafruit", 'By clicking "Agree and Proceed" you will be redirected to adafruit.com, a third party website not managed by Microsoft. Please note that your activity on adafruit.com is subject to Adafruit\'s privacy policy' ), + THIRD_PARTY_WEBSITE_PIP: localize( + "info.thirdPartyWebsitePip", + 'By clicking "Agree and Proceed" you will be redirected to pip.pypa.io, a third party website not managed by Microsoft. Please note that your activity on pip.pypa.io is subject to PyPA\'s privacy policy' + ), + THIRD_PARTY_WEBSITE_PYTHON: localize( + "info.thirdPartyWebsitePython", + 'By clicking "Agree and Proceed" you will be redirected to python.org, a third party website not managed by Microsoft. Please note that your activity on python.org is subject to Python\'s privacy policy' + ), + UPDATED_TO_EXTENSION_VENV: localize( + "info.updatedToExtensionsVenv", + "Automatically updated interpreter to point to extension's virtual environment." + ), WELCOME_OUTPUT_TAB: localize( "info.welcomeOutputTab", - "Welcome to the Adafruit Simulator output tab!\n\n" + "Welcome to the Device Simulator Express output tab!\n\n" ), }, LABEL: { @@ -207,6 +245,7 @@ export const CONSTANTS = { ), }, LINKS: { + DOWNLOAD_PIP: "https://pip.pypa.io/en/stable/installing/", DOWNLOAD_PYTHON: "https://www.python.org/downloads/", EXAMPLE_CODE: "https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/tree/master/examples", @@ -233,6 +272,10 @@ export const CONSTANTS = { ), }, NAME: localize("name", "Device Simulator Express"), + TEMPLATE: { + CPX: "cpx_template.py", + MICROBIT: "microbit_template.py", + }, WARNING: { ACCEPT_AND_RUN: localize( "warning.agreeAndRun", @@ -274,57 +317,72 @@ export enum CONFIG_KEYS { export enum TelemetryEventName { FAILED_TO_OPEN_SIMULATOR = "SIMULATOR.FAILED_TO_OPEN", + // Debugger + CPX_DEBUGGER_INIT_SUCCESS = "CPX.DEBUGGER.INIT.SUCCESS", + CPX_DEBUGGER_INIT_FAIL = "CPX.DEBUGGER.INIT.FAIL", + MICROBIT_DEBUGGER_INIT_SUCCESS = "MICROBIT.DEBUGGER.INIT.SUCCESS", + MICROBIT_DEBUGGER_INIT_FAIL = "MICROBIT.DEBUGGER.INIT.FAIL", + // Extension commands - COMMAND_DEPLOY_DEVICE = "COMMAND.DEPLOY.DEVICE", - COMMAND_NEW_FILE = "COMMAND.NEW.FILE", - COMMAND_OPEN_SIMULATOR = "COMMAND.OPEN.SIMULATOR", COMMAND_RUN_SIMULATOR_BUTTON = "COMMAND.RUN.SIMULATOR_BUTTON", COMMAND_RUN_PALETTE = "COMMAND.RUN.PALETTE", - COMMAND_RUN_EDITOR_ICON = "COMMAND.RUN.EDITOR_ICON", - COMMAND_SERIAL_MONITOR_CHOOSE_PORT = "COMMAND.SERIAL_MONITOR.CHOOSE_PORT", - COMMAND_SERIAL_MONITOR_OPEN = "COMMAND.SERIAL_MONITOR.OPEN", - COMMAND_SERIAL_MONITOR_BAUD_RATE = "COMMAND.SERIAL_MONITOR.BAUD_RATE", - COMMAND_SERIAL_MONITOR_CLOSE = "COMMAND.SERIAL_MONITOR.CLOSE", + COMMAND_INSTALL_EXTENSION_DEPENDENCIES = "COMMAND.INSTALL.EXTENSION.DEPENDENCIES", + + CPX_COMMAND_DEPLOY_DEVICE = "CPX.COMMAND.DEPLOY.DEVICE", + CPX_COMMAND_NEW_FILE = "CPX.COMMAND.NEW.FILE.CPX", + CPX_COMMAND_OPEN_SIMULATOR = "CPX.COMMAND.OPEN.SIMULATOR", + CPX_COMMAND_SERIAL_MONITOR_CHOOSE_PORT = "CPX.COMMAND.SERIAL_MONITOR.CHOOSE_PORT", + CPX_COMMAND_SERIAL_MONITOR_OPEN = "CPX.COMMAND.SERIAL_MONITOR.OPEN", + CPX_COMMAND_SERIAL_MONITOR_BAUD_RATE = "CPX.COMMAND.SERIAL_MONITOR.BAUD_RATE", + CPX_COMMAND_SERIAL_MONITOR_CLOSE = "CPX.COMMAND.SERIAL_MONITOR.CLOSE", + + MICROBIT_COMMAND_NEW_FILE = "MICROBIT.COMMAND.NEW.FILE", + MICROBIT_COMMAND_OPEN_SIMULATOR = "MICROBIT.COMMAND.OPEN.SIMULATOR", // Simulator interaction - SIMULATOR_BUTTON_A = "SIMULATOR.BUTTON.A", - SIMULATOR_BUTTON_B = "SIMULATOR.BUTTON.B", - SIMULATOR_BUTTON_AB = "SIMULATOR.BUTTON.AB", - SIMULATOR_SWITCH = "SIMULATOR.SWITCH", + CPX_SIMULATOR_BUTTON_A = "CPX.SIMULATOR.BUTTON.A", + CPX_SIMULATOR_BUTTON_B = "CPX.SIMULATOR.BUTTON.B", + CPX_SIMULATOR_BUTTON_AB = "CPX.SIMULATOR.BUTTON.AB", + CPX_SIMULATOR_SWITCH = "CPX.SIMULATOR.SWITCH", + + MICROBIT_SIMULATOR_BUTTON_A = "MICROBIT.SIMULATOR.BUTTON.A", + MICROBIT_SIMULATOR_BUTTON_B = "MICROBIT.SIMULATOR.BUTTON.B", + MICROBIT_SIMULATOR_BUTTON_AB = "MICROBIT.SIMULATOR.BUTTON.AB", // Sensors - SIMULATOR_TEMPERATURE_SENSOR = "SIMULATOR.TEMPERATURE", - SIMULATOR_LIGHT_SENSOR = " SIMULATOR.LIGHT", - SIMULATOR_MOTION_SENSOR = "SIMULATOR.MOTION", - SIMULATOR_SHAKE = "SIMULATOR.SHAKE", - SIMULATOR_CAPACITIVE_TOUCH = "SIMULATOR.CAPACITIVE.TOUCH", + CPX_SIMULATOR_TEMPERATURE_SENSOR = "CPX.SIMULATOR.TEMPERATURE", + CPX_SIMULATOR_LIGHT_SENSOR = "CPX.SIMULATOR.LIGHT", + CPX_SIMULATOR_MOTION_SENSOR = "CPX.SIMULATOR.MOTION", + CPX_SIMULATOR_SHAKE = "CPX.SIMULATOR.SHAKE", + CPX_SIMULATOR_CAPACITIVE_TOUCH = "CPX.SIMULATOR.CAPACITIVE.TOUCH", + + MICROBIT_SIMULATOR_TEMPERATURE_SENSOR = "MICROBIT.SIMULATOR.TEMPERATURE", + MICROBIT_SIMULATOR_LIGHT_SENSOR = "MICROBIT.SIMULATOR.LIGHT", + MICROBIT_SIMULATOR_MOTION_SENSOR = "MICROBIT.SIMULATOR.MOTION", // Pop-up dialog - CLICK_DIALOG_DONT_SHOW = "CLICK.DIALOG.DONT.SHOW", - CLICK_DIALOG_EXAMPLE_CODE = "CLICK.DIALOG.EXAMPLE.CODE", - CLICK_DIALOG_HELP_DEPLOY_TO_DEVICE = "CLICK.DIALOG.HELP.DEPLOY.TO.DEVICE", - CLICK_DIALOG_TUTORIALS = "CLICK.DIALOG.TUTORIALS", + CPX_CLICK_DIALOG_DONT_SHOW = "CPX.CLICK.DIALOG.DONT.SHOW", + CPX_CLICK_DIALOG_EXAMPLE_CODE = "CPX.CLICK.DIALOG.EXAMPLE.CODE", + CPX_CLICK_DIALOG_HELP_DEPLOY_TO_DEVICE = "CPX.CLICK.DIALOG.HELP.DEPLOY.TO.DEVICE", + CPX_CLICK_DIALOG_TUTORIALS = "CPX.CLICK.DIALOG.TUTORIALS", - ERROR_PYTHON_DEVICE_PROCESS = "ERROR.PYTHON.DEVICE.PROCESS", ERROR_PYTHON_PROCESS = "ERROR.PYTHON.PROCESS", - ERROR_COMMAND_NEW_FILE = "ERROR.COMMAND.NEW.FILE", - ERROR_DEPLOY_WITHOUT_DEVICE = "ERROR.DEPLOY.WITHOUT.DEVICE", + CPX_ERROR_COMMAND_NEW_FILE = "CPX.ERROR.COMMAND.NEW.FILE", + CPX_ERROR_DEPLOY_WITHOUT_DEVICE = "CPX.ERROR.DEPLOY.WITHOUT.DEVICE", + CPX_ERROR_PYTHON_DEVICE_PROCESS = "CPX.ERROR.PYTHON.DEVICE.PROCESS", + CPX_SUCCESS_COMMAND_DEPLOY_DEVICE = "CPX.SUCCESS.COMMAND.DEPLOY.DEVICE", - SUCCESS_COMMAND_DEPLOY_DEVICE = "SUCCESS.COMMAND.DEPLOY.DEVICE", + MICROBIT_ERROR_COMMAND_NEW_FILE = "MICROBIT.ERROR.COMMAND.NEW.FILE", // Performance - PERFORMANCE_DEPLOY_DEVICE = "PERFORMANCE.DEPLOY.DEVICE", - PERFORMANCE_NEW_FILE = "PERFORMANCE.NEW.FILE", - PERFORMANCE_OPEN_SIMULATOR = "PERFORMANCE.OPEN.SIMULATOR", -} + CPX_PERFORMANCE_DEPLOY_DEVICE = "CPX.PERFORMANCE.DEPLOY.DEVICE", + CPX_PERFORMANCE_NEW_FILE = "CPX.PERFORMANCE.NEW.FILE", + CPX_PERFORMANCE_OPEN_SIMULATOR = "CPX.PERFORMANCE.OPEN.SIMULATOR", -export enum WebviewMessages { - BUTTON_PRESS = "button-press", - PLAY_SIMULATOR = "play-simulator", - SENSOR_CHANGED = "sensor-changed", - REFRESH_SIMULATOR = "refresh-simulator", - SLIDER_TELEMETRY = "slider-telemetry", + MICROBIT_PERFORMANCE_NEW_FILE = "MICROBIT.PERFORMANCE.NEW.FILE", + MICROBIT_PERFORMANCE_OPEN_SIMULATOR = "MICROBIT.PERFORMANCE.OPEN.SIMULATOR", } +export const DEFAULT_DEVICE = CONSTANTS.DEVICE_NAME.CPX; // tslint:disable-next-line: no-namespace export namespace DialogResponses { @@ -367,6 +425,12 @@ export namespace DialogResponses { export const MESSAGE_UNDERSTOOD: MessageItem = { title: localize("dialogResponses.messageUnderstood", "Got It"), }; + export const INSTALL_PIP: MessageItem = { + title: localize( + "dialogResponses.installPip", + "Install from Pip's webpage" + ), + }; export const INSTALL_PYTHON: MessageItem = { title: localize( "dialogResponses.installPython", @@ -397,4 +461,21 @@ export const STATUS_BAR_PRIORITY = { BAUD_RATE: 40, }; +export const VERSIONS = { + MIN_PY_VERSION: "3.7.0", +}; + +export const HELPER_FILES = { + CHECK_IF_VENV_PY: "check_if_venv.py", + CHECK_PYTHON_DEPENDENCIES: "check_python_dependencies.py", + DEVICE_PY: "device.py", + PROCESS_USER_CODE_PY: "process_user_code.py", + PYTHON_EXE: "python.exe", + PYTHON: "python", +}; + +export const GLOBAL_ENV_VARS = { + PYTHON: "python", +}; + export default CONSTANTS; diff --git a/src/debug_user_code.py b/src/debug_user_code.py index 8d5b57873..c4b3dd2c5 100644 --- a/src/debug_user_code.py +++ b/src/debug_user_code.py @@ -6,7 +6,10 @@ import traceback from pathlib import Path import python_constants as CONSTANTS +import check_python_dependencies +# will propagate errors if dependencies aren't sufficient +check_python_dependencies.check_for_dependencies() # Insert absolute path to Adafruit library into sys.path abs_path_to_parent_dir = os.path.dirname(os.path.abspath(__file__)) @@ -15,12 +18,12 @@ # Insert absolute path to python libraries into sys.path abs_path_to_parent_dir = os.path.dirname(os.path.abspath(__file__)) -abs_path_to_lib = os.path.join(abs_path_to_parent_dir, CONSTANTS.PYTHON_LIBS_DIR) sys.path.insert(0, abs_path_to_lib) # This import must happen after the sys.path is modified from adafruit_circuitplayground.express import cpx -from adafruit_circuitplayground import debugger_communication_client +from microbit.__model.microbit_model import __mb as mb +from common import debugger_communication_client ## Execute User Code ## @@ -45,6 +48,7 @@ cpx._Express__abs_path_to_code_file = abs_path_to_code_file cpx._Express__debug_mode = True cpx.pixels._Pixel__set_debug_mode(True) +mb._MicrobitModel__set_debug_mode(True) # Execute the user's code file with open(abs_path_to_code_file) as user_code_file: diff --git a/src/debugger/debugAdapter.ts b/src/debugger/debugAdapter.ts new file mode 100644 index 000000000..59a78482e --- /dev/null +++ b/src/debugger/debugAdapter.ts @@ -0,0 +1,49 @@ +import { DebugAdapterTracker, DebugConsole, DebugSession } from "vscode"; +import { DebuggerCommunicationService } from "../service/debuggerCommunicationService"; +import { MessagingService } from "../service/messagingService"; +import { DEBUG_COMMANDS } from "../view/constants"; + +export class DebugAdapter implements DebugAdapterTracker { + private readonly console: DebugConsole | undefined; + private readonly messagingService: MessagingService; + private debugCommunicationService: DebuggerCommunicationService; + constructor( + debugSession: DebugSession, + messagingService: MessagingService, + debugCommunicationService: DebuggerCommunicationService + ) { + this.console = debugSession.configuration.console; + this.messagingService = messagingService; + this.debugCommunicationService = debugCommunicationService; + } + onWillStartSession() { + // To Implement + } + onWillReceiveMessage(message: any): void { + if (message.command) { + // Only send pertinent debug messages + switch (message.command) { + case DEBUG_COMMANDS.CONTINUE: + this.messagingService.sendStartMessage(); + break; + case DEBUG_COMMANDS.STACK_TRACE: + this.messagingService.sendPauseMessage(); + break; + case DEBUG_COMMANDS.DISCONNECT: + // Triggered on stop event for debugger + if (!message.arguments.restart) { + this.debugCommunicationService.handleStopEvent(); + } + break; + } + } + } + // A debugger error should unlock the webview + onError() { + this.messagingService.sendStartMessage(); + } + // Device is always running when exiting debugging mode + onExit() { + this.messagingService.sendStartMessage(); + } +} diff --git a/src/debugger/debugAdapterFactory.ts b/src/debugger/debugAdapterFactory.ts new file mode 100644 index 000000000..5b0e2b401 --- /dev/null +++ b/src/debugger/debugAdapterFactory.ts @@ -0,0 +1,33 @@ +import { + DebugAdapterTracker, + DebugAdapterTrackerFactory, + DebugSession, + ProviderResult, +} from "vscode"; +import { DebuggerCommunicationService } from "../service/debuggerCommunicationService"; +import { MessagingService } from "../service/messagingService"; +import { DebugAdapter } from "./debugAdapter"; + +export class DebugAdapterFactory implements DebugAdapterTrackerFactory { + private debugSession: DebugSession; + private messagingService: MessagingService; + private debugCommunicationService: DebuggerCommunicationService; + constructor( + debugSession: DebugSession, + messagingService: MessagingService, + debugCommunicationService: DebuggerCommunicationService + ) { + this.debugSession = debugSession; + this.messagingService = messagingService; + this.debugCommunicationService = debugCommunicationService; + } + public createDebugAdapterTracker( + session: DebugSession + ): ProviderResult { + return new DebugAdapter( + session, + this.messagingService, + this.debugCommunicationService + ); + } +} diff --git a/src/debuggerCommunicationServer.ts b/src/debuggerCommunicationServer.ts index 76eb02f42..86a4aeef2 100644 --- a/src/debuggerCommunicationServer.ts +++ b/src/debuggerCommunicationServer.ts @@ -6,15 +6,32 @@ import * as socketio from "socket.io"; import { WebviewPanel } from "vscode"; import { SERVER_INFO } from "./constants"; +export const DEBUGGER_MESSAGES = { + EMITTER: { + INPUT_CHANGED: "input_changed", + RECEIVED_STATE: "received_state", + DISCONNECT: "process_disconnect", + }, + LISTENER: { + UPDATE_STATE: "updateState", + RECEIVED_STATE: "receivedState", + DISCONNECT: "disconnect", + }, +}; + export class DebuggerCommunicationServer { private port: number; private serverHttp: http.Server; private serverIo: socketio.Server; private simulatorWebview: WebviewPanel | undefined; + private currentActiveDevice; + private isPendingResponse = false; + private pendingCallbacks: Function[] = []; constructor( webviewPanel: WebviewPanel | undefined, - port = SERVER_INFO.DEFAULT_SERVER_PORT + port = SERVER_INFO.DEFAULT_SERVER_PORT, + currentActiveDevice: string ) { this.port = port; this.serverHttp = new http.Server(); @@ -24,28 +41,41 @@ export class DebuggerCommunicationServer { this.simulatorWebview = webviewPanel; this.initEventsHandlers(); console.info(`Server running on port ${this.port}`); + + this.currentActiveDevice = currentActiveDevice; } + // send the message to start closing the connection public closeConnection(): void { - this.serverIo.close(); - this.serverHttp.close(); - console.info("Closing the server"); + this.sendDisconnectEvent(); } public setWebview(webviewPanel: WebviewPanel | undefined) { this.simulatorWebview = webviewPanel; } - - // Emit Buttons Inputs Events - public emitButtonPress(newState: string): void { - console.log(`Emit Button Press: ${newState} \n`); - this.serverIo.emit("button_press", newState); + // Events are pushed when the previous processed event is over + public emitInputChanged(newState: string): void { + if (this.isPendingResponse) { + this.pendingCallbacks.push(() => { + this.serverIo.emit( + DEBUGGER_MESSAGES.EMITTER.INPUT_CHANGED, + newState + ); + }); + } else { + this.serverIo.emit( + DEBUGGER_MESSAGES.EMITTER.INPUT_CHANGED, + newState + ); + this.isPendingResponse = true; + } } - - // Emit Sensors Inputs Events - public emitSensorChanged(newState: string): void { - console.log(`Emit Sensor Changed: ${newState} \n`); - this.serverIo.emit("sensor_changed", newState); + public disconnectFromPort() { + this.serverIo.close(); + this.serverHttp.close(); + } + private sendDisconnectEvent() { + this.serverIo.emit(DEBUGGER_MESSAGES.EMITTER.DISCONNECT, {}); } private initHttpServer(): void { @@ -57,14 +87,25 @@ export class DebuggerCommunicationServer { private initEventsHandlers(): void { this.serverIo.on("connection", (socket: any) => { - console.log("Connection received"); - - socket.on("updateState", (data: any) => { + socket.on(DEBUGGER_MESSAGES.LISTENER.UPDATE_STATE, (data: any) => { this.handleState(data); + this.serverIo.emit( + DEBUGGER_MESSAGES.EMITTER.RECEIVED_STATE, + {} + ); + }); + socket.on(DEBUGGER_MESSAGES.LISTENER.RECEIVED_STATE, () => { + if (this.pendingCallbacks.length > 0) { + const currentCall = this.pendingCallbacks.shift(); + currentCall(); + this.isPendingResponse = true; + } else { + this.isPendingResponse = false; + } }); - socket.on("disconnect", () => { - console.log("Socket disconnected"); + socket.on(DEBUGGER_MESSAGES.LISTENER.DISCONNECT, () => { + this.serverIo.emit(DEBUGGER_MESSAGES.EMITTER.DISCONNECT, {}); if (this.simulatorWebview) { this.simulatorWebview.webview.postMessage({ command: "reset-state", @@ -81,6 +122,7 @@ export class DebuggerCommunicationServer { console.log(`State recieved: ${messageToWebview.data}`); if (this.simulatorWebview) { this.simulatorWebview.webview.postMessage({ + active_device: this.currentActiveDevice, command: "set-state", state: JSON.parse(messageToWebview.data), }); diff --git a/src/extension.ts b/src/extension.ts index 888015803..c14532a0a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -4,40 +4,56 @@ import * as cp from "child_process"; import * as fs from "fs"; import * as open from "open"; +import * as os from "os"; import * as path from "path"; import * as vscode from "vscode"; import { CONFIG, CONSTANTS, CPX_CONFIG_FILE, + DEFAULT_DEVICE, DialogResponses, + GLOBAL_ENV_VARS, + HELPER_FILES, SERVER_INFO, TelemetryEventName, - WebviewMessages, } from "./constants"; import { CPXWorkspace } from "./cpxWorkspace"; +import { DebugAdapterFactory } from "./debugger/debugAdapterFactory"; import { DebuggerCommunicationServer } from "./debuggerCommunicationServer"; import * as utils from "./extension_utils/utils"; import { SerialMonitor } from "./serialMonitor"; +import { DebuggerCommunicationService } from "./service/debuggerCommunicationService"; +import { MessagingService } from "./service/messagingService"; import { SimulatorDebugConfigurationProvider } from "./simulatorDebugConfigurationProvider"; import TelemetryAI from "./telemetry/telemetryAI"; import { UsbDetector } from "./usbDetector"; +import { VSCODE_MESSAGES_TO_WEBVIEW, WEBVIEW_MESSAGES } from "./view/constants"; +import { PopupService } from "./service/PopupService"; +import getPackageInfo from "./telemetry/getPackageInfo"; +import { registerDefaultFontFaces } from "office-ui-fabric-react"; let currentFileAbsPath: string = ""; let currentTextDocument: vscode.TextDocument; let telemetryAI: TelemetryAI; -let pythonExecutableName: string = "python"; +let pythonExecutablePath: string = GLOBAL_ENV_VARS.PYTHON; let configFileCreated: boolean = false; let inDebugMode: boolean = false; -let debuggerCommunicationHandler: DebuggerCommunicationServer; // Notification booleans let firstTimeClosed: boolean = true; let shouldShowInvalidFileNamePopup: boolean = true; let shouldShowRunCodePopup: boolean = true; +const messagingService = new MessagingService(); +const debuggerCommunicationService = new DebuggerCommunicationService(); + +let currentActiveDevice: string = DEFAULT_DEVICE; + export let outChannel: vscode.OutputChannel | undefined; function loadScript(context: vscode.ExtensionContext, scriptPath: string) { - return ``; } @@ -50,11 +66,23 @@ const setPathAndSendMessage = ( if (currentPanel) { currentPanel.webview.postMessage({ command: "current-file", - state: { running_file: newFilePath }, + active_device: currentActiveDevice, + + state: { + running_file: newFilePath, + }, }); } }; +const sendCurrentDeviceMessage = (currentPanel: vscode.WebviewPanel) => { + if (currentPanel) { + currentPanel.webview.postMessage({ + command: VSCODE_MESSAGES_TO_WEBVIEW.SET_DEVICE, + active_device: currentActiveDevice, + }); + } +}; // Extension activation export async function activate(context: vscode.ExtensionContext) { console.info(CONSTANTS.INFO.EXTENSION_ACTIVATED); @@ -72,11 +100,8 @@ export async function activate(context: vscode.ExtensionContext) { // doesn't trigger lint errors updatePylintArgs(context); - pythonExecutableName = await utils.setPythonExectuableName(); - - await utils.checkPythonDependencies(context, pythonExecutableName); + pythonExecutablePath = await utils.setupEnv(context); - // Generate cpx.json try { utils.generateCPXConfig(); configFileCreated = true; @@ -85,7 +110,7 @@ export async function activate(context: vscode.ExtensionContext) { configFileCreated = false; } - if (pythonExecutableName === "") { + if (pythonExecutablePath === "") { return; } @@ -100,8 +125,21 @@ export async function activate(context: vscode.ExtensionContext) { } ); + const currVersionReleaseName = + "release_note_" + getPackageInfo(context).extensionVersion; + const viewedReleaseNote = context.globalState.get( + currVersionReleaseName, + false + ); + + if (!viewedReleaseNote) { + PopupService.openReleaseNote(); + context.globalState.update(currVersionReleaseName, true); + } + const openWebview = () => { if (currentPanel) { + messagingService.setWebview(currentPanel.webview); currentPanel.reveal(vscode.ViewColumn.Beside); } else { currentPanel = vscode.window.createWebviewPanel( @@ -123,6 +161,7 @@ export async function activate(context: vscode.ExtensionContext) { ); currentPanel.webview.html = getWebviewContent(context); + messagingService.setWebview(currentPanel.webview); if (messageListener !== undefined) { messageListener.dispose(); @@ -146,26 +185,29 @@ export async function activate(context: vscode.ExtensionContext) { // Handle messages from webview messageListener = currentPanel.webview.onDidReceiveMessage( message => { - const messageJson = JSON.stringify(message.text); + const messageJson = JSON.stringify({ + active_device: currentActiveDevice, + state: message.text, + }); switch (message.command) { - case WebviewMessages.BUTTON_PRESS: + case WEBVIEW_MESSAGES.BUTTON_PRESS: // Send input to the Python process handleButtonPressTelemetry(message.text); console.log(`About to write ${messageJson} \n`); if ( inDebugMode && - debuggerCommunicationHandler + debuggerCommunicationService.getCurrentDebuggerServer() ) { - debuggerCommunicationHandler.emitButtonPress( - messageJson - ); + debuggerCommunicationService + .getCurrentDebuggerServer() + .emitInputChanged(messageJson); } else if (childProcess) { childProcess.stdin.write( messageJson + "\n" ); } break; - case WebviewMessages.PLAY_SIMULATOR: + case WEBVIEW_MESSAGES.TOGGLE_PLAY_STOP: console.log(`Play button ${messageJson} \n`); if (message.text.state as boolean) { setPathAndSendMessage( @@ -187,30 +229,42 @@ export async function activate(context: vscode.ExtensionContext) { } else { killProcessIfRunning(); } + + if (childProcess) { + childProcess.stdin.write( + messageJson + "\n" + ); + } + break; - case WebviewMessages.SENSOR_CHANGED: - checkForTelemetry(message.text); + + case WEBVIEW_MESSAGES.SENSOR_CHANGED: + handleGestureTelemetry(message.text); console.log(`Sensor changed ${messageJson} \n`); if ( inDebugMode && - debuggerCommunicationHandler + debuggerCommunicationService.getCurrentDebuggerServer() ) { - debuggerCommunicationHandler.emitSensorChanged( - messageJson - ); + debuggerCommunicationService + .getCurrentDebuggerServer() + .emitInputChanged(messageJson); } else if (childProcess) { childProcess.stdin.write( messageJson + "\n" ); } break; - case WebviewMessages.REFRESH_SIMULATOR: + case WEBVIEW_MESSAGES.REFRESH_SIMULATOR: console.log("Refresh button"); runSimulatorCommand(); break; - case WebviewMessages.SLIDER_TELEMETRY: + case WEBVIEW_MESSAGES.SLIDER_TELEMETRY: handleSensorTelemetry(message.text); break; + case WEBVIEW_MESSAGES.SWITCH_DEVICE: + switchDevice(message.text.active_device); + killProcessIfRunning(); + break; default: vscode.window.showInformationMessage( CONSTANTS.ERROR.UNEXPECTED_MESSAGE @@ -232,8 +286,12 @@ export async function activate(context: vscode.ExtensionContext) { currentPanel.onDidDispose( () => { currentPanel = undefined; - if (debuggerCommunicationHandler) { - debuggerCommunicationHandler.setWebview(undefined); + if ( + debuggerCommunicationService.getCurrentDebuggerServer() + ) { + debuggerCommunicationService + .getCurrentDebuggerServer() + .setWebview(undefined); } killProcessIfRunning(); if (firstTimeClosed) { @@ -247,31 +305,66 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions ); } + sendCurrentDeviceMessage(currentPanel); + }; + + const openCPXWebview = () => { + switchDevice(CONSTANTS.DEVICE_NAME.CPX); + openWebview(); + }; + + const openMicrobitWebview = () => { + switchDevice(CONSTANTS.DEVICE_NAME.MICROBIT); + openWebview(); }; // Open Simulator on the webview - const openSimulator: vscode.Disposable = vscode.commands.registerCommand( - "deviceSimulatorExpress.openSimulator", + const cpxOpenSimulator: vscode.Disposable = vscode.commands.registerCommand( + "deviceSimulatorExpress.cpx.openSimulator", + () => { + telemetryAI.trackFeatureUsage( + TelemetryEventName.CPX_COMMAND_OPEN_SIMULATOR + ); + telemetryAI.runWithLatencyMeasure( + openCPXWebview, + TelemetryEventName.CPX_PERFORMANCE_OPEN_SIMULATOR + ); + } + ); + + const microbitOpenSimulator: vscode.Disposable = vscode.commands.registerCommand( + "deviceSimulatorExpress.microbit.openSimulator", () => { telemetryAI.trackFeatureUsage( - TelemetryEventName.COMMAND_OPEN_SIMULATOR + TelemetryEventName.MICROBIT_COMMAND_OPEN_SIMULATOR ); telemetryAI.runWithLatencyMeasure( - openWebview, - TelemetryEventName.PERFORMANCE_OPEN_SIMULATOR + openMicrobitWebview, + TelemetryEventName.MICROBIT_PERFORMANCE_OPEN_SIMULATOR ); } ); - const openTemplateFile = () => { - const fileName = "template.py"; - const filePath = __dirname + path.sep + fileName; + const openCPXTemplateFile = () => { + switchDevice(CONSTANTS.DEVICE_NAME.CPX); + openTemplateFile(CONSTANTS.TEMPLATE.CPX); + }; + + const openMicrobitTemplateFile = () => { + switchDevice(CONSTANTS.DEVICE_NAME.MICROBIT); + openTemplateFile(CONSTANTS.TEMPLATE.MICROBIT); + }; + + const openTemplateFile = (template: string) => { + const fileName = template; + const filePath = + __dirname + path.sep + "templates" + path.sep + fileName; const file = fs.readFileSync(filePath, "utf8"); const showNewFilePopup: boolean = vscode.workspace .getConfiguration() .get(CONFIG.SHOW_NEW_FILE_POPUP); - if (showNewFilePopup) { + if (showNewFilePopup && template === CONSTANTS.TEMPLATE.CPX) { vscode.window .showInformationMessage( CONSTANTS.INFO.NEW_FILE, @@ -285,21 +378,24 @@ export async function activate(context: vscode.ExtensionContext) { .getConfiguration() .update(CONFIG.SHOW_NEW_FILE_POPUP, false); telemetryAI.trackFeatureUsage( - TelemetryEventName.CLICK_DIALOG_DONT_SHOW + TelemetryEventName.CPX_CLICK_DIALOG_DONT_SHOW ); } else if (selection === DialogResponses.EXAMPLE_CODE) { open(CONSTANTS.LINKS.EXAMPLE_CODE); telemetryAI.trackFeatureUsage( - TelemetryEventName.CLICK_DIALOG_EXAMPLE_CODE + TelemetryEventName.CPX_CLICK_DIALOG_EXAMPLE_CODE ); } else if (selection === DialogResponses.TUTORIALS) { const okAction = () => { open(CONSTANTS.LINKS.TUTORIALS); telemetryAI.trackFeatureUsage( - TelemetryEventName.CLICK_DIALOG_TUTORIALS + TelemetryEventName.CPX_CLICK_DIALOG_TUTORIALS ); }; - utils.showPrivacyModal(okAction); + utils.showPrivacyModal( + okAction, + CONSTANTS.INFO.THIRD_PARTY_WEBSITE_ADAFRUIT + ); } }); } @@ -314,20 +410,43 @@ export async function activate(context: vscode.ExtensionContext) { }), // tslint:disable-next-line: no-unused-expression (error: any) => { - telemetryAI.trackFeatureUsage( - TelemetryEventName.ERROR_COMMAND_NEW_FILE - ); + handleNewFileErrorTelemetry(); console.error(`Failed to open a new text document: ${error}`); }; }; - const newFile: vscode.Disposable = vscode.commands.registerCommand( - "deviceSimulatorExpress.newFile", + const cpxNewFile: vscode.Disposable = vscode.commands.registerCommand( + "deviceSimulatorExpress.cpx.newFile", + () => { + telemetryAI.trackFeatureUsage( + TelemetryEventName.CPX_COMMAND_NEW_FILE + ); + telemetryAI.runWithLatencyMeasure( + openCPXTemplateFile, + TelemetryEventName.CPX_PERFORMANCE_NEW_FILE + ); + } + ); + + const microbitNewFile: vscode.Disposable = vscode.commands.registerCommand( + "deviceSimulatorExpress.microbit.newFile", () => { - telemetryAI.trackFeatureUsage(TelemetryEventName.COMMAND_NEW_FILE); + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_COMMAND_NEW_FILE + ); telemetryAI.runWithLatencyMeasure( - openTemplateFile, - TelemetryEventName.PERFORMANCE_NEW_FILE + openMicrobitTemplateFile, + TelemetryEventName.MICROBIT_PERFORMANCE_NEW_FILE + ); + } + ); + + const installDependencies: vscode.Disposable = vscode.commands.registerCommand( + "deviceSimulatorExpress.common.installDependencies", + async () => { + pythonExecutablePath = await utils.setupEnv(context, true); + telemetryAI.trackFeatureUsage( + TelemetryEventName.COMMAND_INSTALL_EXTENSION_DEPENDENCIES ); } ); @@ -336,7 +455,10 @@ export async function activate(context: vscode.ExtensionContext) { if (childProcess !== undefined) { if (currentPanel) { console.info("Sending clearing state command"); - currentPanel.webview.postMessage({ command: "reset-state" }); + currentPanel.webview.postMessage({ + command: "reset-state", + active_device: currentActiveDevice, + }); } // TODO: We need to check the process was correctly killed childProcess.kill(); @@ -436,20 +558,23 @@ export async function activate(context: vscode.ExtensionContext) { if (selection === DialogResponses.DONT_SHOW) { shouldShowInvalidFileNamePopup = false; telemetryAI.trackFeatureUsage( - TelemetryEventName.CLICK_DIALOG_DONT_SHOW + TelemetryEventName.CPX_CLICK_DIALOG_DONT_SHOW ); } }); } // Activate the run webview button - currentPanel.webview.postMessage({ command: "activate-play" }); + currentPanel.webview.postMessage({ + command: "activate-play", + active_device: currentActiveDevice, + }); - childProcess = cp.spawn(pythonExecutableName, [ + childProcess = cp.spawn(pythonExecutablePath, [ utils.getPathToScript( context, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, - "process_user_code.py" + HELPER_FILES.PROCESS_USER_CODE_PY ), currentFileAbsPath, JSON.stringify({ enable_telemetry: utils.getTelemetryState() }), @@ -480,12 +605,19 @@ export async function activate(context: vscode.ExtensionContext) { console.log( `Process state output = ${messageToWebview.data}` ); - currentPanel.webview.postMessage({ - command: "set-state", - state: JSON.parse( - messageToWebview.data - ), - }); + const messageData = JSON.parse( + messageToWebview.data + ); + if ( + messageData.device_name === + currentActiveDevice + ) { + currentPanel.webview.postMessage({ + active_device: currentActiveDevice, + command: "set-state", + state: messageData, + }); + } break; case "print": @@ -530,6 +662,7 @@ export async function activate(context: vscode.ExtensionContext) { if (currentPanel) { console.log("Sending clearing state command"); currentPanel.webview.postMessage({ + active_device: currentActiveDevice, command: "reset-state", }); } @@ -542,19 +675,9 @@ export async function activate(context: vscode.ExtensionContext) { } }; - const runSimulatorEditorButton: vscode.Disposable = vscode.commands.registerCommand( - "deviceSimulatorExpress.runSimulatorEditorButton", - () => { - telemetryAI.trackFeatureUsage( - TelemetryEventName.COMMAND_RUN_EDITOR_ICON - ); - runSimulatorCommand(); - } - ); - // Send message to the webview const runSimulator: vscode.Disposable = vscode.commands.registerCommand( - "deviceSimulatorExpress.runSimulator", + "deviceSimulatorExpress.common.runSimulator", () => { telemetryAI.trackFeatureUsage( TelemetryEventName.COMMAND_RUN_PALETTE @@ -563,7 +686,7 @@ export async function activate(context: vscode.ExtensionContext) { } ); - const deployCodeToDevice = async () => { + const cpxDeployCodeToDevice = async () => { console.info("Sending code to device"); utils.logToOutputChannel( @@ -606,11 +729,11 @@ export async function activate(context: vscode.ExtensionContext) { CONSTANTS.INFO.FILE_SELECTED(currentFileAbsPath) ); - const deviceProcess = cp.spawn(pythonExecutableName, [ + const deviceProcess = cp.spawn(pythonExecutablePath, [ utils.getPathToScript( context, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, - "device.py" + HELPER_FILES.DEVICE_PY ), currentFileAbsPath, ]); @@ -628,7 +751,7 @@ export async function activate(context: vscode.ExtensionContext) { switch (messageToWebview.type) { case "complete": telemetryAI.trackFeatureUsage( - TelemetryEventName.SUCCESS_COMMAND_DEPLOY_DEVICE + TelemetryEventName.CPX_SUCCESS_COMMAND_DEPLOY_DEVICE ); utils.logToOutputChannel( outChannel, @@ -638,7 +761,7 @@ export async function activate(context: vscode.ExtensionContext) { case "no-device": telemetryAI.trackFeatureUsage( - TelemetryEventName.ERROR_DEPLOY_WITHOUT_DEVICE + TelemetryEventName.CPX_ERROR_DEPLOY_WITHOUT_DEVICE ); vscode.window .showErrorMessage( @@ -657,10 +780,14 @@ export async function activate(context: vscode.ExtensionContext) { const okAction = () => { open(CONSTANTS.LINKS.HELP); telemetryAI.trackFeatureUsage( - TelemetryEventName.CLICK_DIALOG_HELP_DEPLOY_TO_DEVICE + TelemetryEventName.CPX_CLICK_DIALOG_HELP_DEPLOY_TO_DEVICE ); }; - utils.showPrivacyModal(okAction); + utils.showPrivacyModal( + okAction, + CONSTANTS.INFO + .THIRD_PARTY_WEBSITE_ADAFRUIT + ); } } ); @@ -682,7 +809,7 @@ export async function activate(context: vscode.ExtensionContext) { // Std error output deviceProcess.stderr.on("data", data => { telemetryAI.trackFeatureUsage( - TelemetryEventName.ERROR_PYTHON_DEVICE_PROCESS, + TelemetryEventName.CPX_ERROR_PYTHON_DEVICE_PROCESS, { error: `${data}` } ); console.error( @@ -702,15 +829,15 @@ export async function activate(context: vscode.ExtensionContext) { } }; - const runDevice: vscode.Disposable = vscode.commands.registerCommand( - "deviceSimulatorExpress.runDevice", + const cpxDeployToDevice: vscode.Disposable = vscode.commands.registerCommand( + "deviceSimulatorExpress.cpx.deployToDevice", () => { telemetryAI.trackFeatureUsage( - TelemetryEventName.COMMAND_DEPLOY_DEVICE + TelemetryEventName.CPX_COMMAND_DEPLOY_DEVICE ); telemetryAI.runWithLatencyMeasure( - deployCodeToDevice, - TelemetryEventName.PERFORMANCE_DEPLOY_DEVICE + cpxDeployCodeToDevice, + TelemetryEventName.CPX_PERFORMANCE_DEPLOY_DEVICE ); } ); @@ -721,13 +848,13 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(serialMonitor); } - const selectSerialPort: vscode.Disposable = vscode.commands.registerCommand( - "deviceSimulatorExpress.selectSerialPort", + const cpxSelectSerialPort: vscode.Disposable = vscode.commands.registerCommand( + "deviceSimulatorExpress.cpx.selectSerialPort", () => { if (serialMonitor) { telemetryAI.runWithLatencyMeasure(() => { serialMonitor.selectSerialPort(null, null); - }, TelemetryEventName.COMMAND_SERIAL_MONITOR_CHOOSE_PORT); + }, TelemetryEventName.CPX_COMMAND_SERIAL_MONITOR_CHOOSE_PORT); } else { vscode.window.showErrorMessage( CONSTANTS.ERROR.NO_FOLDER_OPENED @@ -737,13 +864,13 @@ export async function activate(context: vscode.ExtensionContext) { } ); - const openSerialMonitor: vscode.Disposable = vscode.commands.registerCommand( - "deviceSimulatorExpress.openSerialMonitor", + const cpxOpenSerialMonitor: vscode.Disposable = vscode.commands.registerCommand( + "deviceSimulatorExpress.cpx.openSerialMonitor", () => { if (serialMonitor) { telemetryAI.runWithLatencyMeasure( serialMonitor.openSerialMonitor.bind(serialMonitor), - TelemetryEventName.COMMAND_SERIAL_MONITOR_OPEN + TelemetryEventName.CPX_COMMAND_SERIAL_MONITOR_OPEN ); } else { vscode.window.showErrorMessage( @@ -754,13 +881,13 @@ export async function activate(context: vscode.ExtensionContext) { } ); - const changeBaudRate: vscode.Disposable = vscode.commands.registerCommand( - "deviceSimulatorExpress.changeBaudRate", + const cpxChangeBaudRate: vscode.Disposable = vscode.commands.registerCommand( + "deviceSimulatorExpress.cpx.changeBaudRate", () => { if (serialMonitor) { telemetryAI.runWithLatencyMeasure( serialMonitor.changeBaudRate.bind(serialMonitor), - TelemetryEventName.COMMAND_SERIAL_MONITOR_BAUD_RATE + TelemetryEventName.CPX_COMMAND_SERIAL_MONITOR_BAUD_RATE ); } else { vscode.window.showErrorMessage( @@ -771,13 +898,29 @@ export async function activate(context: vscode.ExtensionContext) { } ); - const closeSerialMonitor: vscode.Disposable = vscode.commands.registerCommand( - "deviceSimulatorExpress.closeSerialMonitor", + const cpxCloseSerialMonitor: vscode.Disposable = vscode.commands.registerCommand( + "deviceSimulatorExpress.cpx.closeSerialMonitor", (port, showWarning = true) => { if (serialMonitor) { telemetryAI.runWithLatencyMeasure(() => { serialMonitor.closeSerialMonitor(port, showWarning); - }, TelemetryEventName.COMMAND_SERIAL_MONITOR_CLOSE); + }, TelemetryEventName.CPX_COMMAND_SERIAL_MONITOR_CLOSE); + } else { + vscode.window.showErrorMessage( + CONSTANTS.ERROR.NO_FOLDER_OPENED + ); + console.info("Serial monitor is not defined."); + } + } + ); + + const showReleaseNote = vscode.commands.registerCommand( + "deviceSimulatorExpress.", + (port, showWarning = true) => { + if (serialMonitor) { + telemetryAI.runWithLatencyMeasure(() => { + serialMonitor.closeSerialMonitor(port, showWarning); + }, TelemetryEventName.CPX_COMMAND_SERIAL_MONITOR_CLOSE); } else { vscode.window.showErrorMessage( CONSTANTS.ERROR.NO_FOLDER_OPENED @@ -809,29 +952,45 @@ export async function activate(context: vscode.ExtensionContext) { utils.getPathToScript(context, "out/", "debug_user_code.py") ); + const debugAdapterFactory = new DebugAdapterFactory( + vscode.debug.activeDebugSession, + messagingService, + debuggerCommunicationService + ); + vscode.debug.registerDebugAdapterTrackerFactory( + "python", + debugAdapterFactory + ); // On Debug Session Start: Init comunication const debugSessionsStarted = vscode.debug.onDidStartDebugSession(() => { if (simulatorDebugConfiguration.deviceSimulatorExpressDebug) { // Reinitialize process killProcessIfRunning(); - console.log("Debug Started"); inDebugMode = true; try { // Shut down existing server on debug restart - if (debuggerCommunicationHandler) { - debuggerCommunicationHandler.closeConnection(); - debuggerCommunicationHandler = undefined; + if (debuggerCommunicationService.getCurrentDebuggerServer()) { + debuggerCommunicationService.resetCurrentDebuggerServer(); } - debuggerCommunicationHandler = new DebuggerCommunicationServer( - currentPanel, - utils.getServerPortConfig() + debuggerCommunicationService.setCurrentDebuggerServer( + new DebuggerCommunicationServer( + currentPanel, + utils.getServerPortConfig(), + currentActiveDevice + ) ); + + handleDebuggerTelemetry(); + openWebview(); if (currentPanel) { - debuggerCommunicationHandler.setWebview(currentPanel); + debuggerCommunicationService + .getCurrentDebuggerServer() + .setWebview(currentPanel); currentPanel.webview.postMessage({ + currentActiveDevice, command: "activate-play", }); } @@ -840,6 +999,9 @@ export async function activate(context: vscode.ExtensionContext) { console.error( `Error trying to init the server on port ${utils.getServerPortConfig()}` ); + + handleDebuggerFailTelemetry(); + vscode.window.showErrorMessage( CONSTANTS.ERROR.DEBUGGER_SERVER_INIT_FAILED( utils.getServerPortConfig() @@ -853,35 +1015,47 @@ export async function activate(context: vscode.ExtensionContext) { // On Debug Session Stop: Stop communiation const debugSessionStopped = vscode.debug.onDidTerminateDebugSession(() => { if (simulatorDebugConfiguration.deviceSimulatorExpressDebug) { - console.log("Debug Stopped"); inDebugMode = false; simulatorDebugConfiguration.deviceSimulatorExpressDebug = false; - if (debuggerCommunicationHandler) { - debuggerCommunicationHandler.closeConnection(); - debuggerCommunicationHandler = undefined; + if (debuggerCommunicationService.getCurrentDebuggerServer()) { + debuggerCommunicationService.resetCurrentDebuggerServer(); } if (currentPanel) { - currentPanel.webview.postMessage({ command: "reset-state" }); + currentPanel.webview.postMessage({ + command: "reset-state", + active_device: currentActiveDevice, + }); } } }); + const configsChanged = vscode.workspace.onDidChangeConfiguration( + async () => { + if (utils.checkConfig(CONFIG.CONFIG_ENV_ON_SWITCH)) { + pythonExecutablePath = await utils.setupEnv(context); + } + } + ); + context.subscriptions.push( - changeBaudRate, - closeSerialMonitor, - openSerialMonitor, - openSimulator, - newFile, + installDependencies, runSimulator, - runSimulatorEditorButton, - runDevice, - selectSerialPort, + cpxChangeBaudRate, + cpxCloseSerialMonitor, + cpxDeployToDevice, + cpxNewFile, + cpxOpenSerialMonitor, + cpxOpenSimulator, + cpxSelectSerialPort, + microbitOpenSimulator, + microbitNewFile, vscode.debug.registerDebugConfigurationProvider( CONSTANTS.DEBUG_CONFIGURATION_TYPE, simulatorDebugConfiguration ), debugSessionsStarted, - debugSessionStopped + debugSessionStopped, + configsChanged ); } @@ -918,61 +1092,204 @@ const updateCurrentFileIfPython = async ( } }; +const handleDebuggerTelemetry = () => { + switch (currentActiveDevice) { + case CONSTANTS.DEVICE_NAME.CPX: + telemetryAI.trackFeatureUsage( + TelemetryEventName.CPX_DEBUGGER_INIT_SUCCESS + ); + break; + case CONSTANTS.DEVICE_NAME.MICROBIT: + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_DEBUGGER_INIT_SUCCESS + ); + break; + default: + break; + } +}; + +const handleDebuggerFailTelemetry = () => { + switch (currentActiveDevice) { + case CONSTANTS.DEVICE_NAME.CPX: + telemetryAI.trackFeatureUsage( + TelemetryEventName.CPX_DEBUGGER_INIT_FAIL + ); + break; + case CONSTANTS.DEVICE_NAME.MICROBIT: + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_DEBUGGER_INIT_FAIL + ); + break; + default: + break; + } +}; + const handleButtonPressTelemetry = (buttonState: any) => { + switch (currentActiveDevice) { + case CONSTANTS.DEVICE_NAME.CPX: + handleCPXButtonPressTelemetry(buttonState); + break; + case CONSTANTS.DEVICE_NAME.MICROBIT: + handleMicrobitButtonPressTelemetry(buttonState); + break; + default: + break; + } +}; + +const handleGestureTelemetry = (sensorState: any) => { + switch (currentActiveDevice) { + case CONSTANTS.DEVICE_NAME.CPX: + handleCPXGestureTelemetry(sensorState); + break; + case CONSTANTS.DEVICE_NAME.MICROBIT: + break; + default: + break; + } +}; + +const handleSensorTelemetry = (sensor: string) => { + switch (currentActiveDevice) { + case CONSTANTS.DEVICE_NAME.CPX: + handleCPXSensorTelemetry(sensor); + break; + case CONSTANTS.DEVICE_NAME.MICROBIT: + handleMicrobitSensorTelemetry(sensor); + break; + default: + break; + } +}; + +const handleCPXButtonPressTelemetry = (buttonState: any) => { if (buttonState.button_a && buttonState.button_b) { - telemetryAI.trackFeatureUsage(TelemetryEventName.SIMULATOR_BUTTON_AB); + telemetryAI.trackFeatureUsage( + TelemetryEventName.CPX_SIMULATOR_BUTTON_AB + ); } else if (buttonState.button_a) { - telemetryAI.trackFeatureUsage(TelemetryEventName.SIMULATOR_BUTTON_A); + telemetryAI.trackFeatureUsage( + TelemetryEventName.CPX_SIMULATOR_BUTTON_A + ); } else if (buttonState.button_b) { - telemetryAI.trackFeatureUsage(TelemetryEventName.SIMULATOR_BUTTON_B); + telemetryAI.trackFeatureUsage( + TelemetryEventName.CPX_SIMULATOR_BUTTON_B + ); } else if (buttonState.switch) { - telemetryAI.trackFeatureUsage(TelemetryEventName.SIMULATOR_SWITCH); + telemetryAI.trackFeatureUsage(TelemetryEventName.CPX_SIMULATOR_SWITCH); } }; -const handleSensorTelemetry = (sensor: string) => { +const handleCPXGestureTelemetry = (sensorState: any) => { + if (sensorState.shake) { + handleCPXSensorTelemetry("shake"); + } else if (sensorState.touch) { + handleCPXSensorTelemetry("touch"); + } +}; + +const handleCPXSensorTelemetry = (sensor: string) => { switch (sensor) { case "temperature": telemetryAI.trackFeatureUsage( - TelemetryEventName.SIMULATOR_TEMPERATURE_SENSOR + TelemetryEventName.CPX_SIMULATOR_TEMPERATURE_SENSOR ); break; case "light": telemetryAI.trackFeatureUsage( - TelemetryEventName.SIMULATOR_LIGHT_SENSOR + TelemetryEventName.CPX_SIMULATOR_LIGHT_SENSOR ); break; case "motion_x": telemetryAI.trackFeatureUsage( - TelemetryEventName.SIMULATOR_MOTION_SENSOR + TelemetryEventName.CPX_SIMULATOR_MOTION_SENSOR ); break; case "motion_y": telemetryAI.trackFeatureUsage( - TelemetryEventName.SIMULATOR_MOTION_SENSOR + TelemetryEventName.CPX_SIMULATOR_MOTION_SENSOR ); break; case "motion_z": telemetryAI.trackFeatureUsage( - TelemetryEventName.SIMULATOR_MOTION_SENSOR + TelemetryEventName.CPX_SIMULATOR_MOTION_SENSOR ); break; case "shake": - telemetryAI.trackFeatureUsage(TelemetryEventName.SIMULATOR_SHAKE); + telemetryAI.trackFeatureUsage( + TelemetryEventName.CPX_SIMULATOR_SHAKE + ); break; case "touch": telemetryAI.trackFeatureUsage( - TelemetryEventName.SIMULATOR_CAPACITIVE_TOUCH + TelemetryEventName.CPX_SIMULATOR_CAPACITIVE_TOUCH ); break; } }; -const checkForTelemetry = (sensorState: any) => { - if (sensorState.shake) { - handleSensorTelemetry("shake"); - } else if (sensorState.touch) { - handleSensorTelemetry("touch"); +const handleMicrobitButtonPressTelemetry = (buttonState: any) => { + if (buttonState.button_a && buttonState.button_b) { + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_SIMULATOR_BUTTON_AB + ); + } else if (buttonState.button_a) { + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_SIMULATOR_BUTTON_A + ); + } else if (buttonState.button_b) { + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_SIMULATOR_BUTTON_B + ); + } +}; + +const handleMicrobitSensorTelemetry = (sensor: string) => { + switch (sensor) { + case "temperature": + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_SIMULATOR_TEMPERATURE_SENSOR + ); + break; + case "light": + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_SIMULATOR_LIGHT_SENSOR + ); + break; + case "motion_x": + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_SIMULATOR_MOTION_SENSOR + ); + break; + case "motion_y": + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_SIMULATOR_MOTION_SENSOR + ); + break; + case "motion_z": + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_SIMULATOR_MOTION_SENSOR + ); + break; + } +}; + +const handleNewFileErrorTelemetry = () => { + switch (currentActiveDevice) { + case CONSTANTS.DEVICE_NAME.CPX: + telemetryAI.trackFeatureUsage( + TelemetryEventName.CPX_ERROR_COMMAND_NEW_FILE + ); + break; + case CONSTANTS.DEVICE_NAME.MICROBIT: + telemetryAI.trackFeatureUsage( + TelemetryEventName.MICROBIT_ERROR_COMMAND_NEW_FILE + ); + break; + default: + break; } }; @@ -985,35 +1302,20 @@ const updatePythonExtraPaths = () => { }; const updatePylintArgs = (context: vscode.ExtensionContext) => { - const outPath: string = createEscapedPath( + const outPath: string = utils.createEscapedPath( context.extensionPath, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY ); - const pyLibsPath: string = createEscapedPath( - context.extensionPath, - CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, - CONSTANTS.FILESYSTEM.PYTHON_LIBS_DIR - ); // update pylint args to extend system path // to include python libs local to extention updateConfigLists( "python.linting.pylintArgs", - [ - "--init-hook", - `import sys; sys.path.extend([\"${outPath}\",\"${pyLibsPath}\"])`, - ], + ["--init-hook", `import sys; sys.path.append(\"${outPath}\")`], vscode.ConfigurationTarget.Workspace ); }; -const createEscapedPath = (...pieces: string[]) => { - const initialPath: string = path.join(...pieces); - - // escape all instances of backslashes - return initialPath.replace(/\\/g, "\\\\"); -}; - const updateConfigLists = ( section: string, newItems: string[], @@ -1042,14 +1344,18 @@ function getWebviewContent(context: vscode.ExtensionContext) {
- + ${loadScript(context, "out/vendor.js")} ${loadScript(context, "out/simulator.js")} `; } +function switchDevice(deviceName: string) { + currentActiveDevice = deviceName; +} // this method is called when your extension is deactivated export async function deactivate() { diff --git a/src/extension_utils/dependencyChecker.ts b/src/extension_utils/dependencyChecker.ts deleted file mode 100644 index de18806cc..000000000 --- a/src/extension_utils/dependencyChecker.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as cp from "child_process"; -import * as compareVersions from "compare-versions"; -import * as os from "os"; -import * as util from "util"; -import { CONSTANTS } from "../constants"; -const exec = util.promisify(cp.exec); - -interface IPayloadResponse { - payload: IDependency; -} - -interface IDependency { - dependency: string; - installed: boolean; -} - -const PYTHON3_REGEX = RegExp("^(Python )(3\\.[0-9]+\\.[0-9]+)"); -const MINIMUM_PYTHON_VERSION = "3.7.0"; - -export class DependencyChecker { - constructor() {} - - public async checkDependency( - dependencyName: string - ): Promise { - let state: boolean = false; - if (dependencyName === CONSTANTS.DEPENDENCY_CHECKER.PYTHON) { - if ( - await this.runCommandVersion( - CONSTANTS.DEPENDENCY_CHECKER.PYTHON3, - MINIMUM_PYTHON_VERSION - ) - ) { - state = true; - dependencyName = CONSTANTS.DEPENDENCY_CHECKER.PYTHON3; - } else if ( - await this.runCommandVersion( - CONSTANTS.DEPENDENCY_CHECKER.PYTHON, - MINIMUM_PYTHON_VERSION - ) - ) { - state = true; - dependencyName = CONSTANTS.DEPENDENCY_CHECKER.PYTHON; - } else { - state = false; - } - } - return { - payload: { - dependency: dependencyName, - installed: state, - }, - }; - } - - private async runCommandVersion( - command: string, - versionDependency?: string - ) { - let installed: boolean = false; - try { - const { stdout } = await exec(command + " --version"); - const matches = PYTHON3_REGEX.exec(stdout); - if (versionDependency) { - installed = matches - ? compareVersions(matches[2], versionDependency) >= 0 - : false; - } else { - installed = true; - } - } catch (err) { - installed = false; - } - return installed; - } -} diff --git a/src/extension_utils/utils.ts b/src/extension_utils/utils.ts index a9c61a37f..ba51c6815 100644 --- a/src/extension_utils/utils.ts +++ b/src/extension_utils/utils.ts @@ -13,20 +13,26 @@ import { CONSTANTS, CPX_CONFIG_FILE, DialogResponses, + GLOBAL_ENV_VARS, + HELPER_FILES, SERVER_INFO, USER_CODE_NAMES, + VERSIONS, } from "../constants"; import { CPXWorkspace } from "../cpxWorkspace"; import { DeviceContext } from "../deviceContext"; -import { DependencyChecker } from "./dependencyChecker"; const exec = util.promisify(cp.exec); +const errorChannel = vscode.window.createOutputChannel( + CONSTANTS.ERROR.INSTALLATION_ERROR +); + // tslint:disable-next-line: export-name export const getPathToScript = ( context: vscode.ExtensionContext, folderName: string, - fileName: string + fileName: string = "" ) => { const onDiskPath = vscode.Uri.file( path.join(context.extensionPath, folderName, fileName) @@ -42,10 +48,13 @@ export const validCodeFileName = (filePath: string) => { ); }; -export const showPrivacyModal = (okAction: () => void) => { +export const showPrivacyModal = ( + okAction: () => void, + thirdPartyDisclaimer: string +) => { vscode.window .showInformationMessage( - `${CONSTANTS.INFO.THIRD_PARTY_WEBSITE}: ${CONSTANTS.LINKS.PRIVACY}`, + `${thirdPartyDisclaimer}: ${CONSTANTS.LINKS.PRIVACY}`, DialogResponses.AGREE_AND_PROCEED, DialogResponses.CANCEL ) @@ -160,45 +169,33 @@ export function generateCPXConfig(): void { mkdirRecursivelySync(path.dirname(cpxConfigFilePath)); fs.writeFileSync(cpxConfigFilePath, JSON.stringify(cpxJson, null, 4)); } -export const checkPythonDependency = async () => { - const dependencyChecker: DependencyChecker = new DependencyChecker(); - const result = await dependencyChecker.checkDependency( - CONSTANTS.DEPENDENCY_CHECKER.PYTHON - ); - return result.payload; -}; -export const checkPipDependency = async () => { - const dependencyChecker: DependencyChecker = new DependencyChecker(); - const result = await dependencyChecker.checkDependency( - CONSTANTS.DEPENDENCY_CHECKER.PIP3 - ); - return result.payload; -}; - -export const setPythonExectuableName = async () => { - // Find our what command is the PATH for python - let executableName: string = ""; - const dependencyCheck = await checkPythonDependency(); - if (dependencyCheck.installed) { - executableName = dependencyCheck.dependency; - } else { +export const isPipInstalled = async (pythonExecutablePath: string) => { + try { + const { stdout } = await executePythonCommand( + pythonExecutablePath, + " -m pip" + ); + return true; + } catch (err) { vscode.window .showErrorMessage( - CONSTANTS.ERROR.NO_PYTHON_PATH, - DialogResponses.INSTALL_PYTHON + CONSTANTS.ERROR.NO_PIP, + DialogResponses.INSTALL_PIP ) .then((selection: vscode.MessageItem | undefined) => { - if (selection === DialogResponses.INSTALL_PYTHON) { + if (selection === DialogResponses.INSTALL_PIP) { const okAction = () => { - open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); + open(CONSTANTS.LINKS.DOWNLOAD_PIP); }; - showPrivacyModal(okAction); + showPrivacyModal( + okAction, + CONSTANTS.INFO.THIRD_PARTY_WEBSITE_PIP + ); } }); + return false; } - - return executableName; }; export const addVisibleTextEditorCallback = ( @@ -227,7 +224,7 @@ export const addVisibleTextEditorCallback = ( export const filterForPythonFiles = (textEditors: vscode.TextEditor[]) => { return textEditors - .filter(editor => editor.document.languageId === "python") + .filter(editor => editor.document.languageId === GLOBAL_ENV_VARS.PYTHON) .map(editor => editor.document.fileName); }; @@ -258,105 +255,231 @@ export const checkConfig = (configName: string): boolean => { return vscode.workspace.getConfiguration().get(configName) === true; }; -export const checkPythonDependencies = async ( +export const getConfig = (configName: string): string => { + return vscode.workspace.getConfiguration().get(configName); +}; + +export const createEscapedPath = (...pieces: string[]) => { + const initialPath: string = path.join(...pieces); + + // escape all special characters + // https://stackoverflow.com/questions/1779858/how-do-i-escape-a-string-for-a-shell-command-in-node + return `"` + initialPath.replace(/(["'$`\\])/g, "\\$1") + `"`; +}; + +export const getTelemetryState = () => { + return vscode.workspace + .getConfiguration() + .get("telemetry.enableTelemetry", true); +}; + +// Setup code starts + +export const checkIfVenv = async ( context: vscode.ExtensionContext, - pythonExecutable: string + pythonExecutablePath: string ) => { - let hasInstalledDependencies: boolean = false; - const pathToLibs: string = getPathToScript( + const venvCheckerPath: string = getPathToScript( context, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, - CONSTANTS.FILESYSTEM.PYTHON_LIBS_DIR + HELPER_FILES.CHECK_IF_VENV_PY ); - if (checkPipDependency() && checkPythonDependency()) { - if (checkConfig(CONFIG.SHOW_DEPENDENCY_INSTALL)) { - // check if ./out/python_libs exists; if not, the dependencies - // for adafruit_circuitpython are not (successfully) installed yet - hasInstalledDependencies = - fs.existsSync(pathToLibs) || - (await promptInstallPythonDependencies( - context, - pythonExecutable, - pathToLibs - )); - } + const { stdout } = await executePythonCommand( + pythonExecutablePath, + `"${venvCheckerPath}"` + ); + return stdout.trim() === "1"; +}; + +export const executePythonCommand = async ( + pythonExecutablePath: string, + command: string +) => { + return exec(`${createEscapedPath(pythonExecutablePath)} ${command}`); +}; + +export const validatePythonVersion = async (pythonExecutablePath: string) => { + const { stdout } = await executePythonCommand( + pythonExecutablePath, + "--version" + ); + if (stdout < VERSIONS.MIN_PY_VERSION) { + vscode.window + .showInformationMessage( + CONSTANTS.ERROR.INVALID_PYTHON_PATH, + DialogResponses.INSTALL_PYTHON + ) + .then((installChoice: vscode.MessageItem | undefined) => { + if (installChoice === DialogResponses.INSTALL_PYTHON) { + const okAction = () => { + open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); + }; + showPrivacyModal( + okAction, + CONSTANTS.INFO.THIRD_PARTY_WEBSITE_PYTHON + ); + } + }); + return false; } else { - hasInstalledDependencies = false; + return true; } - return hasInstalledDependencies; }; -export const promptInstallPythonDependencies = ( +export const hasVenv = async (context: vscode.ExtensionContext) => { + const pathToEnv: string = getPathToScript( + context, + CONSTANTS.FILESYSTEM.PYTHON_VENV_DIR + ); + + return fs.existsSync(pathToEnv); +}; + +export const promptInstallVenv = ( context: vscode.ExtensionContext, pythonExecutable: string, - pathToLibs: string + pythonExecutableName: string ) => { return vscode.window .showInformationMessage( - CONSTANTS.INFO.INSTALL_PYTHON_DEPENDENCIES, + CONSTANTS.INFO.INSTALL_PYTHON_VENV, DialogResponses.YES, DialogResponses.NO ) .then((selection: vscode.MessageItem | undefined) => { if (selection === DialogResponses.YES) { - return installPythonDependencies( + return installPythonVenv( context, pythonExecutable, - pathToLibs + pythonExecutableName ); - } else if (selection === DialogResponses.NO) { - return vscode.window - .showInformationMessage( - CONSTANTS.INFO.ARE_YOU_SURE, - DialogResponses.INSTALL_NOW, - DialogResponses.DONT_INSTALL - ) - .then((installChoice: vscode.MessageItem | undefined) => { - if (installChoice === DialogResponses.INSTALL_NOW) { - return installPythonDependencies( - context, - pythonExecutable, - pathToLibs - ); - } else { - return false; - } - }); + } else { + // return pythonExecutable, notifying the caller + // that the user was unwilling to create venv + // and by default, this will trigger the extension to + // try using pythonExecutable + return pythonExecutable; } }); }; -export const getTelemetryState = () => { - return vscode.workspace - .getConfiguration() - .get("telemetry.enableTelemetry", true); + +export const getPythonVenv = async ( + context: vscode.ExtensionContext, + pythonExecutableName: string +) => { + const subFolder = os.platform() === "win32" ? "Scripts" : "bin"; + + return getPathToScript( + context, + path.join(CONSTANTS.FILESYSTEM.PYTHON_VENV_DIR, subFolder), + pythonExecutableName + ); }; -export const installPythonDependencies = async ( +export const installPythonVenv = async ( context: vscode.ExtensionContext, pythonExecutable: string, - pathToLibs: string + pythonExecutableName: string ) => { - let installed: boolean = false; - try { - vscode.window.showInformationMessage( - CONSTANTS.INFO.INSTALLING_PYTHON_DEPENDENCIES - ); + const pathToEnv: string = getPathToScript( + context, + CONSTANTS.FILESYSTEM.PYTHON_VENV_DIR + ); - const requirementsPath: string = getPathToScript( - context, - CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, - "requirements.txt" - ); + vscode.window.showInformationMessage(CONSTANTS.INFO.INSTALLING_PYTHON_VENV); + + const pythonPath: string = await getPythonVenv( + context, + pythonExecutableName + ); + try { + // make venv // run command to download dependencies to out/python_libs - const { stdout } = await exec( - `${pythonExecutable} -m pip install -r ${requirementsPath} -t ${pathToLibs}` + await executePythonCommand(pythonExecutable, `-m venv "${pathToEnv}"`); + } catch (err) { + vscode.window + .showErrorMessage( + `Virtual environment for download could not be completed. Using original interpreter at: ${pythonExecutable}.`, + DialogResponses.READ_INSTALL_MD + ) + .then((selection: vscode.MessageItem | undefined) => { + if (selection === DialogResponses.READ_INSTALL_MD) { + open(CONSTANTS.LINKS.INSTALL); + } + }); + + console.error(err); + + return pythonExecutable; + } + + return installDependenciesWrapper(context, pythonPath, pythonExecutable); +}; + +export const areDependenciesInstalled = async ( + context: vscode.ExtensionContext, + pythonPath: string +) => { + const dependencyCheckerPath: string = getPathToScript( + context, + CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, + HELPER_FILES.CHECK_PYTHON_DEPENDENCIES + ); + try { + // python script will throw exception + // if not all dependencies are downloaded + const { stdout } = await executePythonCommand( + pythonPath, + `"${dependencyCheckerPath}"` ); + + // output for debugging purposes console.info(stdout); - installed = true; + return true; + } catch (err) { + return false; + } +}; +export const installDependencies = async ( + context: vscode.ExtensionContext, + pythonPath: string +) => { + const requirementsPath: string = getPathToScript( + context, + CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, + "requirements.txt" + ); + + if (!isPipInstalled(pythonPath)) { + return false; + } + + try { + const { stdout } = await executePythonCommand( + pythonPath, + `-m pip install -r "${requirementsPath}"` + ); + + console.info(stdout); vscode.window.showInformationMessage(CONSTANTS.INFO.SUCCESSFUL_INSTALL); + return true; } catch (err) { + return false; + } +}; + +export const installDependenciesWrapper = async ( + context: vscode.ExtensionContext, + pythonPath: string, + backupPythonPath: string = "" +) => { + let errMessage = CONSTANTS.ERROR.DEPENDENCY_DOWNLOAD_ERROR; + if (backupPythonPath !== "") { + errMessage = `${errMessage} Using original interpreter at: ${backupPythonPath}.`; + } + if (!(await installDependencies(context, pythonPath))) { vscode.window .showErrorMessage( CONSTANTS.ERROR.DEPENDENCY_DOWNLOAD_ERROR, @@ -367,9 +490,175 @@ export const installPythonDependencies = async ( open(CONSTANTS.LINKS.INSTALL); } }); + return backupPythonPath; + } + return pythonPath; +}; +export const getCurrentpythonExecutablePath = async () => { + let originalpythonExecutablePath = ""; - console.error(err); - installed = false; + // try to get name from interpreter + try { + originalpythonExecutablePath = getConfig(CONFIG.PYTHON_PATH); + } catch (err) { + originalpythonExecutablePath = GLOBAL_ENV_VARS.PYTHON; + } + + if ( + originalpythonExecutablePath === GLOBAL_ENV_VARS.PYTHON || + originalpythonExecutablePath === "" + ) { + try { + const { stdout } = await executePythonCommand( + GLOBAL_ENV_VARS.PYTHON, + `-c "import sys; print(sys.executable)"` + ); + originalpythonExecutablePath = stdout.trim(); + } catch (err) { + vscode.window + .showErrorMessage( + CONSTANTS.ERROR.NO_PYTHON_PATH, + DialogResponses.INSTALL_PYTHON + ) + .then((selection: vscode.MessageItem | undefined) => { + if (selection === DialogResponses.INSTALL_PYTHON) { + const okAction = () => { + open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); + }; + showPrivacyModal( + okAction, + CONSTANTS.INFO.THIRD_PARTY_WEBSITE_PYTHON + ); + } + }); + + // no python installed, cannot get path + return ""; + } } - return installed; + // fix path to be absolute + if (!path.isAbsolute(originalpythonExecutablePath)) { + originalpythonExecutablePath = path.join( + vscode.workspace.rootPath, + originalpythonExecutablePath + ); + } + + if (!fs.existsSync(originalpythonExecutablePath)) { + await vscode.window.showErrorMessage(CONSTANTS.ERROR.BAD_PYTHON_PATH); + return ""; + } + + if (!(await validatePythonVersion(originalpythonExecutablePath))) { + return ""; + } + + return originalpythonExecutablePath; +}; +export const setupEnv = async ( + context: vscode.ExtensionContext, + needsResponse: boolean = false +) => { + const originalpythonExecutablePath = await getCurrentpythonExecutablePath(); + let pythonExecutablePath = originalpythonExecutablePath; + let pythonExecutableName: string = + os.platform() === "win32" + ? HELPER_FILES.PYTHON_EXE + : HELPER_FILES.PYTHON; + + if (!(await areDependenciesInstalled(context, pythonExecutablePath))) { + // environment needs to install dependencies + if (!(await checkIfVenv(context, pythonExecutablePath))) { + const pythonExecutablePathVenv = await getPythonVenv( + context, + pythonExecutableName + ); + if (await hasVenv(context)) { + // venv in extention exists with wrong dependencies + if ( + !(await areDependenciesInstalled( + context, + pythonExecutablePathVenv + )) + ) { + pythonExecutablePath = await installDependenciesWrapper( + context, + pythonExecutablePathVenv, + pythonExecutablePath + ); + } else { + pythonExecutablePath = pythonExecutablePathVenv; + } + } else { + pythonExecutablePath = await promptInstallVenv( + context, + originalpythonExecutablePath, + pythonExecutableName + ); + } + + if (pythonExecutablePath === pythonExecutablePathVenv) { + vscode.window.showInformationMessage( + CONSTANTS.INFO.UPDATED_TO_EXTENSION_VENV + ); + vscode.workspace + .getConfiguration() + .update(CONFIG.PYTHON_PATH, pythonExecutablePath); + } + } + if (pythonExecutablePath === originalpythonExecutablePath) { + // going with original interpreter, either because + // already in venv or error in creating custom venv + if (checkConfig(CONFIG.SHOW_DEPENDENCY_INSTALL)) { + await vscode.window + .showInformationMessage( + CONSTANTS.INFO.INSTALL_PYTHON_DEPS, + DialogResponses.INSTALL_NOW, + DialogResponses.DONT_INSTALL + ) + .then( + async ( + installChoice: vscode.MessageItem | undefined + ) => { + if (installChoice === DialogResponses.INSTALL_NOW) { + await installDependenciesWrapper( + context, + pythonExecutablePath + ); + } else { + await vscode.window + .showInformationMessage( + CONSTANTS.INFO.ARE_YOU_SURE, + DialogResponses.INSTALL_NOW, + DialogResponses.DONT_INSTALL + ) + .then( + async ( + installChoice2: + | vscode.MessageItem + | undefined + ) => { + if ( + installChoice2 === + DialogResponses.INSTALL_NOW + ) { + await installDependenciesWrapper( + context, + pythonExecutablePath + ); + } + } + ); + } + } + ); + } + } + } else if (needsResponse) { + vscode.window.showInformationMessage( + CONSTANTS.INFO.ALREADY_SUCCESSFUL_INSTALL + ); + } + + return pythonExecutablePath; }; diff --git a/src/latest_release_note.ts b/src/latest_release_note.ts new file mode 100644 index 000000000..a4e1ddabd --- /dev/null +++ b/src/latest_release_note.ts @@ -0,0 +1,67 @@ +// TODO: find a better way of loading html into a string +export const LATEST_RELEASE_NOTE = `

Device Simulator Express Release Notes 👩🏾‍💻 👨🏾‍💻 (Feb. 27, 2020)

+

+ Welcome to the first update to the Device Simulator Express! Please feel free to enable our feature flag in + Settings + (under the setting titled “deviceSimulatorExpress.previewMode” in the User settings). +

+

Changes

+

+

Fixes (enabled by default):

+
    +
  • Enabled support for “from adafruit_circuitplayground import cp” as an import statement for the CPX and + changed + “New File” template to use this format.
  • + +
  • State for sensor selection persists.
  • +
  • More reliable dependency installation and more informative setup fail information.
  • +
  • Fixes to Serial Monitor for CPX device deployment.
  • +
  • More robust debugger functionality.
  • +
  • Fixed spelling and clarity errors in documentation and pop-up messages.
  • +
+

New features (only available with feature flag enabled):

+
    +
  • BBC micro:bit simulator and debugger – open up a new micro:bit file, write code for the micro:bit and + test it out! +
      +
    • Ability to interact with LEDs, buttons, and sensors.
    • +
    • Includes autocompletion and error flagging.
    • +
    • Supports the following:
    • +
        +
      • Classes: +
          +
        • display
        • +
        • image
        • +
        • accelerometer
        • +
        • button
        • +
        +
      +
        +
      • Global static functions:
      • +
          +
        • sleep()
        • +
        • running_time()
        • +
        • temperature()
        • +
        +
      +
    +
      +
    • Includes accessibility considerations for simulation.
    • +
        +
      • Has ability to use keyboard for button presses and navigation.
      • +
      +
    +
+

+

Upcoming Improvements

+
    +
  • Deploying to device on the micro:bit with serial monitor interaction.
  • +
+
+

Happy Hacking! ✨✨🐍🐍🍰
+       - The Device Simulator Express Team

`; diff --git a/src/microbit/__init__.py b/src/microbit/__init__.py new file mode 100644 index 000000000..e444b34f0 --- /dev/null +++ b/src/microbit/__init__.py @@ -0,0 +1,35 @@ +from .__model.image import Image +from .__model.microbit_model import __mb +from common.telemetry import telemetry_py +from common.telemetry_events import TelemetryEvent + +accelerometer = __mb.accelerometer +button_a = __mb.button_a +button_b = __mb.button_b +display = __mb.display + + +def sleep(n): + """ + Wait for ``n`` milliseconds. One second is 1000 milliseconds, so:: + microbit.sleep(1000) + will pause the execution for one second. ``n`` can be an integer or + a floating point number. + """ + __mb.sleep(n) + + +def running_time(): + """ + Return the number of milliseconds since the board was switched on or + restarted. + """ + return __mb.running_time() + + +def temperature(): + """ + Return the temperature of the micro:bit in degrees Celcius. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_TEMPERATURE) + return __mb.temperature() diff --git a/src/microbit/__model/accelerometer.py b/src/microbit/__model/accelerometer.py new file mode 100644 index 000000000..6360ce982 --- /dev/null +++ b/src/microbit/__model/accelerometer.py @@ -0,0 +1,130 @@ +from . import constants as CONSTANTS +from common.telemetry import telemetry_py +from common.telemetry_events import TelemetryEvent + + +class Accelerometer: + # The implementation is based off of https://microbit-micropython.readthedocs.io/en/v1.0.1/accelerometer.html. + def __init__(self): + self.__x = 0 + self.__y = 0 + self.__z = 0 + self.__current_gesture = "" + self.__prev_gestures = set() + self.__gestures = [] + + def get_x(self): + """ + Get the acceleration measurement in the ``x`` axis, as a positive or + negative integer, depending on the direction. The measurement is given in + milli-g. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_ACCELEROMETER) + return self.__x + + def get_y(self): + """ + Get the acceleration measurement in the ``y`` axis, as a positive or + negative integer, depending on the direction. The measurement is given in + milli-g. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_ACCELEROMETER) + return self.__y + + def get_z(self): + """ + Get the acceleration measurement in the ``z`` axis, as a positive or + negative integer, depending on the direction. The measurement is given in + milli-g. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_ACCELEROMETER) + return self.__z + + def get_values(self): + """ + Get the acceleration measurements in all axes at once, as a three-element + tuple of integers ordered as X, Y, Z. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_ACCELEROMETER) + return (self.__x, self.__y, self.__z) + + def current_gesture(self): + """ + Return the name of the current gesture. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_GESTURE) + self.__add_current_gesture_to_gesture_lists() + return self.__current_gesture + + def is_gesture(self, name): + """ + Return True or False to indicate if the named gesture is currently active. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_GESTURE) + self.__add_current_gesture_to_gesture_lists() + if name not in CONSTANTS.GESTURES: + raise ValueError(CONSTANTS.INVALID_GESTURE_ERR) + return name == self.__current_gesture + + def was_gesture(self, name): + """ + Return True or False to indicate if the named gesture was active since the + last [was_gesture] call. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_GESTURE) + self.__add_current_gesture_to_gesture_lists() + if name not in CONSTANTS.GESTURES: + raise ValueError(CONSTANTS.INVALID_GESTURE_ERR) + was_gesture = name in self.__prev_gestures + self.__prev_gestures.clear() + return was_gesture + + def get_gestures(self): + """ + Return a tuple of the gesture history. The most recent is listed last. + Also clears the gesture history before returning. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_GESTURE) + self.__add_current_gesture_to_gesture_lists() + gestures = tuple(self.__gestures) + self.__gestures.clear() + return gestures + + # Helpers and Hidden Functions + + def __get_accel(self, axis): + if axis == "x": + return self.get_x() + elif axis == "y": + return self.get_y() + elif axis == "z": + return self.get_z() + + def __set_accel(self, axis, accel): + if accel < CONSTANTS.MIN_ACCELERATION or accel > CONSTANTS.MAX_ACCELERATION: + raise ValueError(CONSTANTS.INVALID_ACCEL_ERR) + if axis == "x": + self.__x = accel + elif axis == "y": + self.__y = accel + elif axis == "z": + self.__z = accel + + def __set_gesture(self, gesture): + if gesture in CONSTANTS.GESTURES: + self.__current_gesture = gesture + elif gesture == "": + self.__current_gesture = "" + else: + raise ValueError(CONSTANTS.INVALID_GESTURE_ERR) + + def __add_current_gesture_to_gesture_lists(self): + if self.__current_gesture in CONSTANTS.GESTURES: + self.__gestures.append(self.__current_gesture) + self.__prev_gestures.add(self.__current_gesture) + + def __update(self, axis, accel): + if accel is not None: + previous_accel = self.__get_accel(axis) + if accel != previous_accel: + self.__set_accel(axis, accel) diff --git a/src/microbit/__model/button.py b/src/microbit/__model/button.py new file mode 100644 index 000000000..1bbe4ddbc --- /dev/null +++ b/src/microbit/__model/button.py @@ -0,0 +1,59 @@ +from common.telemetry import telemetry_py +from common.telemetry_events import TelemetryEvent + + +class Button: + # The implementation is based off of https://microbit-micropython.readthedocs.io/en/v1.0.1/button.html. + def __init__(self): + self.__pressed = False + self.__presses = 0 + self.__prev_pressed = False + + def is_pressed(self): + """ + Returns ``True`` if the specified button ``button`` is currently being + held down, and ``False`` otherwise. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_BUTTON) + return self.__pressed + + def was_pressed(self): + """ + Returns ``True`` or ``False`` to indicate if the button was pressed + (went from up to down) since the device started or the last time this + method was called. Calling this method will clear the press state so + that the button must be pressed again before this method will return + ``True`` again. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_BUTTON) + res = self.__prev_pressed + self.__prev_pressed = False + return res + + def get_presses(self): + """ + Returns the running total of button presses, and resets this total + to zero before returning. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_BUTTON) + res = self.__presses + self.__presses = 0 + return res + + def __press_down(self): + self.__pressed = True + self.__prev_pressed = True + self.__presses += 1 + + def __release(self): + self.__pressed = False + + def __update(self, is_button_pressed): + if is_button_pressed is not None: + was_button_pressed = self.is_pressed() + + if is_button_pressed != was_button_pressed: + if is_button_pressed: + self.__press_down() + else: + self.__release() diff --git a/src/microbit/__model/constants.py b/src/microbit/__model/constants.py new file mode 100644 index 000000000..141f7fcde --- /dev/null +++ b/src/microbit/__model/constants.py @@ -0,0 +1,167 @@ +MICROBIT = "micro:bit" + +# string arguments for constructor +BLANK_5X5 = "00000:00000:00000:00000:00000:" + +# pre-defined image patterns +IMAGE_PATTERNS = { + "HEART": "09090:99999:99999:09990:00900:", + "HEART_SMALL": "00000:09090:09990:00900:00000:", + "HAPPY": "00000:09090:00000:90009:09990:", + "SMILE": "00000:00000:00000:90009:09990:", + "SAD": "00000:09090:00000:09990:90009:", + "CONFUSED": "00000:09090:00000:09090:90909:", + "ANGRY": "90009:09090:00000:99999:90909:", + "ASLEEP": "00000:99099:00000:09990:00000:", + "SURPRISED": "09090:00000:00900:09090:00900:", + "SILLY": "90009:00000:99999:00909:00999:", + "FABULOUS": "99999:99099:00000:09090:09990:", + "MEH": "09090:00000:00090:00900:09000:", + "YES": "00000:00009:00090:90900:09000:", + "NO": "90009:09090:00900:09090:90009:", + "CLOCK12": "00900:00900:00900:00000:00000:", + "CLOCK11": "09000:09000:00900:00000:00000:", + "CLOCK10": "00000:99000:00900:00000:00000:", + "CLOCK9": "00000:00000:99900:00000:00000:", + "CLOCK8": "00000:00000:00900:99000:00000:", + "CLOCK7": "00000:00000:00900:09000:09000:", + "CLOCK6": "00000:00000:00900:00900:00900:", + "CLOCK5": "00000:00000:00900:00090:00090:", + "CLOCK4": "00000:00000:00900:00099:00000:", + "CLOCK3": "00000:00000:00999:00000:00000:", + "CLOCK2": "00000:00099:00900:00000:00000:", + "CLOCK1": "00090:00090:00900:00000:00000:", + "ARROW_N": "00900:09990:90909:00900:00900:", + "ARROW_NE": "00999:00099:00909:09000:90000:", + "ARROW_E": "00900:00090:99999:00090:00900:", + "ARROW_SE": "90000:09000:00909:00099:00999:", + "ARROW_S": "00900:00900:90909:09990:00900:", + "ARROW_SW": "00009:00090:90900:99000:99900:", + "ARROW_W": "00900:09000:99999:09000:00900:", + "ARROW_NW": "99900:99000:90900:00090:00009:", + "TRIANGLE": "00000:00900:09090:99999:00000:", + "TRIANGLE_LEFT": "90000:99000:90900:90090:99999:", + "CHESSBOARD": "09090:90909:09090:90909:09090:", + "DIAMOND": "00900:09090:90009:09090:00900:", + "DIAMOND_SMALL": "00000:00900:09090:00900:00000:", + "SQUARE": "99999:90009:90009:90009:99999:", + "SQUARE_SMALL": "00000:09990:09090:09990:00000:", + "RABBIT": "90900:90900:99990:99090:99990:", + "COW": "90009:90009:99999:09990:00900:", + "MUSIC_CROTCHET": "00900:00900:00900:99900:99900:", + "MUSIC_QUAVER": "00900:00990:00909:99900:99900:", + "MUSIC_QUAVERS": "09999:09009:09009:99099:99099:", + "PITCHFORK": "90909:90909:99999:00900:00900:", + "XMAS": "00900:09990:00900:09990:99999:", + "PACMAN": "09999:99090:99900:99990:09999:", + "TARGET": "00900:09990:99099:09990:00900:", + "TSHIRT": "99099:99999:09990:09990:09990:", + "ROLLERSKATE": "00099:00099:99999:99999:09090:", + "DUCK": "09900:99900:09999:09990:00000:", + "HOUSE": "00900:09990:99999:09990:09090:", + "TORTOISE": "00000:09990:99999:09090:00000:", + "BUTTERFLY": "99099:99999:00900:99999:99099:", + "STICKFIGURE": "00900:99999:00900:09090:90009:", + "GHOST": "99999:90909:99999:99999:90909:", + "SWORD": "00900:00900:00900:09990:00900:", + "GIRAFFE": "99000:09000:09000:09990:09090:", + "SKULL": "09990:90909:99999:09990:09990:", + "UMBRELLA": "09990:99999:00900:90900:09900:", + "SNAKE": "99000:99099:09090:09990:00000:", +} + +IMAGE_TUPLE_LOOKUP = { + "ALL_CLOCKS": [ + "CLOCK12", + "CLOCK11", + "CLOCK10", + "CLOCK9", + "CLOCK8", + "CLOCK7", + "CLOCK6", + "CLOCK5", + "CLOCK4", + "CLOCK3", + "CLOCK2", + "CLOCK1", + ], + "ALL_ARROWS": [ + "ARROW_N", + "ARROW_NE", + "ARROW_E", + "ARROW_SE", + "ARROW_S", + "ARROW_SW", + "ARROW_W", + "ARROW_NW", + ], +} + +# 5x5 Alphabet +# Taken from https://raw.githubusercontent.com/micropython/micropython/264d80c84e034541bd6e4b461bfece4443ffd0ac/ports/nrf/boards/microbit/modules/microbitfont.h +ALPHABET = b"\x00\x00\x00\x00\x00\x08\x08\x08\x00\x08\x0a\x4a\x40\x00\x00\x0a\x5f\xea\x5f\xea\x0e\xd9\x2e\xd3\x6e\x19\x32\x44\x89\x33\x0c\x92\x4c\x92\x4d\x08\x08\x00\x00\x00\x04\x88\x08\x08\x04\x08\x04\x84\x84\x88\x00\x0a\x44\x8a\x40\x00\x04\x8e\xc4\x80\x00\x00\x00\x04\x88\x00\x00\x0e\xc0\x00\x00\x00\x00\x08\x00\x01\x22\x44\x88\x10\x0c\x92\x52\x52\x4c\x04\x8c\x84\x84\x8e\x1c\x82\x4c\x90\x1e\x1e\xc2\x44\x92\x4c\x06\xca\x52\x5f\xe2\x1f\xf0\x1e\xc1\x3e\x02\x44\x8e\xd1\x2e\x1f\xe2\x44\x88\x10\x0e\xd1\x2e\xd1\x2e\x0e\xd1\x2e\xc4\x88\x00\x08\x00\x08\x00\x00\x04\x80\x04\x88\x02\x44\x88\x04\x82\x00\x0e\xc0\x0e\xc0\x08\x04\x82\x44\x88\x0e\xd1\x26\xc0\x04\x0e\xd1\x35\xb3\x6c\x0c\x92\x5e\xd2\x52\x1c\x92\x5c\x92\x5c\x0e\xd0\x10\x10\x0e\x1c\x92\x52\x52\x5c\x1e\xd0\x1c\x90\x1e\x1e\xd0\x1c\x90\x10\x0e\xd0\x13\x71\x2e\x12\x52\x5e\xd2\x52\x1c\x88\x08\x08\x1c\x1f\xe2\x42\x52\x4c\x12\x54\x98\x14\x92\x10\x10\x10\x10\x1e\x11\x3b\x75\xb1\x31\x11\x39\x35\xb3\x71\x0c\x92\x52\x52\x4c\x1c\x92\x5c\x90\x10\x0c\x92\x52\x4c\x86\x1c\x92\x5c\x92\x51\x0e\xd0\x0c\x82\x5c\x1f\xe4\x84\x84\x84\x12\x52\x52\x52\x4c\x11\x31\x31\x2a\x44\x11\x31\x35\xbb\x71\x12\x52\x4c\x92\x52\x11\x2a\x44\x84\x84\x1e\xc4\x88\x10\x1e\x0e\xc8\x08\x08\x0e\x10\x08\x04\x82\x41\x0e\xc2\x42\x42\x4e\x04\x8a\x40\x00\x00\x00\x00\x00\x00\x1f\x08\x04\x80\x00\x00\x00\x0e\xd2\x52\x4f\x10\x10\x1c\x92\x5c\x00\x0e\xd0\x10\x0e\x02\x42\x4e\xd2\x4e\x0c\x92\x5c\x90\x0e\x06\xc8\x1c\x88\x08\x0e\xd2\x4e\xc2\x4c\x10\x10\x1c\x92\x52\x08\x00\x08\x08\x08\x02\x40\x02\x42\x4c\x10\x14\x98\x14\x92\x08\x08\x08\x08\x06\x00\x1b\x75\xb1\x31\x00\x1c\x92\x52\x52\x00\x0c\x92\x52\x4c\x00\x1c\x92\x5c\x90\x00\x0e\xd2\x4e\xc2\x00\x0e\xd0\x10\x10\x00\x06\xc8\x04\x98\x08\x08\x0e\xc8\x07\x00\x12\x52\x52\x4f\x00\x11\x31\x2a\x44\x00\x11\x31\x35\xbb\x00\x12\x4c\x8c\x92\x00\x11\x2a\x44\x98\x00\x1e\xc4\x88\x1e\x06\xc4\x8c\x84\x86\x08\x08\x08\x08\x08\x18\x08\x0c\x88\x18\x00\x00\x0c\x83\x60" +# We support ASCII characters between these indexes on the microbit +ASCII_START = 32 +ASCII_END = 126 +SPACE_BETWEEN_LETTERS_WIDTH = 1 +WHITESPACE_WIDTH = 3 + +# numerical LED values +LED_HEIGHT = 5 +LED_WIDTH = 5 +BRIGHTNESS_MIN = 0 +BRIGHTNESS_MAX = 9 + +# sensor max/min values +MAX_TEMPERATURE = 125 +MIN_TEMPERATURE = -55 +MAX_LIGHT_LEVEL = 255 +MIN_LIGHT_LEVEL = 0 +MAX_ACCELERATION = 1023 +MIN_ACCELERATION = -1023 + +GESTURES = set( + [ + "up", + "down", + "left", + "right", + "face up", + "face down", + "freefall", + "3g", + "6g", + "8g", + "shake", + ] +) + +# error messages +BRIGHTNESS_ERR = "brightness out of bounds" +COPY_ERR_MESSAGE = "please call copy function first" +INCORR_IMAGE_SIZE = "image data is incorrect size" +INDEX_ERR = "index out of bounds" +NOT_IMPLEMENTED_ERROR = "This method is not implemented by the simulator" +UNSUPPORTED_ADD_TYPE = "unsupported types for __add__:" +SAME_SIZE_ERR = "images must be the same size" +INVALID_GESTURE_ERR = "invalid gesture" +INVALID_ACCEL_ERR = "invalid acceleration" +INVALID_LIGHT_LEVEL_ERR = "invalid light level" +INVALID_TEMPERATURE_ERR = "invalid temperature" + +TIME_DELAY = 0.03 + +EXPECTED_INPUT_BUTTONS = [ + "button_a", + "button_b", +] + +EXPECTED_INPUT_ACCEL = { + "motion_x": "x", + "motion_y": "y", + "motion_z": "z", +} + +EXPECTED_INPUT_LIGHT = "light" + +EXPECTED_INPUT_TEMP = "temperature" diff --git a/src/microbit/__model/display.py b/src/microbit/__model/display.py new file mode 100644 index 000000000..eee651064 --- /dev/null +++ b/src/microbit/__model/display.py @@ -0,0 +1,370 @@ +import copy +import time +import threading +import common + +from common import utils +from common.telemetry import telemetry_py +from common.telemetry_events import TelemetryEvent +from . import constants as CONSTANTS +from .image import Image + + +class Display: + # The implementation based off of https://microbit-micropython.readthedocs.io/en/v1.0.1/display.html. + + def __init__(self): + self.__image = Image() + self.__on = True + self.__light_level = 0 + self.__blank_image = Image() + + self.__current_pid = None + self.__lock = threading.Lock() + self.__debug_mode = False + + def scroll(self, value, delay=150, wait=True, loop=False, monospace=False): + """ + Scrolls ``value`` horizontally on the display. If ``value`` is an integer or float it is + first converted to a string using ``str()``. The ``delay`` parameter controls how fast + the text is scrolling. + + If ``wait`` is ``True``, this function will block until the animation is + finished, otherwise the animation will happen in the background. + + If ``loop`` is ``True``, the animation will repeat forever. + + If ``monospace`` is ``True``, the characters will all take up 5 pixel-columns + in width, otherwise there will be exactly 1 blank pixel-column between each + character as they scroll. + + Note that the ``wait``, ``loop`` and ``monospace`` arguments must be specified + using their keyword. + """ + if not wait: + thread = threading.Thread( + target=self.scroll, args=(value, delay, True, loop, monospace) + ) + thread.start() + return + + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_DISPLAY_SCROLL) + + # Set current_pid to the thread's identifier + self.__lock.acquire() + self.__current_pid = threading.get_ident() + self.__lock.release() + + if isinstance(value, (str, int, float)): + value = str(value) + else: + raise TypeError(f"can't convert {type(value)} object to str implicitly") + + letters = [] + for c in value: + if monospace: + letters.append(Display.__get_image_from_char(c)) + letters.append( + Image(CONSTANTS.SPACE_BETWEEN_LETTERS_WIDTH, CONSTANTS.LED_HEIGHT) + ) + else: + if c == " ": + letters.append( + Image(CONSTANTS.WHITESPACE_WIDTH, CONSTANTS.LED_HEIGHT) + ) + else: + letters.append( + Display.__strip_unlit_columns(Display.__get_image_from_char(c)) + ) + letters.append( + Image( + CONSTANTS.SPACE_BETWEEN_LETTERS_WIDTH, CONSTANTS.LED_HEIGHT, + ) + ) + appended_image = Display.__create_scroll_image(letters) + + while True: + # Show the scrolled image one square at a time. + for x in range(appended_image.width() - CONSTANTS.LED_WIDTH + 1): + self.__lock.acquire() + + # If show or scroll is called again, there will be a different pid and break + if self.__current_pid != threading.get_ident(): + self.__lock.release() + break + + self.__image.blit( + appended_image, x, 0, CONSTANTS.LED_WIDTH, CONSTANTS.LED_HEIGHT + ) + self.__lock.release() + self.__update_client() + + Display.sleep_ms(delay) + + if not loop: + break + + def show(self, value, delay=400, wait=True, loop=False, clear=False): + """ + Display the ``image``. + + If ``value`` is a string, float or integer, display letters/digits in sequence. + Otherwise, if ``value`` is an iterable sequence of images, display these images in sequence. + Each letter, digit or image is shown with ``delay`` milliseconds between them. + + If ``wait`` is ``True``, this function will block until the animation is + finished, otherwise the animation will happen in the background. + + If ``loop`` is ``True``, the animation will repeat forever. + + If ``clear`` is ``True``, the display will be cleared after the iterable has finished. + + Note that the ``wait``, ``loop`` and ``clear`` arguments must be specified + using their keyword. + """ + if not wait: + thread = threading.Thread( + target=self.show, args=(value, delay, True, loop, clear) + ) + thread.start() + return + + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_DISPLAY_SHOW) + + # Set current_pid to the thread's identifier + self.__lock.acquire() + self.__current_pid = threading.get_ident() + self.__lock.release() + + images = [] + use_delay = False + if isinstance(value, Image): + images.append(value.crop(0, 0, CONSTANTS.LED_WIDTH, CONSTANTS.LED_HEIGHT)) + elif isinstance(value, (str, int, float)): + chars = list(str(value)) + for c in chars: + images.append(Display.__get_image_from_char(c)) + if len(chars) > 1: + use_delay = True + else: + # Check if iterable + try: + _ = iter(value) + except TypeError as e: + raise e + + for elem in value: + if isinstance(elem, Image): + images.append( + elem.crop(0, 0, CONSTANTS.LED_WIDTH, CONSTANTS.LED_HEIGHT) + ) + elif isinstance(elem, str) and len(elem) == 1: + images.append(Display.__get_image_from_char(elem)) + # If elem is not char or image, break without iterating through rest of list + else: + break + use_delay = True + + while True: + for image in images: + self.__lock.acquire() + + # If show or scroll is called again, there will be a different pid and break + if self.__current_pid != threading.get_ident(): + self.__lock.release() + break + + self.__image = image + self.__lock.release() + self.__update_client() + + if use_delay: + Display.sleep_ms(delay) + + if not loop: + break + if clear: + self.clear() + + def get_pixel(self, x, y): + """ + Return the brightness of the LED at column ``x`` and row ``y`` as an + integer between 0 (off) and 9 (bright). + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_DISPLAY_OTHER) + self.__lock.acquire() + pixel = self.__image.get_pixel(x, y) + self.__lock.release() + return pixel + + def set_pixel(self, x, y, value): + """ + Set the brightness of the LED at column ``x`` and row ``y`` to ``value``, + which has to be an integer between 0 and 9. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_DISPLAY_OTHER) + self.__lock.acquire() + self.__image.set_pixel(x, y, value) + self.__lock.release() + self.__update_client() + + def clear(self): + """ + Set the brightness of all LEDs to 0 (off). + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_DISPLAY_OTHER) + self.__lock.acquire() + self.__image = Image() + self.__lock.release() + self.__update_client() + + def on(self): + """ + Use on() to turn on the display. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_DISPLAY_OTHER) + self.__on = True + + def off(self): + """ + Use off() to turn off the display. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_DISPLAY_OTHER) + self.__on = False + + def is_on(self): + """ + Returns ``True`` if the display is on, otherwise returns ``False``. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_DISPLAY_OTHER) + return self.__on + + def read_light_level(self): + """ + Use the display's LEDs in reverse-bias mode to sense the amount of light + falling on the display. Returns an integer between 0 and 255 representing + the light level, with larger meaning more light. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_LIGHT_LEVEL) + return self.__light_level + + def __set_light_level(self, level): + if level < CONSTANTS.MIN_LIGHT_LEVEL or level > CONSTANTS.MAX_LIGHT_LEVEL: + raise ValueError(CONSTANTS.INVALID_LIGHT_LEVEL_ERR) + else: + self.__light_level = level + + # Helpers + + def __get_array(self): + self.__lock.acquire() + if self.is_on(): + leds = copy.deepcopy(self.__image._Image__LED) + else: + leds = self.__blank_image._Image__LED + self.__lock.release() + return leds + + @staticmethod + def __get_image_from_char(c): + # If c is not between the ASCII alphabet we cover, make it a question mark + if ord(c) < CONSTANTS.ASCII_START or ord(c) > CONSTANTS.ASCII_END: + c = "?" + offset = (ord(c) - CONSTANTS.ASCII_START) * CONSTANTS.LED_WIDTH + representative_bytes = CONSTANTS.ALPHABET[ + offset : offset + CONSTANTS.LED_HEIGHT + ] + return Image(Display.__convert_bytearray_to_image_str(representative_bytes)) + + # Removes columns that are not lit + @staticmethod + def __strip_unlit_columns(image): + min_index = CONSTANTS.LED_WIDTH - 1 + max_index = 0 + for row in image._Image__LED: + for index, bit in enumerate(row): + if bit > 0: + min_index = min(min_index, index) + max_index = max(max_index, index) + return image.crop(min_index, 0, max_index - min_index + 1, CONSTANTS.LED_HEIGHT) + + # This method is different from Image's __bytes_to_array. + # This one requires a conversion from binary of the ALPHABET constant to an image. + @staticmethod + def __convert_bytearray_to_image_str(byte_array): + arr = [] + for b in byte_array: + # Convert byte to binary + b_as_bits = str(bin(b))[2:] + sub_arr = [] + while len(sub_arr) < 5: + # Iterate throught bits + # If there is a 1 at b, then the pixel at column b is lit + for bit in b_as_bits[::-1]: + if len(sub_arr) < 5: + sub_arr.insert(0, int(bit) * CONSTANTS.BRIGHTNESS_MAX) + else: + break + # Add 0s to the front until the list is 5 long + while len(sub_arr) < 5: + sub_arr.insert(0, 0) + arr.append(sub_arr) + image_str = "" + for row in arr: + for elem in row: + image_str += str(elem) + image_str += ":" + return image_str + + @staticmethod + def __insert_blank_column(image): + for row in image._Image__LED: + row.append(0) + + @staticmethod + def __create_scroll_image(images): + blank_5x5_image = Image() + front_of_scroll_image = Image(4, 5) + images.insert(0, front_of_scroll_image) + + scroll_image = Image._Image__append_images(images) + end_of_scroll_image = Image() + # Insert columns of 0s until the ending is a 5x5 blank + end_of_scroll_image.blit( + scroll_image, + scroll_image.width() - CONSTANTS.LED_WIDTH, + 0, + CONSTANTS.LED_WIDTH, + CONSTANTS.LED_HEIGHT, + ) + while not Image._Image__same_image(end_of_scroll_image, blank_5x5_image): + Display.__insert_blank_column(scroll_image) + end_of_scroll_image.blit( + scroll_image, + scroll_image.width() - CONSTANTS.LED_WIDTH, + 0, + CONSTANTS.LED_WIDTH, + CONSTANTS.LED_HEIGHT, + ) + + return scroll_image + + def __update_client(self): + sendable_json = {"leds": self.__get_array()} + + if self.__debug_mode: + common.debugger_communication_client.debug_send_to_simulator( + sendable_json, CONSTANTS.MICROBIT + ) + else: + common.utils.send_to_simulator(sendable_json, CONSTANTS.MICROBIT) + + def __update_light_level(self, new_light_level): + if new_light_level is not None: + previous_light_level = self.read_light_level() + if new_light_level != previous_light_level: + self.__set_light_level(new_light_level) + + @staticmethod + def sleep_ms(ms): + time.sleep(ms / 1000) diff --git a/src/microbit/__model/image.py b/src/microbit/__model/image.py new file mode 100644 index 000000000..391e17e1e --- /dev/null +++ b/src/microbit/__model/image.py @@ -0,0 +1,539 @@ +from . import constants as CONSTANTS +from .producer_property import ProducerProperty +from common.telemetry import telemetry_py +from common.telemetry_events import TelemetryEvent + + +class Image: + """ + If ``string`` is used, it has to consist of digits 0-9 arranged into + lines, describing the image, for example:: + + image = Image("90009:" + "09090:" + "00900:" + "09090:" + "90009") + + will create a 5×5 image of an X. The end of a line is indicated by a colon. + It's also possible to use a newline (\\n) to indicate the end of a line + like this:: + + image = Image("90009\\n" + "09090\\n" + "00900\\n" + "09090\\n" + "90009") + + The other form creates an empty image with ``width`` columns and + ``height`` rows. Optionally ``buffer`` can be an array of + ``width``×``height`` integers in range 0-9 to initialize the image:: + + Image(2, 2, b'\x08\x08\x08\x08') + + or:: + + Image(2, 2, bytearray([9,9,9,9])) + + Will create a 2 x 2 pixel image at full brightness. + + .. note:: + + Keyword arguments cannot be passed to ``buffer``. + """ + + # Attributes assigned (to functions) later; + # having this here helps the pylint. + HEART = None + HEART_SMALL = None + HAPPY = None + SMILE = None + SAD = None + CONFUSED = None + ANGRY = None + ASLEEP = None + SURPRISED = None + SILLY = None + FABULOUS = None + MEH = None + YES = None + NO = None + CLOCK12 = None + CLOCK11 = None + CLOCK10 = None + CLOCK9 = None + CLOCK8 = None + CLOCK7 = None + CLOCK6 = None + CLOCK5 = None + CLOCK4 = None + CLOCK3 = None + CLOCK2 = None + CLOCK1 = None + ARROW_N = None + ARROW_NE = None + ARROW_E = None + ARROW_SE = None + ARROW_S = None + ARROW_SW = None + ARROW_W = None + ARROW_NW = None + TRIANGLE = None + TRIANGLE_LEFT = None + CHESSBOARD = None + DIAMOND = None + DIAMOND_SMALL = None + SQUARE = None + SQUARE_SMALL = None + RABBIT = None + COW = None + MUSIC_CROTCHET = None + MUSIC_QUAVER = None + MUSIC_QUAVERS = None + PITCHFORK = None + XMAS = None + PACMAN = None + TARGET = None + TSHIRT = None + ROLLERSKATE = None + DUCK = None + HOUSE = None + TORTOISE = None + BUTTERFLY = None + STICKFIGURE = None + GHOST = None + SWORD = None + GIRAFFE = None + SKULL = None + UMBRELLA = None + SNAKE = None + ALL_CLOCKS = None + ALL_ARROWS = None + + # implementing image model as described here: + # https://microbit-micropython.readthedocs.io/en/v1.0.1/image.html + + def __init__(self, *args, **kwargs): + # Depending on the number of arguments + # in constructor, it treat args differently. + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_CREATION) + if len(args) == 0: + # default constructor + self.__LED = self.__string_to_square_array(CONSTANTS.BLANK_5X5) + elif len(args) == 1: + pattern = args[0] + if isinstance(pattern, str): + self.__LED = self.__string_to_square_array(pattern) + else: + raise TypeError("Image(s) takes a string") + else: + + width = args[0] + height = args[1] + + if width < 0 or height < 0: + # This is not in original, but ideally, + # image should fail non-silently + raise ValueError(CONSTANTS.INDEX_ERR) + + if len(args) == 3: + # This option is for potential third bytearray arguments + byte_arr = args[2] + self.__LED = self.__bytes_to_array(width, height, byte_arr) + else: + self.__LED = self.__create_leds(width, height) + self.read_only = False + + def width(self): + """ + Return the number of columns in the image. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + if len(self.__LED) > 0: + return len(self.__LED[0]) + else: + return 0 + + def height(self): + """ + Return the numbers of rows in the image. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + return len(self.__LED) + + def set_pixel(self, x, y, value): + """ + Set the brightness of the pixel at column ``x`` and row ``y`` to the + ``value``, which has to be between 0 (dark) and 9 (bright). + + This method will raise an exception when called on any of the built-in + read-only images, like ``Image.HEART``. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + if self.read_only: + raise TypeError(CONSTANTS.COPY_ERR_MESSAGE) + elif not self.__valid_pos(x, y): + raise ValueError(CONSTANTS.INDEX_ERR) + elif not self.__valid_brightness(value): + raise ValueError(CONSTANTS.BRIGHTNESS_ERR) + else: + self.__LED[y][x] = value + + def get_pixel(self, x, y): + """ + Return the brightness of pixel at column ``x`` and row ``y`` as an + integer between 0 and 9. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + if self.__valid_pos(x, y): + return self.__LED[y][x] + else: + raise ValueError(CONSTANTS.INDEX_ERR) + + def shift_up(self, n): + """ + Return a new image created by shifting the picture up by ``n`` rows. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + return self.__shift_vertical(-n) + + def shift_down(self, n): + """ + Return a new image created by shifting the picture down by ``n`` rows. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + return self.__shift_vertical(n) + + def shift_right(self, n): + """ + Return a new image created by shifting the picture right by ``n`` + columns. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + return self.__shift_horizontal(n) + + def shift_left(self, n): + """ + Return a new image created by shifting the picture left by ``n`` + columns. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + return self.__shift_horizontal(-n) + + def crop(self, x, y, w, h): + """ + Return a new image by cropping the picture to a width of ``w`` and a + height of ``h``, starting with the pixel at column ``x`` and row ``y``. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + res = Image(w, h) + res.blit(self, x, y, w, h) + return res + + def copy(self): + """ + Return an exact copy of the image. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + return Image(self.__create_string()) + + # This inverts the brightness of each LED. + # ie: Pixel that is at brightness 4 would become brightness 5 + # and pixel that is at brightness 9 would become brightness 0. + def invert(self): + """ + Return a new image by inverting the brightness of the pixels in the + source image. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + for y in range(self.height()): + for x in range(self.width()): + self.set_pixel(x, y, CONSTANTS.BRIGHTNESS_MAX - self.get_pixel(x, y)) + + # This fills all LEDs with same brightness. + def fill(self, value): + """ + Set the brightness of all the pixels in the image to the + ``value``, which has to be between 0 (dark) and 9 (bright). + + This method will raise an exception when called on any of the built-in + read-only images, like ``Image.HEART``. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + for y in range(self.height()): + for x in range(self.width()): + self.set_pixel(x, y, value) + + # This transposes a certain area (w x h) on src onto the current image. + def blit(self, src, x, y, w, h, xdest=0, ydest=0): + """ + Copy the rectangle defined by ``x``, ``y``, ``w``, ``h`` from the image ``src`` into + this image at ``xdest``, ``ydest``. + Areas in the source rectangle, but outside the source image are treated as having a value of 0. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + if not src.__valid_pos(x, y): + raise ValueError(CONSTANTS.INDEX_ERR) + + for count_y in range(h): + for count_x in range(w): + if self.__valid_pos(xdest + count_x, ydest + count_y): + if src.__valid_pos(x + count_x, y + count_y): + transfer_pixel = src.get_pixel(x + count_x, y + count_y) + else: + transfer_pixel = 0 + self.set_pixel(xdest + count_x, ydest + count_y, transfer_pixel) + + # This adds two images (if other object is not an image, throws error). + # The images must be the same size. + def __add__(self, other): + """ + Create a new image by adding the brightness values from the two images for each pixel. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + if not isinstance(other, Image): + raise TypeError( + CONSTANTS.UNSUPPORTED_ADD_TYPE + f"'{type(self)}', '{type(other)}'" + ) + elif not (other.height() == self.height() and other.width() == self.width()): + raise ValueError(CONSTANTS.SAME_SIZE_ERR) + else: + res = Image(self.width(), self.height()) + + for y in range(self.height()): + for x in range(self.width()): + sum_value = other.get_pixel(x, y) + self.get_pixel(x, y) + display_result = min(CONSTANTS.BRIGHTNESS_MAX, sum_value) + res.set_pixel(x, y, display_result) + + return res + + # This multiplies image by number (if other factor is not a number, it throws an error). + def __mul__(self, other): + """ + Create a new image by multiplying the brightness of each pixel by n. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + try: + float_val = float(other) + except TypeError: + raise TypeError(f"can't convert {type(other)} to float") + + res = Image(self.width(), self.height()) + + for y in range(self.height()): + for x in range(self.width()): + product = self.get_pixel(x, y) * float_val + res.set_pixel(x, y, min(CONSTANTS.BRIGHTNESS_MAX, product)) + + return res + + def __repr__(self): + """ + Get a compact string representation of the image. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + ret_str = "Image('" + for index_y in range(self.height()): + ret_str += self.__row_to_str(index_y) + + ret_str += "')" + + return ret_str + + def __str__(self): + """ + Get a readable string representation of the image. + """ + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_OTHER) + ret_str = "Image('\n" + for index_y in range(self.height()): + ret_str += "\t" + self.__row_to_str(index_y) + "\n" + + ret_str += "')" + + return ret_str + + # HELPER FUNCTIONS + + # This create 2D array of off LEDs with + # width w and height h + def __create_leds(self, w, h): + arr = [] + for _ in range(h): + sub_arr = [] + for _ in range(w): + sub_arr.append(0) + arr.append(sub_arr) + + return arr + + # This turns byte array to 2D array for LED field. + def __bytes_to_array(self, width, height, byte_arr): + bytes_translated = bytes(byte_arr) + + if not len(bytes_translated) == height * width: + raise ValueError(CONSTANTS.INCORR_IMAGE_SIZE) + + arr = [] + sub_arr = [] + + for index, elem in enumerate(bytes_translated): + if index % width == 0 and index != 0: + arr.append(sub_arr) + sub_arr = [] + + sub_arr.append(elem) + + arr.append(sub_arr) + return arr + + # This converts string (with different rows separated by ":") + # to 2d array arrangement. + def __string_to_square_array(self, pattern): + initial_array, max_subarray_len = self.__string_directly_to_array(pattern) + + # Fill in empty spaces in w x h matrix. + for arr_y in initial_array: + num_extra_spaces = max_subarray_len - len(arr_y) + for _ in range(num_extra_spaces): + arr_y.append(0) + + return initial_array + + def __string_directly_to_array(self, pattern): + # The result may have spaces in the 2D array + # and may uneven sub-array lengths + arr = [] + sub_arr = [] + + max_subarray_len = 0 + + for elem in pattern: + if elem == ":" or elem == "\n": + if len(sub_arr) > max_subarray_len: + max_subarray_len = len(sub_arr) + arr.append(sub_arr) + sub_arr = [] + else: + sub_arr.append(int(elem)) + + if ( + len(pattern) > 0 + and not str(pattern)[-1] == ":" + and not str(pattern)[-1] == "\n" + and len(sub_arr) != 0 + ): + if len(sub_arr) > max_subarray_len: + max_subarray_len = len(sub_arr) + arr.append(sub_arr) + + return arr, max_subarray_len + + def __valid_brightness(self, value): + return value >= CONSTANTS.BRIGHTNESS_MIN and value <= CONSTANTS.BRIGHTNESS_MAX + + def __valid_pos(self, x, y): + return x >= 0 and x < self.width() and y >= 0 and y < self.height() + + def __shift_vertical(self, n): + res = Image(self.width(), self.height()) + + if n > 0: + # down + res.blit(self, 0, 0, self.width(), self.height() - n, 0, n) + else: + # up + if self.__valid_pos(0, abs(n)): + res.blit(self, 0, abs(n), self.width(), self.height() - abs(n), 0, 0) + + return res + + def __shift_horizontal(self, n): + res = Image(self.width(), self.height()) + if n > 0: + # right + res.blit(self, 0, 0, self.width() - n, self.height(), n, 0) + else: + # left + if self.__valid_pos(abs(n), 0): + res.blit(self, abs(n), 0, self.width() - abs(n), self.height(), 0, 0) + + return res + + def __create_string(self): + ret_str = "" + for index_y in range(self.height()): + ret_str += self.__row_to_str(index_y) + return ret_str + + def __row_to_str(self, y): + new_str = "" + for x in range(self.width()): + new_str += str(self.get_pixel(x, y)) + + new_str += ":" + + return new_str + + @staticmethod + def __append_images(images): + width = 0 + height = 0 + for image in images: + width += image.width() + height = max(height, image.height()) + res = Image(width, height) + x_ind = 0 + for image in images: + res.blit(image, 0, 0, image.width(), image.height(), xdest=x_ind) + x_ind += image.width() + return res + + @staticmethod + def __same_image(i1, i2): + if i1.width() != i2.width() or i1.height() != i2.height(): + return False + for y in range(i1.height()): + for x in range(i1.width()): + if i1.get_pixel(x, y) != i2.get_pixel(x, y): + return False + return True + + +# This is for generating functions like Image.HEART +# that return a new read-only Image +def create_const_func(func_name): + telemetry_py.send_telemetry(TelemetryEvent.MICROBIT_API_IMAGE_STATIC) + + def func(*args): + const_instance = Image(CONSTANTS.IMAGE_PATTERNS[func_name]) + const_instance.read_only = True + return const_instance + + func.__name__ = func_name + return ProducerProperty(func) + + +# for attributes like Image.ALL_CLOCKS +# that return tuples +def create_const_list_func(func_name): + def func(*args): + collection_names = CONSTANTS.IMAGE_TUPLE_LOOKUP[func_name] + ret_list = [] + for image_name in collection_names: + const_instance = Image(CONSTANTS.IMAGE_PATTERNS[image_name]) + const_instance.read_only = True + ret_list.append(const_instance) + + return tuple(ret_list) + + func.__name__ = func_name + return ProducerProperty(func) + + +for name in CONSTANTS.IMAGE_PATTERNS.keys(): + setattr(Image, name, create_const_func(name)) + +for name in CONSTANTS.IMAGE_TUPLE_LOOKUP.keys(): + setattr(Image, name, create_const_list_func(name)) diff --git a/src/microbit/__model/microbit_model.py b/src/microbit/__model/microbit_model.py new file mode 100644 index 000000000..e1bbb8971 --- /dev/null +++ b/src/microbit/__model/microbit_model.py @@ -0,0 +1,78 @@ +import time + +from .accelerometer import Accelerometer +from .button import Button +from .display import Display +from . import constants as CONSTANTS + + +class MicrobitModel: + def __init__(self): + # State in the Python process + self.accelerometer = Accelerometer() + self.button_a = Button() + self.button_b = Button() + self.display = Display() + + self.__start_time = time.time() + self.__temperature = 0 + self.__microbit_button_dict = { + "button_a": self.button_a, + "button_b": self.button_b, + } + + def sleep(self, n): + time.sleep(n / 1000) + + def running_time(self): + print(f"time. time: {time.time()}") + return time.time() - self.__start_time + + def temperature(self): + return self.__temperature + + def __set_temperature(self, temperature): + if ( + temperature < CONSTANTS.MIN_TEMPERATURE + or temperature > CONSTANTS.MAX_TEMPERATURE + ): + raise ValueError(CONSTANTS.INVALID_TEMPERATURE_ERR) + else: + self.__temperature = temperature + + def update_state(self, new_state): + self.__update_buttons(new_state) + self.__update_motion(new_state) + self.__update_light(new_state) + self.__update_temp(new_state) + + # helpers + def __update_buttons(self, new_state): + # get button pushes + for button_name in CONSTANTS.EXPECTED_INPUT_BUTTONS: + button = self.__microbit_button_dict[button_name] + button._Button__update(new_state.get(button_name)) + + def __update_motion(self, new_state): + # set motion_x, motion_y, motion_z + for name, direction in CONSTANTS.EXPECTED_INPUT_ACCEL.items(): + self.accelerometer._Accelerometer__update(direction, new_state.get(name)) + + def __update_light(self, new_state): + # set light level + new_light_level = new_state.get(CONSTANTS.EXPECTED_INPUT_LIGHT) + self.display._Display__update_light_level(new_light_level) + + def __update_temp(self, new_state): + # set temperature + new_temp = new_state.get(CONSTANTS.EXPECTED_INPUT_TEMP) + if new_temp is not None: + previous_temp = self.temperature() + if new_temp != previous_temp: + self._MicrobitModel__set_temperature(new_temp) + + def __set_debug_mode(self, mode): + self.display._Display__debug_mode = mode + + +__mb = MicrobitModel() diff --git a/src/microbit/__model/producer_property.py b/src/microbit/__model/producer_property.py new file mode 100644 index 000000000..6a6ed593a --- /dev/null +++ b/src/microbit/__model/producer_property.py @@ -0,0 +1,3 @@ +class ProducerProperty(property): + def __get__(self, cls, owner): + return classmethod(self.fget).__get__(cls, owner)() diff --git a/src/microbit/test/__init__.py b/src/microbit/test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/microbit/test/test_accelerometer.py b/src/microbit/test/test_accelerometer.py new file mode 100644 index 000000000..0e654727c --- /dev/null +++ b/src/microbit/test/test_accelerometer.py @@ -0,0 +1,104 @@ +import pytest +from unittest import mock + +from ..__model.accelerometer import Accelerometer +from ..__model import constants as CONSTANTS + + +class TestAccelerometer(object): + def setup_method(self): + self.accelerometer = Accelerometer() + + @pytest.mark.parametrize( + "accel", + [ + CONSTANTS.MIN_ACCELERATION, + CONSTANTS.MIN_ACCELERATION + 1, + 100, + CONSTANTS.MAX_ACCELERATION - 1, + CONSTANTS.MAX_ACCELERATION, + ], + ) + def test_x_y_z(self, accel): + self.accelerometer._Accelerometer__set_accel("x", accel) + assert accel == self.accelerometer.get_x() + self.accelerometer._Accelerometer__set_accel("y", accel) + assert accel == self.accelerometer.get_y() + self.accelerometer._Accelerometer__set_accel("z", accel) + assert accel == self.accelerometer.get_z() + + @pytest.mark.parametrize("axis", ["x", "y", "z"]) + def test_x_y_z_invalid_accel(self, axis): + with pytest.raises(ValueError): + self.accelerometer._Accelerometer__set_accel( + axis, CONSTANTS.MAX_ACCELERATION + 1 + ) + with pytest.raises(ValueError): + self.accelerometer._Accelerometer__set_accel( + axis, CONSTANTS.MIN_ACCELERATION - 1 + ) + + @pytest.mark.parametrize( + "accels", + [ + (23, 25, 26), + (204, 234, -534), + (CONSTANTS.MIN_ACCELERATION + 10, 234, CONSTANTS.MAX_ACCELERATION), + ], + ) + def test_get_values(self, accels): + self.accelerometer._Accelerometer__set_accel("x", accels[0]) + self.accelerometer._Accelerometer__set_accel("y", accels[1]) + self.accelerometer._Accelerometer__set_accel("z", accels[2]) + assert accels == self.accelerometer.get_values() + + @pytest.mark.parametrize("gesture", ["up", "face down", "freefall", "8g"]) + def test_current_gesture(self, gesture): + self.accelerometer._Accelerometer__set_gesture(gesture) + assert gesture == self.accelerometer.current_gesture() + + @pytest.mark.parametrize("gesture", ["up", "face down", "freefall", "8g"]) + def test_is_gesture(self, gesture): + self.accelerometer._Accelerometer__set_gesture(gesture) + assert self.accelerometer.is_gesture(gesture) + for g in CONSTANTS.GESTURES: + if g != gesture: + assert not self.accelerometer.is_gesture(g) + + def test_is_gesture_error(self): + with pytest.raises(ValueError): + self.accelerometer.is_gesture("sideways") + + def test_was_gesture(self): + mock_gesture_up = "up" + mock_gesture_down = "down" + + assert not self.accelerometer.was_gesture(mock_gesture_up) + self.accelerometer._Accelerometer__set_gesture(mock_gesture_up) + self.accelerometer.current_gesture() # Call is needed for gesture detection so it can be added to the lists. + self.accelerometer._Accelerometer__set_gesture("") + assert self.accelerometer.was_gesture(mock_gesture_up) + assert not self.accelerometer.was_gesture(mock_gesture_up) + + def test_was_gesture_error(self): + with pytest.raises(ValueError): + self.accelerometer.was_gesture("sideways") + + def test_get_gestures(self): + mock_gesture_up = "up" + mock_gesture_down = "down" + mock_gesture_freefall = "freefall" + + self.accelerometer._Accelerometer__set_gesture(mock_gesture_up) + self.accelerometer.current_gesture() # Call is needed for gesture detection so it can be added to the lists. + self.accelerometer._Accelerometer__set_gesture(mock_gesture_down) + self.accelerometer.current_gesture() + self.accelerometer._Accelerometer__set_gesture(mock_gesture_freefall) + self.accelerometer.current_gesture() + self.accelerometer._Accelerometer__set_gesture("") + assert ( + mock_gesture_up, + mock_gesture_down, + mock_gesture_freefall, + ) == self.accelerometer.get_gestures() + assert () == self.accelerometer.get_gestures() diff --git a/src/microbit/test/test_button.py b/src/microbit/test/test_button.py new file mode 100644 index 000000000..9e0b3cbcb --- /dev/null +++ b/src/microbit/test/test_button.py @@ -0,0 +1,46 @@ +import pytest +from ..__model.button import Button + + +class TestButton(object): + def setup_method(self): + self.button = Button() + + def test_press_down(self): + self.button._Button__press_down() + assert self.button._Button__presses == 1 + assert self.button._Button__pressed + assert self.button._Button__prev_pressed + self.button._Button__press_down() + assert self.button._Button__presses == 2 + assert self.button._Button__pressed + assert self.button._Button__prev_pressed + + def test_release(self): + self.button._Button__pressed = True + self.button._Button__prev_pressed = False + self.button._Button__release() + assert not self.button._Button__pressed + + def test_is_pressed(self): + assert not self.button.is_pressed() + self.button._Button__press_down() + assert self.button.is_pressed() + + def test_was_pressed(self): + assert not self.button.was_pressed() + self.button._Button__press_down() + self.button._Button__release() + assert self.button.was_pressed() + # Button resets __prev_pressed after was_pressed() is called. + assert not self.button.was_pressed() + + @pytest.mark.parametrize("presses", [1, 2, 4]) + def test_get_presses(self, presses): + assert 0 == self.button.get_presses() + for i in range(presses): + self.button._Button__press_down() + self.button._Button__release() + assert presses == self.button.get_presses() + # Presses is reset to 0 after get_presses() is called. + assert 0 == self.button.get_presses() diff --git a/src/microbit/test/test_display.py b/src/microbit/test/test_display.py new file mode 100644 index 000000000..06cc6609e --- /dev/null +++ b/src/microbit/test/test_display.py @@ -0,0 +1,185 @@ +import pytest +import threading +from unittest import mock +from common import utils + +from ..__model import constants as CONSTANTS +from ..__model.display import Display +from ..__model.image import Image + + +STR_A = "09900:90090:99990:90090:90090" +STR_QUESTION_MARK = "09990:90009:00990:00000:00900" +STR_EXCLAMATION_MARK = "09000:09000:09000:00000:09000:" +STR_SIX = "00090:00900:09990:90009:09990" + + +class TestDisplay(object): + def setup_method(self): + self.display = Display() + utils.send_to_simulator = mock.Mock() + + @pytest.mark.parametrize("x, y, brightness", [(1, 1, 4), (2, 3, 6), (4, 4, 9)]) + def test_set_and_get_pixel(self, x, y, brightness): + self.display.set_pixel(x, y, brightness) + assert brightness == self.display.get_pixel(x, y) + + @pytest.mark.parametrize("x, y", [(5, 0), (0, -1), (0, 5)]) + def test_get_pixel_error(self, x, y): + with pytest.raises(ValueError, match=CONSTANTS.INDEX_ERR): + self.display.get_pixel(x, y) + + @pytest.mark.parametrize( + "x, y, brightness, err_msg", + [ + (5, 0, 0, CONSTANTS.INDEX_ERR), + (0, -1, 0, CONSTANTS.INDEX_ERR), + (0, 0, -1, CONSTANTS.BRIGHTNESS_ERR), + ], + ) + def test_set_pixel_error(self, x, y, brightness, err_msg): + with pytest.raises(ValueError, match=err_msg): + self.display.set_pixel(x, y, brightness) + + def test_clear(self): + self.display.set_pixel(2, 3, 7) + self.display.set_pixel(3, 4, 6) + self.display.set_pixel(4, 4, 9) + assert not self.__is_clear() + self.display.clear() + assert self.__is_clear() + + def test_on_off(self): + self.display.on() + assert self.display.is_on() + self.display.off() + assert not self.display.is_on() + + def test_show_one_image(self): + img = Image() + img.set_pixel(0, 0, 8) + img.set_pixel(0, 1, 9) + img.set_pixel(0, 2, 7) + img.set_pixel(2, 2, 6) + self.display.show(img, delay=0) + assert Image._Image__same_image(img, self.display._Display__image) + + def test_show_different_size_image(self): + img = Image(3, 7) + img.set_pixel(1, 1, 9) + img.set_pixel(2, 6, 9) # Will not be on display + expected = Image(5, 5) + expected.set_pixel(1, 1, 9) + self.display.show(img, delay=0) + assert Image._Image__same_image(expected, self.display._Display__image) + + def test_show_smaller_image(self): + img = Image(2, 2) + img.set_pixel(1, 1, 9) + expected = Image(5, 5) + expected.set_pixel(1, 1, 9) + self.display.show(img, delay=0) + assert Image._Image__same_image(expected, self.display._Display__image) + + @pytest.mark.parametrize( + "value, expected_str", + [ + ("!", STR_EXCLAMATION_MARK), + ("A", STR_A), + (" ", CONSTANTS.BLANK_5X5), + (6, STR_SIX), + ("\x7F", STR_QUESTION_MARK), # Character is out of our ASCII range + ], + ) + def test_show_char(self, value, expected_str): + expected = Image(expected_str) + self.display.show(value, delay=0) + assert Image._Image__same_image(expected, self.display._Display__image) + + def test_show_char_with_clear(self): + image = Image(STR_EXCLAMATION_MARK) + self.display.show(image, delay=0, clear=True) + assert self.__is_clear() + + def test_show_iterable(self): + expected = Image(STR_A) + value = [Image(STR_EXCLAMATION_MARK), "A", "ab"] + self.display.show(value, delay=0) + assert Image._Image__same_image(expected, self.display._Display__image) + + def test_show_non_iterable(self): + with pytest.raises(TypeError): + self.display.show(TestDisplay()) + + def test_scroll(self): + self.display.scroll("a b") + self.__is_clear() + + def test_scroll_type_error(self): + with pytest.raises(TypeError): + self.display.scroll(["a", 1]) + + # Should change these threaded tests to test behaviour in the future + def test_show_threaded(self): + threading.Thread = mock.Mock() + self.display.show("a", delay=0, wait=False) + threading.Thread.assert_called_once() + + def test_scroll_threaded(self): + threading.Thread = mock.Mock() + self.display.scroll("test", delay=0, wait=False) + threading.Thread.assert_called_once() + + def test_get_array(self): + self.display.set_pixel(3, 3, 3) + self.display.off() + assert self.display._Display__get_array() == [ + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + ] + + self.display.on() + assert self.display._Display__get_array() == [ + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 3, 0], + [0, 0, 0, 0, 0], + ] + + # The second show call should immedaitely stop the first show call. + # Therefore the final result of display should be 6. + def test_async_tests(self): + self.display.show("MMMMMMMMMMMMMM", delay=100, wait=False) + self.display.show("6", delay=0) + assert Image._Image__same_image(Image(STR_SIX), self.display._Display__image) + + @pytest.mark.parametrize( + "light_level", + [ + CONSTANTS.MIN_LIGHT_LEVEL, + CONSTANTS.MIN_LIGHT_LEVEL + 1, + 100, + CONSTANTS.MAX_LIGHT_LEVEL - 1, + CONSTANTS.MAX_LIGHT_LEVEL, + ], + ) + def test_light_level(self, light_level): + self.display._Display__set_light_level(light_level) + assert light_level == self.display.read_light_level() + + @pytest.mark.parametrize( + "invalid_light_level", + [CONSTANTS.MIN_LIGHT_LEVEL - 1, CONSTANTS.MAX_LIGHT_LEVEL + 1], + ) + def test_invalid_light_level(self, invalid_light_level): + with pytest.raises(ValueError): + self.display._Display__set_light_level(invalid_light_level) + + # Helpers + def __is_clear(self): + i = Image(CONSTANTS.BLANK_5X5) + return Image._Image__same_image(i, self.display._Display__image) diff --git a/src/microbit/test/test_image.py b/src/microbit/test/test_image.py new file mode 100644 index 000000000..c4d2731d6 --- /dev/null +++ b/src/microbit/test/test_image.py @@ -0,0 +1,283 @@ +import pytest +from ..__model.image import Image + +from ..__model import constants as CONSTANTS + + +class TestImage(object): + def setup_method(self): + self.image = Image() + self.image_heart = Image(CONSTANTS.IMAGE_PATTERNS["HEART"]) + + @pytest.mark.parametrize("x, y, brightness", [(1, 1, 4), (2, 3, 6), (4, 4, 9)]) + def test_get_set_pixel(self, x, y, brightness): + self.image.set_pixel(x, y, brightness) + assert brightness == self.image.get_pixel(x, y) + + @pytest.mark.parametrize("x, y", [(5, 0), (0, -1), (0, 5)]) + def test_get_pixel_error(self, x, y): + with pytest.raises(ValueError, match=CONSTANTS.INDEX_ERR): + self.image.get_pixel(x, y) + + @pytest.mark.parametrize( + "x, y, brightness, err_msg", + [ + (5, 0, 0, CONSTANTS.INDEX_ERR), + (0, -1, 0, CONSTANTS.INDEX_ERR), + (0, 0, -1, CONSTANTS.BRIGHTNESS_ERR), + ], + ) + def test_set_pixel_error(self, x, y, brightness, err_msg): + with pytest.raises(ValueError, match=err_msg): + self.image.set_pixel(x, y, brightness) + + @pytest.mark.parametrize( + "image, height, width", + [ + (Image(), 5, 5), + (Image(3, 3), 3, 3), + (Image(""), 0, 0), + (Image("00:00000"), 2, 5), + (Image("0000:0000"), 2, 4), + ], + ) + def test_width_and_height(self, image, height, width): + print(str(image)) + assert image.height() == height + assert image.width() == width + + @pytest.mark.parametrize( + "x, y, w, h, x_dest, y_dest, actual", + [ + (0, 0, 3, 2, 2, 1, Image("00000:00090:00999:00000:00000:")), + (0, 0, 3, 3, 8, 8, Image("00000:00000:00000:00000:00000:")), + (3, 0, 3, 3, 0, 0, Image("90000:99000:99000:00000:00000:")), + (3, 0, 7, 7, 0, 0, Image("90000:99000:99000:90000:00000:")), + ], + ) + def test_blit_heart(self, x, y, w, h, x_dest, y_dest, actual): + result = Image() + result.blit(self.image_heart, x, y, w, h, x_dest, y_dest) + assert result._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "x, y, w, h, x_dest, y_dest, actual", + [ + (1, 1, 2, 4, 3, 3, Image("09090:99999:99999:09999:00999:")), + (0, 0, 3, 3, 8, 8, Image(CONSTANTS.IMAGE_PATTERNS["HEART"])), + (0, 0, 7, 7, 0, 0, Image(CONSTANTS.IMAGE_PATTERNS["HEART"])), + (3, 0, 7, 7, 0, 0, Image("90000:99000:99000:90000:00000:")), + ], + ) + def test_blit_heart_nonblank(self, x, y, w, h, x_dest, y_dest, actual): + result = Image(CONSTANTS.IMAGE_PATTERNS["HEART"]) + src = Image(CONSTANTS.IMAGE_PATTERNS["HEART"]) + result.blit(src, x, y, w, h, x_dest, y_dest) + assert result._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "x, y, w, h, x_dest, y_dest", [(5, 6, 2, 4, 3, 3), (5, 0, 3, 3, 8, 8)] + ) + def test_blit_heart_valueerror(self, x, y, w, h, x_dest, y_dest): + result = Image(CONSTANTS.IMAGE_PATTERNS["HEART"]) + with pytest.raises(ValueError, match=CONSTANTS.INDEX_ERR): + result.blit(self.image_heart, x, y, w, h, x_dest, y_dest) + + @pytest.mark.parametrize( + "image1, image2", [(Image(2, 2, bytearray([4, 4, 4, 4])), Image("44:44"))] + ) + def test_constructor_bytearray(self, image1, image2): + assert image1._Image__LED == image2._Image__LED + + @pytest.mark.parametrize( + "x, y, w, h, actual", [(1, 1, 2, 4, Image("99:99:99:09:"))] + ) + def test_crop_heart(self, x, y, w, h, actual): + result = self.image_heart.crop(1, 1, 2, 4) + assert result._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "target, actual", [(Image("99:99:99:00:"), Image("22:22:22:22:"))] + ) + def test_fill(self, target, actual): + target.fill(2) + assert target._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "target, actual", [(Image("012:345:678:900:"), Image("987:654:321:099:"))] + ) + def test_invert(self, target, actual): + target.invert() + assert target._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "target, value, actual", + [ + (Image("012:345:678:900:"), 1, Image("001:034:067:090:")), + (Image("012:345:678:900:"), 6, Image("000:000:000:000:")), + (Image("012:345:678:900:"), -1, Image("120:450:780:000:")), + ], + ) + def test_shift_right(self, target, value, actual): + result = target.shift_right(value) + assert result._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "target, value, actual", + [ + (Image("012:345:678:900:"), 2, Image("200:500:800:000:")), + (Image("012:345:678:900:"), 6, Image("000:000:000:000:")), + (Image("012:345:678:900:"), -2, Image("000:003:006:009:")), + ], + ) + def test_shift_left(self, target, value, actual): + result = target.shift_left(value) + assert result._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "target, value, actual", + [ + (Image("012:345:678:900:"), 2, Image("678:900:000:000:")), + (Image("012:345:678:900:"), 6, Image("000:000:000:000:")), + (Image("012:345:678:900:"), -2, Image("000:000:012:345:")), + ], + ) + def test_shift_up(self, target, value, actual): + result = target.shift_up(value) + assert result._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "target, value, actual", + [ + (Image("012:345:678:900:"), 1, Image("000:012:345:678")), + (Image("012:345:678:900:"), 6, Image("000:000:000:000:")), + (Image("012:345:678:900:"), -1, Image("345:678:900:000:")), + ], + ) + def test_shift_down(self, target, value, actual): + result = target.shift_down(value) + assert result._Image__LED == actual._Image__LED + + @pytest.mark.parametrize("target", [(Image("012:345:678:900:"))]) + def test_copy(self, target): + result = target.copy() + assert result._Image__LED == target._Image__LED + + @pytest.mark.parametrize( + "target, multiplier, actual", + [ + (Image("012:345:678:900:"), 2, Image("024:689:999:900:")), + (Image("012:345:678:900:"), 0, Image("000:000:000:000:")), + ], + ) + def test_multiply(self, target, multiplier, actual): + result = target * multiplier + assert result._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "target, multiplier", + [ + (Image("012:345:678:900:"), []), + (Image("012:345:678:900:"), Image("000:000:000:000:")), + ], + ) + def test_multiply_error(self, target, multiplier): + + with pytest.raises( + TypeError, match=f"can't convert {type(multiplier)} to float" + ): + target * multiplier + + @pytest.mark.parametrize( + "target, value, actual", + [ + ( + Image("012:345:678:900:"), + Image("024:689:999:900:"), + Image("036:999:999:900:"), + ), + ( + Image("999:999:999:000:"), + Image("999:999:999:000:"), + Image("999:999:999:000:"), + ), + ], + ) + def test_add(self, target, value, actual): + result = target + value + assert result._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "target, value, err_message", + [ + ( + Image("012:345:678:900:"), + 2, + CONSTANTS.UNSUPPORTED_ADD_TYPE + f"'{type(Image())}', '{type(2)}'", + ), + ( + Image("012:345:678:900:"), + [], + CONSTANTS.UNSUPPORTED_ADD_TYPE + f"'{type(Image())}', '{type([])}'", + ), + ], + ) + def test_add_typeerror(self, target, value, err_message): + with pytest.raises(TypeError, match=err_message): + target + value + + @pytest.mark.parametrize( + "target, value", [(Image(2, 3), Image(3, 3)), (Image(2, 1), Image(0, 0))] + ) + def test_add_valueerror(self, target, value): + with pytest.raises(ValueError, match=CONSTANTS.SAME_SIZE_ERR): + target + value + + @pytest.mark.parametrize( + "initial, actual", + [ + (Image("0:000:00:0000:"), Image("0000:0000:0000:0000:")), + (Image("12125:1212:12:1:"), Image("12125:12120:12000:10000:")), + ], + ) + def test_uneven_strings(self, initial, actual): + assert initial._Image__LED == actual._Image__LED + + @pytest.mark.parametrize( + "image, repr_actual, str_actual", + [ + ( + Image("05150:05050:05050:99999:09990:"), + "Image('05150:05050:05050:99999:09990:')", + "Image('\n 05150:\n 05050:\n 05050:\n 99999:\n 09990:\n')", + ), + (Image(""), "Image('')", "Image('\n')"), + ( + Image("00000:00000:00000:00000:00000:"), + "Image('00000:00000:00000:00000:00000:')", + "Image('\n 00000:\n 00000:\n 00000:\n 00000:\n 00000:\n')", + ), + ( + Image("00:00:00:00:"), + "Image('00:00:00:00:')", + "Image('\n 00:\n 00:\n 00:\n 00:\n')", + ), + ], + ) + def test_str(self, image, repr_actual, str_actual): + repr_output = repr(image) + str_output = str(image) + assert repr_actual == repr_output + assert str_actual == str_output + + @pytest.mark.parametrize( + "const, actual", + [ + (Image.SNAKE, Image(CONSTANTS.IMAGE_PATTERNS["SNAKE"])), + (Image.PITCHFORK, Image(CONSTANTS.IMAGE_PATTERNS["PITCHFORK"])), + ], + ) + def test_image_constants(self, const, actual): + assert const._Image__LED == actual._Image__LED + with pytest.raises(TypeError, match=CONSTANTS.COPY_ERR_MESSAGE): + const.set_pixel(0, 0, 5) diff --git a/src/microbit/test/test_init.py b/src/microbit/test/test_init.py new file mode 100644 index 000000000..c6882ac75 --- /dev/null +++ b/src/microbit/test/test_init.py @@ -0,0 +1,45 @@ +import time + +import pytest +from unittest import mock + +from .. import * +from ..__model.microbit_model import MicrobitModel + +# tests methods in __init__.py + + +class TestShim(object): + def test_sleep(self): + # Save pointer to function about to be mocked + real_function = MicrobitModel.sleep + + milliseconds = 100 + MicrobitModel.sleep = mock.Mock() + sleep(milliseconds) + MicrobitModel.sleep.assert_called_with(milliseconds) + + # Restore original function + MicrobitModel.sleep = real_function + + def test_running_time(self): + # Save pointer to function about to be mocked + real_function = MicrobitModel.running_time + + MicrobitModel.running_time = mock.Mock() + running_time() + MicrobitModel.running_time.assert_called_once() + + # Restore original function + MicrobitModel.running_time = real_function + + def test_temperature(self): + # Save pointer to function about to be mocked + real_function = MicrobitModel.temperature + + MicrobitModel.temperature = mock.Mock() + temperature() + MicrobitModel.temperature.asser_called_once() + + # Restore original function + MicrobitModel.temperature = real_function diff --git a/src/microbit/test/test_microbit_model.py b/src/microbit/test/test_microbit_model.py new file mode 100644 index 000000000..1577bf24a --- /dev/null +++ b/src/microbit/test/test_microbit_model.py @@ -0,0 +1,48 @@ +import time + +import pytest +from unittest import mock +from ..__model import constants as CONSTANTS +from ..__model.microbit_model import MicrobitModel + + +class TestMicrobitModel(object): + def setup_method(self): + self.__mb = MicrobitModel() + + @pytest.mark.parametrize("value", [9, 30, 1999]) + def test_sleep(self, value): + time.sleep = mock.Mock() + self.__mb.sleep(value) + time.sleep.assert_called_with(value / 1000) + + def test_running_time(self): + mock_start_time = 10 + mock_end_time = 300 + self.__mb._MicrobitModel__start_time = mock_start_time + time.time = mock.MagicMock(return_value=mock_end_time) + assert mock_end_time - mock_start_time == pytest.approx( + self.__mb.running_time() + ) + + @pytest.mark.parametrize( + "temperature", + [ + CONSTANTS.MIN_TEMPERATURE, + CONSTANTS.MIN_TEMPERATURE + 1, + 0, + CONSTANTS.MAX_TEMPERATURE - 1, + CONSTANTS.MAX_TEMPERATURE, + ], + ) + def test_temperature(self, temperature): + self.__mb._MicrobitModel__set_temperature(temperature) + assert temperature == self.__mb.temperature() + + @pytest.mark.parametrize( + "invalid_temperature", + [CONSTANTS.MIN_TEMPERATURE - 1, CONSTANTS.MAX_TEMPERATURE + 1], + ) + def test_invalid_temperature(self, invalid_temperature): + with pytest.raises(ValueError): + self.__mb._MicrobitModel__set_temperature(invalid_temperature) diff --git a/src/process_user_code.py b/src/process_user_code.py index 1991f9816..3349ce0a5 100644 --- a/src/process_user_code.py +++ b/src/process_user_code.py @@ -10,11 +10,10 @@ import traceback import python_constants as CONSTANTS from pathlib import Path +import check_python_dependencies -# Insert absolute path to python libraries into sys.path -abs_path_to_parent_dir = os.path.dirname(os.path.abspath(__file__)) -abs_path_to_lib = os.path.join(abs_path_to_parent_dir, CONSTANTS.PYTHON_LIBS_DIR) -sys.path.insert(0, abs_path_to_lib) +# will propagate errors if dependencies aren't sufficient +check_python_dependencies.check_for_dependencies() read_val = "" threads = [] @@ -28,8 +27,13 @@ sys.path.insert(0, abs_path_to_lib) # This import must happen after the sys.path is modified +from common.telemetry import telemetry_py + from adafruit_circuitplayground.express import cpx -from adafruit_circuitplayground.telemetry import telemetry_py +from adafruit_circuitplayground.constants import CPX + +from microbit.__model.microbit_model import __mb as mb +from microbit.__model.constants import MICROBIT # Handle User Inputs Thread @@ -38,15 +42,18 @@ def __init__(self): threading.Thread.__init__(self) def run(self): + device_dict = {CPX: cpx, MICROBIT: mb} while True: read_val = sys.stdin.readline() sys.stdin.flush() try: - new_state = json.loads(read_val) - for event in CONSTANTS.EXPECTED_INPUT_EVENTS: - cpx._Express__state[event] = new_state.get( - event, cpx._Express__state[event] - ) + new_state_message = json.loads(read_val) + device = new_state_message.get(CONSTANTS.ACTIVE_DEVICE_FIELD) + new_state = new_state_message.get(CONSTANTS.STATE_FIELD, {}) + if device in device_dict: + device_dict[device].update_state(new_state) + else: + raise Exception(CONSTANTS.DEVICE_NOT_IMPLEMENTED_ERROR) except Exception as e: print(CONSTANTS.ERROR_SENDING_EVENT, e, file=sys.stderr, flush=True) @@ -95,6 +102,7 @@ def execute_user_code(abs_path_to_code_file): user_code = threading.Thread(args=(sys.argv[1],), target=execute_user_code) telemetry_state = json.loads(sys.argv[2]) + telemetry_py._Telemetry__enable_telemetry = telemetry_state.get( CONSTANTS.ENABLE_TELEMETRY, True ) diff --git a/src/python_constants.py b/src/python_constants.py index a700a3143..1e8442d38 100644 --- a/src/python_constants.py +++ b/src/python_constants.py @@ -1,21 +1,15 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. +ACTIVE_DEVICE_FIELD = "active_device" + CPX_DRIVE_NAME = "CIRCUITPY" +DEPEND_ERR = 'The required dependencies aren\'t downloaded. Please use CTRL+SHIFT+P to open the command palette and select "Device Simulator Express: Install Extension Dependencies".' + +DEVICE_NOT_IMPLEMENTED_ERROR = "Device not implemented." + ENABLE_TELEMETRY = "enable_telemetry" -EXPECTED_INPUT_EVENTS = [ - "button_a", - "button_b", - "switch", - "temperature", - "light", - "shake", - "motion_x", - "motion_y", - "motion_z", - "touch", -] EXEC_COMMAND = "exec" ERROR_SENDING_EVENT = "Error trying to send event to the process : " @@ -35,10 +29,14 @@ NOT_SUPPORTED_OS = 'The OS "{}" not supported.' NOT_IMPLEMENTED_ERROR = "This method is not implemented by the simulator" -PYTHON_LIBS_DIR = "python_libs" +STATE_FIELD = "state" UTF_FORMAT = "utf-8" WINDOWS_OS = "win32" DEFAULT_PORT = "5577" + +CPX = "CPX" + +MICROBIT = "micro:bit" diff --git a/src/serialMonitor.ts b/src/serialMonitor.ts index 630154859..2fd01588f 100644 --- a/src/serialMonitor.ts +++ b/src/serialMonitor.ts @@ -77,7 +77,7 @@ export class SerialMonitor implements vscode.Disposable { STATUS_BAR_PRIORITY.PORT ); this._portsStatusBar.command = - "deviceSimulatorExpress.selectSerialPort"; + "deviceSimulatorExpress.cpx.selectSerialPort"; this._portsStatusBar.tooltip = "Select Serial Port"; this._portsStatusBar.show(); @@ -86,7 +86,7 @@ export class SerialMonitor implements vscode.Disposable { STATUS_BAR_PRIORITY.OPEN_PORT ); this._openPortStatusBar.command = - "deviceSimulatorExpress.openSerialMonitor"; + "deviceSimulatorExpress.cpx.openSerialMonitor"; this._openPortStatusBar.text = `$(plug)`; this._openPortStatusBar.tooltip = "Open Serial Monitor"; this._openPortStatusBar.show(); @@ -96,7 +96,7 @@ export class SerialMonitor implements vscode.Disposable { STATUS_BAR_PRIORITY.BAUD_RATE ); this._baudRateStatusBar.command = - "deviceSimulatorExpress.changeBaudRate"; + "deviceSimulatorExpress.cpx.changeBaudRate"; this._baudRateStatusBar.tooltip = "Baud Rate"; this._baudRateStatusBar.text = defaultBaudRate.toString(); this.updatePortListStatus(null); @@ -281,13 +281,13 @@ export class SerialMonitor implements vscode.Disposable { private updatePortStatus(isOpened: boolean) { if (isOpened) { this._openPortStatusBar.command = - "deviceSimulatorExpress.closeSerialMonitor"; + "deviceSimulatorExpress.cpx.closeSerialMonitor"; this._openPortStatusBar.text = `$(x)`; this._openPortStatusBar.tooltip = "Close Serial Monitor"; this._baudRateStatusBar.show(); } else { this._openPortStatusBar.command = - "deviceSimulatorExpress.openSerialMonitor"; + "deviceSimulatorExpress.cpx.openSerialMonitor"; this._openPortStatusBar.text = `$(plug)`; this._openPortStatusBar.tooltip = "Open Serial Monitor"; this._baudRateStatusBar.hide(); diff --git a/src/service/PopupService.ts b/src/service/PopupService.ts new file mode 100644 index 000000000..9bff8ba5b --- /dev/null +++ b/src/service/PopupService.ts @@ -0,0 +1,16 @@ +// import { Webview } from "vscode"; +import * as vscode from "vscode"; +import { LATEST_RELEASE_NOTE } from "../latest_release_note"; + +export class PopupService { + public static openReleaseNote() { + const panel = vscode.window.createWebviewPanel( + "releaseNote", + "Release Note", + vscode.ViewColumn.One, + {} + ); + + panel.webview.html = LATEST_RELEASE_NOTE; + } +} diff --git a/src/service/debuggerCommunicationService.ts b/src/service/debuggerCommunicationService.ts new file mode 100644 index 000000000..9a8c1d6f0 --- /dev/null +++ b/src/service/debuggerCommunicationService.ts @@ -0,0 +1,27 @@ +import { DebuggerCommunicationServer } from "../debuggerCommunicationServer"; + +export class DebuggerCommunicationService { + private currentDebuggerServer?: DebuggerCommunicationServer; + private previousDebuggerServerToDisconnect?: DebuggerCommunicationServer; + + public setCurrentDebuggerServer(debugServer: DebuggerCommunicationServer) { + this.currentDebuggerServer = debugServer; + } + // Used for restart and stop event + public resetCurrentDebuggerServer() { + if (this.currentDebuggerServer) { + this.currentDebuggerServer.closeConnection(); + } + this.previousDebuggerServerToDisconnect = this.currentDebuggerServer; + this.currentDebuggerServer = undefined; + } + public getCurrentDebuggerServer() { + return this.currentDebuggerServer; + } + // Only used for stop event + public handleStopEvent() { + if (this.previousDebuggerServerToDisconnect) { + this.previousDebuggerServerToDisconnect.disconnectFromPort(); + } + } +} diff --git a/src/service/messagingService.ts b/src/service/messagingService.ts new file mode 100644 index 000000000..9e37f20a8 --- /dev/null +++ b/src/service/messagingService.ts @@ -0,0 +1,26 @@ +import { Webview } from "vscode"; +import { VSCODE_MESSAGES_TO_WEBVIEW } from "../view/constants"; +export class MessagingService { + private currentWebviewTarget: Webview | undefined; + + public setWebview(webview: Webview) { + this.currentWebviewTarget = webview; + } + + // Send a message to webview if it exists + public sendMessageToWebview(debugCommand: string, state: Object) { + if (this.currentWebviewTarget) { + this.currentWebviewTarget.postMessage({ command: debugCommand }); + } + } + public sendStartMessage() { + this.currentWebviewTarget.postMessage({ + command: VSCODE_MESSAGES_TO_WEBVIEW.RUN_DEVICE, + }); + } + public sendPauseMessage() { + this.currentWebviewTarget.postMessage({ + command: VSCODE_MESSAGES_TO_WEBVIEW.PAUSE_DEVICE, + }); + } +} diff --git a/src/template.py b/src/templates/cpx_template.py similarity index 81% rename from src/template.py rename to src/templates/cpx_template.py index b32caaae0..3c118c7e9 100644 --- a/src/template.py +++ b/src/templates/cpx_template.py @@ -1,15 +1,16 @@ -"""Save your file as "code.py" or "main.py" to run on the actual device. - -Getting started with CPX and CircuitPython intro on: -https://learn.adafruit.com/circuitpython-made-easy-on-circuit-playground-express/circuit-playground-express-library - -Find example code for CPX on: -https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/tree/master/examples -""" - -# import CPX library -from adafruit_circuitplayground import cp - -while True: - # start your code here - pass +""" +Save your file as "code.py" or "main.py" to run on the actual device. + +Getting started with CPX and CircuitPython intro on: +https://learn.adafruit.com/circuitpython-made-easy-on-circuit-playground-express/circuit-playground-express-library + +Find example code for CPX on: +https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/tree/master/examples +""" + +# import CPX library +from adafruit_circuitplayground import cp + +while True: + # start your code here + pass diff --git a/src/templates/microbit_template.py b/src/templates/microbit_template.py new file mode 100644 index 000000000..3fe2da077 --- /dev/null +++ b/src/templates/microbit_template.py @@ -0,0 +1,9 @@ +""" +Get started with micro:bit and MicroPython on: +https://microbit-micropython.readthedocs.io/en/latest/. +""" + +from microbit import * + +while True: + display.scroll("Hello World!") diff --git a/src/view/App.spec.tsx b/src/view/App.spec.tsx new file mode 100644 index 000000000..66d6fc9d5 --- /dev/null +++ b/src/view/App.spec.tsx @@ -0,0 +1,28 @@ +import * as React from "react"; +import * as ReactDOM from "react-dom"; +import { IntlProvider } from "react-intl"; +import * as testRenderer from "react-test-renderer"; +import App from "./App"; + +describe("App component ", () => { + it("should render correctly", () => { + const component = testRenderer + .create( + + + + ) + .toJSON(); + expect(component).toMatchSnapshot(); + }); + it("should render without crashing", () => { + const div = document.createElement("div"); + ReactDOM.render( + + + , + div + ); + ReactDOM.unmountComponentAtNode(div); + }); +}); diff --git a/src/view/App.test.tsx b/src/view/App.test.tsx deleted file mode 100644 index 3822593f7..000000000 --- a/src/view/App.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from "react"; -import * as ReactDOM from "react-dom"; -import { IntlProvider } from "react-intl"; -import App from "./App"; - -it("renders without crashing", () => { - const div = document.createElement("div"); - ReactDOM.render( - - - , - div - ); - ReactDOM.unmountComponentAtNode(div); -}); diff --git a/src/view/App.tsx b/src/view/App.tsx index b52993907..eb9da7b02 100644 --- a/src/view/App.tsx +++ b/src/view/App.tsx @@ -1,21 +1,78 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -"use strict"; import * as React from "react"; import "./App.css"; -import Device from "./container/device/Device"; +import { + DEVICE_LIST_KEY, + VIEW_STATE, + VSCODE_MESSAGES_TO_WEBVIEW, +} from "./constants"; +import { Device } from "./container/device/Device"; +import { ViewStateContext } from "./context"; + +interface IState { + currentDevice: string; + viewState: VIEW_STATE; +} + +const defaultState = { + currentDevice: DEVICE_LIST_KEY.CPX, + viewState: VIEW_STATE.RUNNING, +}; + +class App extends React.Component<{}, IState> { + constructor() { + super({}); + this.state = defaultState; + } + componentDidMount() { + if (document.currentScript) { + const initialDevice = document.currentScript.getAttribute( + "initialDevice" + ); + + if (initialDevice) { + this.setState({ currentDevice: initialDevice }); + } + } + window.addEventListener("message", this.handleMessage); + } + componentWillUnmount() { + window.removeEventListener("message", this.handleMessage); + } -class App extends React.Component { render() { return (
- + + +
); } + + handleMessage = (event: any): void => { + const message = event.data; + + switch (message.command) { + case VSCODE_MESSAGES_TO_WEBVIEW.SET_DEVICE: + if (message.active_device !== this.state.currentDevice) { + this.setState({ currentDevice: message.active_device }); + } + break; + case VSCODE_MESSAGES_TO_WEBVIEW.RUN_DEVICE: + this.setState({ viewState: VIEW_STATE.RUNNING }); + break; + case VSCODE_MESSAGES_TO_WEBVIEW.PAUSE_DEVICE: + this.setState({ viewState: VIEW_STATE.PAUSE }); + break; + } + }; } export default App; diff --git a/src/view/__snapshots__/App.spec.tsx.snap b/src/view/__snapshots__/App.spec.tsx.snap new file mode 100644 index 000000000..ac3521338 --- /dev/null +++ b/src/view/__snapshots__/App.spec.tsx.snap @@ -0,0 +1,4720 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`App component should render correctly 1`] = ` +
+
+
+
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+`; diff --git a/src/view/components/cpx/Cpx.spec.tsx b/src/view/components/cpx/Cpx.spec.tsx new file mode 100644 index 000000000..deb6da57d --- /dev/null +++ b/src/view/components/cpx/Cpx.spec.tsx @@ -0,0 +1,29 @@ +import * as React from "react"; +import * as ReactDOM from "react-dom"; +import { IntlProvider } from "react-intl"; +import * as testRenderer from "react-test-renderer"; +import { Cpx } from "./Cpx"; + +describe("Device component", () => { + it("should render correctly", () => { + const component = testRenderer + .create( + + + + ) + .toJSON(); + expect(component).toMatchSnapshot(); + }); + + it("should render without crashing", () => { + const div = document.createElement("div"); + ReactDOM.render( + + + , + div + ); + ReactDOM.unmountComponentAtNode(div); + }); +}); diff --git a/src/view/components/cpx/Cpx.tsx b/src/view/components/cpx/Cpx.tsx new file mode 100644 index 000000000..d91728fba --- /dev/null +++ b/src/view/components/cpx/Cpx.tsx @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import * as React from "react"; +import { CPX_TOOLBAR_ICON_ID } from "../../components/toolbar/SensorModalUtils"; +import ToolBar from "../../components/toolbar/ToolBar"; +import { SENSOR_LIST, VSCODE_MESSAGES_TO_WEBVIEW } from "../../constants"; +import * as TOOLBAR_SVG from "../../svgs/toolbar_svg"; +import Simulator from "./CpxSimulator"; + +// Component grouping the functionality for circuit playground express +const DEFAULT_STATE = { + sensors: { + [SENSOR_LIST.TEMPERATURE]: 0, + [SENSOR_LIST.LIGHT]: 0, + [SENSOR_LIST.MOTION_X]: 0, + [SENSOR_LIST.MOTION_Y]: 0, + [SENSOR_LIST.MOTION_Z]: 0, + }, +}; + +export class Cpx extends React.Component { + state = DEFAULT_STATE; + componentDidMount() { + window.addEventListener("message", this.handleMessage); + } + + componentWillUnmount() { + // Make sure to remove the DOM listener when the component is unmounted. + window.removeEventListener("message", this.handleMessage); + } + handleMessage = (event: any): void => { + const message = event.data; + + switch (message.command) { + case VSCODE_MESSAGES_TO_WEBVIEW.RESET: + this.setState({ ...DEFAULT_STATE }); + break; + } + }; + + render() { + return ( + + + + + ); + } + updateSensor = (sensor: SENSOR_LIST, value: number) => { + this.setState({ sensors: { ...this.state.sensors, [sensor]: value } }); + }; +} + +const CPX_TOOLBAR_BUTTONS: Array<{ label: any; image: any }> = [ + { + image: TOOLBAR_SVG.SLIDER_SWITCH_SVG, + label: CPX_TOOLBAR_ICON_ID.SWITCH, + }, + { + image: TOOLBAR_SVG.PUSH_BUTTON_SVG, + label: CPX_TOOLBAR_ICON_ID.PUSH_BUTTON, + }, + { + image: TOOLBAR_SVG.RED_LED_SVG, + label: CPX_TOOLBAR_ICON_ID.RED_LED, + }, + { + image: TOOLBAR_SVG.SOUND_SVG, + label: CPX_TOOLBAR_ICON_ID.SOUND, + }, + { + image: TOOLBAR_SVG.TEMPERATURE_SVG, + label: CPX_TOOLBAR_ICON_ID.TEMPERATURE, + }, + { + image: TOOLBAR_SVG.LIGHT_SVG, + label: CPX_TOOLBAR_ICON_ID.LIGHT, + }, + { + image: TOOLBAR_SVG.NEO_PIXEL_SVG, + label: CPX_TOOLBAR_ICON_ID.NEO_PIXEL, + }, + { + image: TOOLBAR_SVG.SPEAKER_SVG, + label: CPX_TOOLBAR_ICON_ID.SPEAKER, + }, + { + image: TOOLBAR_SVG.MOTION_SVG, + label: CPX_TOOLBAR_ICON_ID.MOTION, + }, + { + image: TOOLBAR_SVG.IR_SVG, + label: CPX_TOOLBAR_ICON_ID.IR, + }, + { + image: TOOLBAR_SVG.GPIO_SVG, + label: CPX_TOOLBAR_ICON_ID.GPIO, + }, +]; diff --git a/src/view/components/cpx/CpxImage.tsx b/src/view/components/cpx/CpxImage.tsx index 0c74dd936..ee3d02201 100644 --- a/src/view/components/cpx/CpxImage.tsx +++ b/src/view/components/cpx/CpxImage.tsx @@ -20,30 +20,59 @@ interface IProps { onMouseLeave: (button: HTMLElement, event: Event) => void; } -let firstTime = true; - -// Functional Component render -const CpxImage: React.FC = props => { - const svgElement = window.document.getElementById("cpx_svg"); - - if (svgElement) { - if (firstTime) { - initSvgStyle(svgElement, props.brightness); - setupButtons(props); - setupPins(props); - setupKeyPresses(props.onKeyEvent); - setupSwitch(props); - firstTime = false; +export class CpxImage extends React.Component { + componentDidMount() { + const svgElement = window.document.getElementById("cpx_svg"); + if (svgElement) { + initSvgStyle(svgElement, this.props.brightness); + setupButtons(this.props); + setupPins(this.props); + this.setupKeyPresses(this.props.onKeyEvent); + setupSwitch(this.props); + this.updateImage(); } - // Update Neopixels and red LED state - updateNeopixels(props); - updateRedLED(props.red_led); - updatePowerLED(props.on); - updateSwitch(props.switch); } + componentWillUnmount() { + window.document.removeEventListener("keydown", this.handleKeyDown); + window.document.removeEventListener("keyup", this.handleKeyUp); + } + componentDidUpdate() { + this.updateImage(); + } + setupKeyPresses = ( + onKeyEvent: (event: KeyboardEvent, active: boolean) => void + ) => { + window.document.addEventListener("keydown", this.handleKeyDown); + window.document.addEventListener("keyup", this.handleKeyUp); + }; - return CPX_SVG; -}; + handleKeyDown = (event: KeyboardEvent) => { + const keyEvents = [event.key, event.code]; + // Don't listen to keydown events for the switch, run button, restart button and enter key + if ( + !( + keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.S) || + keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.CAPITAL_F) || + keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.CAPITAL_R) || + keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.ENTER) + ) + ) { + this.props.onKeyEvent(event, true); + } + }; + handleKeyUp = (event: KeyboardEvent) => { + this.props.onKeyEvent(event, false); + }; + render() { + return CPX_SVG; + } + private updateImage() { + updateNeopixels(this.props); + updateRedLED(this.props.red_led); + updatePowerLED(this.props.on); + updateSwitch(this.props.switch); + } +} const makeButton = ( g: SVGElement, @@ -308,32 +337,18 @@ const setupButton = (button: HTMLElement, className: string, props: IProps) => { } svgButton.onmousedown = e => props.onMouseDown(button, e); svgButton.onmouseup = e => props.onMouseUp(button, e); - svgButton.onkeydown = e => props.onKeyEvent(e, true); + svgButton.onkeydown = e => { + // ensure that the keydown is enter. + // Or else, if the key is a shortcut instead, + // it may register shortcuts twice + if (e.key === CONSTANTS.KEYBOARD_KEYS.ENTER) { + props.onKeyEvent(e, true); + } + }; svgButton.onkeyup = e => props.onKeyEvent(e, false); svgButton.onmouseleave = e => props.onMouseLeave(button, e); }; -const setupKeyPresses = ( - onKeyEvent: (event: KeyboardEvent, active: boolean) => void -) => { - window.document.addEventListener("keydown", event => { - const keyEvents = [event.key, event.code]; - // Don't listen to keydown events for the switch, run button and enter key - if ( - !( - keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.S) || - keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.CAPITAL_F) || - keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.ENTER) - ) - ) { - onKeyEvent(event, true); - } - }); - window.document.addEventListener("keyup", event => - onKeyEvent(event, false) - ); -}; - const setupSwitch = (props: IProps): void => { const switchElement = window.document.getElementById("SWITCH"); const swInnerElement = window.document.getElementById("SWITCH_INNER"); diff --git a/src/view/components/Simulator.tsx b/src/view/components/cpx/CpxSimulator.tsx similarity index 91% rename from src/view/components/Simulator.tsx rename to src/view/components/cpx/CpxSimulator.tsx index a1ddee6b6..21a13524a 100644 --- a/src/view/components/Simulator.tsx +++ b/src/view/components/cpx/CpxSimulator.tsx @@ -2,14 +2,16 @@ // Licensed under the MIT license. import * as React from "react"; -import { CONSTANTS } from "../constants"; -import "../styles/Simulator.css"; -import PlayLogo from "../svgs/play_svg"; -import StopLogo from "../svgs/stop_svg"; -import { BUTTON_NEUTRAL, BUTTON_PRESSED } from "./cpx/Cpx_svg_style"; -import CpxImage, { updatePinTouch, updateSwitch } from "./cpx/CpxImage"; -import Dropdown from "./Dropdown"; -import ActionBar from "./simulator/ActionBar"; +import { CONSTANTS, DEVICE_LIST_KEY, WEBVIEW_MESSAGES } from "../../constants"; +import { sendMessage } from "../../utils/MessageUtils"; + +import "../../styles/Simulator.css"; +import PlayLogo from "../../svgs/play_svg"; +import StopLogo from "../../svgs/stop_svg"; +import Dropdown from "../Dropdown"; +import ActionBar from "../simulator/ActionBar"; +import { BUTTON_NEUTRAL, BUTTON_PRESSED } from "./Cpx_svg_style"; +import { CpxImage, updatePinTouch, updateSwitch } from "./CpxImage"; interface ICpxState { pixels: number[][]; @@ -29,9 +31,6 @@ interface IState { cpx: ICpxState; play_button: boolean; } -interface IMyProps { - children?: any; -} const DEFAULT_CPX_STATE: ICpxState = { brightness: 1.0, @@ -55,18 +54,8 @@ const DEFAULT_CPX_STATE: ICpxState = { shake: false, }; -interface vscode { - postMessage(message: any): void; -} - -declare const vscode: vscode; - -const sendMessage = (type: string, state: any) => { - vscode.postMessage({ command: type, text: state }); -}; - -class Simulator extends React.Component { - constructor(props: IMyProps) { +class Simulator extends React.Component<{}, IState> { + constructor(props: Readonly<{}>) { super(props); this.state = { active_editors: [], @@ -88,11 +77,13 @@ class Simulator extends React.Component { handleMessage = (event: any): void => { const message = event.data; // The JSON data our extension sent + if (message.active_device !== DEVICE_LIST_KEY.CPX) { + return; + } switch (message.command) { case "reset-state": console.log("Clearing the state"); this.setState({ - ...this.state, cpx: DEFAULT_CPX_STATE, play_button: false, }); @@ -102,14 +93,12 @@ class Simulator extends React.Component { "Setting the state: " + JSON.stringify(message.state) ); this.setState({ - ...this.state, cpx: message.state, play_button: true, }); break; case "activate-play": this.setState({ - ...this.state, play_button: !this.state.play_button, }); break; @@ -119,21 +108,15 @@ class Simulator extends React.Component { message.state.activePythonEditors ); this.setState({ - ...this.state, active_editors: message.state.activePythonEditors, }); break; case "current-file": console.log("Setting current file", message.state.running_file); this.setState({ - ...this.state, running_file: message.state.running_file, }); break; - default: - console.log("Invalid message received from the extension."); - this.setState({ ...this.state, cpx: DEFAULT_CPX_STATE }); - break; } }; @@ -149,6 +132,7 @@ class Simulator extends React.Component { render() { const playStopImage = this.state.play_button ? StopLogo : PlayLogo; + const playStopLabel = this.state.play_button ? "stop" : "play"; return (
@@ -178,37 +162,37 @@ class Simulator extends React.Component { onTogglePlay={this.togglePlayClick} onToggleRefresh={this.refreshSimulatorClick} playStopImage={playStopImage} + playStopLabel={playStopLabel} />
); } protected togglePlayClick() { - sendMessage("play-simulator", { - selected_file: this.state.selected_file, - state: !this.state.play_button, - }); const button = window.document.getElementById(CONSTANTS.ID_NAME.PLAY_BUTTON) || window.document.getElementById(CONSTANTS.ID_NAME.STOP_BUTTON); if (button) { button.focus(); } + sendMessage(WEBVIEW_MESSAGES.TOGGLE_PLAY_STOP, { + selected_file: this.state.selected_file, + state: !this.state.play_button, + }); } protected refreshSimulatorClick() { - sendMessage("refresh-simulator", true); const button = window.document.getElementById( CONSTANTS.ID_NAME.REFRESH_BUTTON ); if (button) { button.focus(); } + sendMessage(WEBVIEW_MESSAGES.REFRESH_SIMULATOR, true); } protected onSelectBlur(event: React.FocusEvent) { this.setState({ - ...this.state, selected_file: event.currentTarget.value, }); } @@ -234,6 +218,12 @@ class Simulator extends React.Component { element = window.document.getElementById( CONSTANTS.ID_NAME.BUTTON_B ); + } else if ( + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.C) + ) { + element = window.document.getElementById( + CONSTANTS.ID_NAME.BUTTON_AB + ); } else if ( [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.S) ) { diff --git a/src/view/components/cpx/Svg_utils.tsx b/src/view/components/cpx/Svg_utils.tsx index b80e66165..f190bffae 100644 --- a/src/view/components/cpx/Svg_utils.tsx +++ b/src/view/components/cpx/Svg_utils.tsx @@ -3,35 +3,44 @@ // Adapted from : https://github.com/microsoft/pxt/blob/master/pxtsim/svg.ts +// tslint:disable-next-line: no-namespace namespace svg { export function addClass(el: SVGElement, cls: string) { - if (el.classList) el.classList.add(cls); - else if (el.className.baseVal.indexOf(cls) < 0) + if (el.classList) { + el.classList.add(cls); + } else if (el.className.baseVal.indexOf(cls) < 0) { el.className.baseVal += " " + cls; + } } export function removeClass(el: SVGElement, cls: string) { - if (el.classList) el.classList.remove(cls); - else + if (el.classList) { + el.classList.remove(cls); + } else { el.className.baseVal = el.className.baseVal .replace(cls, "") .replace(/\s{2,}/, " "); + } } export function hydrate(el: SVGElement, props: any) { - for (let k in props) { + for (const k in props) { if (k == "title") { svg.title(el, props[k]); - } else el.setAttributeNS(null, k, props[k]); + } else { + el.setAttributeNS(null, k, props[k]); + } } } export function createElement(name: string, props?: any): SVGElement { - let newElement = document.createElementNS( + const newElement = document.createElementNS( "http://www.w3.org/2000/svg", name ); - if (props) svg.hydrate(newElement, props); + if (props) { + svg.hydrate(newElement, props); + } return newElement; } @@ -40,7 +49,7 @@ namespace svg { name: string, props?: any ): SVGElement { - let childElement = svg.createElement(name, props); + const childElement = svg.createElement(name, props); parent.appendChild(childElement); return childElement; } @@ -58,13 +67,13 @@ namespace svg { } export function mkTitle(txt: string): SVGTitleElement { - let t = svg.createElement("title") as SVGTitleElement; + const t = svg.createElement("title") as SVGTitleElement; t.textContent = txt; return t; } export function title(el: SVGElement, txt: string): SVGTitleElement { - let t = mkTitle(txt); + const t = mkTitle(txt); el.appendChild(t); return t; } diff --git a/src/view/components/cpx/__snapshots__/Cpx.spec.tsx.snap b/src/view/components/cpx/__snapshots__/Cpx.spec.tsx.snap new file mode 100644 index 000000000..2d51b191f --- /dev/null +++ b/src/view/components/cpx/__snapshots__/Cpx.spec.tsx.snap @@ -0,0 +1,4710 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Device component should render correctly 1`] = ` +Array [ +
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
, +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
, +] +`; diff --git a/src/view/components/microbit/Microbit.tsx b/src/view/components/microbit/Microbit.tsx new file mode 100644 index 000000000..03f11fed9 --- /dev/null +++ b/src/view/components/microbit/Microbit.tsx @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import * as React from "react"; +import { MICROBIT_TOOLBAR_ID } from "../../components/toolbar/SensorModalUtils"; +import { SENSOR_LIST, VSCODE_MESSAGES_TO_WEBVIEW } from "../../constants"; +import "../../styles/Simulator.css"; +import * as TOOLBAR_SVG from "../../svgs/toolbar_svg"; +import ToolBar from "../toolbar/ToolBar"; +import { MicrobitSimulator } from "./MicrobitSimulator"; + +// Component grouping the functionality for micro:bit functionalities +interface IState { + sensors: { [key: string]: number }; +} +const DEFAULT_STATE = { + sensors: { + [SENSOR_LIST.TEMPERATURE]: 0, + [SENSOR_LIST.LIGHT]: 0, + [SENSOR_LIST.MOTION_X]: 0, + [SENSOR_LIST.MOTION_Y]: 0, + [SENSOR_LIST.MOTION_Z]: 0, + }, +}; + +export class Microbit extends React.Component<{}, IState> { + state = DEFAULT_STATE; + + componentDidMount() { + window.addEventListener("message", this.handleMessage); + } + + componentWillUnmount() { + // Make sure to remove the DOM listener when the component is unmounted. + window.removeEventListener("message", this.handleMessage); + } + handleMessage = (event: any): void => { + const message = event.data; + + switch (message.command) { + case VSCODE_MESSAGES_TO_WEBVIEW.RESET: + this.setState({ ...DEFAULT_STATE }); + break; + } + }; + render() { + return ( + + + + + ); + } + updateSensor = (sensor: SENSOR_LIST, value: number) => { + this.setState({ sensors: { ...this.state.sensors, [sensor]: value } }); + }; +} + +const MICROBIT_TOOLBAR_BUTTONS: Array<{ label: string; image: JSX.Element }> = [ + { + image: TOOLBAR_SVG.PUSH_BUTTON_SVG, + label: MICROBIT_TOOLBAR_ID.PUSH_BUTTON, + }, + { + image: TOOLBAR_SVG.RED_LED_SVG, + label: MICROBIT_TOOLBAR_ID.LEDS, + }, + { + image: TOOLBAR_SVG.TEMPERATURE_SVG, + label: MICROBIT_TOOLBAR_ID.TEMPERATURE, + }, + { + image: TOOLBAR_SVG.LIGHT_SVG, + label: MICROBIT_TOOLBAR_ID.LIGHT, + }, + { + image: TOOLBAR_SVG.MOTION_SVG, + label: MICROBIT_TOOLBAR_ID.ACCELEROMETER, + }, +]; diff --git a/src/view/components/microbit/MicrobitImage.tsx b/src/view/components/microbit/MicrobitImage.tsx new file mode 100644 index 000000000..326d0a611 --- /dev/null +++ b/src/view/components/microbit/MicrobitImage.tsx @@ -0,0 +1,176 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import * as React from "react"; +import { VIEW_STATE } from "../../constants"; +import { ViewStateContext } from "../../context"; +import CONSTANTS, { MICROBIT_BUTTON_STYLING_CLASSES } from "../../constants"; +import "../../styles/Microbit.css"; +import { IRefObject, MicrobitSvg } from "./Microbit_svg"; + +interface EventTriggers { + onMouseUp: (event: Event, buttonKey: string) => void; + onMouseDown: (event: Event, buttonKey: string) => void; + onMouseLeave: (event: Event, buttonKey: string) => void; + onKeyEvent: (event: KeyboardEvent, active: boolean, key: string) => void; +} +interface IProps { + eventTriggers: EventTriggers; + leds: number[][]; +} + +const BUTTON_CLASSNAME = { + ACTIVE: "sim-button-outer", + DEACTIVATED: "sim-button-deactivated", +}; + +export enum BUTTONS_KEYS { + BTN_A = "BTN_A", + BTN_B = "BTN_B", + BTN_AB = "BTN_AB", +} +// Displays the SVG and call necessary svg modification. +export class MicrobitImage extends React.Component { + private svgRef: React.RefObject = React.createRef(); + constructor(props: IProps) { + super(props); + } + componentDidMount() { + const svgElement = this.svgRef.current; + if (svgElement) { + updateAllLeds(this.props.leds, svgElement.getLeds()); + setupAllButtons(this.props.eventTriggers, svgElement.getButtons()); + this.setupKeyPresses(this.props.eventTriggers.onKeyEvent); + } + } + componentDidUpdate() { + if (this.svgRef.current) { + updateAllLeds(this.props.leds, this.svgRef.current.getLeds()); + if (this.context === VIEW_STATE.PAUSE) { + disableAllButtons(this.svgRef.current.getButtons()); + } else if (this.context === VIEW_STATE.RUNNING) { + setupAllButtons( + this.props.eventTriggers, + this.svgRef.current.getButtons() + ); + } + } + } + componentWillUnmount() { + window.document.removeEventListener("keydown", this.handleKeyDown); + window.document.removeEventListener("keyup", this.handleKeyUp); + } + setupKeyPresses = ( + onKeyEvent: (event: KeyboardEvent, active: boolean, key: string) => void + ) => { + window.document.addEventListener("keydown", this.handleKeyDown); + window.document.addEventListener("keyup", this.handleKeyUp); + }; + handleKeyDown = (event: KeyboardEvent) => { + const keyEvents = [event.key, event.code]; + // Don't listen to keydown events for the run button, restart button and enter key + if ( + !( + keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.CAPITAL_F) || + keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.CAPITAL_R) || + keyEvents.includes(CONSTANTS.KEYBOARD_KEYS.ENTER) + ) + ) { + this.props.eventTriggers.onKeyEvent(event, true, event.key); + } + }; + handleKeyUp = (event: KeyboardEvent) => { + this.props.eventTriggers.onKeyEvent(event, false, event.key); + }; + render() { + return ; + } + public updateButtonAttributes(key: BUTTONS_KEYS, isActive: boolean) { + if (this.svgRef.current) { + const button = this.svgRef.current.getButtons()[key].current; + if (button) { + button.focus(); + if (isActive) { + button.children[0].setAttribute( + "class", + MICROBIT_BUTTON_STYLING_CLASSES.KEYPRESSED + ); + } else { + button.children[0].setAttribute( + "class", + MICROBIT_BUTTON_STYLING_CLASSES.DEFAULT + ); + } + button.setAttribute("pressed", `${isActive}`); + button.setAttribute("aria-pressed", `${isActive}`); + } + } + } +} + +MicrobitImage.contextType = ViewStateContext; +const setupButton = ( + buttonElement: SVGRectElement, + eventTriggers: EventTriggers, + key: string +) => { + buttonElement.onmousedown = e => { + buttonElement.focus(); + eventTriggers.onMouseDown(e, key); + }; + buttonElement.onmouseup = e => { + eventTriggers.onMouseUp(e, key); + }; + buttonElement.onmouseleave = e => { + eventTriggers.onMouseLeave(e, key); + }; + buttonElement.onkeydown = e => { + // ensure that the keydown is enter, + // or else it may register shortcuts twice + if (e.key === CONSTANTS.KEYBOARD_KEYS.ENTER) { + eventTriggers.onKeyEvent(e, true, key); + } + }; + buttonElement.onkeyup = e => { + eventTriggers.onKeyEvent(e, false, key); + }; +}; +const setupAllButtons = ( + eventTriggers: EventTriggers, + buttonRefs: IRefObject +) => { + for (const [key, ref] of Object.entries(buttonRefs)) { + if (ref.current) { + setupButton(ref.current, eventTriggers, key); + } + } +}; +const disableAllButtons = (buttonRefs: IRefObject) => { + for (const [, ref] of Object.entries(buttonRefs)) { + if (ref.current) { + // to implement + ref.current.onmousedown = null; + ref.current.onmouseup = null; + ref.current.onmouseleave = null; + ref.current.onkeydown = null; + ref.current.onkeyup = null; + ref.current.setAttribute("class", BUTTON_CLASSNAME.DEACTIVATED); + } + } +}; +const updateAllLeds = ( + leds: number[][], + ledRefs: Array>> +) => { + for (let j = 0; j < leds.length; j++) { + for (let i = 0; i < leds[0].length; i++) { + const ledElement = ledRefs[j][i].current; + if (ledElement) { + setupLed(ledElement, leds[i][j]); + } + } + } +}; +const setupLed = (ledElement: SVGRectElement, brightness: number) => { + ledElement.style.opacity = (brightness / 10).toString(); +}; diff --git a/src/view/components/microbit/MicrobitSimulator.tsx b/src/view/components/microbit/MicrobitSimulator.tsx new file mode 100644 index 000000000..c05611396 --- /dev/null +++ b/src/view/components/microbit/MicrobitSimulator.tsx @@ -0,0 +1,253 @@ +import * as React from "react"; +import { + CONSTANTS, + DEVICE_LIST_KEY, + MICROBIT_BUTTONS_KEYS, + WEBVIEW_MESSAGES, +} from "../../constants"; +import PlayLogo from "../../svgs/play_svg"; +import StopLogo from "../../svgs/stop_svg"; +import { sendMessage } from "../../utils/MessageUtils"; +import Dropdown from "../Dropdown"; +import ActionBar from "../simulator/ActionBar"; +import { MicrobitImage, BUTTONS_KEYS } from "./MicrobitImage"; + +const DEFAULT_MICROBIT_STATE: IMicrobitState = { + leds: [ + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + ], + buttons: { button_a: false, button_b: false }, +}; + +interface IState { + active_editors: string[]; + running_file: string; + play_button: boolean; + selected_file: string; + microbit: IMicrobitState; +} + +interface IMicrobitState { + leds: number[][]; + buttons: { button_a: boolean; button_b: boolean }; +} +export class MicrobitSimulator extends React.Component { + private imageRef: React.RefObject = React.createRef(); + constructor() { + super({}); + this.state = { + microbit: DEFAULT_MICROBIT_STATE, + play_button: false, + selected_file: "", + active_editors: [], + running_file: "", + }; + this.onKeyEvent = this.onKeyEvent.bind(this); + } + handleMessage = (event: any): void => { + const message = event.data; + + if (message.active_device !== DEVICE_LIST_KEY.MICROBIT) { + return; + } + + switch (message.command) { + case "reset-state": + this.setState({ + microbit: DEFAULT_MICROBIT_STATE, + play_button: false, + }); + break; + case "set-state": + this.setState({ + microbit: { + ...this.state.microbit, + leds: message.state.leds, + }, + }); + break; + case "activate-play": + this.setState({ + play_button: !this.state.play_button, + }); + break; + case "visible-editors": + this.setState({ + active_editors: message.state.activePythonEditors, + }); + break; + case "current-file": + this.setState({ + running_file: message.state.running_file, + }); + break; + } + }; + componentDidMount() { + window.addEventListener("message", this.handleMessage); + } + componentWillUnmount() { + window.removeEventListener("message", this.handleMessage); + } + + render() { + const playStopImage = this.state.play_button ? StopLogo : PlayLogo; + const playStopLabel = this.state.play_button ? "stop" : "play"; + return ( +
+
+ +
+
+ +
+ +
+ ); + } + protected togglePlayClick = () => { + const button = + window.document.getElementById(CONSTANTS.ID_NAME.PLAY_BUTTON) || + window.document.getElementById(CONSTANTS.ID_NAME.STOP_BUTTON); + if (button) { + button.focus(); + } + sendMessage(WEBVIEW_MESSAGES.TOGGLE_PLAY_STOP, { + selected_file: this.state.selected_file, + state: !this.state.play_button, + }); + }; + protected onSelectFile(event: React.FocusEvent) { + this.setState({ + selected_file: event.currentTarget.value, + }); + } + protected refreshSimulatorClick = () => { + const button = window.document.getElementById( + CONSTANTS.ID_NAME.REFRESH_BUTTON + ); + if (button) { + button.focus(); + } + sendMessage(WEBVIEW_MESSAGES.REFRESH_SIMULATOR, true); + }; + protected handleButtonClick = (key: string, isActive: boolean) => { + let newButtonState = this.state.microbit.buttons; + switch (key) { + case MICROBIT_BUTTONS_KEYS.BTN_A: + newButtonState.button_a = isActive; + break; + case MICROBIT_BUTTONS_KEYS.BTN_B: + newButtonState.button_b = isActive; + break; + case MICROBIT_BUTTONS_KEYS.BTN_AB: + newButtonState = { + button_a: isActive, + button_b: isActive, + }; + break; + } + sendMessage(WEBVIEW_MESSAGES.BUTTON_PRESS, newButtonState); + this.setState({ + microbit: { + ...this.state.microbit, + buttons: newButtonState, + }, + }); + }; + protected onMouseUp = (event: Event, key: string) => { + event.preventDefault(); + this.handleButtonClick(key, false); + }; + protected onMouseDown = (event: Event, key: string) => { + event.preventDefault(); + this.handleButtonClick(key, true); + }; + protected onMouseLeave = (event: Event, key: string) => { + event.preventDefault(); + console.log(`To implement onMouseLeave ${key}`); + }; + protected onKeyEvent(event: KeyboardEvent, active: boolean, key: string) { + event.stopPropagation(); + if ([event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.ENTER)) { + this.handleButtonClick(key, active); + if (this.imageRef.current) { + if (key === BUTTONS_KEYS.BTN_A) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_A, + active + ); + } else if (key === BUTTONS_KEYS.BTN_B) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_B, + active + ); + } else if (key === BUTTONS_KEYS.BTN_AB) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_AB, + active + ); + } + } + } else if ( + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.A) + ) { + this.handleButtonClick(BUTTONS_KEYS.BTN_A, active); + if (this.imageRef.current) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_A, + active + ); + } + } else if ( + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.B) + ) { + this.handleButtonClick(BUTTONS_KEYS.BTN_B, active); + if (this.imageRef.current) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_B, + active + ); + } + } else if ( + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.C) + ) { + this.handleButtonClick(BUTTONS_KEYS.BTN_AB, active); + if (this.imageRef.current) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_AB, + active + ); + } + } else if (event.key === CONSTANTS.KEYBOARD_KEYS.CAPITAL_F) { + this.togglePlayClick(); + } else if (event.key === CONSTANTS.KEYBOARD_KEYS.CAPITAL_R) { + this.refreshSimulatorClick(); + } + } +} diff --git a/src/view/components/microbit/Microbit_svg.tsx b/src/view/components/microbit/Microbit_svg.tsx new file mode 100644 index 000000000..e2e147412 --- /dev/null +++ b/src/view/components/microbit/Microbit_svg.tsx @@ -0,0 +1,1888 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +// Adapted from : https://makecode.microbit.org/#editor + +import * as React from "react"; +export interface IRefObject { + [key: string]: React.RefObject; +} +/* tslint:disable */ + +const N_LED_COLUMN = 5; +const N_LED_ROW = 5; +export class MicrobitSvg extends React.Component { + constructor(props: Readonly<{}>) { + super(props); + for (let j = 0; j < N_LED_ROW; j++) { + const led_row: React.RefObject[] = []; + for (let i = 0; i < N_LED_COLUMN; i++) { + led_row.push(React.createRef()); + } + this.ledRefs.push(led_row); + } + } + private svgRef: React.RefObject = React.createRef(); + + private buttonRefs: IRefObject = { + BTN_A: React.createRef(), + BTN_B: React.createRef(), + BTN_AB: React.createRef(), + }; + + private ledRefs: React.RefObject[][] = []; + public getSvgRef(): React.RefObject { + return this.svgRef; + } + public getButtons(): IRefObject { + return this.buttonRefs; + } + public getLeds(): React.RefObject[][] { + return this.ledRefs; + } + + render() { + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (0,0) + + + + (1,0) + + + + (2,0) + + + + (3,0) + + + + (4,0) + + + + (0,1) + + + + (1,1) + + + + (2,1) + + + + (3,1) + + + + (4,1) + + + + (0,2) + + + + (1,2) + + + + (2,2) + + + + (3,2) + + + + (4,2) + + + + (0,3) + + + + (1,3) + + + + (2,3) + + + + (3,3) + + + + (4,3) + + + + (0,4) + + + + (1,4) + + + + (2,4) + + + + (3,4) + + + + (4,4) + + + + + + + + + + P0, ANALOG IN + + + P1, ANALOG IN + + + P2, ANALOG IN + + + P3, ANALOG IN, LED Col 1 + + + P4, ANALOG IN, LED Col 2 + + + P5, BUTTON A + + + P6, LED Col 9 + + + P7, LED Col 8 + + + P8 + + + P9, LED Col 7 + + + P10, ANALOG IN, LED Col 3 + + + P11, BUTTON B + + + P12, RESERVED ACCESSIBILITY + + + P13, SPI - SCK + + + P14, SPI - MISO + + + P15, SPI - MOSI + + + P16, SPI - Chip Select + + + P17, +3v3 + + + P18, +3v3 + + + P19, I2C - SCL + + + P20, I2C - SDA + + + GND + + + GND + + + +3v3 + + + GND + + + + + + + + + + + + + + + + + + + + + + A+B + + + + + + + + + + + + + + + + + + + + + + + +
+ ); + } +} diff --git a/src/view/components/simulator/ActionBar.tsx b/src/view/components/simulator/ActionBar.tsx index 2188555b2..b760817b8 100644 --- a/src/view/components/simulator/ActionBar.tsx +++ b/src/view/components/simulator/ActionBar.tsx @@ -10,13 +10,19 @@ interface IProps { onTogglePlay: (event: React.MouseEvent) => void; onToggleRefresh: (event: React.MouseEvent) => void; playStopImage: JSX.Element; + playStopLabel: string; } // Component including the actions done on the Simulator (play/stop, refresh) class ActionBar extends React.Component { public render() { - const { onTogglePlay, onToggleRefresh, playStopImage } = this.props; + const { + onTogglePlay, + onToggleRefresh, + playStopImage, + playStopLabel, + } = this.props; return (
); diff --git a/src/view/components/toolbar/ToolBar.tsx b/src/view/components/toolbar/ToolBar.tsx index 88b064261..c604cbc3b 100644 --- a/src/view/components/toolbar/ToolBar.tsx +++ b/src/view/components/toolbar/ToolBar.tsx @@ -1,17 +1,19 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +import { TooltipHost } from "office-ui-fabric-react"; import * as React from "react"; import { FormattedMessage, injectIntl, WrappedComponentProps, } from "react-intl"; +import { SENSOR_LIST } from "../../constants"; import "../../styles/ToolBar.css"; import Button from "../Button"; import { DEFAULT_MODAL_CONTENT, + getModalContent, IModalContent, - LABEL_TO_MODAL_CONTENT, } from "./SensorModalUtils"; interface IToolbarState { @@ -24,6 +26,8 @@ interface IProps extends WrappedComponentProps { label: any; image: any; }>; + onUpdateSensor: (sensor: SENSOR_LIST, value: number) => void; + sensorValues: { [key: string]: number }; } class ToolBar extends React.Component { @@ -46,22 +50,33 @@ class ToolBar extends React.Component { {buttonList.map( (currrentButton: any, index: number) => { return ( - + +
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +`; diff --git a/src/view/context.ts b/src/view/context.ts new file mode 100644 index 000000000..24fafc556 --- /dev/null +++ b/src/view/context.ts @@ -0,0 +1,6 @@ +import * as React from "react"; +import { VIEW_STATE } from "./constants"; + +// View is running by default + +export const ViewStateContext = React.createContext(VIEW_STATE.RUNNING); diff --git a/src/view/index.tsx b/src/view/index.tsx index 9b0fc44a2..32e7400b1 100644 --- a/src/view/index.tsx +++ b/src/view/index.tsx @@ -14,7 +14,6 @@ const locale = "en"; const message = { en: messageEn, }; - ReactDOM.render( diff --git a/src/view/styles/Microbit.css b/src/view/styles/Microbit.css new file mode 100644 index 000000000..b8a741988 --- /dev/null +++ b/src/view/styles/Microbit.css @@ -0,0 +1,173 @@ +.microbit-svg { + padding: 0 0 0 10px; +} +svg.sim { + box-sizing: border-box; + width: 100%; + height: 100%; + display: block; +} +svg.sim.grayscale { + -moz-filter: grayscale(1); + -webkit-filter: grayscale(1); + filter: grayscale(1); +} +.sim-button-group { + cursor: pointer; +} +.sim-button { + pointer-events: none; + fill: "rgb(17, 17, 17)"; +} +.sim-button:active { + fill: orange; +} + +.sim-board, +.sim-display, +sim-button { + fill: #111; +} +.sim-button-outer:hover { + stroke: orange; + stroke-width: 4px; +} +.sim-button-outer:active { + fill: orange; +} + +.sim-button-key-press { + fill: orange; +} + +.sim-button-nut { + fill: #704a4a; + pointer-events: none; +} + +/* +.sim-button-nut:hover { + stroke: 1px solid #704a4a; +} +.sim-pin:hover { + stroke: #d4af37; + stroke-width: 2px; +} +.sim-pin-touch.touched:hover { + stroke: darkorange; +} +.sim-led-back:hover { + stroke: #a0a0a0; + stroke-width: 3px; +} +.sim-led:hover { + stroke: #ff7f7f; + stroke-width: 3px; +} */ +.sim-systemled { + fill: #333; + stroke: #555; + stroke-width: 1px; +} +.sim-light-level-button { + stroke: #fff; + stroke-width: 3px; +} +.sim-antenna { + stroke: #555; + stroke-width: 2px; +} +.sim-text { + font-family: "Lucida Console", Monaco, monospace; + font-size: 25px; + fill: #fff; + pointer-events: none; +} +.sim-text-pin { + font-family: "Lucida Console", Monaco, monospace; + font-size: 20px; + fill: #fff; + pointer-events: none; +} +.sim-thermometer { + stroke: #aaa; + stroke-width: 3px; +} +/* animations */ +.sim-flash { + animation-name: sim-flash-animation; + animation-duration: 0.1s; +} +@keyframes sim-flash-animation { + from { + fill: yellow; + } + to { + fill: default; + } +} +.sim-flash-stroke { + animation-name: sim-flash-stroke-animation; + animation-duration: 0.4s; + animation-timing-function: ease-in; +} +@keyframes sim-flash-stroke-animation { + from { + stroke: yellow; + } + to { + stroke: default; + } +} +/* wireframe */ +.sim-wireframe * { + fill: none; + stroke: black; +} +.sim-wireframe .sim-display, +.sim-wireframe .sim-led, +.sim-wireframe .sim-led-back, +.sim-wireframe .sim-head, +.sim-wireframe .sim-theme, +.sim-wireframe .sim-button-group, +.sim-wireframe .sim-button-label, +.sim-wireframe .sim-button, +.sim-wireframe .sim-text-pin { + visibility: hidden; +} +.sim-wireframe .sim-label { + stroke: none; + fill: #777; +} +.sim-label, +.sim-button-label { + fill: #000; +} +.sim-wireframe .sim-board { + stroke-width: 2px; +} +*:focus { + outline: none; +} +.sim-button-group:focus { + stroke: #4d90fe; + stroke-width: 4px; +} +.sim-button-group:focus { + stroke: #4d90fe; + stroke-width: 4px; +} +*:focus .sim-button-outer, +.sim-pin:focus, +.sim-thermometer:focus, +.sim-shake:focus, +.no-drag, +.sim-text, +.sim-text-pin { + user-drag: none; + user-select: none; + -moz-user-select: none; + -webkit-user-drag: none; + -webkit-user-select: none; + -ms-user-select: none; +} diff --git a/src/view/styles/Simulator.css b/src/view/styles/Simulator.css index 62a2f3547..99f14ee48 100644 --- a/src/view/styles/Simulator.css +++ b/src/view/styles/Simulator.css @@ -2,6 +2,7 @@ display: flex; flex-direction: column; justify-content: center; + align-items: center; max-width: 700px; max-height: 700px; margin-left: auto; @@ -63,12 +64,10 @@ } } -.simulator { - display: flex; - flex-direction: column; - justify-content: center; - max-width: 700px; - max-height: 700px; - margin-left: auto; - margin-right: auto; +.microbit-container { + max-width: 350px; + padding: 20px; +} +.cpx-container { + width: 100%; } diff --git a/src/view/translations/en.json b/src/view/translations/en.json index 0cd7f7f98..03ba3349c 100644 --- a/src/view/translations/en.json +++ b/src/view/translations/en.json @@ -1,36 +1,45 @@ -{ - "toolbar-gpio.description": "8 GPIOs on the device! Pin A1 - A7 can also be used as capacitive touch sensors, and A0 is a true analog output pin.", - "toolbar-gpio.title": "GPIO", - "toolbar-gpio.tryItDescription": "Use your mouse to interact with the pin A1 - A7 or use your keyboard SHIFT+”1” - “7”", - "toolbar-ir-sensor.description": "Allows you to send commands to the device with a remote control, or even send messages between multiple devices! You can also do very simple proximity sensing since it reads the reflected light.", - "toolbar-ir-sensor.title": "IR Transmit & Receiver", - "toolbar-ir-sensor.tryItDescription": "We’re working hard to support this sensor on the simulator in the Device Simulator Express. You can try it on MakeCode!", - "toolbar-ir-sensor.tryItTitle": "We’re working hard to support this sensor on the simulator in the Device Simulator Express. You can try it on MakeCode!", - "toolbar-light-sensor.description": "An analog light sensor can be used to detect ambient light, with similar spectral response to the human eye.", - "toolbar-light-sensor.title": "Light Sensor", - "toolbar-light-sensor.tryItDescription": "Change the brightness from 0 - 255 here!", - "toolbar-motion-sensor.description": "Detects acceleration in XYZ orientations. And can also detect 'tap' and 'double tap' strikes on the board and when the board is shaken.", - "toolbar-motion-sensor.title": "Motion Sensor", - "toolbar-motion-sensor.tryItDescription": "Change the acceleration here and click or click on the button to simulate a shake.The tap feature is not supported by the Device Simulator Express. You can try it on MakeCode!", - "toolbar-neo-pixels.description": "The 10 full color RGB LEDs surrounding the outer edge of the boards can be set to any color. Great for beautiful lighting effects!", - "toolbar-neo-pixels.title": "NeoPixels", - "toolbar-neo-pixels.tryItDescription": "Run your code and see the cool effects on the simulator!", - "toolbar-push-button.description": "Two push buttons A and B are connected to digital pin #4 (Left) and #5 (Right) each.", - "toolbar-push-button.title": "Push Buttons", - "toolbar-push-button.tryItDescription": "Click them with your mouse or by pressing “A” “B” on your keyboard!", - "toolbar-red-led.description": "This Red LED is connected to the digital #13 GPIO pin. It can be very handy when you want an indicator LED.", - "toolbar-red-led.title": "Red LED", - "toolbar-red-led.tryItDescription": "Run your code and see the cool effects on the simulator!", - "toolbar-sound-sensor.description": "A digital microphone can detect audio volume and even perform basic FFT functions but cannot read it like an analog voltage.", - "toolbar-sound-sensor.title": "Sound Sensor", - "toolbar-sound-sensor.tryItDescription": "We’re working hard to support this sensor on the simulator in the Device Simulator Express. You can try it on MakeCode!", - "toolbar-slider-switch.description": "This slide switch returns True or False depending on whether it's ON or OFF and can be used as a toggle switch in your code!", - "toolbar-slider-switch.title": "Slider Switch", - "toolbar-slider-switch.tryItDescription": "Click it with your mouse or press 'S' on your keyboard to switch it ON and OFF!", - "toolbar-speaker.description": "This speaker can play .wav file and different tones and also has a class D amplifier that is connected to an output A0 pin built in! You can turn it off using the shutdown control on pin #11 on the physical device.", - "toolbar-speaker.title": "Speaker", - "toolbar-speaker.tryItDescription": "Right now the tones are not supported yet on the simulator, but you can play it on your device!", - "toolbar-temperature-sensor.description": "This sensor uses an NTC thermistor to sense temperature an calculate it with the analog voltage on analog pin #A9.", - "toolbar-temperature-sensor.title": "Temperature Sensor", - "toolbar-temperature-sensor.tryItDescription": "You can set the temperature range from your code!" -} +{ + "toolbar-gpio.description": "8 GPIOs on the device! Pin A1 - A7 can also be used as capacitive touch sensors, and A0 is a true analog output pin.", + "toolbar-gpio.title": "GPIO", + "toolbar-gpio.tryItDescription": "Use your mouse to interact with the pin A1 - A7 or use your keyboard SHIFT+”1” - “7”.", + "toolbar-ir-sensor.description": "Allows you to send commands to the device with a remote control, or even send messages between multiple devices! You can also do very simple proximity sensing since it reads the reflected light.", + "toolbar-ir-sensor.title": "IR Transmit & Receiver", + "toolbar-ir-sensor.tryItDescription": "We’re working hard to support this sensor on the simulator in the Device Simulator Express. You can try it on MakeCode!", + "toolbar-ir-sensor.tryItTitle": "We’re working hard to support this sensor on the simulator in the Device Simulator Express. You can try it on MakeCode!", + "toolbar-light-sensor.description": "An analog light sensor can be used to detect ambient light, with similar spectral response to the human eye.", + "toolbar-light-sensor.title": "Light Sensor", + "toolbar-light-sensor.tryItDescription": "Change the brightness from 0 - 255 here!", + "toolbar-motion-sensor.description": "Detects acceleration in XYZ orientations. And can also detect 'tap' and 'double tap' strikes on the board and when the board is shaken.", + "toolbar-motion-sensor.title": "Motion Sensor", + "toolbar-motion-sensor.tryItDescription": "Change the acceleration here and click or click on the button to simulate a shake.The tap feature is not supported by the Device Simulator Express. You can try it on MakeCode!", + "toolbar-neo-pixels.description": "The 10 full color RGB LEDs surrounding the outer edge of the boards can be set to any color. Great for beautiful lighting effects!", + "toolbar-neo-pixels.title": "NeoPixels", + "toolbar-neo-pixels.tryItDescription": "Run your code and see the cool effects on the simulator!", + "toolbar-push-button.description": "Two push buttons A and B are connected to digital pin #4 (Left) and #5 (Right) each.", + "toolbar-push-button.title": "Push Buttons", + "toolbar-push-button.tryItDescription": "Click them with your mouse or by pressing “A” “B” on your keyboard!", + "toolbar-red-led.description": "This Red LED is connected to the digital #13 GPIO pin. It can be very handy when you want an indicator LED.", + "toolbar-red-led.title": "Red LED", + "toolbar-red-led.tryItDescription": "Run your code and see the cool effects on the simulator!", + "toolbar-sound-sensor.description": "A digital microphone can detect audio volume and even perform basic FFT functions but cannot read it like an analog voltage.", + "toolbar-sound-sensor.title": "Sound Sensor", + "toolbar-sound-sensor.tryItDescription": "We’re working hard to support this sensor on the simulator in the Device Simulator Express. You can try it on MakeCode!", + "toolbar-slider-switch.description": "This slide switch returns True or False depending on whether it's ON or OFF and can be used as a toggle switch in your code!", + "toolbar-slider-switch.title": "Slider Switch", + "toolbar-slider-switch.tryItDescription": "Click it with your mouse or press 'S' on your keyboard to switch it ON and OFF!", + "toolbar-speaker.description": "This speaker can play .wav file and different tones and also has a class D amplifier that is connected to an output A0 pin built in! You can turn it off using the shutdown control on pin #11 on the physical device.", + "toolbar-speaker.title": "Speaker", + "toolbar-speaker.tryItDescription": "Right now the tones are not supported yet on the simulator, but you can play it on your device!", + "toolbar-temperature-sensor.description": "This sensor uses an NTC thermistor to sense temperature an calculate it with the analog voltage on analog pin #A9.", + "toolbar-temperature-sensor.title": "Temperature Sensor", + "toolbar-temperature-sensor.tryItDescription": "You can set the temperature range from your code!", + "toolbar-accelerometer-sensor.title": "Accelerometer", + "toolbar-accelerometer-sensor.description": "An accelerometer measures the acceleration of your micro:bit; this component senses when the micro:bit is moved.", + "toolbar-accelerometer-sensor.tryItDescription": "Change the acceleration here.", + "toolbar-microbit-led.title": "LEDs", + "toolbar-microbit-led.description": "The microbit has 25 LEDs for you to play with. The LEDs have 9 levels of brightness.", + "toolbar-microbit-led.tryItDescription": "Run your code and see the LEDs light up!", + "toolbar-microbit-button.title": "Buttons", + "toolbar-microbit-button.description": "There are two buttons on the front of the micro:bit (labelled A and B). The third button is to trigger both A and B buttons. You can detect when these buttons are pressed, allowing you to trigger code on the device.", + "toolbar-microbit-button.tryItDescription": "Click them with your mouse. Pressing “A” “B” on your keyboard will be implemented soon!" +} \ No newline at end of file diff --git a/src/view/utils/MessageUtils.tsx b/src/view/utils/MessageUtils.tsx new file mode 100644 index 000000000..41e093455 --- /dev/null +++ b/src/view/utils/MessageUtils.tsx @@ -0,0 +1,12 @@ +interface vscode { + postMessage(message: any): void; +} + +declare const vscode: vscode; + +export const sendMessage = ( + type: string, + state: TState +) => { + vscode.postMessage({ command: type, text: state }); +}; diff --git a/src/view/viewUtils.tsx b/src/view/viewUtils.tsx index 7b6efed48..445b916b2 100644 --- a/src/view/viewUtils.tsx +++ b/src/view/viewUtils.tsx @@ -1,3 +1,5 @@ +import { SENSOR_LIST } from "./constants"; + // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. export interface ISliderProps { @@ -5,8 +7,10 @@ export interface ISliderProps { maxValue: number; maxLabel: string; minLabel: string; - type: string; + type: string | SENSOR_LIST; axisLabel: string; + value?: number; + onUpdateValue?: (sensor: SENSOR_LIST, value: number) => void; } export interface ISensorButtonProps { @@ -17,7 +21,6 @@ export interface ISensorButtonProps { onKeyUp: (event: React.KeyboardEvent) => void; onKeyDown: (event: React.KeyboardEvent) => void; } - export interface ISensorProps { LABEL: string; sliderProps: ISliderProps[]; diff --git a/tslint.json b/tslint.json index 4b199b36e..534279116 100644 --- a/tslint.json +++ b/tslint.json @@ -1,32 +1,34 @@ { - "rulesDirectory": ["node_modules/tslint-microsoft-contrib"], - "extends": [ - "tslint:latest", - "tslint-react", - "tslint-config-prettier", - "tslint-react-hooks", - "tslint-microsoft-contrib/latest" - ], - "rules": { - "no-implicit-dependencies": [true, "dev"], - "no-string-throw": true, - "no-unused-expression": true, - "no-duplicate-variable": true, - "no-empty": false, - "no-relative-imports": false, - "max-func-body-length": false, - "curly": true, - "class-name": true, - "triple-equals": true, - "object-literal-sort-keys": true, - "react-hooks-nesting": "error", - "ordered-imports": true, - "import-name": false, - "member-access": false, - "no-console": false, - "jsx-boolean-value": false, - "no-unnecessary-semicolons": false, - "no-http-string": false - }, - "defaultSeverity": "warning" + "rulesDirectory": ["node_modules/tslint-microsoft-contrib"], + "extends": [ + "tslint:latest", + "tslint-react", + "tslint-config-prettier", + "tslint-react-hooks", + "tslint-microsoft-contrib/latest" + ], + "rules": { + "no-implicit-dependencies": [true, "dev"], + "no-string-throw": true, + "no-unused-expression": true, + "no-duplicate-variable": true, + "no-empty": false, + "no-relative-imports": false, + "max-func-body-length": false, + "curly": true, + "class-name": true, + "triple-equals": true, + "object-literal-sort-keys": true, + "react-hooks-nesting": "error", + "ordered-imports": true, + "import-name": false, + "member-access": false, + "no-console": false, + "jsx-boolean-value": false, + "no-unnecessary-semicolons": false, + "no-http-string": false, + "export-name": false, + "interface-name": false + }, + "defaultSeverity": "warning" } diff --git a/vendor/node-usb-native/.eslintrc b/vendor/node-usb-native/.eslintrc index 2b063c78c..3ade3b9dd 100644 --- a/vendor/node-usb-native/.eslintrc +++ b/vendor/node-usb-native/.eslintrc @@ -1,26 +1,26 @@ -{ - "extends": [ - "standard" - ], - "plugins": [ - "require-path-exists" - ], - "env": { - "node": true, - "mocha": true - }, - "rules": { - "arrow-parens": [2, "as-needed", {"requireForBlockBody": true }], - "no-unused-vars": [2, { "vars": "all", "args": "after-used" }], - "object-curly-spacing": [2, "always"], - "prefer-arrow-callback": 2, - "prefer-const": 2, - "prefer-template": 2, - "require-path-exists/exists": 2, - "require-path-exists/notEmpty": 2, - "require-path-exists/tooManyArguments": 2, - "semi": [2, "always", {"omitLastInOneLineBlock": true}], - "space-before-function-paren": [2, "never"], - "standard/object-curly-even-spacing": 0 - } +{ + "extends": [ + "standard" + ], + "plugins": [ + "require-path-exists" + ], + "env": { + "node": true, + "mocha": true + }, + "rules": { + "arrow-parens": [2, "as-needed", {"requireForBlockBody": true }], + "no-unused-vars": [2, { "vars": "all", "args": "after-used" }], + "object-curly-spacing": [2, "always"], + "prefer-arrow-callback": 2, + "prefer-const": 2, + "prefer-template": 2, + "require-path-exists/exists": 2, + "require-path-exists/notEmpty": 2, + "require-path-exists/tooManyArguments": 2, + "semi": [2, "always", {"omitLastInOneLineBlock": true}], + "space-before-function-paren": [2, "never"], + "standard/object-curly-even-spacing": 0 + } } \ No newline at end of file diff --git a/vendor/node-usb-native/.gitignore b/vendor/node-usb-native/.gitignore index 8d2b1ae24..41ace66fd 100644 --- a/vendor/node-usb-native/.gitignore +++ b/vendor/node-usb-native/.gitignore @@ -1,14 +1,14 @@ -$ cat .gitignore - -# Can ignore specific files -.settings.xml -.monitor -.DS_Store - -# Use wildcards as well -*~ -#*.swp - -# Can also ignore all directories and files in a directory. -node_modules/ -build/ +$ cat .gitignore + +# Can ignore specific files +.settings.xml +.monitor +.DS_Store + +# Use wildcards as well +*~ +#*.swp + +# Can also ignore all directories and files in a directory. +node_modules/ +build/ diff --git a/vendor/node-usb-native/.npmignore b/vendor/node-usb-native/.npmignore index b38db2f29..27b90ed90 100644 --- a/vendor/node-usb-native/.npmignore +++ b/vendor/node-usb-native/.npmignore @@ -1,2 +1,2 @@ -node_modules/ -build/ +node_modules/ +build/ diff --git a/vendor/node-usb-native/README.md b/vendor/node-usb-native/README.md index 5de5318a6..329164300 100644 --- a/vendor/node-usb-native/README.md +++ b/vendor/node-usb-native/README.md @@ -1,4 +1,4 @@ -This is a natvie package contains two modules: detector and serialport, detector provides the functionality of detecting usb changes and serialport provides the functionality of listing serial ports, openning serial ports and sending/receiving message to/from serial ports. - - require("../../../vendor/node-usb-native").SerialPort; - require("../../../vendor/node-usb-native").detector; +This is a natvie package contains two modules: detector and serialport, detector provides the functionality of detecting usb changes and serialport provides the functionality of listing serial ports, openning serial ports and sending/receiving message to/from serial ports. + + require("../../../vendor/node-usb-native").SerialPort; + require("../../../vendor/node-usb-native").detector; diff --git a/vendor/node-usb-native/binding.gyp b/vendor/node-usb-native/binding.gyp index c967103e1..10be49615 100644 --- a/vendor/node-usb-native/binding.gyp +++ b/vendor/node-usb-native/binding.gyp @@ -1,64 +1,64 @@ -{ - "targets": [ - { - "target_name": "usb-native", - "sources": [ - "src/detection.cpp", - "src/detection.h", - "src/deviceList.cpp", - "src/combined.cpp", - "src/serialport.cpp" - ], - "include_dirs": [ - " { - // Suss out the optional parameters - if (!pid && !callback) { - callback = vid; - vid = undefined; - } else if (!callback) { - callback = pid; - pid = undefined; - } - - return new Promise((resolve, reject) => { - // Assemble the optional args into something we can use with `apply` - var args = []; - if (vid) { - args = args.concat(vid); - } - if (pid) { - args = args.concat(pid); - } - - // Tack on our own callback that takes care of things - args = args.concat((err, devices) => { - // We call the callback if they passed one - if (callback) { - callback.call(callback, err, devices); - } - - // But also do the promise stuff - if (err) { - reject(err); - return; - } - resolve(devices); - }); - - // Fire off the `find` function that actually does all of the work - detection.find.apply(detection, args); - }); -}; -if (detection.registerAdded) { - detection.registerAdded((device) => { - detector.emit(`add:${device.vendorId}:${device.productId}`, device); - detector.emit(`insert:${device.vendorId}:${device.productId}`, device); - detector.emit(`add:${device.vendorId}`, device); - detector.emit(`insert:${device.vendorId}`, device); - detector.emit('add', device); - detector.emit('insert', device); - - detector.emit(`change:${device.vendorId}:${device.productId}`, device); - detector.emit(`change:${device.vendorId}`, device); - detector.emit('change', device); - }); - - detection.registerRemoved((device) => { - detector.emit(`remove:${device.vendorId}:${device.productId}`, device); - detector.emit(`remove:${device.vendorId}`, device); - detector.emit('remove', device); - - detector.emit(`change:${device.vendorId}:${device.productId}`, device); - detector.emit(`change:${device.vendorId}`, device); - detector.emit('change', device); - }); - - var started = true; - - detector.startMonitoring = () => { - if (started) { - return; - } - - started = true; - detection.startMonitoring(); - }; - - detector.stopMonitoring = () => { - if (!started) { - return; - } - - started = false; - detection.stopMonitoring(); - }; -} - -module.exports = detector; +var detection = require('./bindings'); +var EventEmitter2 = require('eventemitter2').EventEmitter2; + +var detector = new EventEmitter2({ + wildcard: true, + delimiter: ':', + maxListeners: 1000 // default would be 10! +}); + +// detector.find = detection.find; +detector.find = (vid, pid, callback) => { + // Suss out the optional parameters + if (!pid && !callback) { + callback = vid; + vid = undefined; + } else if (!callback) { + callback = pid; + pid = undefined; + } + + return new Promise((resolve, reject) => { + // Assemble the optional args into something we can use with `apply` + var args = []; + if (vid) { + args = args.concat(vid); + } + if (pid) { + args = args.concat(pid); + } + + // Tack on our own callback that takes care of things + args = args.concat((err, devices) => { + // We call the callback if they passed one + if (callback) { + callback.call(callback, err, devices); + } + + // But also do the promise stuff + if (err) { + reject(err); + return; + } + resolve(devices); + }); + + // Fire off the `find` function that actually does all of the work + detection.find.apply(detection, args); + }); +}; +if (detection.registerAdded) { + detection.registerAdded((device) => { + detector.emit(`add:${device.vendorId}:${device.productId}`, device); + detector.emit(`insert:${device.vendorId}:${device.productId}`, device); + detector.emit(`add:${device.vendorId}`, device); + detector.emit(`insert:${device.vendorId}`, device); + detector.emit('add', device); + detector.emit('insert', device); + + detector.emit(`change:${device.vendorId}:${device.productId}`, device); + detector.emit(`change:${device.vendorId}`, device); + detector.emit('change', device); + }); + + detection.registerRemoved((device) => { + detector.emit(`remove:${device.vendorId}:${device.productId}`, device); + detector.emit(`remove:${device.vendorId}`, device); + detector.emit('remove', device); + + detector.emit(`change:${device.vendorId}:${device.productId}`, device); + detector.emit(`change:${device.vendorId}`, device); + detector.emit('change', device); + }); + + var started = true; + + detector.startMonitoring = () => { + if (started) { + return; + } + + started = true; + detection.startMonitoring(); + }; + + detector.stopMonitoring = () => { + if (!started) { + return; + } + + started = false; + detection.stopMonitoring(); + }; +} + +module.exports = detector; diff --git a/vendor/node-usb-native/lib/index.js b/vendor/node-usb-native/lib/index.js index 3a5c973fe..09bfc7115 100644 --- a/vendor/node-usb-native/lib/index.js +++ b/vendor/node-usb-native/lib/index.js @@ -1,2 +1,2 @@ -exports.detector = require('./detector'); -exports.SerialPort = require('./serialport'); +exports.detector = require('./detector'); +exports.SerialPort = require('./serialport'); diff --git a/vendor/node-usb-native/lib/list-unix.js b/vendor/node-usb-native/lib/list-unix.js index e3b6de297..32e6719a9 100644 --- a/vendor/node-usb-native/lib/list-unix.js +++ b/vendor/node-usb-native/lib/list-unix.js @@ -1,109 +1,109 @@ -'use strict'; - -var childProcess = require('child_process'); -var fs = require('fs'); -var path = require('path'); - -function promisify(func) { - return (arg) => { - return new Promise((resolve, reject) => { - func(arg, (err, data) => { - if (err) { - return reject(err); - } - resolve(data); - }); - }); - }; -} - -function promisedFilter(func) { - return (data) => { - var shouldKeep = data.map(func); - return Promise.all(shouldKeep).then((keep) => { - return data.filter((path, index) => { - return keep[index]; - }); - }); - }; -} - -var statAsync = promisify(fs.stat); -var readdirAsync = promisify(fs.readdir); -var execAsync = promisify(childProcess.exec); - -function udevParser(output) { - var udevInfo = output.split('\n').reduce((info, line) => { - if (!line || line.trim() === '') { - return info; - } - var parts = line.split('=').map((part) => { - return part.trim(); - }); - - info[parts[0].toLowerCase()] = parts[1]; - - return info; - }, {}); - - var pnpId; - if (udevInfo.devlinks) { - udevInfo.devlinks.split(' ').forEach((path) => { - if (path.indexOf('/by-id/') === -1) { return } - pnpId = path.substring(path.lastIndexOf('/') + 1); - }); - } - - var vendorId = udevInfo.id_vendor_id; - if (vendorId && vendorId.substring(0, 2) !== '0x') { - vendorId = `0x${vendorId}`; - } - - var productId = udevInfo.id_model_id; - if (productId && productId.substring(0, 2) !== '0x') { - productId = `0x${productId}`; - } - - return { - comName: udevInfo.devname, - manufacturer: udevInfo.id_vendor, - serialNumber: udevInfo.id_serial, - pnpId: pnpId, - vendorId: vendorId, - productId: productId - }; -} - -function checkPathAndDevice(path) { - // get only serial port names - if (!(/(tty(S|ACM|USB|AMA|MFD)|rfcomm)/).test(path)) { - return false; - } - return statAsync(path).then((stats) => { - return stats.isCharacterDevice(); - }); -} - -function lookupPort(file) { - var udevadm = `udevadm info --query=property -p $(udevadm info -q path -n ${file})`; - return execAsync(udevadm).then(udevParser); -} - -function listUnix(callback) { - var dirName = '/dev'; - readdirAsync(dirName) - .catch((err) => { - // if this directory is not found we just pretend everything is OK - // TODO Depreciated this check? - if (err.errno === 34) { - return []; - } - throw err; - }) - .then((data) => { return data.map((file) => { return path.join(dirName, file) }) }) - .then(promisedFilter(checkPathAndDevice)) - .then((data) => { return Promise.all(data.map(lookupPort)) }) - .then((data) => { callback(null, data) }, (err) => { callback(err) }); -} - -module.exports = listUnix; +'use strict'; + +var childProcess = require('child_process'); +var fs = require('fs'); +var path = require('path'); + +function promisify(func) { + return (arg) => { + return new Promise((resolve, reject) => { + func(arg, (err, data) => { + if (err) { + return reject(err); + } + resolve(data); + }); + }); + }; +} + +function promisedFilter(func) { + return (data) => { + var shouldKeep = data.map(func); + return Promise.all(shouldKeep).then((keep) => { + return data.filter((path, index) => { + return keep[index]; + }); + }); + }; +} + +var statAsync = promisify(fs.stat); +var readdirAsync = promisify(fs.readdir); +var execAsync = promisify(childProcess.exec); + +function udevParser(output) { + var udevInfo = output.split('\n').reduce((info, line) => { + if (!line || line.trim() === '') { + return info; + } + var parts = line.split('=').map((part) => { + return part.trim(); + }); + + info[parts[0].toLowerCase()] = parts[1]; + + return info; + }, {}); + + var pnpId; + if (udevInfo.devlinks) { + udevInfo.devlinks.split(' ').forEach((path) => { + if (path.indexOf('/by-id/') === -1) { return } + pnpId = path.substring(path.lastIndexOf('/') + 1); + }); + } + + var vendorId = udevInfo.id_vendor_id; + if (vendorId && vendorId.substring(0, 2) !== '0x') { + vendorId = `0x${vendorId}`; + } + + var productId = udevInfo.id_model_id; + if (productId && productId.substring(0, 2) !== '0x') { + productId = `0x${productId}`; + } + + return { + comName: udevInfo.devname, + manufacturer: udevInfo.id_vendor, + serialNumber: udevInfo.id_serial, + pnpId: pnpId, + vendorId: vendorId, + productId: productId + }; +} + +function checkPathAndDevice(path) { + // get only serial port names + if (!(/(tty(S|ACM|USB|AMA|MFD)|rfcomm)/).test(path)) { + return false; + } + return statAsync(path).then((stats) => { + return stats.isCharacterDevice(); + }); +} + +function lookupPort(file) { + var udevadm = `udevadm info --query=property -p $(udevadm info -q path -n ${file})`; + return execAsync(udevadm).then(udevParser); +} + +function listUnix(callback) { + var dirName = '/dev'; + readdirAsync(dirName) + .catch((err) => { + // if this directory is not found we just pretend everything is OK + // TODO Depreciated this check? + if (err.errno === 34) { + return []; + } + throw err; + }) + .then((data) => { return data.map((file) => { return path.join(dirName, file) }) }) + .then(promisedFilter(checkPathAndDevice)) + .then((data) => { return Promise.all(data.map(lookupPort)) }) + .then((data) => { callback(null, data) }, (err) => { callback(err) }); +} + +module.exports = listUnix; diff --git a/vendor/node-usb-native/lib/native/usb-native_Ubuntu14.04_6.1.4_ia32.node b/vendor/node-usb-native/lib/native/usb-native_Ubuntu14.04_6.1.4_ia32.node new file mode 100644 index 0000000000000000000000000000000000000000..83b71d78049d0d06b910220b4c6c3ae1a4c437b8 GIT binary patch literal 128327 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 z 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 WOjN+>E{_S*kDYv^s$;7?@Bad0)D|fK literal 0 HcmV?d00001 diff --git a/vendor/node-usb-native/lib/native/usb-native_win32_6.1.4_ia32.node b/vendor/node-usb-native/lib/native/usb-native_win32_6.1.4_ia32.node new file mode 100644 index 0000000000000000000000000000000000000000..277de25a26fc3803d63440094b9fc74d1547bbc4 GIT binary patch literal 193536 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 P4Vi|){m=FPoh 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�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
4g45<0&T$Wg_qsV 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 DmD<~J literal 0 HcmV?d00001 diff --git a/vendor/node-usb-native/lib/native_loader.js b/vendor/node-usb-native/lib/native_loader.js index 0f1fc2ebf..ce4e0ea22 100644 --- a/vendor/node-usb-native/lib/native_loader.js +++ b/vendor/node-usb-native/lib/native_loader.js @@ -1,24 +1,24 @@ -const glob = require('glob'); -const path = require('path'); -const loadLibrary = function(parentFolder, libraryName) { - const nodegypFiles = glob(path.join(__dirname, `../build/+(Release|Debug)/${libraryName}.node`), { - sync: true - }); - const nodepregypFiles = glob(`${parentFolder.replace(/\\/g, '/')}/${libraryName}*${process.arch}*.node`, { - sync: true - }); - var binding = null; - nodegypFiles.concat(nodepregypFiles).forEach((file) => { - try { - var _temp = require(file); - binding = _temp; - console.log('using', file); - } catch (e) { - } - }); - if (!binding) { - console.log('[Warn]', 'no library available after trying files', nodegypFiles.concat(nodepregypFiles)); - } - return binding; -}; -exports.load = loadLibrary; +const glob = require('glob'); +const path = require('path'); +const loadLibrary = function(parentFolder, libraryName) { + const nodegypFiles = glob(path.join(__dirname, `../build/+(Release|Debug)/${libraryName}.node`), { + sync: true + }); + const nodepregypFiles = glob(`${parentFolder.replace(/\\/g, '/')}/${libraryName}*${process.arch}*.node`, { + sync: true + }); + var binding = null; + nodegypFiles.concat(nodepregypFiles).forEach((file) => { + try { + var _temp = require(file); + binding = _temp; + console.log('using', file); + } catch (e) { + } + }); + if (!binding) { + console.log('[Warn]', 'no library available after trying files', nodegypFiles.concat(nodepregypFiles)); + } + return binding; +}; +exports.load = loadLibrary; diff --git a/vendor/node-usb-native/lib/parsers.js b/vendor/node-usb-native/lib/parsers.js index 2783c1425..303fba50d 100644 --- a/vendor/node-usb-native/lib/parsers.js +++ b/vendor/node-usb-native/lib/parsers.js @@ -1,64 +1,64 @@ -'use strict'; - -// Copyright 2011 Chris Williams - -module.exports = { - raw: function(emitter, buffer) { - emitter.emit('data', buffer); - }, - - // encoding: ascii utf8 utf16le ucs2 base64 binary hex - // More: http://nodejs.org/api/buffer.html#buffer_buffer - readline: function(delimiter, encoding) { - if (typeof delimiter === 'undefined' || delimiter === null) { delimiter = '\r' } - if (typeof encoding === 'undefined' || encoding === null) { encoding = 'utf8' } - // Delimiter buffer saved in closure - var data = ''; - return function(emitter, buffer) { - // Collect data - data += buffer.toString(encoding); - // Split collected data by delimiter - var parts = data.split(delimiter); - data = parts.pop(); - parts.forEach((part) => { - emitter.emit('data', part); - }); - }; - }, - - // Emit a data event every `length` bytes - byteLength: function(length) { - var data = Buffer.alloc(0); - return function(emitter, buffer) { - data = Buffer.concat([data, buffer]); - while (data.length >= length) { - var out = data.slice(0, length); - data = data.slice(length); - emitter.emit('data', out); - } - }; - }, - - // Emit a data event each time a byte sequence (delimiter is an array of byte) is found - // Sample usage : byteDelimiter([10, 13]) - byteDelimiter: function(delimiter) { - if (Object.prototype.toString.call(delimiter) !== '[object Array]') { - delimiter = [ delimiter ]; - } - var buf = []; - var nextDelimIndex = 0; - return function(emitter, buffer) { - for (var i = 0; i < buffer.length; i++) { - buf[buf.length] = buffer[i]; - if (buf[buf.length - 1] === delimiter[nextDelimIndex]) { - nextDelimIndex++; - } - if (nextDelimIndex === delimiter.length) { - emitter.emit('data', buf); - buf = []; - nextDelimIndex = 0; - } - } - }; - } -}; +'use strict'; + +// Copyright 2011 Chris Williams + +module.exports = { + raw: function(emitter, buffer) { + emitter.emit('data', buffer); + }, + + // encoding: ascii utf8 utf16le ucs2 base64 binary hex + // More: http://nodejs.org/api/buffer.html#buffer_buffer + readline: function(delimiter, encoding) { + if (typeof delimiter === 'undefined' || delimiter === null) { delimiter = '\r' } + if (typeof encoding === 'undefined' || encoding === null) { encoding = 'utf8' } + // Delimiter buffer saved in closure + var data = ''; + return function(emitter, buffer) { + // Collect data + data += buffer.toString(encoding); + // Split collected data by delimiter + var parts = data.split(delimiter); + data = parts.pop(); + parts.forEach((part) => { + emitter.emit('data', part); + }); + }; + }, + + // Emit a data event every `length` bytes + byteLength: function(length) { + var data = Buffer.alloc(0); + return function(emitter, buffer) { + data = Buffer.concat([data, buffer]); + while (data.length >= length) { + var out = data.slice(0, length); + data = data.slice(length); + emitter.emit('data', out); + } + }; + }, + + // Emit a data event each time a byte sequence (delimiter is an array of byte) is found + // Sample usage : byteDelimiter([10, 13]) + byteDelimiter: function(delimiter) { + if (Object.prototype.toString.call(delimiter) !== '[object Array]') { + delimiter = [ delimiter ]; + } + var buf = []; + var nextDelimIndex = 0; + return function(emitter, buffer) { + for (var i = 0; i < buffer.length; i++) { + buf[buf.length] = buffer[i]; + if (buf[buf.length - 1] === delimiter[nextDelimIndex]) { + nextDelimIndex++; + } + if (nextDelimIndex === delimiter.length) { + emitter.emit('data', buf); + buf = []; + nextDelimIndex = 0; + } + } + }; + } +}; diff --git a/vendor/node-usb-native/lib/serialport.js b/vendor/node-usb-native/lib/serialport.js index 6fcc88e16..754f21769 100644 --- a/vendor/node-usb-native/lib/serialport.js +++ b/vendor/node-usb-native/lib/serialport.js @@ -1,502 +1,502 @@ -'use strict'; - -// Copyright 2011 Chris Williams - -const _debug = false; -const debug = (message) => { - if (_debug) console.log(message); -}; - -// shims -// Internal Dependencies -var SerialPortBinding = require('./bindings'); -var parsers = require('./parsers'); - -// Built-ins Dependencies -var fs = require('fs'); -var stream = require('stream'); -var util = require('util'); - -// VALIDATION ARRAYS -var DATABITS = [5, 6, 7, 8]; -var STOPBITS = [1, 1.5, 2]; -var PARITY = ['none', 'even', 'mark', 'odd', 'space']; -var FLOWCONTROLS = ['xon', 'xoff', 'xany', 'rtscts']; -var SET_OPTIONS = ['brk', 'cts', 'dtr', 'dts', 'rts']; - -// Stuff from ReadStream, refactored for our usage: -var kPoolSize = 40 * 1024; -var kMinPoolSpace = 128; - -var defaultSettings = { - baudRate: 9600, - autoOpen: true, - parity: 'none', - xon: false, - xoff: false, - xany: false, - rtscts: false, - hupcl: true, - dataBits: 8, - stopBits: 1, - bufferSize: 64 * 1024, - lock: true, - parser: parsers.raw, - platformOptions: SerialPortBinding.platformOptions -}; - -var defaultSetFlags = { - brk: false, - cts: false, - dtr: true, - dts: false, - rts: true -}; - -// deprecate the lowercase version of these options next major release -var LOWERCASE_OPTIONS = [ - 'baudRate', - 'dataBits', - 'stopBits', - 'bufferSize', - 'platformOptions' -]; - -function correctOptions(options) { - LOWERCASE_OPTIONS.forEach((name) => { - var lowerName = name.toLowerCase(); - if (options.hasOwnProperty(lowerName)) { - var value = options[lowerName]; - delete options[lowerName]; - options[name] = value; - } - }); - return options; -} - -function SerialPort(path, options, callback) { - if (typeof callback === 'boolean') { - throw new TypeError('`openImmediately` is now called `autoOpen` and is a property of options'); - } - - if (typeof options === 'function') { - callback = options; - options = {}; - } - - options = options || {}; - - stream.Stream.call(this); - - if (!path) { - throw new TypeError('No path specified'); - } - - this.path = path; - - var correctedOptions = correctOptions(options); - var settings = Object.assign({}, defaultSettings, correctedOptions); - - if (typeof settings.baudRate !== 'number') { - throw new TypeError(`Invalid "baudRate" must be a number got: ${settings.baudRate}`); - } - - if (DATABITS.indexOf(settings.dataBits) === -1) { - throw new TypeError(`Invalid "databits": ${settings.dataBits}`); - } - - if (STOPBITS.indexOf(settings.stopBits) === -1) { - throw new TypeError(`Invalid "stopbits": ${settings.stopBits}`); - } - - if (PARITY.indexOf(settings.parity) === -1) { - throw new TypeError(`Invalid "parity": ${settings.parity}`); - } - - FLOWCONTROLS.forEach((control) => { - if (typeof settings[control] !== 'boolean') { - throw new TypeError(`Invalid "${control}" is not boolean`); - } - }); - - settings.disconnectedCallback = this._disconnected.bind(this); - settings.dataCallback = settings.parser.bind(this, this); - - this.fd = null; - this.paused = true; - this.opening = false; - this.closing = false; - - if (process.platform !== 'win32') { - this.bufferSize = settings.bufferSize; - this.readable = true; - this.reading = false; - } - - this.options = settings; - - if (this.options.autoOpen) { - // is nextTick necessary? - process.nextTick(this.open.bind(this, callback)); - } -} - -util.inherits(SerialPort, stream.Stream); - -SerialPort.prototype._error = function(error, callback) { - if (callback) { - callback.call(this, error); - } else { - this.emit('error', error); - } -}; - -SerialPort.prototype.open = function(callback) { - if (this.isOpen()) { - return this._error(new Error('Port is already open'), callback); - } - - if (this.opening) { - return this._error(new Error('Port is opening'), callback); - } - - this.paused = true; - this.readable = true; - this.reading = false; - this.opening = true; - - SerialPortBinding.open(this.path, this.options, (err, fd) => { - this.opening = false; - if (err) { - debug('SerialPortBinding.open had an error', err); - return this._error(err, callback); - } - this.fd = fd; - this.paused = false; - - if (process.platform !== 'win32') { - this.serialPoller = new SerialPortBinding.SerialportPoller(this.fd, (err) => { - if (!err) { - this._read(); - } else { - this._disconnected(err); - } - }); - this.serialPoller.start(); - } - - this.emit('open'); - if (callback) { - callback.call(this, null); - } - }); -}; - -SerialPort.prototype.update = function(options, callback) { - if (!this.isOpen()) { - debug('update attempted, but port is not open'); - return this._error(new Error('Port is not open'), callback); - } - - var correctedOptions = correctOptions(options); - var settings = Object.assign({}, defaultSettings, correctedOptions); - this.options.baudRate = settings.baudRate; - - SerialPortBinding.update(this.fd, this.options, (err) => { - if (err) { - return this._error(err, callback); - } - if (callback) { - callback.call(this, null); - } - }); -}; - -SerialPort.prototype.isOpen = function() { - return this.fd !== null && !this.closing; -}; - -SerialPort.prototype.write = function(buffer, ending, callback) { - if (!this.isOpen()) { - debug('write attempted, but port is not open'); - return this._error(new Error('Port is not open'), callback); - } - - if (!Buffer.isBuffer(buffer)) { - buffer = Buffer.from(buffer); - } - - switch (ending) { - case 'Newline': - buffer = Buffer.concat([buffer, Buffer.from('\n')]); - break; - case 'Carriage return': - buffer = Buffer.concat([buffer, Buffer.from('\r')]); - break; - case 'Both NL & CR': - buffer = Buffer.concat([buffer, Buffer.from('\r\n')]); - break; - default: - break; - } - - debug(`write ${buffer.length} bytes of data`); - SerialPortBinding.write(this.fd, buffer, (err) => { - if (err) { - debug('SerialPortBinding.write had an error', err); - return this._error(err, callback); - } - if (callback) { - callback.call(this, null); - } - }); -}; - -if (process.platform !== 'win32') { - SerialPort.prototype._read = function() { - if (!this.readable || this.paused || this.reading || this.closing) { - return; - } - - this.reading = true; - - if (!this.pool || this.pool.length - this.pool.used < kMinPoolSpace) { - // discard the old pool. Can't add to the free list because - // users might have references to slices on it. - this.pool = Buffer.alloc(kPoolSize); - this.pool.used = 0; - } - - // Grab another reference to the pool in the case that while we're in the - // thread pool another read() finishes up the pool, and allocates a new - // one. - var toRead = Math.min(this.pool.length - this.pool.used, ~~this.bufferSize); - var start = this.pool.used; - - var _afterRead = (err, bytesRead, readPool, bytesRequested) => { - this.reading = false; - if (err) { - if (err.code && err.code === 'EAGAIN') { - if (this.isOpen()) { - this.serialPoller.start(); - } - // handle edge case were mac/unix doesn't clearly know the error. - } else if (err.code && (err.code === 'EBADF' || err.code === 'ENXIO' || (err.errno === -1 || err.code === 'UNKNOWN'))) { - this._disconnected(err); - } else { - this.fd = null; - this.readable = false; - this.emit('error', err); - } - return; - } - - // Since we will often not read the number of bytes requested, - // let's mark the ones we didn't need as available again. - this.pool.used -= bytesRequested - bytesRead; - - if (bytesRead === 0) { - if (this.isOpen()) { - this.serialPoller.start(); - } - } else { - var b = this.pool.slice(start, start + bytesRead); - - // do not emit events if the stream is paused - if (this.paused) { - if (!this.buffer) { - this.buffer = Buffer.alloc(0); - } - this.buffer = Buffer.concat([this.buffer, b]); - return; - } - this._emitData(b); - - // do not emit events anymore after we declared the stream unreadable - if (!this.readable) { - return; - } - this._read(); - } - }; - - fs.read(this.fd, this.pool, this.pool.used, toRead, null, (err, bytesRead) => { - var readPool = this.pool; - var bytesRequested = toRead; - _afterRead(err, bytesRead, readPool, bytesRequested); - }); - - this.pool.used += toRead; - }; - - SerialPort.prototype._emitData = function(data) { - this.options.dataCallback(data); - }; - - SerialPort.prototype.pause = function() { - this.paused = true; - }; - - SerialPort.prototype.resume = function() { - this.paused = false; - - if (this.buffer) { - var buffer = this.buffer; - this.buffer = null; - this._emitData(buffer); - } - - // No longer open? - if (!this.isOpen()) { - return; - } - - this._read(); - }; -} // if !'win32' - -SerialPort.prototype._disconnected = function(err) { - this.paused = true; - this.emit('disconnect', err); - if (this.closing) { - return; - } - - if (this.fd === null) { - return; - } - - this.closing = true; - if (process.platform !== 'win32') { - this.readable = false; - this.serialPoller.close(); - } - - SerialPortBinding.close(this.fd, (err) => { - this.closing = false; - if (err) { - debug('Disconnect close completed with error: ', err); - } - this.fd = null; - this.emit('close'); - }); -}; - -SerialPort.prototype.close = function(callback) { - this.paused = true; - - if (this.closing) { - debug('close attempted, but port is already closing'); - return this._error(new Error('Port is not open'), callback); - } - - if (!this.isOpen()) { - debug('close attempted, but port is not open'); - return this._error(new Error('Port is not open'), callback); - } - - this.closing = true; - - // Stop polling before closing the port. - if (process.platform !== 'win32') { - this.readable = false; - this.serialPoller.close(); - } - SerialPortBinding.close(this.fd, (err) => { - this.closing = false; - if (err) { - debug('SerialPortBinding.close had an error', err); - return this._error(err, callback); - } - - this.fd = null; - this.emit('close'); - if (callback) { - callback.call(this, null); - } - }); -}; - -SerialPort.prototype.flush = function(callback) { - if (!this.isOpen()) { - debug('flush attempted, but port is not open'); - return this._error(new Error('Port is not open'), callback); - } - - SerialPortBinding.flush(this.fd, (err, result) => { - if (err) { - debug('SerialPortBinding.flush had an error', err); - return this._error(err, callback); - } - if (callback) { - callback.call(this, null, result); - } - }); -}; - -SerialPort.prototype.set = function(options, callback) { - if (!this.isOpen()) { - debug('set attempted, but port is not open'); - return this._error(new Error('Port is not open'), callback); - } - - options = options || {}; - if (!callback && typeof options === 'function') { - callback = options; - options = {}; - } - - var settings = {}; - for (var i = SET_OPTIONS.length - 1; i >= 0; i--) { - var flag = SET_OPTIONS[i]; - if (options[flag] !== undefined) { - settings[flag] = options[flag]; - } else { - settings[flag] = defaultSetFlags[flag]; - } - } - - SerialPortBinding.set(this.fd, settings, (err) => { - if (err) { - debug('SerialPortBinding.set had an error', err); - return this._error(err, callback); - } - if (callback) { - callback.call(this, null); - } - }); -}; - -SerialPort.prototype.drain = function(callback) { - if (!this.isOpen()) { - debug('drain attempted, but port is not open'); - return this._error(new Error('Port is not open'), callback); - } - - SerialPortBinding.drain(this.fd, (err) => { - if (err) { - debug('SerialPortBinding.drain had an error', err); - return this._error(err, callback); - } - if (callback) { - callback.call(this, null); - } - }); -}; - -SerialPort.parsers = parsers; -SerialPort.list = SerialPortBinding.list; - -// Write a depreciation warning once -Object.defineProperty(SerialPort, 'SerialPort', { - get: function() { - // console.warn('DEPRECATION: Please use `require(\'serialport\')` instead of `require(\'serialport\').SerialPort`'); - Object.defineProperty(SerialPort, 'SerialPort', { - value: SerialPort - }); - return SerialPort; - }, - configurable: true -}); - -module.exports = SerialPort; +'use strict'; + +// Copyright 2011 Chris Williams + +const _debug = false; +const debug = (message) => { + if (_debug) console.log(message); +}; + +// shims +// Internal Dependencies +var SerialPortBinding = require('./bindings'); +var parsers = require('./parsers'); + +// Built-ins Dependencies +var fs = require('fs'); +var stream = require('stream'); +var util = require('util'); + +// VALIDATION ARRAYS +var DATABITS = [5, 6, 7, 8]; +var STOPBITS = [1, 1.5, 2]; +var PARITY = ['none', 'even', 'mark', 'odd', 'space']; +var FLOWCONTROLS = ['xon', 'xoff', 'xany', 'rtscts']; +var SET_OPTIONS = ['brk', 'cts', 'dtr', 'dts', 'rts']; + +// Stuff from ReadStream, refactored for our usage: +var kPoolSize = 40 * 1024; +var kMinPoolSpace = 128; + +var defaultSettings = { + baudRate: 9600, + autoOpen: true, + parity: 'none', + xon: false, + xoff: false, + xany: false, + rtscts: false, + hupcl: true, + dataBits: 8, + stopBits: 1, + bufferSize: 64 * 1024, + lock: true, + parser: parsers.raw, + platformOptions: SerialPortBinding.platformOptions +}; + +var defaultSetFlags = { + brk: false, + cts: false, + dtr: true, + dts: false, + rts: true +}; + +// deprecate the lowercase version of these options next major release +var LOWERCASE_OPTIONS = [ + 'baudRate', + 'dataBits', + 'stopBits', + 'bufferSize', + 'platformOptions' +]; + +function correctOptions(options) { + LOWERCASE_OPTIONS.forEach((name) => { + var lowerName = name.toLowerCase(); + if (options.hasOwnProperty(lowerName)) { + var value = options[lowerName]; + delete options[lowerName]; + options[name] = value; + } + }); + return options; +} + +function SerialPort(path, options, callback) { + if (typeof callback === 'boolean') { + throw new TypeError('`openImmediately` is now called `autoOpen` and is a property of options'); + } + + if (typeof options === 'function') { + callback = options; + options = {}; + } + + options = options || {}; + + stream.Stream.call(this); + + if (!path) { + throw new TypeError('No path specified'); + } + + this.path = path; + + var correctedOptions = correctOptions(options); + var settings = Object.assign({}, defaultSettings, correctedOptions); + + if (typeof settings.baudRate !== 'number') { + throw new TypeError(`Invalid "baudRate" must be a number got: ${settings.baudRate}`); + } + + if (DATABITS.indexOf(settings.dataBits) === -1) { + throw new TypeError(`Invalid "databits": ${settings.dataBits}`); + } + + if (STOPBITS.indexOf(settings.stopBits) === -1) { + throw new TypeError(`Invalid "stopbits": ${settings.stopBits}`); + } + + if (PARITY.indexOf(settings.parity) === -1) { + throw new TypeError(`Invalid "parity": ${settings.parity}`); + } + + FLOWCONTROLS.forEach((control) => { + if (typeof settings[control] !== 'boolean') { + throw new TypeError(`Invalid "${control}" is not boolean`); + } + }); + + settings.disconnectedCallback = this._disconnected.bind(this); + settings.dataCallback = settings.parser.bind(this, this); + + this.fd = null; + this.paused = true; + this.opening = false; + this.closing = false; + + if (process.platform !== 'win32') { + this.bufferSize = settings.bufferSize; + this.readable = true; + this.reading = false; + } + + this.options = settings; + + if (this.options.autoOpen) { + // is nextTick necessary? + process.nextTick(this.open.bind(this, callback)); + } +} + +util.inherits(SerialPort, stream.Stream); + +SerialPort.prototype._error = function(error, callback) { + if (callback) { + callback.call(this, error); + } else { + this.emit('error', error); + } +}; + +SerialPort.prototype.open = function(callback) { + if (this.isOpen()) { + return this._error(new Error('Port is already open'), callback); + } + + if (this.opening) { + return this._error(new Error('Port is opening'), callback); + } + + this.paused = true; + this.readable = true; + this.reading = false; + this.opening = true; + + SerialPortBinding.open(this.path, this.options, (err, fd) => { + this.opening = false; + if (err) { + debug('SerialPortBinding.open had an error', err); + return this._error(err, callback); + } + this.fd = fd; + this.paused = false; + + if (process.platform !== 'win32') { + this.serialPoller = new SerialPortBinding.SerialportPoller(this.fd, (err) => { + if (!err) { + this._read(); + } else { + this._disconnected(err); + } + }); + this.serialPoller.start(); + } + + this.emit('open'); + if (callback) { + callback.call(this, null); + } + }); +}; + +SerialPort.prototype.update = function(options, callback) { + if (!this.isOpen()) { + debug('update attempted, but port is not open'); + return this._error(new Error('Port is not open'), callback); + } + + var correctedOptions = correctOptions(options); + var settings = Object.assign({}, defaultSettings, correctedOptions); + this.options.baudRate = settings.baudRate; + + SerialPortBinding.update(this.fd, this.options, (err) => { + if (err) { + return this._error(err, callback); + } + if (callback) { + callback.call(this, null); + } + }); +}; + +SerialPort.prototype.isOpen = function() { + return this.fd !== null && !this.closing; +}; + +SerialPort.prototype.write = function(buffer, ending, callback) { + if (!this.isOpen()) { + debug('write attempted, but port is not open'); + return this._error(new Error('Port is not open'), callback); + } + + if (!Buffer.isBuffer(buffer)) { + buffer = Buffer.from(buffer); + } + + switch (ending) { + case 'Newline': + buffer = Buffer.concat([buffer, Buffer.from('\n')]); + break; + case 'Carriage return': + buffer = Buffer.concat([buffer, Buffer.from('\r')]); + break; + case 'Both NL & CR': + buffer = Buffer.concat([buffer, Buffer.from('\r\n')]); + break; + default: + break; + } + + debug(`write ${buffer.length} bytes of data`); + SerialPortBinding.write(this.fd, buffer, (err) => { + if (err) { + debug('SerialPortBinding.write had an error', err); + return this._error(err, callback); + } + if (callback) { + callback.call(this, null); + } + }); +}; + +if (process.platform !== 'win32') { + SerialPort.prototype._read = function() { + if (!this.readable || this.paused || this.reading || this.closing) { + return; + } + + this.reading = true; + + if (!this.pool || this.pool.length - this.pool.used < kMinPoolSpace) { + // discard the old pool. Can't add to the free list because + // users might have references to slices on it. + this.pool = Buffer.alloc(kPoolSize); + this.pool.used = 0; + } + + // Grab another reference to the pool in the case that while we're in the + // thread pool another read() finishes up the pool, and allocates a new + // one. + var toRead = Math.min(this.pool.length - this.pool.used, ~~this.bufferSize); + var start = this.pool.used; + + var _afterRead = (err, bytesRead, readPool, bytesRequested) => { + this.reading = false; + if (err) { + if (err.code && err.code === 'EAGAIN') { + if (this.isOpen()) { + this.serialPoller.start(); + } + // handle edge case were mac/unix doesn't clearly know the error. + } else if (err.code && (err.code === 'EBADF' || err.code === 'ENXIO' || (err.errno === -1 || err.code === 'UNKNOWN'))) { + this._disconnected(err); + } else { + this.fd = null; + this.readable = false; + this.emit('error', err); + } + return; + } + + // Since we will often not read the number of bytes requested, + // let's mark the ones we didn't need as available again. + this.pool.used -= bytesRequested - bytesRead; + + if (bytesRead === 0) { + if (this.isOpen()) { + this.serialPoller.start(); + } + } else { + var b = this.pool.slice(start, start + bytesRead); + + // do not emit events if the stream is paused + if (this.paused) { + if (!this.buffer) { + this.buffer = Buffer.alloc(0); + } + this.buffer = Buffer.concat([this.buffer, b]); + return; + } + this._emitData(b); + + // do not emit events anymore after we declared the stream unreadable + if (!this.readable) { + return; + } + this._read(); + } + }; + + fs.read(this.fd, this.pool, this.pool.used, toRead, null, (err, bytesRead) => { + var readPool = this.pool; + var bytesRequested = toRead; + _afterRead(err, bytesRead, readPool, bytesRequested); + }); + + this.pool.used += toRead; + }; + + SerialPort.prototype._emitData = function(data) { + this.options.dataCallback(data); + }; + + SerialPort.prototype.pause = function() { + this.paused = true; + }; + + SerialPort.prototype.resume = function() { + this.paused = false; + + if (this.buffer) { + var buffer = this.buffer; + this.buffer = null; + this._emitData(buffer); + } + + // No longer open? + if (!this.isOpen()) { + return; + } + + this._read(); + }; +} // if !'win32' + +SerialPort.prototype._disconnected = function(err) { + this.paused = true; + this.emit('disconnect', err); + if (this.closing) { + return; + } + + if (this.fd === null) { + return; + } + + this.closing = true; + if (process.platform !== 'win32') { + this.readable = false; + this.serialPoller.close(); + } + + SerialPortBinding.close(this.fd, (err) => { + this.closing = false; + if (err) { + debug('Disconnect close completed with error: ', err); + } + this.fd = null; + this.emit('close'); + }); +}; + +SerialPort.prototype.close = function(callback) { + this.paused = true; + + if (this.closing) { + debug('close attempted, but port is already closing'); + return this._error(new Error('Port is not open'), callback); + } + + if (!this.isOpen()) { + debug('close attempted, but port is not open'); + return this._error(new Error('Port is not open'), callback); + } + + this.closing = true; + + // Stop polling before closing the port. + if (process.platform !== 'win32') { + this.readable = false; + this.serialPoller.close(); + } + SerialPortBinding.close(this.fd, (err) => { + this.closing = false; + if (err) { + debug('SerialPortBinding.close had an error', err); + return this._error(err, callback); + } + + this.fd = null; + this.emit('close'); + if (callback) { + callback.call(this, null); + } + }); +}; + +SerialPort.prototype.flush = function(callback) { + if (!this.isOpen()) { + debug('flush attempted, but port is not open'); + return this._error(new Error('Port is not open'), callback); + } + + SerialPortBinding.flush(this.fd, (err, result) => { + if (err) { + debug('SerialPortBinding.flush had an error', err); + return this._error(err, callback); + } + if (callback) { + callback.call(this, null, result); + } + }); +}; + +SerialPort.prototype.set = function(options, callback) { + if (!this.isOpen()) { + debug('set attempted, but port is not open'); + return this._error(new Error('Port is not open'), callback); + } + + options = options || {}; + if (!callback && typeof options === 'function') { + callback = options; + options = {}; + } + + var settings = {}; + for (var i = SET_OPTIONS.length - 1; i >= 0; i--) { + var flag = SET_OPTIONS[i]; + if (options[flag] !== undefined) { + settings[flag] = options[flag]; + } else { + settings[flag] = defaultSetFlags[flag]; + } + } + + SerialPortBinding.set(this.fd, settings, (err) => { + if (err) { + debug('SerialPortBinding.set had an error', err); + return this._error(err, callback); + } + if (callback) { + callback.call(this, null); + } + }); +}; + +SerialPort.prototype.drain = function(callback) { + if (!this.isOpen()) { + debug('drain attempted, but port is not open'); + return this._error(new Error('Port is not open'), callback); + } + + SerialPortBinding.drain(this.fd, (err) => { + if (err) { + debug('SerialPortBinding.drain had an error', err); + return this._error(err, callback); + } + if (callback) { + callback.call(this, null); + } + }); +}; + +SerialPort.parsers = parsers; +SerialPort.list = SerialPortBinding.list; + +// Write a depreciation warning once +Object.defineProperty(SerialPort, 'SerialPort', { + get: function() { + // console.warn('DEPRECATION: Please use `require(\'serialport\')` instead of `require(\'serialport\').SerialPort`'); + Object.defineProperty(SerialPort, 'SerialPort', { + value: SerialPort + }); + return SerialPort; + }, + configurable: true +}); + +module.exports = SerialPort; diff --git a/vendor/node-usb-native/license b/vendor/node-usb-native/license index 8cff664c4..4322c5ab6 100644 --- a/vendor/node-usb-native/license +++ b/vendor/node-usb-native/license @@ -1,19 +1,19 @@ -Copyright (c) 2013 Kaba AG - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Copyright (c) 2013 Kaba AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/node-usb-native/package.json b/vendor/node-usb-native/package.json index c62428c71..7779f1140 100644 --- a/vendor/node-usb-native/package.json +++ b/vendor/node-usb-native/package.json @@ -1,34 +1,34 @@ -{ - "name": "usb-native", - "version": "0.0.1", - "description": "node-usb && node-serialport combined.", - "main": "lib/index.js", - "gypfile": true, - "keywords": [ - "usb", - "device", - "hardware", - "list", - "insert", - "add", - "remove", - "change", - "plug", - "unplug", - "notification" - ], - "license": "MIT", - "scripts": { - "install": "node-gyp rebuild --target=1.6.6 --arch=x64 --dist-url=https://atom.io/download/electron" - }, - "dependencies": { - "eventemitter2": "^4.1.0" - }, - "devDependencies": { - "chai": "^3.0.0", - "chai-as-promised": "^5.1.0", - "chalk": "^1.0.0", - "mocha": "^2.2.5", - "nan": "^2.12.1" - } +{ + "name": "usb-native", + "version": "0.0.1", + "description": "node-usb && node-serialport combined.", + "main": "lib/index.js", + "gypfile": true, + "keywords": [ + "usb", + "device", + "hardware", + "list", + "insert", + "add", + "remove", + "change", + "plug", + "unplug", + "notification" + ], + "license": "MIT", + "scripts": { + "install": "node-gyp rebuild --target=1.6.6 --arch=x64 --dist-url=https://atom.io/download/electron" + }, + "dependencies": { + "eventemitter2": "^4.1.0" + }, + "devDependencies": { + "chai": "^3.0.0", + "chai-as-promised": "^5.1.0", + "chalk": "^1.0.0", + "mocha": "^2.2.5", + "nan": "^2.12.1" + } } \ No newline at end of file diff --git a/vendor/node-usb-native/src/combined.cpp b/vendor/node-usb-native/src/combined.cpp index a7f4cc0ff..28c3ec526 100644 --- a/vendor/node-usb-native/src/combined.cpp +++ b/vendor/node-usb-native/src/combined.cpp @@ -1,24 +1,24 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern "C" { - void init_serialport(v8::Handle target); -#ifndef DISABLE_USB_DETECTOR - void init_detector(v8::Handle target); -#endif - void initAll(v8::Handle target) { - init_serialport(target); - #ifndef DISABLE_USB_DETECTOR - init_detector(target); - #endif - } -} - -NODE_MODULE(detection, initAll); +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { + void init_serialport( v8::Local target); +#ifndef DISABLE_USB_DETECTOR + void init_detector( v8::Local target); +#endif + void initAll( v8::Local target) { + init_serialport(target); + #ifndef DISABLE_USB_DETECTOR + init_detector(target); + #endif + } +} + +NODE_MODULE(detection, initAll); diff --git a/vendor/node-usb-native/src/detection.cpp b/vendor/node-usb-native/src/detection.cpp index 5a16729f7..13f7bdc6a 100644 --- a/vendor/node-usb-native/src/detection.cpp +++ b/vendor/node-usb-native/src/detection.cpp @@ -1,222 +1,222 @@ -#include "detection.h" - - -#define OBJECT_ITEM_LOCATION_ID "locationId" -#define OBJECT_ITEM_VENDOR_ID "vendorId" -#define OBJECT_ITEM_PRODUCT_ID "productId" -#define OBJECT_ITEM_DEVICE_NAME "deviceName" -#define OBJECT_ITEM_MANUFACTURER "manufacturer" -#define OBJECT_ITEM_SERIAL_NUMBER "serialNumber" -#define OBJECT_ITEM_DEVICE_ADDRESS "deviceAddress" - - -Nan::Callback* addedCallback; -bool isAddedRegistered = false; - -Nan::Callback* removedCallback; -bool isRemovedRegistered = false; - -void RegisterAdded(const Nan::FunctionCallbackInfo& args) { - Nan::HandleScope scope; - - v8::Local callback; - - if (args.Length() == 0) { - return Nan::ThrowTypeError("First argument must be a function"); - } - - if (args.Length() == 1) { - // callback - if(!args[0]->IsFunction()) { - return Nan::ThrowTypeError("First argument must be a function"); - } - - callback = args[0].As(); - } - - addedCallback = new Nan::Callback(callback); - isAddedRegistered = true; -} - -void NotifyAdded(ListResultItem_t* it) { - Nan::HandleScope scope; - - if (it == NULL) { - return; - } - - if (isAddedRegistered){ - v8::Local argv[1]; - v8::Local item = Nan::New(); - item->Set(Nan::New(OBJECT_ITEM_LOCATION_ID).ToLocalChecked(), Nan::New(it->locationId)); - item->Set(Nan::New(OBJECT_ITEM_VENDOR_ID).ToLocalChecked(), Nan::New(it->vendorId)); - item->Set(Nan::New(OBJECT_ITEM_PRODUCT_ID).ToLocalChecked(), Nan::New(it->productId)); - item->Set(Nan::New(OBJECT_ITEM_DEVICE_NAME).ToLocalChecked(), Nan::New(it->deviceName.c_str()).ToLocalChecked()); - item->Set(Nan::New(OBJECT_ITEM_MANUFACTURER).ToLocalChecked(), Nan::New(it->manufacturer.c_str()).ToLocalChecked()); - item->Set(Nan::New(OBJECT_ITEM_SERIAL_NUMBER).ToLocalChecked(), Nan::New(it->serialNumber.c_str()).ToLocalChecked()); - item->Set(Nan::New(OBJECT_ITEM_DEVICE_ADDRESS).ToLocalChecked(), Nan::New(it->deviceAddress)); - argv[0] = item; - - addedCallback->Call(1, argv); - } -} - -void RegisterRemoved(const Nan::FunctionCallbackInfo& args) { - Nan::HandleScope scope; - - v8::Local callback; - - if (args.Length() == 0) { - return Nan::ThrowTypeError("First argument must be a function"); - } - - if (args.Length() == 1) { - // callback - if(!args[0]->IsFunction()) { - return Nan::ThrowTypeError("First argument must be a function"); - } - - callback = args[0].As(); - } - - removedCallback = new Nan::Callback(callback); - isRemovedRegistered = true; -} - -void NotifyRemoved(ListResultItem_t* it) { - Nan::HandleScope scope; - - if (it == NULL) { - return; - } - - if (isRemovedRegistered) { - v8::Local argv[1]; - v8::Local item = Nan::New(); - item->Set(Nan::New(OBJECT_ITEM_LOCATION_ID).ToLocalChecked(), Nan::New(it->locationId)); - item->Set(Nan::New(OBJECT_ITEM_VENDOR_ID).ToLocalChecked(), Nan::New(it->vendorId)); - item->Set(Nan::New(OBJECT_ITEM_PRODUCT_ID).ToLocalChecked(), Nan::New(it->productId)); - item->Set(Nan::New(OBJECT_ITEM_DEVICE_NAME).ToLocalChecked(), Nan::New(it->deviceName.c_str()).ToLocalChecked()); - item->Set(Nan::New(OBJECT_ITEM_MANUFACTURER).ToLocalChecked(), Nan::New(it->manufacturer.c_str()).ToLocalChecked()); - item->Set(Nan::New(OBJECT_ITEM_SERIAL_NUMBER).ToLocalChecked(), Nan::New(it->serialNumber.c_str()).ToLocalChecked()); - item->Set(Nan::New(OBJECT_ITEM_DEVICE_ADDRESS).ToLocalChecked(), Nan::New(it->deviceAddress)); - argv[0] = item; - - removedCallback->Call(1, argv); - } -} - -void Find(const Nan::FunctionCallbackInfo& args) { - Nan::HandleScope scope; - - int vid = 0; - int pid = 0; - v8::Local callback; - - if (args.Length() == 0) { - return Nan::ThrowTypeError("First argument must be a function"); - } - - if (args.Length() == 3) { - if (args[0]->IsNumber() && args[1]->IsNumber()) { - vid = (int) args[0]->NumberValue(); - pid = (int) args[1]->NumberValue(); - } - - // callback - if(!args[2]->IsFunction()) { - return Nan::ThrowTypeError("Third argument must be a function"); - } - - callback = args[2].As(); - } - - if (args.Length() == 2) { - if (args[0]->IsNumber()) { - vid = (int) args[0]->NumberValue(); - } - - // callback - if(!args[1]->IsFunction()) { - return Nan::ThrowTypeError("Second argument must be a function"); - } - - callback = args[1].As(); - } - - if (args.Length() == 1) { - // callback - if(!args[0]->IsFunction()) { - return Nan::ThrowTypeError("First argument must be a function"); - } - - callback = args[0].As(); - } - - ListBaton* baton = new ListBaton(); - strcpy(baton->errorString, ""); - baton->callback = new Nan::Callback(callback); - baton->vid = vid; - baton->pid = pid; - - uv_work_t* req = new uv_work_t(); - req->data = baton; - uv_queue_work(uv_default_loop(), req, EIO_Find, (uv_after_work_cb)EIO_AfterFind); -} - -void EIO_AfterFind(uv_work_t* req) { - Nan::HandleScope scope; - - ListBaton* data = static_cast(req->data); - - v8::Local argv[2]; - if(data->errorString[0]) { - argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); - argv[1] = Nan::Undefined(); - } - else { - v8::Local results = Nan::New(); - int i = 0; - for(std::list::iterator it = data->results.begin(); it != data->results.end(); it++, i++) { - v8::Local item = Nan::New(); - item->Set(Nan::New(OBJECT_ITEM_LOCATION_ID).ToLocalChecked(), Nan::New((*it)->locationId)); - item->Set(Nan::New(OBJECT_ITEM_VENDOR_ID).ToLocalChecked(), Nan::New((*it)->vendorId)); - item->Set(Nan::New(OBJECT_ITEM_PRODUCT_ID).ToLocalChecked(), Nan::New((*it)->productId)); - item->Set(Nan::New(OBJECT_ITEM_DEVICE_NAME).ToLocalChecked(), Nan::New((*it)->deviceName.c_str()).ToLocalChecked()); - item->Set(Nan::New(OBJECT_ITEM_MANUFACTURER).ToLocalChecked(), Nan::New((*it)->manufacturer.c_str()).ToLocalChecked()); - item->Set(Nan::New(OBJECT_ITEM_SERIAL_NUMBER).ToLocalChecked(), Nan::New((*it)->serialNumber.c_str()).ToLocalChecked()); - item->Set(Nan::New(OBJECT_ITEM_DEVICE_ADDRESS).ToLocalChecked(), Nan::New((*it)->deviceAddress)); - results->Set(i, item); - } - argv[0] = Nan::Undefined(); - argv[1] = results; - } - - data->callback->Call(2, argv); - - for(std::list::iterator it = data->results.begin(); it != data->results.end(); it++) { - delete *it; - } - delete data; - delete req; -} - -void StartMonitoring(const Nan::FunctionCallbackInfo& args) { - Start(); -} - -void StopMonitoring(const Nan::FunctionCallbackInfo& args) { - Stop(); -} - -extern "C" { - void init_detector (v8::Handle target) { - Nan::SetMethod(target, "find", Find); - Nan::SetMethod(target, "registerAdded", RegisterAdded); - Nan::SetMethod(target, "registerRemoved", RegisterRemoved); - Nan::SetMethod(target, "startMonitoring", StartMonitoring); - Nan::SetMethod(target, "stopMonitoring", StopMonitoring); - InitDetection(); - - } +#include "detection.h" + + +#define OBJECT_ITEM_LOCATION_ID "locationId" +#define OBJECT_ITEM_VENDOR_ID "vendorId" +#define OBJECT_ITEM_PRODUCT_ID "productId" +#define OBJECT_ITEM_DEVICE_NAME "deviceName" +#define OBJECT_ITEM_MANUFACTURER "manufacturer" +#define OBJECT_ITEM_SERIAL_NUMBER "serialNumber" +#define OBJECT_ITEM_DEVICE_ADDRESS "deviceAddress" + + +Nan::Callback* addedCallback; +bool isAddedRegistered = false; + +Nan::Callback* removedCallback; +bool isRemovedRegistered = false; + +void RegisterAdded(const Nan::FunctionCallbackInfo& args) { + Nan::HandleScope scope; + + v8::Local callback; + + if (args.Length() == 0) { + return Nan::ThrowTypeError("First argument must be a function"); + } + + if (args.Length() == 1) { + // callback + if(!args[0]->IsFunction()) { + return Nan::ThrowTypeError("First argument must be a function"); + } + + callback = args[0].As(); + } + + addedCallback = new Nan::Callback(callback); + isAddedRegistered = true; +} + +void NotifyAdded(ListResultItem_t* it) { + Nan::HandleScope scope; + + if (it == NULL) { + return; + } + + if (isAddedRegistered){ + v8::Local argv[1]; + v8::Local item = Nan::New(); + item->Set(Nan::New(OBJECT_ITEM_LOCATION_ID).ToLocalChecked(), Nan::New(it->locationId)); + item->Set(Nan::New(OBJECT_ITEM_VENDOR_ID).ToLocalChecked(), Nan::New(it->vendorId)); + item->Set(Nan::New(OBJECT_ITEM_PRODUCT_ID).ToLocalChecked(), Nan::New(it->productId)); + item->Set(Nan::New(OBJECT_ITEM_DEVICE_NAME).ToLocalChecked(), Nan::New(it->deviceName.c_str()).ToLocalChecked()); + item->Set(Nan::New(OBJECT_ITEM_MANUFACTURER).ToLocalChecked(), Nan::New(it->manufacturer.c_str()).ToLocalChecked()); + item->Set(Nan::New(OBJECT_ITEM_SERIAL_NUMBER).ToLocalChecked(), Nan::New(it->serialNumber.c_str()).ToLocalChecked()); + item->Set(Nan::New(OBJECT_ITEM_DEVICE_ADDRESS).ToLocalChecked(), Nan::New(it->deviceAddress)); + argv[0] = item; + + addedCallback->Call(1, argv); + } +} + +void RegisterRemoved(const Nan::FunctionCallbackInfo& args) { + Nan::HandleScope scope; + + v8::Local callback; + + if (args.Length() == 0) { + return Nan::ThrowTypeError("First argument must be a function"); + } + + if (args.Length() == 1) { + // callback + if(!args[0]->IsFunction()) { + return Nan::ThrowTypeError("First argument must be a function"); + } + + callback = args[0].As(); + } + + removedCallback = new Nan::Callback(callback); + isRemovedRegistered = true; +} + +void NotifyRemoved(ListResultItem_t* it) { + Nan::HandleScope scope; + + if (it == NULL) { + return; + } + + if (isRemovedRegistered) { + v8::Local argv[1]; + v8::Local item = Nan::New(); + item->Set(Nan::New(OBJECT_ITEM_LOCATION_ID).ToLocalChecked(), Nan::New(it->locationId)); + item->Set(Nan::New(OBJECT_ITEM_VENDOR_ID).ToLocalChecked(), Nan::New(it->vendorId)); + item->Set(Nan::New(OBJECT_ITEM_PRODUCT_ID).ToLocalChecked(), Nan::New(it->productId)); + item->Set(Nan::New(OBJECT_ITEM_DEVICE_NAME).ToLocalChecked(), Nan::New(it->deviceName.c_str()).ToLocalChecked()); + item->Set(Nan::New(OBJECT_ITEM_MANUFACTURER).ToLocalChecked(), Nan::New(it->manufacturer.c_str()).ToLocalChecked()); + item->Set(Nan::New(OBJECT_ITEM_SERIAL_NUMBER).ToLocalChecked(), Nan::New(it->serialNumber.c_str()).ToLocalChecked()); + item->Set(Nan::New(OBJECT_ITEM_DEVICE_ADDRESS).ToLocalChecked(), Nan::New(it->deviceAddress)); + argv[0] = item; + + removedCallback->Call(1, argv); + } +} + +void Find(const Nan::FunctionCallbackInfo& args) { + Nan::HandleScope scope; + + int vid = 0; + int pid = 0; + v8::Local callback; + + if (args.Length() == 0) { + return Nan::ThrowTypeError("First argument must be a function"); + } + + if (args.Length() == 3) { + if (args[0]->IsNumber() && args[1]->IsNumber()) { + vid = (int) args[0]->NumberValue(); + pid = (int) args[1]->NumberValue(); + } + + // callback + if(!args[2]->IsFunction()) { + return Nan::ThrowTypeError("Third argument must be a function"); + } + + callback = args[2].As(); + } + + if (args.Length() == 2) { + if (args[0]->IsNumber()) { + vid = (int) args[0]->NumberValue(); + } + + // callback + if(!args[1]->IsFunction()) { + return Nan::ThrowTypeError("Second argument must be a function"); + } + + callback = args[1].As(); + } + + if (args.Length() == 1) { + // callback + if(!args[0]->IsFunction()) { + return Nan::ThrowTypeError("First argument must be a function"); + } + + callback = args[0].As(); + } + + ListBaton* baton = new ListBaton(); + strcpy(baton->errorString, ""); + baton->callback = new Nan::Callback(callback); + baton->vid = vid; + baton->pid = pid; + + uv_work_t* req = new uv_work_t(); + req->data = baton; + uv_queue_work(uv_default_loop(), req, EIO_Find, (uv_after_work_cb)EIO_AfterFind); +} + +void EIO_AfterFind(uv_work_t* req) { + Nan::HandleScope scope; + + ListBaton* data = static_cast(req->data); + + v8::Local argv[2]; + if(data->errorString[0]) { + argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); + argv[1] = Nan::Undefined(); + } + else { + v8::Local results = Nan::New(); + int i = 0; + for(std::list::iterator it = data->results.begin(); it != data->results.end(); it++, i++) { + v8::Local item = Nan::New(); + item->Set(Nan::New(OBJECT_ITEM_LOCATION_ID).ToLocalChecked(), Nan::New((*it)->locationId)); + item->Set(Nan::New(OBJECT_ITEM_VENDOR_ID).ToLocalChecked(), Nan::New((*it)->vendorId)); + item->Set(Nan::New(OBJECT_ITEM_PRODUCT_ID).ToLocalChecked(), Nan::New((*it)->productId)); + item->Set(Nan::New(OBJECT_ITEM_DEVICE_NAME).ToLocalChecked(), Nan::New((*it)->deviceName.c_str()).ToLocalChecked()); + item->Set(Nan::New(OBJECT_ITEM_MANUFACTURER).ToLocalChecked(), Nan::New((*it)->manufacturer.c_str()).ToLocalChecked()); + item->Set(Nan::New(OBJECT_ITEM_SERIAL_NUMBER).ToLocalChecked(), Nan::New((*it)->serialNumber.c_str()).ToLocalChecked()); + item->Set(Nan::New(OBJECT_ITEM_DEVICE_ADDRESS).ToLocalChecked(), Nan::New((*it)->deviceAddress)); + results->Set(i, item); + } + argv[0] = Nan::Undefined(); + argv[1] = results; + } + + data->callback->Call(2, argv); + + for(std::list::iterator it = data->results.begin(); it != data->results.end(); it++) { + delete *it; + } + delete data; + delete req; +} + +void StartMonitoring(const Nan::FunctionCallbackInfo& args) { + Start(); +} + +void StopMonitoring(const Nan::FunctionCallbackInfo& args) { + Stop(); +} + +extern "C" { + void init_detector ( v8::Local target) { + Nan::SetMethod(target, "find", Find); + Nan::SetMethod(target, "registerAdded", RegisterAdded); + Nan::SetMethod(target, "registerRemoved", RegisterRemoved); + Nan::SetMethod(target, "startMonitoring", StartMonitoring); + Nan::SetMethod(target, "stopMonitoring", StopMonitoring); + InitDetection(); + + } } \ No newline at end of file diff --git a/vendor/node-usb-native/src/detection.h b/vendor/node-usb-native/src/detection.h index 39b21c735..dbcf672cd 100644 --- a/vendor/node-usb-native/src/detection.h +++ b/vendor/node-usb-native/src/detection.h @@ -1,42 +1,42 @@ - -#ifndef _USB_DETECTION_H -#define _USB_DETECTION_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "deviceList.h" - -void Find(const Nan::FunctionCallbackInfo& args); -void EIO_Find(uv_work_t* req); -void EIO_AfterFind(uv_work_t* req); -void InitDetection(); -void StartMonitoring(const Nan::FunctionCallbackInfo& args); -void Start(); -void StopMonitoring(const Nan::FunctionCallbackInfo& args); -void Stop(); - - -struct ListBaton { - public: - //v8::Persistent callback; - Nan::Callback* callback; - std::list results; - char errorString[1024]; - int vid; - int pid; -}; - -void RegisterAdded(const Nan::FunctionCallbackInfo& args); -void NotifyAdded(ListResultItem_t* it); -void RegisterRemoved(const Nan::FunctionCallbackInfo& args); -void NotifyRemoved(ListResultItem_t* it); - -#endif + +#ifndef _USB_DETECTION_H +#define _USB_DETECTION_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "deviceList.h" + +void Find(const Nan::FunctionCallbackInfo& args); +void EIO_Find(uv_work_t* req); +void EIO_AfterFind(uv_work_t* req); +void InitDetection(); +void StartMonitoring(const Nan::FunctionCallbackInfo& args); +void Start(); +void StopMonitoring(const Nan::FunctionCallbackInfo& args); +void Stop(); + + +struct ListBaton { + public: + //v8::Persistent callback; + Nan::Callback* callback; + std::list results; + char errorString[1024]; + int vid; + int pid; +}; + +void RegisterAdded(const Nan::FunctionCallbackInfo& args); +void NotifyAdded(ListResultItem_t* it); +void RegisterRemoved(const Nan::FunctionCallbackInfo& args); +void NotifyRemoved(ListResultItem_t* it); + +#endif diff --git a/vendor/node-usb-native/src/detection_linux.cpp b/vendor/node-usb-native/src/detection_linux.cpp index aaa618f72..4c23877ce 100644 --- a/vendor/node-usb-native/src/detection_linux.cpp +++ b/vendor/node-usb-native/src/detection_linux.cpp @@ -1,317 +1,317 @@ -#include -#include - -#include "detection.h" -#include "deviceList.h" - -using namespace std; - - - -/********************************** - * Local defines - **********************************/ -#define DEVICE_ACTION_ADDED "add" -#define DEVICE_ACTION_REMOVED "remove" - -#define DEVICE_TYPE_DEVICE "usb_device" - -#define DEVICE_PROPERTY_NAME "ID_MODEL" -#define DEVICE_PROPERTY_SERIAL "ID_SERIAL_SHORT" -#define DEVICE_PROPERTY_VENDOR "ID_VENDOR" - - -/********************************** - * Local typedefs - **********************************/ - - - -/********************************** - * Local Variables - **********************************/ -ListResultItem_t* currentItem; -bool isAdded; - -struct udev *udev; -struct udev_enumerate *enumerate; -struct udev_list_entry *devices, *dev_list_entry; -struct udev_device *dev; - -struct udev_monitor *mon; -int fd; - -pthread_t thread; -pthread_mutex_t notify_mutex; -pthread_cond_t notifyNewDevice; -pthread_cond_t notifyDeviceHandled; - -bool newDeviceAvailable = false; -bool deviceHandled = true; - -bool isRunning = false; -/********************************** - * Local Helper Functions protoypes - **********************************/ -void BuildInitialDeviceList(); - -void* ThreadFunc(void* ptr); -void WaitForDeviceHandled(); -void SignalDeviceHandled(); -void WaitForNewDevice(); -void SignalDeviceAvailable(); - -/********************************** - * Public Functions - **********************************/ -void NotifyAsync(uv_work_t* req) { - WaitForNewDevice(); -} - -void NotifyFinished(uv_work_t* req) { - if (isRunning) { - if (isAdded) { - NotifyAdded(currentItem); - } - else { - NotifyRemoved(currentItem); - } - } - - // Delete Item in case of removal - if(isAdded == false) { - delete currentItem; - } - - SignalDeviceHandled(); - uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); -} - -void Start() { - isRunning = true; -} - -void Stop() { - isRunning = false; - pthread_mutex_lock(¬ify_mutex); - pthread_cond_signal(¬ifyNewDevice); - pthread_mutex_unlock(¬ify_mutex); -} - -void InitDetection() { - /* Create the udev object */ - udev = udev_new(); - if (!udev) - { - printf("Can't create udev\n"); - return; - } - - /* Set up a monitor to monitor devices */ - mon = udev_monitor_new_from_netlink(udev, "udev"); - udev_monitor_enable_receiving(mon); - - /* Get the file descriptor (fd) for the monitor. - This fd will get passed to select() */ - fd = udev_monitor_get_fd(mon); - - BuildInitialDeviceList(); - - pthread_mutex_init(¬ify_mutex, NULL); - pthread_cond_init(¬ifyNewDevice, NULL); - pthread_cond_init(¬ifyDeviceHandled, NULL); - - uv_work_t* req = new uv_work_t(); - uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); - - pthread_create(&thread, NULL, ThreadFunc, NULL); - - Start(); -} - - -void EIO_Find(uv_work_t* req) { - ListBaton* data = static_cast(req->data); - - CreateFilteredList(&data->results, data->vid, data->pid); -} - -/********************************** - * Local Functions - **********************************/ -void WaitForDeviceHandled() { - pthread_mutex_lock(¬ify_mutex); - if(deviceHandled == false) { - pthread_cond_wait(¬ifyDeviceHandled, ¬ify_mutex); - } - deviceHandled = false; - pthread_mutex_unlock(¬ify_mutex); -} - -void SignalDeviceHandled() { - pthread_mutex_lock(¬ify_mutex); - deviceHandled = true; - pthread_cond_signal(¬ifyDeviceHandled); - pthread_mutex_unlock(¬ify_mutex); -} - -void WaitForNewDevice() { - pthread_mutex_lock(¬ify_mutex); - if(newDeviceAvailable == false){ - pthread_cond_wait(¬ifyNewDevice, ¬ify_mutex); - } - newDeviceAvailable = false; - pthread_mutex_unlock(¬ify_mutex); -} - -void SignalDeviceAvailable() { - pthread_mutex_lock(¬ify_mutex); - newDeviceAvailable = true; - pthread_cond_signal(¬ifyNewDevice); - pthread_mutex_unlock(¬ify_mutex); -} - - - ListResultItem_t* GetProperties(struct udev_device* dev, ListResultItem_t* item) { - struct udev_list_entry* sysattrs; - struct udev_list_entry* entry; - sysattrs = udev_device_get_properties_list_entry(dev); - udev_list_entry_foreach(entry, sysattrs) { - const char *name, *value; - name = udev_list_entry_get_name(entry); - value = udev_list_entry_get_value(entry); - - if(strcmp(name, DEVICE_PROPERTY_NAME) == 0) { - item->deviceName = value; - } - else if(strcmp(name, DEVICE_PROPERTY_SERIAL) == 0) { - item->serialNumber = value; - } - else if(strcmp(name, DEVICE_PROPERTY_VENDOR) == 0) { - item->manufacturer = value; - } - } - item->vendorId = strtol(udev_device_get_sysattr_value(dev,"idVendor"), NULL, 16); - item->productId = strtol(udev_device_get_sysattr_value(dev,"idProduct"), NULL, 16); - item->deviceAddress = 0; - item->locationId = 0; - - return item; -} - -void DeviceAdded(struct udev_device* dev) { - DeviceItem_t* item = new DeviceItem_t(); - GetProperties(dev, &item->deviceParams); - - AddItemToList((char *)udev_device_get_devnode(dev), item); - - currentItem = &item->deviceParams; - isAdded = true; - - SignalDeviceAvailable(); -} - -void DeviceRemoved(struct udev_device* dev) { - ListResultItem_t* item = NULL; - - if(IsItemAlreadyStored((char *)udev_device_get_devnode(dev))) { - DeviceItem_t* deviceItem = GetItemFromList((char *)udev_device_get_devnode(dev)); - if(deviceItem) { - item = CopyElement(&deviceItem->deviceParams); - } - RemoveItemFromList(deviceItem); - delete deviceItem; - } - - if(item == NULL) { - item = new ListResultItem_t(); - GetProperties(dev, item); - } - - currentItem = item; - isAdded = false; - - SignalDeviceAvailable(); -} - - -void* ThreadFunc(void* ptr) { - while (1) { - /* Make the call to receive the device. - select() ensured that this will not block. */ - dev = udev_monitor_receive_device(mon); - if (dev) { - if(udev_device_get_devtype(dev) && strcmp(udev_device_get_devtype(dev), DEVICE_TYPE_DEVICE) == 0) { - if(strcmp(udev_device_get_action(dev), DEVICE_ACTION_ADDED) == 0) { - WaitForDeviceHandled(); - DeviceAdded(dev); - } - else if(strcmp(udev_device_get_action(dev), DEVICE_ACTION_REMOVED) == 0) { - WaitForDeviceHandled(); - DeviceRemoved(dev); - } - } - udev_device_unref(dev); - } - } - - return NULL; -} - - -void BuildInitialDeviceList() { - /* Create a list of the devices */ - enumerate = udev_enumerate_new(udev); - udev_enumerate_scan_devices(enumerate); - devices = udev_enumerate_get_list_entry(enumerate); - /* For each item enumerated, print out its information. - udev_list_entry_foreach is a macro which expands to - a loop. The loop will be executed for each member in - devices, setting dev_list_entry to a list entry - which contains the device's path in /sys. */ - udev_list_entry_foreach(dev_list_entry, devices) { - const char *path; - - /* Get the filename of the /sys entry for the device - and create a udev_device object (dev) representing it */ - path = udev_list_entry_get_name(dev_list_entry); - dev = udev_device_new_from_syspath(udev, path); - - /* usb_device_get_devnode() returns the path to the device node - itself in /dev. */ - if(udev_device_get_devnode(dev) == NULL || udev_device_get_sysattr_value(dev,"idVendor") == NULL) { - continue; - } - - /* From here, we can call get_sysattr_value() for each file - in the device's /sys entry. The strings passed into these - functions (idProduct, idVendor, serial, etc.) correspond - directly to the files in the /sys directory which - represents the USB device. Note that USB strings are - Unicode, UCS2 encoded, but the strings returned from - udev_device_get_sysattr_value() are UTF-8 encoded. */ - - DeviceItem_t* item = new DeviceItem_t(); - item->deviceParams.vendorId = strtol (udev_device_get_sysattr_value(dev,"idVendor"), NULL, 16); - item->deviceParams.productId = strtol (udev_device_get_sysattr_value(dev,"idProduct"), NULL, 16); - if(udev_device_get_sysattr_value(dev,"product") != NULL) { - item->deviceParams.deviceName = udev_device_get_sysattr_value(dev,"product"); - } - if(udev_device_get_sysattr_value(dev,"manufacturer") != NULL) { - item->deviceParams.manufacturer = udev_device_get_sysattr_value(dev,"manufacturer"); - } - if(udev_device_get_sysattr_value(dev,"serial") != NULL) { - item->deviceParams.serialNumber = udev_device_get_sysattr_value(dev, "serial"); - } - item->deviceParams.deviceAddress = 0; - item->deviceParams.locationId = 0; - - item->deviceState = DeviceState_Connect; - - AddItemToList((char *)udev_device_get_devnode(dev), item); - - udev_device_unref(dev); - } - /* Free the enumerator object */ - udev_enumerate_unref(enumerate); -} +#include +#include + +#include "detection.h" +#include "deviceList.h" + +using namespace std; + + + +/********************************** + * Local defines + **********************************/ +#define DEVICE_ACTION_ADDED "add" +#define DEVICE_ACTION_REMOVED "remove" + +#define DEVICE_TYPE_DEVICE "usb_device" + +#define DEVICE_PROPERTY_NAME "ID_MODEL" +#define DEVICE_PROPERTY_SERIAL "ID_SERIAL_SHORT" +#define DEVICE_PROPERTY_VENDOR "ID_VENDOR" + + +/********************************** + * Local typedefs + **********************************/ + + + +/********************************** + * Local Variables + **********************************/ +ListResultItem_t* currentItem; +bool isAdded; + +struct udev *udev; +struct udev_enumerate *enumerate; +struct udev_list_entry *devices, *dev_list_entry; +struct udev_device *dev; + +struct udev_monitor *mon; +int fd; + +pthread_t thread; +pthread_mutex_t notify_mutex; +pthread_cond_t notifyNewDevice; +pthread_cond_t notifyDeviceHandled; + +bool newDeviceAvailable = false; +bool deviceHandled = true; + +bool isRunning = false; +/********************************** + * Local Helper Functions protoypes + **********************************/ +void BuildInitialDeviceList(); + +void* ThreadFunc(void* ptr); +void WaitForDeviceHandled(); +void SignalDeviceHandled(); +void WaitForNewDevice(); +void SignalDeviceAvailable(); + +/********************************** + * Public Functions + **********************************/ +void NotifyAsync(uv_work_t* req) { + WaitForNewDevice(); +} + +void NotifyFinished(uv_work_t* req) { + if (isRunning) { + if (isAdded) { + NotifyAdded(currentItem); + } + else { + NotifyRemoved(currentItem); + } + } + + // Delete Item in case of removal + if(isAdded == false) { + delete currentItem; + } + + SignalDeviceHandled(); + uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); +} + +void Start() { + isRunning = true; +} + +void Stop() { + isRunning = false; + pthread_mutex_lock(¬ify_mutex); + pthread_cond_signal(¬ifyNewDevice); + pthread_mutex_unlock(¬ify_mutex); +} + +void InitDetection() { + /* Create the udev object */ + udev = udev_new(); + if (!udev) + { + printf("Can't create udev\n"); + return; + } + + /* Set up a monitor to monitor devices */ + mon = udev_monitor_new_from_netlink(udev, "udev"); + udev_monitor_enable_receiving(mon); + + /* Get the file descriptor (fd) for the monitor. + This fd will get passed to select() */ + fd = udev_monitor_get_fd(mon); + + BuildInitialDeviceList(); + + pthread_mutex_init(¬ify_mutex, NULL); + pthread_cond_init(¬ifyNewDevice, NULL); + pthread_cond_init(¬ifyDeviceHandled, NULL); + + uv_work_t* req = new uv_work_t(); + uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); + + pthread_create(&thread, NULL, ThreadFunc, NULL); + + Start(); +} + + +void EIO_Find(uv_work_t* req) { + ListBaton* data = static_cast(req->data); + + CreateFilteredList(&data->results, data->vid, data->pid); +} + +/********************************** + * Local Functions + **********************************/ +void WaitForDeviceHandled() { + pthread_mutex_lock(¬ify_mutex); + if(deviceHandled == false) { + pthread_cond_wait(¬ifyDeviceHandled, ¬ify_mutex); + } + deviceHandled = false; + pthread_mutex_unlock(¬ify_mutex); +} + +void SignalDeviceHandled() { + pthread_mutex_lock(¬ify_mutex); + deviceHandled = true; + pthread_cond_signal(¬ifyDeviceHandled); + pthread_mutex_unlock(¬ify_mutex); +} + +void WaitForNewDevice() { + pthread_mutex_lock(¬ify_mutex); + if(newDeviceAvailable == false){ + pthread_cond_wait(¬ifyNewDevice, ¬ify_mutex); + } + newDeviceAvailable = false; + pthread_mutex_unlock(¬ify_mutex); +} + +void SignalDeviceAvailable() { + pthread_mutex_lock(¬ify_mutex); + newDeviceAvailable = true; + pthread_cond_signal(¬ifyNewDevice); + pthread_mutex_unlock(¬ify_mutex); +} + + + ListResultItem_t* GetProperties(struct udev_device* dev, ListResultItem_t* item) { + struct udev_list_entry* sysattrs; + struct udev_list_entry* entry; + sysattrs = udev_device_get_properties_list_entry(dev); + udev_list_entry_foreach(entry, sysattrs) { + const char *name, *value; + name = udev_list_entry_get_name(entry); + value = udev_list_entry_get_value(entry); + + if(strcmp(name, DEVICE_PROPERTY_NAME) == 0) { + item->deviceName = value; + } + else if(strcmp(name, DEVICE_PROPERTY_SERIAL) == 0) { + item->serialNumber = value; + } + else if(strcmp(name, DEVICE_PROPERTY_VENDOR) == 0) { + item->manufacturer = value; + } + } + item->vendorId = strtol(udev_device_get_sysattr_value(dev,"idVendor"), NULL, 16); + item->productId = strtol(udev_device_get_sysattr_value(dev,"idProduct"), NULL, 16); + item->deviceAddress = 0; + item->locationId = 0; + + return item; +} + +void DeviceAdded(struct udev_device* dev) { + DeviceItem_t* item = new DeviceItem_t(); + GetProperties(dev, &item->deviceParams); + + AddItemToList((char *)udev_device_get_devnode(dev), item); + + currentItem = &item->deviceParams; + isAdded = true; + + SignalDeviceAvailable(); +} + +void DeviceRemoved(struct udev_device* dev) { + ListResultItem_t* item = NULL; + + if(IsItemAlreadyStored((char *)udev_device_get_devnode(dev))) { + DeviceItem_t* deviceItem = GetItemFromList((char *)udev_device_get_devnode(dev)); + if(deviceItem) { + item = CopyElement(&deviceItem->deviceParams); + } + RemoveItemFromList(deviceItem); + delete deviceItem; + } + + if(item == NULL) { + item = new ListResultItem_t(); + GetProperties(dev, item); + } + + currentItem = item; + isAdded = false; + + SignalDeviceAvailable(); +} + + +void* ThreadFunc(void* ptr) { + while (1) { + /* Make the call to receive the device. + select() ensured that this will not block. */ + dev = udev_monitor_receive_device(mon); + if (dev) { + if(udev_device_get_devtype(dev) && strcmp(udev_device_get_devtype(dev), DEVICE_TYPE_DEVICE) == 0) { + if(strcmp(udev_device_get_action(dev), DEVICE_ACTION_ADDED) == 0) { + WaitForDeviceHandled(); + DeviceAdded(dev); + } + else if(strcmp(udev_device_get_action(dev), DEVICE_ACTION_REMOVED) == 0) { + WaitForDeviceHandled(); + DeviceRemoved(dev); + } + } + udev_device_unref(dev); + } + } + + return NULL; +} + + +void BuildInitialDeviceList() { + /* Create a list of the devices */ + enumerate = udev_enumerate_new(udev); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + /* For each item enumerated, print out its information. + udev_list_entry_foreach is a macro which expands to + a loop. The loop will be executed for each member in + devices, setting dev_list_entry to a list entry + which contains the device's path in /sys. */ + udev_list_entry_foreach(dev_list_entry, devices) { + const char *path; + + /* Get the filename of the /sys entry for the device + and create a udev_device object (dev) representing it */ + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(udev, path); + + /* usb_device_get_devnode() returns the path to the device node + itself in /dev. */ + if(udev_device_get_devnode(dev) == NULL || udev_device_get_sysattr_value(dev,"idVendor") == NULL) { + continue; + } + + /* From here, we can call get_sysattr_value() for each file + in the device's /sys entry. The strings passed into these + functions (idProduct, idVendor, serial, etc.) correspond + directly to the files in the /sys directory which + represents the USB device. Note that USB strings are + Unicode, UCS2 encoded, but the strings returned from + udev_device_get_sysattr_value() are UTF-8 encoded. */ + + DeviceItem_t* item = new DeviceItem_t(); + item->deviceParams.vendorId = strtol (udev_device_get_sysattr_value(dev,"idVendor"), NULL, 16); + item->deviceParams.productId = strtol (udev_device_get_sysattr_value(dev,"idProduct"), NULL, 16); + if(udev_device_get_sysattr_value(dev,"product") != NULL) { + item->deviceParams.deviceName = udev_device_get_sysattr_value(dev,"product"); + } + if(udev_device_get_sysattr_value(dev,"manufacturer") != NULL) { + item->deviceParams.manufacturer = udev_device_get_sysattr_value(dev,"manufacturer"); + } + if(udev_device_get_sysattr_value(dev,"serial") != NULL) { + item->deviceParams.serialNumber = udev_device_get_sysattr_value(dev, "serial"); + } + item->deviceParams.deviceAddress = 0; + item->deviceParams.locationId = 0; + + item->deviceState = DeviceState_Connect; + + AddItemToList((char *)udev_device_get_devnode(dev), item); + + udev_device_unref(dev); + } + /* Free the enumerator object */ + udev_enumerate_unref(enumerate); +} diff --git a/vendor/node-usb-native/src/detection_mac.cpp b/vendor/node-usb-native/src/detection_mac.cpp index 30f161cd1..bcdfbef31 100644 --- a/vendor/node-usb-native/src/detection_mac.cpp +++ b/vendor/node-usb-native/src/detection_mac.cpp @@ -1,461 +1,461 @@ -#include "detection.h" -#include "deviceList.h" - -#include - -#include -#include -#include -#include - -#include -#include - -#include - - -typedef struct DeviceListItem { - io_object_t notification; - IOUSBDeviceInterface** deviceInterface; - DeviceItem_t* deviceItem; -} stDeviceListItem; - -static IONotificationPortRef gNotifyPort; -static io_iterator_t gAddedIter; -static CFRunLoopRef gRunLoop; - - -CFMutableDictionaryRef matchingDict; -CFRunLoopSourceRef runLoopSource; - -static pthread_t lookupThread; - -pthread_mutex_t notify_mutex; -pthread_cond_t notifyNewDevice; -pthread_cond_t notifyDeviceHandled; - -bool newDeviceAvailable = false; -bool deviceHandled = true; - -ListResultItem_t* notify_item; -bool isAdded = false; -bool isRunning = false; -bool intialDeviceImport = true; - -void WaitForDeviceHandled(); -void SignalDeviceHandled(); -void WaitForNewDevice(); -void SignalDeviceAvailable(); - -//================================================================================================ -// -// DeviceRemoved -// -// This routine will get called whenever any kIOGeneralInterest notification happens. We are -// interested in the kIOMessageServiceIsTerminated message so that's what we look for. Other -// messages are defined in IOMessage.h. -// -//================================================================================================ -void DeviceRemoved(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { - kern_return_t kr; - stDeviceListItem* deviceListItem = (stDeviceListItem *) refCon; - DeviceItem_t* deviceItem = deviceListItem->deviceItem; - - if(messageType == kIOMessageServiceIsTerminated) { - if(deviceListItem->deviceInterface) { - kr = (*deviceListItem->deviceInterface)->Release(deviceListItem->deviceInterface); - } - - kr = IOObjectRelease(deviceListItem->notification); - - - ListResultItem_t* item = NULL; - if(deviceItem) { - item = CopyElement(&deviceItem->deviceParams); - RemoveItemFromList(deviceItem); - delete deviceItem; - } - else { - item = new ListResultItem_t(); - } - - WaitForDeviceHandled(); - notify_item = item; - isAdded = false; - SignalDeviceAvailable(); - - } -} - -//================================================================================================ -// -// DeviceAdded -// -// This routine is the callback for our IOServiceAddMatchingNotification. When we get called -// we will look at all the devices that were added and we will: -// -// 1. Create some private data to relate to each device (in this case we use the service's name -// and the location ID of the device -// 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device, -// using the refCon field to store a pointer to our private data. When we get called with -// this interest notification, we can grab the refCon and access our private data. -// -//================================================================================================ -void DeviceAdded(void *refCon, io_iterator_t iterator) { - kern_return_t kr; - io_service_t usbDevice; - IOCFPlugInInterface **plugInInterface = NULL; - SInt32 score; - HRESULT res; - - while((usbDevice = IOIteratorNext(iterator))) { - io_name_t deviceName; - CFStringRef deviceNameAsCFString; - UInt32 locationID; - UInt16 vendorId; - UInt16 productId; - UInt16 addr; - - DeviceItem_t* deviceItem = new DeviceItem_t(); - - // Get the USB device's name. - kr = IORegistryEntryGetName(usbDevice, deviceName); - if(KERN_SUCCESS != kr) { - deviceName[0] = '\0'; - } - - deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName, kCFStringEncodingASCII); - - - if(deviceNameAsCFString) { - Boolean result; - char deviceName[MAXPATHLEN]; - - // Convert from a CFString to a C (NUL-terminated) - result = CFStringGetCString(deviceNameAsCFString, - deviceName, - sizeof(deviceName), - kCFStringEncodingUTF8); - - if(result) { - deviceItem->deviceParams.deviceName = deviceName; - } - - CFRelease(deviceNameAsCFString); - } - - CFStringRef manufacturerAsCFString = (CFStringRef)IORegistryEntrySearchCFProperty( - usbDevice, - kIOServicePlane, - CFSTR(kUSBVendorString), - kCFAllocatorDefault, - kIORegistryIterateRecursively - ); - - if(manufacturerAsCFString) { - Boolean result; - char manufacturer[MAXPATHLEN]; - - // Convert from a CFString to a C (NUL-terminated) - result = CFStringGetCString( - manufacturerAsCFString, - manufacturer, - sizeof(manufacturer), - kCFStringEncodingUTF8 - ); - - if(result) { - deviceItem->deviceParams.manufacturer = manufacturer; - } - - CFRelease(manufacturerAsCFString); - } - - CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty( - usbDevice, - kIOServicePlane, - CFSTR(kUSBSerialNumberString), - kCFAllocatorDefault, - kIORegistryIterateRecursively - ); - - if(serialNumberAsCFString) { - Boolean result; - char serialNumber[MAXPATHLEN]; - - // Convert from a CFString to a C (NUL-terminated) - result = CFStringGetCString( - serialNumberAsCFString, - serialNumber, - sizeof(serialNumber), - kCFStringEncodingUTF8 - ); - - if(result) { - deviceItem->deviceParams.serialNumber = serialNumber; - } - - CFRelease(serialNumberAsCFString); - } - - - // Now, get the locationID of this device. In order to do this, we need to create an IOUSBDeviceInterface - // for our device. This will create the necessary connections between our userland application and the - // kernel object for the USB Device. - kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); - - if((kIOReturnSuccess != kr) || !plugInInterface) { - fprintf(stderr, "IOCreatePlugInInterfaceForService returned 0x%08x.\n", kr); - continue; - } - - stDeviceListItem *deviceListItem = new stDeviceListItem(); - - // Use the plugin interface to retrieve the device interface. - res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &deviceListItem->deviceInterface); - - // Now done with the plugin interface. - (*plugInInterface)->Release(plugInInterface); - - if(res || deviceListItem->deviceInterface == NULL) { - fprintf(stderr, "QueryInterface returned %d.\n", (int) res); - continue; - } - - // Now that we have the IOUSBDeviceInterface, we can call the routines in IOUSBLib.h. - // In this case, fetch the locationID. The locationID uniquely identifies the device - // and will remain the same, even across reboots, so long as the bus topology doesn't change. - - kr = (*deviceListItem->deviceInterface)->GetLocationID(deviceListItem->deviceInterface, &locationID); - if(KERN_SUCCESS != kr) { - fprintf(stderr, "GetLocationID returned 0x%08x.\n", kr); - continue; - } - deviceItem->deviceParams.locationId = locationID; - - - kr = (*deviceListItem->deviceInterface)->GetDeviceAddress(deviceListItem->deviceInterface, &addr); - if(KERN_SUCCESS != kr) { - fprintf(stderr, "GetDeviceAddress returned 0x%08x.\n", kr); - continue; - } - deviceItem->deviceParams.deviceAddress = addr; - - - kr = (*deviceListItem->deviceInterface)->GetDeviceVendor(deviceListItem->deviceInterface, &vendorId); - if(KERN_SUCCESS != kr) { - fprintf(stderr, "GetDeviceVendor returned 0x%08x.\n", kr); - continue; - } - deviceItem->deviceParams.vendorId = vendorId; - - kr = (*deviceListItem->deviceInterface)->GetDeviceProduct(deviceListItem->deviceInterface, &productId); - if(KERN_SUCCESS != kr) { - fprintf(stderr, "GetDeviceProduct returned 0x%08x.\n", kr); - continue; - } - deviceItem->deviceParams.productId = productId; - - - // Extract path name as unique key - io_string_t pathName; - IORegistryEntryGetPath(usbDevice, kIOServicePlane, pathName); - deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, pathName, kCFStringEncodingASCII); - char cPathName[MAXPATHLEN]; - - if(deviceNameAsCFString) { - Boolean result; - - // Convert from a CFString to a C (NUL-terminated) - result = CFStringGetCString( - deviceNameAsCFString, - cPathName, - sizeof(cPathName), - kCFStringEncodingUTF8 - ); - - - CFRelease(deviceNameAsCFString); - } - - AddItemToList(cPathName, deviceItem); - deviceListItem->deviceItem = deviceItem; - - if(intialDeviceImport == false) { - WaitForDeviceHandled(); - notify_item = &deviceItem->deviceParams; - isAdded = true; - SignalDeviceAvailable(); - } - - // Register for an interest notification of this device being removed. Use a reference to our - // private data as the refCon which will be passed to the notification callback. - kr = IOServiceAddInterestNotification( - gNotifyPort, // notifyPort - usbDevice, // service - kIOGeneralInterest, // interestType - DeviceRemoved, // callback - deviceListItem, // refCon - &(deviceListItem->notification) // notification - ); - - if(KERN_SUCCESS != kr) { - printf("IOServiceAddInterestNotification returned 0x%08x.\n", kr); - } - - // Done with this USB device; release the reference added by IOIteratorNext - kr = IOObjectRelease(usbDevice); - } -} - - -void WaitForDeviceHandled() { - pthread_mutex_lock(¬ify_mutex); - if(deviceHandled == false) { - pthread_cond_wait(¬ifyDeviceHandled, ¬ify_mutex); - } - deviceHandled = false; - pthread_mutex_unlock(¬ify_mutex); -} - -void SignalDeviceHandled() { - pthread_mutex_lock(¬ify_mutex); - deviceHandled = true; - pthread_cond_signal(¬ifyDeviceHandled); - pthread_mutex_unlock(¬ify_mutex); -} - -void WaitForNewDevice() { - pthread_mutex_lock(¬ify_mutex); - if(newDeviceAvailable == false) { - pthread_cond_wait(¬ifyNewDevice, ¬ify_mutex); - } - newDeviceAvailable = false; - pthread_mutex_unlock(¬ify_mutex); -} - -void SignalDeviceAvailable() { - pthread_mutex_lock(¬ify_mutex); - newDeviceAvailable = true; - pthread_cond_signal(¬ifyNewDevice); - pthread_mutex_unlock(¬ify_mutex); -} - - -void *RunLoop(void * arg) { - - runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); - - gRunLoop = CFRunLoopGetCurrent(); - CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); - - // Start the run loop. Now we'll receive notifications. - CFRunLoopRun(); - - // We should never get here - fprintf(stderr, "Unexpectedly back from CFRunLoopRun()!\n"); - - return NULL; -} - -void NotifyAsync(uv_work_t* req) { - WaitForNewDevice(); -} - -void NotifyFinished(uv_work_t* req) { - if(isRunning) { - if(isAdded) { - NotifyAdded(notify_item); - } - else { - NotifyRemoved(notify_item); - } - } - - // Delete Item in case of removal - if(isAdded == false) { - delete notify_item; - } - - if(isRunning) { - uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); - } - SignalDeviceHandled(); -} - -void Start() { - isRunning = true; -} - -void Stop() { - isRunning = false; - pthread_mutex_lock(¬ify_mutex); - pthread_cond_signal(¬ifyNewDevice); - pthread_mutex_unlock(¬ify_mutex); -} - -void InitDetection() { - - kern_return_t kr; - - // Set up the matching criteria for the devices we're interested in. The matching criteria needs to follow - // the same rules as kernel drivers: mainly it needs to follow the USB Common Class Specification, pp. 6-7. - // See also Technical Q&A QA1076 "Tips on USB driver matching on Mac OS X" - // . - // One exception is that you can use the matching dictionary "as is", i.e. without adding any matching - // criteria to it and it will match every IOUSBDevice in the system. IOServiceAddMatchingNotification will - // consume this dictionary reference, so there is no need to release it later on. - - // Interested in instances of class - // IOUSBDevice and its subclasses - matchingDict = IOServiceMatching(kIOUSBDeviceClassName); - - if (matchingDict == NULL) { - fprintf(stderr, "IOServiceMatching returned NULL.\n"); - } - - // Create a notification port and add its run loop event source to our run loop - // This is how async notifications get set up. - - gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault); - - // Now set up a notification to be called when a device is first matched by I/O Kit. - kr = IOServiceAddMatchingNotification( - gNotifyPort, // notifyPort - kIOFirstMatchNotification, // notificationType - matchingDict, // matching - DeviceAdded, // callback - NULL, // refCon - &gAddedIter // notification - ); - - if (KERN_SUCCESS != kr) { - printf("IOServiceAddMatchingNotification returned 0x%08x.\n", kr); - } - - // Iterate once to get already-present devices and arm the notification - DeviceAdded(NULL, gAddedIter); - intialDeviceImport = false; - - - pthread_mutex_init(¬ify_mutex, NULL); - pthread_cond_init(¬ifyNewDevice, NULL); - pthread_cond_init(¬ifyDeviceHandled, NULL); - - int rc = pthread_create(&lookupThread, NULL, RunLoop, NULL); - if (rc) { - printf("ERROR; return code from pthread_create() is %d\n", rc); - exit(-1); - } - - uv_work_t* req = new uv_work_t(); - uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); - - Start(); -} - -void EIO_Find(uv_work_t* req) { - ListBaton* data = static_cast(req->data); - - CreateFilteredList(&data->results, data->vid, data->pid); -} +#include "detection.h" +#include "deviceList.h" + +#include + +#include +#include +#include +#include + +#include +#include + +#include + + +typedef struct DeviceListItem { + io_object_t notification; + IOUSBDeviceInterface** deviceInterface; + DeviceItem_t* deviceItem; +} stDeviceListItem; + +static IONotificationPortRef gNotifyPort; +static io_iterator_t gAddedIter; +static CFRunLoopRef gRunLoop; + + +CFMutableDictionaryRef matchingDict; +CFRunLoopSourceRef runLoopSource; + +static pthread_t lookupThread; + +pthread_mutex_t notify_mutex; +pthread_cond_t notifyNewDevice; +pthread_cond_t notifyDeviceHandled; + +bool newDeviceAvailable = false; +bool deviceHandled = true; + +ListResultItem_t* notify_item; +bool isAdded = false; +bool isRunning = false; +bool intialDeviceImport = true; + +void WaitForDeviceHandled(); +void SignalDeviceHandled(); +void WaitForNewDevice(); +void SignalDeviceAvailable(); + +//================================================================================================ +// +// DeviceRemoved +// +// This routine will get called whenever any kIOGeneralInterest notification happens. We are +// interested in the kIOMessageServiceIsTerminated message so that's what we look for. Other +// messages are defined in IOMessage.h. +// +//================================================================================================ +void DeviceRemoved(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { + kern_return_t kr; + stDeviceListItem* deviceListItem = (stDeviceListItem *) refCon; + DeviceItem_t* deviceItem = deviceListItem->deviceItem; + + if(messageType == kIOMessageServiceIsTerminated) { + if(deviceListItem->deviceInterface) { + kr = (*deviceListItem->deviceInterface)->Release(deviceListItem->deviceInterface); + } + + kr = IOObjectRelease(deviceListItem->notification); + + + ListResultItem_t* item = NULL; + if(deviceItem) { + item = CopyElement(&deviceItem->deviceParams); + RemoveItemFromList(deviceItem); + delete deviceItem; + } + else { + item = new ListResultItem_t(); + } + + WaitForDeviceHandled(); + notify_item = item; + isAdded = false; + SignalDeviceAvailable(); + + } +} + +//================================================================================================ +// +// DeviceAdded +// +// This routine is the callback for our IOServiceAddMatchingNotification. When we get called +// we will look at all the devices that were added and we will: +// +// 1. Create some private data to relate to each device (in this case we use the service's name +// and the location ID of the device +// 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device, +// using the refCon field to store a pointer to our private data. When we get called with +// this interest notification, we can grab the refCon and access our private data. +// +//================================================================================================ +void DeviceAdded(void *refCon, io_iterator_t iterator) { + kern_return_t kr; + io_service_t usbDevice; + IOCFPlugInInterface **plugInInterface = NULL; + SInt32 score; + HRESULT res; + + while((usbDevice = IOIteratorNext(iterator))) { + io_name_t deviceName; + CFStringRef deviceNameAsCFString; + UInt32 locationID; + UInt16 vendorId; + UInt16 productId; + UInt16 addr; + + DeviceItem_t* deviceItem = new DeviceItem_t(); + + // Get the USB device's name. + kr = IORegistryEntryGetName(usbDevice, deviceName); + if(KERN_SUCCESS != kr) { + deviceName[0] = '\0'; + } + + deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName, kCFStringEncodingASCII); + + + if(deviceNameAsCFString) { + Boolean result; + char deviceName[MAXPATHLEN]; + + // Convert from a CFString to a C (NUL-terminated) + result = CFStringGetCString(deviceNameAsCFString, + deviceName, + sizeof(deviceName), + kCFStringEncodingUTF8); + + if(result) { + deviceItem->deviceParams.deviceName = deviceName; + } + + CFRelease(deviceNameAsCFString); + } + + CFStringRef manufacturerAsCFString = (CFStringRef)IORegistryEntrySearchCFProperty( + usbDevice, + kIOServicePlane, + CFSTR(kUSBVendorString), + kCFAllocatorDefault, + kIORegistryIterateRecursively + ); + + if(manufacturerAsCFString) { + Boolean result; + char manufacturer[MAXPATHLEN]; + + // Convert from a CFString to a C (NUL-terminated) + result = CFStringGetCString( + manufacturerAsCFString, + manufacturer, + sizeof(manufacturer), + kCFStringEncodingUTF8 + ); + + if(result) { + deviceItem->deviceParams.manufacturer = manufacturer; + } + + CFRelease(manufacturerAsCFString); + } + + CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty( + usbDevice, + kIOServicePlane, + CFSTR(kUSBSerialNumberString), + kCFAllocatorDefault, + kIORegistryIterateRecursively + ); + + if(serialNumberAsCFString) { + Boolean result; + char serialNumber[MAXPATHLEN]; + + // Convert from a CFString to a C (NUL-terminated) + result = CFStringGetCString( + serialNumberAsCFString, + serialNumber, + sizeof(serialNumber), + kCFStringEncodingUTF8 + ); + + if(result) { + deviceItem->deviceParams.serialNumber = serialNumber; + } + + CFRelease(serialNumberAsCFString); + } + + + // Now, get the locationID of this device. In order to do this, we need to create an IOUSBDeviceInterface + // for our device. This will create the necessary connections between our userland application and the + // kernel object for the USB Device. + kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); + + if((kIOReturnSuccess != kr) || !plugInInterface) { + fprintf(stderr, "IOCreatePlugInInterfaceForService returned 0x%08x.\n", kr); + continue; + } + + stDeviceListItem *deviceListItem = new stDeviceListItem(); + + // Use the plugin interface to retrieve the device interface. + res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &deviceListItem->deviceInterface); + + // Now done with the plugin interface. + (*plugInInterface)->Release(plugInInterface); + + if(res || deviceListItem->deviceInterface == NULL) { + fprintf(stderr, "QueryInterface returned %d.\n", (int) res); + continue; + } + + // Now that we have the IOUSBDeviceInterface, we can call the routines in IOUSBLib.h. + // In this case, fetch the locationID. The locationID uniquely identifies the device + // and will remain the same, even across reboots, so long as the bus topology doesn't change. + + kr = (*deviceListItem->deviceInterface)->GetLocationID(deviceListItem->deviceInterface, &locationID); + if(KERN_SUCCESS != kr) { + fprintf(stderr, "GetLocationID returned 0x%08x.\n", kr); + continue; + } + deviceItem->deviceParams.locationId = locationID; + + + kr = (*deviceListItem->deviceInterface)->GetDeviceAddress(deviceListItem->deviceInterface, &addr); + if(KERN_SUCCESS != kr) { + fprintf(stderr, "GetDeviceAddress returned 0x%08x.\n", kr); + continue; + } + deviceItem->deviceParams.deviceAddress = addr; + + + kr = (*deviceListItem->deviceInterface)->GetDeviceVendor(deviceListItem->deviceInterface, &vendorId); + if(KERN_SUCCESS != kr) { + fprintf(stderr, "GetDeviceVendor returned 0x%08x.\n", kr); + continue; + } + deviceItem->deviceParams.vendorId = vendorId; + + kr = (*deviceListItem->deviceInterface)->GetDeviceProduct(deviceListItem->deviceInterface, &productId); + if(KERN_SUCCESS != kr) { + fprintf(stderr, "GetDeviceProduct returned 0x%08x.\n", kr); + continue; + } + deviceItem->deviceParams.productId = productId; + + + // Extract path name as unique key + io_string_t pathName; + IORegistryEntryGetPath(usbDevice, kIOServicePlane, pathName); + deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, pathName, kCFStringEncodingASCII); + char cPathName[MAXPATHLEN]; + + if(deviceNameAsCFString) { + Boolean result; + + // Convert from a CFString to a C (NUL-terminated) + result = CFStringGetCString( + deviceNameAsCFString, + cPathName, + sizeof(cPathName), + kCFStringEncodingUTF8 + ); + + + CFRelease(deviceNameAsCFString); + } + + AddItemToList(cPathName, deviceItem); + deviceListItem->deviceItem = deviceItem; + + if(intialDeviceImport == false) { + WaitForDeviceHandled(); + notify_item = &deviceItem->deviceParams; + isAdded = true; + SignalDeviceAvailable(); + } + + // Register for an interest notification of this device being removed. Use a reference to our + // private data as the refCon which will be passed to the notification callback. + kr = IOServiceAddInterestNotification( + gNotifyPort, // notifyPort + usbDevice, // service + kIOGeneralInterest, // interestType + DeviceRemoved, // callback + deviceListItem, // refCon + &(deviceListItem->notification) // notification + ); + + if(KERN_SUCCESS != kr) { + printf("IOServiceAddInterestNotification returned 0x%08x.\n", kr); + } + + // Done with this USB device; release the reference added by IOIteratorNext + kr = IOObjectRelease(usbDevice); + } +} + + +void WaitForDeviceHandled() { + pthread_mutex_lock(¬ify_mutex); + if(deviceHandled == false) { + pthread_cond_wait(¬ifyDeviceHandled, ¬ify_mutex); + } + deviceHandled = false; + pthread_mutex_unlock(¬ify_mutex); +} + +void SignalDeviceHandled() { + pthread_mutex_lock(¬ify_mutex); + deviceHandled = true; + pthread_cond_signal(¬ifyDeviceHandled); + pthread_mutex_unlock(¬ify_mutex); +} + +void WaitForNewDevice() { + pthread_mutex_lock(¬ify_mutex); + if(newDeviceAvailable == false) { + pthread_cond_wait(¬ifyNewDevice, ¬ify_mutex); + } + newDeviceAvailable = false; + pthread_mutex_unlock(¬ify_mutex); +} + +void SignalDeviceAvailable() { + pthread_mutex_lock(¬ify_mutex); + newDeviceAvailable = true; + pthread_cond_signal(¬ifyNewDevice); + pthread_mutex_unlock(¬ify_mutex); +} + + +void *RunLoop(void * arg) { + + runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); + + gRunLoop = CFRunLoopGetCurrent(); + CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); + + // Start the run loop. Now we'll receive notifications. + CFRunLoopRun(); + + // We should never get here + fprintf(stderr, "Unexpectedly back from CFRunLoopRun()!\n"); + + return NULL; +} + +void NotifyAsync(uv_work_t* req) { + WaitForNewDevice(); +} + +void NotifyFinished(uv_work_t* req) { + if(isRunning) { + if(isAdded) { + NotifyAdded(notify_item); + } + else { + NotifyRemoved(notify_item); + } + } + + // Delete Item in case of removal + if(isAdded == false) { + delete notify_item; + } + + if(isRunning) { + uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); + } + SignalDeviceHandled(); +} + +void Start() { + isRunning = true; +} + +void Stop() { + isRunning = false; + pthread_mutex_lock(¬ify_mutex); + pthread_cond_signal(¬ifyNewDevice); + pthread_mutex_unlock(¬ify_mutex); +} + +void InitDetection() { + + kern_return_t kr; + + // Set up the matching criteria for the devices we're interested in. The matching criteria needs to follow + // the same rules as kernel drivers: mainly it needs to follow the USB Common Class Specification, pp. 6-7. + // See also Technical Q&A QA1076 "Tips on USB driver matching on Mac OS X" + // . + // One exception is that you can use the matching dictionary "as is", i.e. without adding any matching + // criteria to it and it will match every IOUSBDevice in the system. IOServiceAddMatchingNotification will + // consume this dictionary reference, so there is no need to release it later on. + + // Interested in instances of class + // IOUSBDevice and its subclasses + matchingDict = IOServiceMatching(kIOUSBDeviceClassName); + + if (matchingDict == NULL) { + fprintf(stderr, "IOServiceMatching returned NULL.\n"); + } + + // Create a notification port and add its run loop event source to our run loop + // This is how async notifications get set up. + + gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault); + + // Now set up a notification to be called when a device is first matched by I/O Kit. + kr = IOServiceAddMatchingNotification( + gNotifyPort, // notifyPort + kIOFirstMatchNotification, // notificationType + matchingDict, // matching + DeviceAdded, // callback + NULL, // refCon + &gAddedIter // notification + ); + + if (KERN_SUCCESS != kr) { + printf("IOServiceAddMatchingNotification returned 0x%08x.\n", kr); + } + + // Iterate once to get already-present devices and arm the notification + DeviceAdded(NULL, gAddedIter); + intialDeviceImport = false; + + + pthread_mutex_init(¬ify_mutex, NULL); + pthread_cond_init(¬ifyNewDevice, NULL); + pthread_cond_init(¬ifyDeviceHandled, NULL); + + int rc = pthread_create(&lookupThread, NULL, RunLoop, NULL); + if (rc) { + printf("ERROR; return code from pthread_create() is %d\n", rc); + exit(-1); + } + + uv_work_t* req = new uv_work_t(); + uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); + + Start(); +} + +void EIO_Find(uv_work_t* req) { + ListBaton* data = static_cast(req->data); + + CreateFilteredList(&data->results, data->vid, data->pid); +} diff --git a/vendor/node-usb-native/src/detection_win.cpp b/vendor/node-usb-native/src/detection_win.cpp index eb02e18c4..4d6645960 100644 --- a/vendor/node-usb-native/src/detection_win.cpp +++ b/vendor/node-usb-native/src/detection_win.cpp @@ -1,471 +1,471 @@ -#include -#include -#include -#include -#include - - -// Include Windows headers -#include -#include -#include -#include -#include - -#include "detection.h" -#include "deviceList.h" - -using namespace std; - -/********************************** - * Local defines - **********************************/ -#define VID_TAG "VID_" -#define PID_TAG "PID_" - -#define LIBRARY_NAME ("setupapi.dll") - - -#define DllImport __declspec(dllimport) - -#define MAX_THREAD_WINDOW_NAME 64 - -/********************************** - * Local typedefs - **********************************/ - - - -/********************************** - * Local Variables - **********************************/ -GUID GUID_DEVINTERFACE_USB_DEVICE = { - 0xA5DCBF10L, - 0x6530, - 0x11D2, - 0x90, - 0x1F, - 0x00, - 0xC0, - 0x4F, - 0xB9, - 0x51, - 0xED -}; - -HWND handle; -DWORD threadId; -HANDLE threadHandle; - -HANDLE deviceChangedRegisteredEvent; -HANDLE deviceChangedSentEvent; - -ListResultItem_t* currentDevice; -bool isAdded; -bool isRunning = false; - -HINSTANCE hinstLib; - - -typedef BOOL (WINAPI *_SetupDiEnumDeviceInfo) (HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData); -typedef HDEVINFO (WINAPI *_SetupDiGetClassDevs) (const GUID *ClassGuid, PCTSTR Enumerator, HWND hwndParent, DWORD Flags); -typedef BOOL (WINAPI *_SetupDiDestroyDeviceInfoList) (HDEVINFO DeviceInfoSet); -typedef BOOL (WINAPI *_SetupDiGetDeviceInstanceId) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PTSTR DeviceInstanceId, DWORD DeviceInstanceIdSize, PDWORD RequiredSize); -typedef BOOL (WINAPI *_SetupDiGetDeviceRegistryProperty) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize); - - -_SetupDiEnumDeviceInfo DllSetupDiEnumDeviceInfo; -_SetupDiGetClassDevs DllSetupDiGetClassDevs; -_SetupDiDestroyDeviceInfoList DllSetupDiDestroyDeviceInfoList; -_SetupDiGetDeviceInstanceId DllSetupDiGetDeviceInstanceId; -_SetupDiGetDeviceRegistryProperty DllSetupDiGetDeviceRegistryProperty; - - -/********************************** - * Local Helper Functions protoypes - **********************************/ -void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam, DeviceState_t state); -DWORD WINAPI ListenerThread(LPVOID lpParam); - -void BuildInitialDeviceList(); - -void NotifyAsync(uv_work_t* req); -void NotifyFinished(uv_work_t* req); - -void ExtractDeviceInfo(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pspDevInfoData, TCHAR* buf, DWORD buffSize, ListResultItem_t* resultItem); -bool CheckValidity(ListResultItem_t* item); - - -/********************************** - * Public Functions - **********************************/ -void NotifyAsync(uv_work_t* req) { - WaitForSingleObject(deviceChangedRegisteredEvent, INFINITE); -} - - -void NotifyFinished(uv_work_t* req) { - if (isRunning) { - if(isAdded) { - NotifyAdded(currentDevice); - } - else { - NotifyRemoved(currentDevice); - } - } - - // Delete Item in case of removal - if(isAdded == false) { - delete currentDevice; - } - - SetEvent(deviceChangedSentEvent); - - currentDevice = NULL; - uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); -} - -void LoadFunctions() { - - bool success; - - hinstLib = LoadLibrary(LIBRARY_NAME); - - if (hinstLib != NULL) { - DllSetupDiEnumDeviceInfo = (_SetupDiEnumDeviceInfo) GetProcAddress(hinstLib, "SetupDiEnumDeviceInfo"); - - DllSetupDiGetClassDevs = (_SetupDiGetClassDevs) GetProcAddress(hinstLib, "SetupDiGetClassDevsA"); - - DllSetupDiDestroyDeviceInfoList = (_SetupDiDestroyDeviceInfoList) GetProcAddress(hinstLib, "SetupDiDestroyDeviceInfoList"); - - DllSetupDiGetDeviceInstanceId = (_SetupDiGetDeviceInstanceId) GetProcAddress(hinstLib, "SetupDiGetDeviceInstanceIdA"); - - DllSetupDiGetDeviceRegistryProperty = (_SetupDiGetDeviceRegistryProperty) GetProcAddress(hinstLib, "SetupDiGetDeviceRegistryPropertyA"); - - success = ( - DllSetupDiEnumDeviceInfo != NULL && - DllSetupDiGetClassDevs != NULL && - DllSetupDiDestroyDeviceInfoList != NULL && - DllSetupDiGetDeviceInstanceId != NULL && - DllSetupDiGetDeviceRegistryProperty != NULL - ); - } - else { - success = false; - } - - if(!success) { - printf("Could not load library functions from dll -> abort (Check if %s is available)\r\n", LIBRARY_NAME); - exit(1); - } -} - -void Start() { - isRunning = true; -} - -void Stop() { - isRunning = false; - SetEvent(deviceChangedRegisteredEvent); -} - -void InitDetection() { - - LoadFunctions(); - - deviceChangedRegisteredEvent = CreateEvent(NULL, false /* auto-reset event */, false /* non-signalled state */, ""); - deviceChangedSentEvent = CreateEvent(NULL, false /* auto-reset event */, true /* non-signalled state */, ""); - - BuildInitialDeviceList(); - - threadHandle = CreateThread( - NULL, // default security attributes - 0, // use default stack size - ListenerThread, // thread function name - NULL, // argument to thread function - 0, // use default creation flags - &threadId - ); - - uv_work_t* req = new uv_work_t(); - uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); - - Start(); -} - - -void EIO_Find(uv_work_t* req) { - - ListBaton* data = static_cast(req->data); - - CreateFilteredList(&data->results, data->vid, data->pid); -} - - -/********************************** - * Local Functions - **********************************/ -void ToUpper(char * buf) { - char* c = buf; - while (*c != '\0') { - *c = toupper((unsigned char)*c); - c++; - } -} - - -void extractVidPid(char * buf, ListResultItem_t * item) { - if(buf == NULL) { - return; - } - - ToUpper(buf); - - char* string; - char* temp; - char* pidStr, *vidStr; - int vid = 0; - int pid = 0; - - string = new char[strlen(buf) + 1]; - memcpy(string, buf, strlen(buf) + 1); - - vidStr = strstr(string, VID_TAG); - pidStr = strstr(string, PID_TAG); - - if(vidStr != NULL) { - temp = (char*) (vidStr + strlen(VID_TAG)); - temp[4] = '\0'; - vid = strtol (temp, NULL, 16); - } - - if(pidStr != NULL) { - temp = (char*) (pidStr + strlen(PID_TAG)); - temp[4] = '\0'; - pid = strtol (temp, NULL, 16); - } - item->vendorId = vid; - item->productId = pid; - - delete string; -} - - -LRESULT CALLBACK DetectCallback(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - if (msg == WM_DEVICECHANGE) { - if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam ) { - PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; - PDEV_BROADCAST_DEVICEINTERFACE pDevInf; - - if(pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { - pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr; - UpdateDevice(pDevInf, wParam, (DBT_DEVICEARRIVAL == wParam) ? DeviceState_Connect : DeviceState_Disconnect); - } - } - } - - return 1; -} - - -DWORD WINAPI ListenerThread( LPVOID lpParam ) { - char className[MAX_THREAD_WINDOW_NAME]; - _snprintf_s(className, MAX_THREAD_WINDOW_NAME, "ListnerThreadUsbDetection_%d", GetCurrentThreadId()); - - WNDCLASSA wincl = {0}; - wincl.hInstance = GetModuleHandle(0); - wincl.lpszClassName = className; - wincl.lpfnWndProc = DetectCallback; - - if (!RegisterClassA(&wincl)) { - DWORD le = GetLastError(); - printf("RegisterClassA() failed [Error: %x]\r\n", le); - return 1; - } - - - HWND hwnd = CreateWindowExA(WS_EX_TOPMOST, className, className, 0, 0, 0, 0, 0, NULL, 0, 0, 0); - if (!hwnd) { - DWORD le = GetLastError(); - printf("CreateWindowExA() failed [Error: %x]\r\n", le); - return 1; - } - - DEV_BROADCAST_DEVICEINTERFACE_A notifyFilter = {0}; - notifyFilter.dbcc_size = sizeof(notifyFilter); - notifyFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - notifyFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; - - HDEVNOTIFY hDevNotify = RegisterDeviceNotificationA(hwnd, ¬ifyFilter, DEVICE_NOTIFY_WINDOW_HANDLE); - if (!hDevNotify) { - DWORD le = GetLastError(); - printf("RegisterDeviceNotificationA() failed [Error: %x]\r\n", le); - return 1; - } - - MSG msg; - while(TRUE) { - BOOL bRet = GetMessage(&msg, hwnd, 0, 0); - if ((bRet == 0) || (bRet == -1)) { - break; - } - - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - return 0; -} - - -void BuildInitialDeviceList() { - TCHAR buf[MAX_PATH]; - DWORD dwFlag = (DIGCF_ALLCLASSES | DIGCF_PRESENT); - HDEVINFO hDevInfo = DllSetupDiGetClassDevs(NULL, "USB", NULL, dwFlag); - - if(INVALID_HANDLE_VALUE == hDevInfo) { - return; - } - - SP_DEVINFO_DATA* pspDevInfoData = (SP_DEVINFO_DATA*) HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA)); - pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA); - for(int i=0; DllSetupDiEnumDeviceInfo(hDevInfo, i, pspDevInfoData); i++) { - DWORD nSize=0 ; - - if (!DllSetupDiGetDeviceInstanceId(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize)) { - break; - } - - DeviceItem_t* item = new DeviceItem_t(); - item->deviceState = DeviceState_Connect; - - DWORD DataT; - DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, MAX_PATH, &nSize); - - AddItemToList(buf, item); - ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, &item->deviceParams); - } - - if(pspDevInfoData) { - HeapFree(GetProcessHeap(), 0, pspDevInfoData); - } - - if(hDevInfo) { - DllSetupDiDestroyDeviceInfoList(hDevInfo); - } -} - - -void ExtractDeviceInfo(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pspDevInfoData, TCHAR* buf, DWORD buffSize, ListResultItem_t* resultItem) { - - DWORD DataT; - DWORD nSize; - static int dummy = 1; - - resultItem->locationId = 0; - resultItem->deviceAddress = dummy++; - - // device found - if (DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, buffSize, &nSize)) { - resultItem->deviceName = buf; - } - else if ( DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, buffSize, &nSize)) - { - resultItem->deviceName = buf; - } - if (DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_MFG, &DataT, (PBYTE)buf, buffSize, &nSize)) { - resultItem->manufacturer = buf; - } - if (DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, buffSize, &nSize)) { - // Use this to extract VID / PID - extractVidPid(buf, resultItem); - } -} - - -void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam, DeviceState_t state) { - // dbcc_name: - // \\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed} - // convert to - // USB\Vid_04e8&Pid_503b\0002F9A9828E0F06 - CString szDevId = pDevInf->dbcc_name+4; - int idx = szDevId.ReverseFind(_T('#')); - - szDevId.Truncate(idx); - szDevId.Replace(_T('#'), _T('\\')); - szDevId.MakeUpper(); - - CString szClass; - idx = szDevId.Find(_T('\\')); - szClass = szDevId.Left(idx); - - // if we are adding device, we only need present devices - // otherwise, we need all devices - DWORD dwFlag = DBT_DEVICEARRIVAL != wParam ? DIGCF_ALLCLASSES : (DIGCF_ALLCLASSES | DIGCF_PRESENT); - HDEVINFO hDevInfo = DllSetupDiGetClassDevs(NULL, szClass, NULL, dwFlag); - if(INVALID_HANDLE_VALUE == hDevInfo) { - return; - } - - SP_DEVINFO_DATA* pspDevInfoData = (SP_DEVINFO_DATA*) HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA)); - pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA); - for(int i=0; DllSetupDiEnumDeviceInfo(hDevInfo, i, pspDevInfoData); i++) { - DWORD nSize=0 ; - TCHAR buf[MAX_PATH]; - - if (!DllSetupDiGetDeviceInstanceId(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize)) { - break; - } - - if(szDevId == buf) { - - WaitForSingleObject(deviceChangedSentEvent, INFINITE); - - DWORD DataT; - DWORD nSize; - DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, MAX_PATH, &nSize); - - if(state == DeviceState_Connect) { - DeviceItem_t* device = new DeviceItem_t(); - - AddItemToList(buf, device); - ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, &device->deviceParams); - - currentDevice = &device->deviceParams; - isAdded = true; - } - else { - - ListResultItem_t* item = NULL; - if(IsItemAlreadyStored(buf)) { - DeviceItem_t* deviceItem = GetItemFromList(buf); - if(deviceItem) - { - item = CopyElement(&deviceItem->deviceParams); - } - RemoveItemFromList(deviceItem); - delete deviceItem; - } - - if(item == NULL) { - item = new ListResultItem_t(); - ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, item); - } - currentDevice = item; - isAdded = false; - } - - break; - } - } - - if (pspDevInfoData) { - HeapFree(GetProcessHeap(), 0, pspDevInfoData); - } - - if(hDevInfo) { - DllSetupDiDestroyDeviceInfoList(hDevInfo); - } - - SetEvent(deviceChangedRegisteredEvent); -} +#include +#include +#include +#include +#include + + +// Include Windows headers +#include +#include +#include +#include +#include + +#include "detection.h" +#include "deviceList.h" + +using namespace std; + +/********************************** + * Local defines + **********************************/ +#define VID_TAG "VID_" +#define PID_TAG "PID_" + +#define LIBRARY_NAME ("setupapi.dll") + + +#define DllImport __declspec(dllimport) + +#define MAX_THREAD_WINDOW_NAME 64 + +/********************************** + * Local typedefs + **********************************/ + + + +/********************************** + * Local Variables + **********************************/ +GUID GUID_DEVINTERFACE_USB_DEVICE = { + 0xA5DCBF10L, + 0x6530, + 0x11D2, + 0x90, + 0x1F, + 0x00, + 0xC0, + 0x4F, + 0xB9, + 0x51, + 0xED +}; + +HWND handle; +DWORD threadId; +HANDLE threadHandle; + +HANDLE deviceChangedRegisteredEvent; +HANDLE deviceChangedSentEvent; + +ListResultItem_t* currentDevice; +bool isAdded; +bool isRunning = false; + +HINSTANCE hinstLib; + + +typedef BOOL (WINAPI *_SetupDiEnumDeviceInfo) (HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData); +typedef HDEVINFO (WINAPI *_SetupDiGetClassDevs) (const GUID *ClassGuid, PCTSTR Enumerator, HWND hwndParent, DWORD Flags); +typedef BOOL (WINAPI *_SetupDiDestroyDeviceInfoList) (HDEVINFO DeviceInfoSet); +typedef BOOL (WINAPI *_SetupDiGetDeviceInstanceId) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PTSTR DeviceInstanceId, DWORD DeviceInstanceIdSize, PDWORD RequiredSize); +typedef BOOL (WINAPI *_SetupDiGetDeviceRegistryProperty) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize); + + +_SetupDiEnumDeviceInfo DllSetupDiEnumDeviceInfo; +_SetupDiGetClassDevs DllSetupDiGetClassDevs; +_SetupDiDestroyDeviceInfoList DllSetupDiDestroyDeviceInfoList; +_SetupDiGetDeviceInstanceId DllSetupDiGetDeviceInstanceId; +_SetupDiGetDeviceRegistryProperty DllSetupDiGetDeviceRegistryProperty; + + +/********************************** + * Local Helper Functions protoypes + **********************************/ +void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam, DeviceState_t state); +DWORD WINAPI ListenerThread(LPVOID lpParam); + +void BuildInitialDeviceList(); + +void NotifyAsync(uv_work_t* req); +void NotifyFinished(uv_work_t* req); + +void ExtractDeviceInfo(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pspDevInfoData, TCHAR* buf, DWORD buffSize, ListResultItem_t* resultItem); +bool CheckValidity(ListResultItem_t* item); + + +/********************************** + * Public Functions + **********************************/ +void NotifyAsync(uv_work_t* req) { + WaitForSingleObject(deviceChangedRegisteredEvent, INFINITE); +} + + +void NotifyFinished(uv_work_t* req) { + if (isRunning) { + if(isAdded) { + NotifyAdded(currentDevice); + } + else { + NotifyRemoved(currentDevice); + } + } + + // Delete Item in case of removal + if(isAdded == false) { + delete currentDevice; + } + + SetEvent(deviceChangedSentEvent); + + currentDevice = NULL; + uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); +} + +void LoadFunctions() { + + bool success; + + hinstLib = LoadLibrary(LIBRARY_NAME); + + if (hinstLib != NULL) { + DllSetupDiEnumDeviceInfo = (_SetupDiEnumDeviceInfo) GetProcAddress(hinstLib, "SetupDiEnumDeviceInfo"); + + DllSetupDiGetClassDevs = (_SetupDiGetClassDevs) GetProcAddress(hinstLib, "SetupDiGetClassDevsA"); + + DllSetupDiDestroyDeviceInfoList = (_SetupDiDestroyDeviceInfoList) GetProcAddress(hinstLib, "SetupDiDestroyDeviceInfoList"); + + DllSetupDiGetDeviceInstanceId = (_SetupDiGetDeviceInstanceId) GetProcAddress(hinstLib, "SetupDiGetDeviceInstanceIdA"); + + DllSetupDiGetDeviceRegistryProperty = (_SetupDiGetDeviceRegistryProperty) GetProcAddress(hinstLib, "SetupDiGetDeviceRegistryPropertyA"); + + success = ( + DllSetupDiEnumDeviceInfo != NULL && + DllSetupDiGetClassDevs != NULL && + DllSetupDiDestroyDeviceInfoList != NULL && + DllSetupDiGetDeviceInstanceId != NULL && + DllSetupDiGetDeviceRegistryProperty != NULL + ); + } + else { + success = false; + } + + if(!success) { + printf("Could not load library functions from dll -> abort (Check if %s is available)\r\n", LIBRARY_NAME); + exit(1); + } +} + +void Start() { + isRunning = true; +} + +void Stop() { + isRunning = false; + SetEvent(deviceChangedRegisteredEvent); +} + +void InitDetection() { + + LoadFunctions(); + + deviceChangedRegisteredEvent = CreateEvent(NULL, false /* auto-reset event */, false /* non-signalled state */, ""); + deviceChangedSentEvent = CreateEvent(NULL, false /* auto-reset event */, true /* non-signalled state */, ""); + + BuildInitialDeviceList(); + + threadHandle = CreateThread( + NULL, // default security attributes + 0, // use default stack size + ListenerThread, // thread function name + NULL, // argument to thread function + 0, // use default creation flags + &threadId + ); + + uv_work_t* req = new uv_work_t(); + uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished); + + Start(); +} + + +void EIO_Find(uv_work_t* req) { + + ListBaton* data = static_cast(req->data); + + CreateFilteredList(&data->results, data->vid, data->pid); +} + + +/********************************** + * Local Functions + **********************************/ +void ToUpper(char * buf) { + char* c = buf; + while (*c != '\0') { + *c = toupper((unsigned char)*c); + c++; + } +} + + +void extractVidPid(char * buf, ListResultItem_t * item) { + if(buf == NULL) { + return; + } + + ToUpper(buf); + + char* string; + char* temp; + char* pidStr, *vidStr; + int vid = 0; + int pid = 0; + + string = new char[strlen(buf) + 1]; + memcpy(string, buf, strlen(buf) + 1); + + vidStr = strstr(string, VID_TAG); + pidStr = strstr(string, PID_TAG); + + if(vidStr != NULL) { + temp = (char*) (vidStr + strlen(VID_TAG)); + temp[4] = '\0'; + vid = strtol (temp, NULL, 16); + } + + if(pidStr != NULL) { + temp = (char*) (pidStr + strlen(PID_TAG)); + temp[4] = '\0'; + pid = strtol (temp, NULL, 16); + } + item->vendorId = vid; + item->productId = pid; + + delete string; +} + + +LRESULT CALLBACK DetectCallback(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + if (msg == WM_DEVICECHANGE) { + if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam ) { + PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; + PDEV_BROADCAST_DEVICEINTERFACE pDevInf; + + if(pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { + pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr; + UpdateDevice(pDevInf, wParam, (DBT_DEVICEARRIVAL == wParam) ? DeviceState_Connect : DeviceState_Disconnect); + } + } + } + + return 1; +} + + +DWORD WINAPI ListenerThread( LPVOID lpParam ) { + char className[MAX_THREAD_WINDOW_NAME]; + _snprintf_s(className, MAX_THREAD_WINDOW_NAME, "ListnerThreadUsbDetection_%d", GetCurrentThreadId()); + + WNDCLASSA wincl = {0}; + wincl.hInstance = GetModuleHandle(0); + wincl.lpszClassName = className; + wincl.lpfnWndProc = DetectCallback; + + if (!RegisterClassA(&wincl)) { + DWORD le = GetLastError(); + printf("RegisterClassA() failed [Error: %x]\r\n", le); + return 1; + } + + + HWND hwnd = CreateWindowExA(WS_EX_TOPMOST, className, className, 0, 0, 0, 0, 0, NULL, 0, 0, 0); + if (!hwnd) { + DWORD le = GetLastError(); + printf("CreateWindowExA() failed [Error: %x]\r\n", le); + return 1; + } + + DEV_BROADCAST_DEVICEINTERFACE_A notifyFilter = {0}; + notifyFilter.dbcc_size = sizeof(notifyFilter); + notifyFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + notifyFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; + + HDEVNOTIFY hDevNotify = RegisterDeviceNotificationA(hwnd, ¬ifyFilter, DEVICE_NOTIFY_WINDOW_HANDLE); + if (!hDevNotify) { + DWORD le = GetLastError(); + printf("RegisterDeviceNotificationA() failed [Error: %x]\r\n", le); + return 1; + } + + MSG msg; + while(TRUE) { + BOOL bRet = GetMessage(&msg, hwnd, 0, 0); + if ((bRet == 0) || (bRet == -1)) { + break; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return 0; +} + + +void BuildInitialDeviceList() { + TCHAR buf[MAX_PATH]; + DWORD dwFlag = (DIGCF_ALLCLASSES | DIGCF_PRESENT); + HDEVINFO hDevInfo = DllSetupDiGetClassDevs(NULL, "USB", NULL, dwFlag); + + if(INVALID_HANDLE_VALUE == hDevInfo) { + return; + } + + SP_DEVINFO_DATA* pspDevInfoData = (SP_DEVINFO_DATA*) HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA)); + pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA); + for(int i=0; DllSetupDiEnumDeviceInfo(hDevInfo, i, pspDevInfoData); i++) { + DWORD nSize=0 ; + + if (!DllSetupDiGetDeviceInstanceId(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize)) { + break; + } + + DeviceItem_t* item = new DeviceItem_t(); + item->deviceState = DeviceState_Connect; + + DWORD DataT; + DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, MAX_PATH, &nSize); + + AddItemToList(buf, item); + ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, &item->deviceParams); + } + + if(pspDevInfoData) { + HeapFree(GetProcessHeap(), 0, pspDevInfoData); + } + + if(hDevInfo) { + DllSetupDiDestroyDeviceInfoList(hDevInfo); + } +} + + +void ExtractDeviceInfo(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pspDevInfoData, TCHAR* buf, DWORD buffSize, ListResultItem_t* resultItem) { + + DWORD DataT; + DWORD nSize; + static int dummy = 1; + + resultItem->locationId = 0; + resultItem->deviceAddress = dummy++; + + // device found + if (DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, buffSize, &nSize)) { + resultItem->deviceName = buf; + } + else if ( DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, buffSize, &nSize)) + { + resultItem->deviceName = buf; + } + if (DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_MFG, &DataT, (PBYTE)buf, buffSize, &nSize)) { + resultItem->manufacturer = buf; + } + if (DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, buffSize, &nSize)) { + // Use this to extract VID / PID + extractVidPid(buf, resultItem); + } +} + + +void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam, DeviceState_t state) { + // dbcc_name: + // \\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed} + // convert to + // USB\Vid_04e8&Pid_503b\0002F9A9828E0F06 + CString szDevId = pDevInf->dbcc_name+4; + int idx = szDevId.ReverseFind(_T('#')); + + szDevId.Truncate(idx); + szDevId.Replace(_T('#'), _T('\\')); + szDevId.MakeUpper(); + + CString szClass; + idx = szDevId.Find(_T('\\')); + szClass = szDevId.Left(idx); + + // if we are adding device, we only need present devices + // otherwise, we need all devices + DWORD dwFlag = DBT_DEVICEARRIVAL != wParam ? DIGCF_ALLCLASSES : (DIGCF_ALLCLASSES | DIGCF_PRESENT); + HDEVINFO hDevInfo = DllSetupDiGetClassDevs(NULL, szClass, NULL, dwFlag); + if(INVALID_HANDLE_VALUE == hDevInfo) { + return; + } + + SP_DEVINFO_DATA* pspDevInfoData = (SP_DEVINFO_DATA*) HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA)); + pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA); + for(int i=0; DllSetupDiEnumDeviceInfo(hDevInfo, i, pspDevInfoData); i++) { + DWORD nSize=0 ; + TCHAR buf[MAX_PATH]; + + if (!DllSetupDiGetDeviceInstanceId(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize)) { + break; + } + + if(szDevId == buf) { + + WaitForSingleObject(deviceChangedSentEvent, INFINITE); + + DWORD DataT; + DWORD nSize; + DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, MAX_PATH, &nSize); + + if(state == DeviceState_Connect) { + DeviceItem_t* device = new DeviceItem_t(); + + AddItemToList(buf, device); + ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, &device->deviceParams); + + currentDevice = &device->deviceParams; + isAdded = true; + } + else { + + ListResultItem_t* item = NULL; + if(IsItemAlreadyStored(buf)) { + DeviceItem_t* deviceItem = GetItemFromList(buf); + if(deviceItem) + { + item = CopyElement(&deviceItem->deviceParams); + } + RemoveItemFromList(deviceItem); + delete deviceItem; + } + + if(item == NULL) { + item = new ListResultItem_t(); + ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, item); + } + currentDevice = item; + isAdded = false; + } + + break; + } + } + + if (pspDevInfoData) { + HeapFree(GetProcessHeap(), 0, pspDevInfoData); + } + + if(hDevInfo) { + DllSetupDiDestroyDeviceInfoList(hDevInfo); + } + + SetEvent(deviceChangedRegisteredEvent); +} diff --git a/vendor/node-usb-native/src/deviceList.cpp b/vendor/node-usb-native/src/deviceList.cpp index 1cdcbdb1e..af9a96a0f 100644 --- a/vendor/node-usb-native/src/deviceList.cpp +++ b/vendor/node-usb-native/src/deviceList.cpp @@ -1,75 +1,75 @@ -#include -#include -#include - -#include "deviceList.h" - - -using namespace std; - -map deviceMap; - -void AddItemToList(char* key, DeviceItem_t * item) { - item->SetKey(key); - deviceMap.insert(pair(item->GetKey(), item)); -} - -void RemoveItemFromList(DeviceItem_t* item) { - deviceMap.erase(item->GetKey()); -} - -DeviceItem_t* GetItemFromList(char* key) { - map::iterator it; - - it = deviceMap.find(key); - if(it == deviceMap.end()) { - return NULL; - } - else { - return it->second; - } -} - -bool IsItemAlreadyStored(char* key) { - map::iterator it; - - it = deviceMap.find(key); - if(it == deviceMap.end()) { - return false; - } - else { - return true; - } - - return true; -} - -ListResultItem_t* CopyElement(ListResultItem_t* item) { - ListResultItem_t* dst = new ListResultItem_t(); - dst->locationId = item->locationId; - dst->vendorId = item->vendorId; - dst->productId = item->productId; - dst->deviceName = item->deviceName; - dst->manufacturer = item->manufacturer; - dst->serialNumber = item->serialNumber; - dst->deviceAddress = item->deviceAddress; - - return dst; -} - -void CreateFilteredList(list *filteredList, int vid, int pid) { - map::iterator it; - - for (it = deviceMap.begin(); it != deviceMap.end(); ++it) { - DeviceItem_t* item = it->second; - - if ( - (( vid != 0 && pid != 0) && (vid == item->deviceParams.vendorId && pid == item->deviceParams.productId)) - || ((vid != 0 && pid == 0) && vid == item->deviceParams.vendorId) - || (vid == 0 && pid == 0) - ) { - (*filteredList).push_back(CopyElement(&item->deviceParams)); - } - - } -} +#include +#include +#include + +#include "deviceList.h" + + +using namespace std; + +map deviceMap; + +void AddItemToList(char* key, DeviceItem_t * item) { + item->SetKey(key); + deviceMap.insert(pair(item->GetKey(), item)); +} + +void RemoveItemFromList(DeviceItem_t* item) { + deviceMap.erase(item->GetKey()); +} + +DeviceItem_t* GetItemFromList(char* key) { + map::iterator it; + + it = deviceMap.find(key); + if(it == deviceMap.end()) { + return NULL; + } + else { + return it->second; + } +} + +bool IsItemAlreadyStored(char* key) { + map::iterator it; + + it = deviceMap.find(key); + if(it == deviceMap.end()) { + return false; + } + else { + return true; + } + + return true; +} + +ListResultItem_t* CopyElement(ListResultItem_t* item) { + ListResultItem_t* dst = new ListResultItem_t(); + dst->locationId = item->locationId; + dst->vendorId = item->vendorId; + dst->productId = item->productId; + dst->deviceName = item->deviceName; + dst->manufacturer = item->manufacturer; + dst->serialNumber = item->serialNumber; + dst->deviceAddress = item->deviceAddress; + + return dst; +} + +void CreateFilteredList(list *filteredList, int vid, int pid) { + map::iterator it; + + for (it = deviceMap.begin(); it != deviceMap.end(); ++it) { + DeviceItem_t* item = it->second; + + if ( + (( vid != 0 && pid != 0) && (vid == item->deviceParams.vendorId && pid == item->deviceParams.productId)) + || ((vid != 0 && pid == 0) && vid == item->deviceParams.vendorId) + || (vid == 0 && pid == 0) + ) { + (*filteredList).push_back(CopyElement(&item->deviceParams)); + } + + } +} diff --git a/vendor/node-usb-native/src/deviceList.h b/vendor/node-usb-native/src/deviceList.h index 23d121bcf..6751e093c 100644 --- a/vendor/node-usb-native/src/deviceList.h +++ b/vendor/node-usb-native/src/deviceList.h @@ -1,63 +1,63 @@ -#ifndef _DEVICE_LIST_H -#define _DEVICE_LIST_H - -#include -#include - -typedef struct { - public: - int locationId; - int vendorId; - int productId; - std::string deviceName; - std::string manufacturer; - std::string serialNumber; - int deviceAddress; -} ListResultItem_t; - -typedef enum _DeviceState_t { - DeviceState_Connect, - DeviceState_Disconnect, -} DeviceState_t; - -typedef struct _DeviceItem_t { - ListResultItem_t deviceParams; - DeviceState_t deviceState; - - private: - char* key; - - - public: - _DeviceItem_t() { - key = NULL; - } - - ~_DeviceItem_t() { - if(this->key != NULL) { - delete this->key; - } - } - - void SetKey(char* key) { - if(this->key != NULL) { - delete this->key; - } - this->key = new char[strlen(key) + 1]; - memcpy(this->key, key, strlen(key) + 1); - } - - char* GetKey() { - return this->key; - } -} DeviceItem_t; - - -void AddItemToList(char* key, DeviceItem_t * item); -void RemoveItemFromList(DeviceItem_t* item); -bool IsItemAlreadyStored(char* identifier); -DeviceItem_t* GetItemFromList(char* key); -ListResultItem_t* CopyElement(ListResultItem_t* item); -void CreateFilteredList(std::list* filteredList, int vid, int pid); - -#endif +#ifndef _DEVICE_LIST_H +#define _DEVICE_LIST_H + +#include +#include + +typedef struct { + public: + int locationId; + int vendorId; + int productId; + std::string deviceName; + std::string manufacturer; + std::string serialNumber; + int deviceAddress; +} ListResultItem_t; + +typedef enum _DeviceState_t { + DeviceState_Connect, + DeviceState_Disconnect, +} DeviceState_t; + +typedef struct _DeviceItem_t { + ListResultItem_t deviceParams; + DeviceState_t deviceState; + + private: + char* key; + + + public: + _DeviceItem_t() { + key = NULL; + } + + ~_DeviceItem_t() { + if(this->key != NULL) { + delete this->key; + } + } + + void SetKey(char* key) { + if(this->key != NULL) { + delete this->key; + } + this->key = new char[strlen(key) + 1]; + memcpy(this->key, key, strlen(key) + 1); + } + + char* GetKey() { + return this->key; + } +} DeviceItem_t; + + +void AddItemToList(char* key, DeviceItem_t * item); +void RemoveItemFromList(DeviceItem_t* item); +bool IsItemAlreadyStored(char* identifier); +DeviceItem_t* GetItemFromList(char* key); +ListResultItem_t* CopyElement(ListResultItem_t* item); +void CreateFilteredList(std::list* filteredList, int vid, int pid); + +#endif diff --git a/vendor/node-usb-native/src/serialport.cpp b/vendor/node-usb-native/src/serialport.cpp index 755037b38..6e9027034 100644 --- a/vendor/node-usb-native/src/serialport.cpp +++ b/vendor/node-usb-native/src/serialport.cpp @@ -1,717 +1,717 @@ -#include "./serialport.h" - -#ifdef WIN32 -#define strncasecmp strnicmp -#else -#include "./serialport_poller.h" -#endif - -struct _WriteQueue { - const int _fd; // the fd that is associated with this write queue - QueuedWrite _write_queue; - uv_mutex_t _write_queue_mutex; - _WriteQueue *_next; - - _WriteQueue(const int fd) : _fd(fd), _write_queue(), _next(NULL) { - uv_mutex_init(&_write_queue_mutex); - } - - void lock() { uv_mutex_lock(&_write_queue_mutex); } - void unlock() { uv_mutex_unlock(&_write_queue_mutex); } - - QueuedWrite &get() { return _write_queue; } -}; - -static _WriteQueue *write_queues = NULL; - -static _WriteQueue *qForFD(const int fd) { - _WriteQueue *q = write_queues; - while (q != NULL) { - if (q->_fd == fd) { - return q; - } - q = q->_next; - } - return NULL; -} - -static _WriteQueue *newQForFD(const int fd) { - _WriteQueue *q = qForFD(fd); - - if (q == NULL) { - if (write_queues == NULL) { - write_queues = new _WriteQueue(fd); - return write_queues; - } else { - q = write_queues; - while (q->_next != NULL) { - q = q->_next; - } - q->_next = new _WriteQueue(fd); - return q->_next; - } - } - - return q; -} - -static void deleteQForFD(const int fd) { - if (write_queues == NULL) - return; - - _WriteQueue *q = write_queues; - if (write_queues->_fd == fd) { - write_queues = write_queues->_next; - delete q; - - return; - } - - while (q->_next != NULL) { - if (q->_next->_fd == fd) { - _WriteQueue *out_q = q->_next; - q->_next = q->_next->_next; - delete out_q; - - return; - } - q = q->_next; - } - - // It wasn't found... -} - -v8::Local getValueFromObject(v8::Local options, std::string key) { - v8::Local v8str = Nan::New(key).ToLocalChecked(); - return Nan::Get(options, v8str).ToLocalChecked(); -} - -int getIntFromObject(v8::Local options, std::string key) { - #if NODE_MAJOR_VERSION >= 10 - return getValueFromObject(options, key)->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - return getValueFromObject(options, key)->ToInt32()->Int32Value(); - #endif -} - -bool getBoolFromObject(v8::Local options, std::string key) { - return getValueFromObject(options, key)->ToBoolean()->BooleanValue(); -} - -v8::Local getStringFromObj(v8::Local options, std::string key) { - return getValueFromObject(options, key)->ToString(); -} - -double getDoubleFromObject(v8::Local options, std::string key) { - #if NODE_MAJOR_VERSION >= 10 - return getValueFromObject(options, key)->ToNumber(v8::Isolate::GetCurrent())->NumberValue(); - #else - return getValueFromObject(options, key)->ToNumber()->NumberValue(); - #endif -} - -NAN_METHOD(Open) { - // path - if (!info[0]->IsString()) { - Nan::ThrowTypeError("First argument must be a string"); - return; - } - v8::String::Utf8Value path(info[0]->ToString()); - - // options - if (!info[1]->IsObject()) { - Nan::ThrowTypeError("Second argument must be an object"); - return; - } - v8::Local options = info[1]->ToObject(); - - // callback - if (!info[2]->IsFunction()) { - Nan::ThrowTypeError("Third argument must be a function"); - return; - } - - OpenBaton* baton = new OpenBaton(); - memset(baton, 0, sizeof(OpenBaton)); - strcpy(baton->path, *path); - baton->baudRate = getIntFromObject(options, "baudRate"); - baton->dataBits = getIntFromObject(options, "dataBits"); - baton->bufferSize = getIntFromObject(options, "bufferSize"); - baton->parity = ToParityEnum(getStringFromObj(options, "parity")); - baton->stopBits = ToStopBitEnum(getDoubleFromObject(options, "stopBits")); - baton->rtscts = getBoolFromObject(options, "rtscts"); - baton->xon = getBoolFromObject(options, "xon"); - baton->xoff = getBoolFromObject(options, "xoff"); - baton->xany = getBoolFromObject(options, "xany"); - baton->hupcl = getBoolFromObject(options, "hupcl"); - baton->lock = getBoolFromObject(options, "lock"); - - v8::Local platformOptions = getValueFromObject(options, "platformOptions")->ToObject(); - baton->platformOptions = ParsePlatformOptions(platformOptions); - - baton->callback.Reset(info[2].As()); - baton->dataCallback = new Nan::Callback(getValueFromObject(options, "dataCallback").As()); - baton->disconnectedCallback = new Nan::Callback(getValueFromObject(options, "disconnectedCallback").As()); - baton->errorCallback = new Nan::Callback(getValueFromObject(options, "errorCallback").As()); - - uv_work_t* req = new uv_work_t(); - req->data = baton; - - uv_queue_work(uv_default_loop(), req, EIO_Open, (uv_after_work_cb)EIO_AfterOpen); - - return; -} - -void EIO_AfterOpen(uv_work_t* req) { - Nan::HandleScope scope; - - OpenBaton* data = static_cast(req->data); - - v8::Local argv[2]; - if (data->errorString[0]) { - argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); - argv[1] = Nan::Undefined(); - // not needed because we're not calling AfterOpenSuccess - delete data->dataCallback; - delete data->errorCallback; - delete data->disconnectedCallback; - } else { - argv[0] = Nan::Null(); - argv[1] = Nan::New(data->result); - - int fd; - #if NODE_MAJOR_VERSION >= 10 - fd = argv[1]->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - fd = argv[1]->ToInt32()->Int32Value(); - #endif - newQForFD(fd); - - AfterOpenSuccess(data->result, data->dataCallback, data->disconnectedCallback, data->errorCallback); - } - - data->callback.Call(2, argv); - - delete data->platformOptions; - delete data; - delete req; -} - -NAN_METHOD(Update) { - // file descriptor - if (!info[0]->IsInt32()) { - Nan::ThrowTypeError("First argument must be an int"); - return; - } - int fd; - #if NODE_MAJOR_VERSION >= 10 - fd = info[0]->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - fd = info[0]->ToInt32()->Int32Value(); - #endif - - // options - if (!info[1]->IsObject()) { - Nan::ThrowTypeError("Second argument must be an object"); - return; - } - v8::Local options = info[1]->ToObject(); - - if (!Nan::Has(options, Nan::New("baudRate").ToLocalChecked()).FromMaybe(false)) { - Nan::ThrowTypeError("baudRate must be set on options object"); - return; - } - - // callback - if (!info[2]->IsFunction()) { - Nan::ThrowTypeError("Third argument must be a function"); - return; - } - - ConnectionOptionsBaton* baton = new ConnectionOptionsBaton(); - memset(baton, 0, sizeof(ConnectionOptionsBaton)); - - baton->fd = fd; - #if NODE_MAJOR_VERSION >= 10 - baton->baudRate = Nan::Get(options, Nan::New("baudRate").ToLocalChecked()).ToLocalChecked()->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - baton->baudRate = Nan::Get(options, Nan::New("baudRate").ToLocalChecked()).ToLocalChecked()->ToInt32()->Int32Value(); - #endif - baton->callback.Reset(info[2].As()); - - uv_work_t* req = new uv_work_t(); - req->data = baton; - - uv_queue_work(uv_default_loop(), req, EIO_Update, (uv_after_work_cb)EIO_AfterUpdate); - - return; -} - -void EIO_AfterUpdate(uv_work_t* req) { - Nan::HandleScope scope; - - ConnectionOptionsBaton* data = static_cast(req->data); - - v8::Local argv[1]; - if (data->errorString[0]) { - argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); - } else { - argv[0] = Nan::Null(); - } - - data->callback.Call(1, argv); - - delete data; - delete req; -} - -NAN_METHOD(Write) { - // file descriptor - if (!info[0]->IsInt32()) { - Nan::ThrowTypeError("First argument must be an int"); - return; - } - int fd; - #if NODE_MAJOR_VERSION >= 10 - fd = info[0]->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - fd = info[0]->ToInt32()->Int32Value(); - #endif - - // buffer - if (!info[1]->IsObject() || !node::Buffer::HasInstance(info[1])) { - Nan::ThrowTypeError("Second argument must be a buffer"); - return; - } - v8::Local buffer = info[1]->ToObject(); - char* bufferData = node::Buffer::Data(buffer); - size_t bufferLength = node::Buffer::Length(buffer); - - // callback - if (!info[2]->IsFunction()) { - Nan::ThrowTypeError("Third argument must be a function"); - return; - } - - WriteBaton* baton = new WriteBaton(); - memset(baton, 0, sizeof(WriteBaton)); - baton->fd = fd; - baton->buffer.Reset(buffer); - baton->bufferData = bufferData; - baton->bufferLength = bufferLength; - baton->offset = 0; - baton->callback.Reset(info[2].As()); - - QueuedWrite* queuedWrite = new QueuedWrite(); - memset(queuedWrite, 0, sizeof(QueuedWrite)); - queuedWrite->baton = baton; - queuedWrite->req.data = queuedWrite; - - _WriteQueue *q = qForFD(fd); - if (!q) { - Nan::ThrowTypeError("There's no write queue for that file descriptor (write)!"); - return; - } - - q->lock(); - QueuedWrite &write_queue = q->get(); - bool empty = write_queue.empty(); - - write_queue.insert_tail(queuedWrite); - - if (empty) { - uv_queue_work(uv_default_loop(), &queuedWrite->req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); - } - q->unlock(); - - return; -} - -void EIO_AfterWrite(uv_work_t* req) { - Nan::HandleScope scope; - - QueuedWrite* queuedWrite = static_cast(req->data); - WriteBaton* data = static_cast(queuedWrite->baton); - - v8::Local argv[1]; - if (data->errorString[0]) { - argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); - } else { - argv[0] = Nan::Null(); - } - - if (data->offset < data->bufferLength && !data->errorString[0]) { - // We're not done with this baton, so throw it right back onto the queue. - // Don't re-push the write in the event loop if there was an error; because same error could occur again! - // TODO: Add a uv_poll here for unix... - // fprintf(stderr, "Write again...\n"); - uv_queue_work(uv_default_loop(), req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); - return; - } - - // throwing errors instead of returning them at this point is rude - int fd = data->fd; - _WriteQueue *q = qForFD(fd); - if (!q) { - Nan::ThrowTypeError("There's no write queue for that file descriptor (after write)!"); - return; - } - - q->lock(); - QueuedWrite &write_queue = q->get(); - - // remove this one from the list - queuedWrite->remove(); - - data->callback.Call(1, argv); - - // If there are any left, start a new thread to write the next one. - if (!write_queue.empty()) { - // Always pull the next work item from the head of the queue - QueuedWrite* nextQueuedWrite = write_queue.next; - uv_queue_work(uv_default_loop(), &nextQueuedWrite->req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); - } - q->unlock(); - - data->buffer.Reset(); - delete data; - delete queuedWrite; -} - -NAN_METHOD(Close) { - // file descriptor - if (!info[0]->IsInt32()) { - Nan::ThrowTypeError("First argument must be an int"); - return; - } - - // callback - if (!info[1]->IsFunction()) { - Nan::ThrowTypeError("Second argument must be a function"); - return; - } - - CloseBaton* baton = new CloseBaton(); - memset(baton, 0, sizeof(CloseBaton)); - #if NODE_MAJOR_VERSION >= 10 - baton->fd = info[0]->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - baton->fd = info[0]->ToInt32()->Int32Value(); - #endif - - baton->callback.Reset(info[1].As()); - - uv_work_t* req = new uv_work_t(); - req->data = baton; - uv_queue_work(uv_default_loop(), req, EIO_Close, (uv_after_work_cb)EIO_AfterClose); - - return; -} - -void EIO_AfterClose(uv_work_t* req) { - Nan::HandleScope scope; - CloseBaton* data = static_cast(req->data); - - v8::Local argv[1]; - if (data->errorString[0]) { - argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); - } else { - argv[0] = Nan::Null(); - - // We don't have an error, so clean up the write queue for that fd - _WriteQueue *q = qForFD(data->fd); - if (q) { - q->lock(); - QueuedWrite &write_queue = q->get(); - while (!write_queue.empty()) { - QueuedWrite *del_q = write_queue.next; - del_q->baton->buffer.Reset(); - del_q->remove(); - } - q->unlock(); - deleteQForFD(data->fd); - } - } - data->callback.Call(1, argv); - - delete data; - delete req; -} - -NAN_METHOD(List) { - // callback - if (!info[0]->IsFunction()) { - Nan::ThrowTypeError("First argument must be a function"); - return; - } - - ListBaton* baton = new ListBaton(); - strcpy(baton->errorString, ""); - baton->callback.Reset(info[0].As()); - - uv_work_t* req = new uv_work_t(); - req->data = baton; - uv_queue_work(uv_default_loop(), req, EIO_List, (uv_after_work_cb)EIO_AfterList); - - return; -} - -void setIfNotEmpty(v8::Local item, std::string key, const char *value) { - v8::Local v8key = Nan::New(key).ToLocalChecked(); - if (strlen(value) > 0) { - Nan::Set(item, v8key, Nan::New(value).ToLocalChecked()); - } else { - Nan::Set(item, v8key, Nan::Undefined()); - } - -} - -void EIO_AfterList(uv_work_t* req) { - Nan::HandleScope scope; - - ListBaton* data = static_cast(req->data); - - v8::Local argv[2]; - if (data->errorString[0]) { - argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); - argv[1] = Nan::Undefined(); - } else { - v8::Local results = Nan::New(); - int i = 0; - for (std::list::iterator it = data->results.begin(); it != data->results.end(); ++it, i++) { - v8::Local item = Nan::New(); - - setIfNotEmpty(item, "comName", (*it)->comName.c_str()); - setIfNotEmpty(item, "manufacturer", (*it)->manufacturer.c_str()); - setIfNotEmpty(item, "serialNumber", (*it)->serialNumber.c_str()); - setIfNotEmpty(item, "pnpId", (*it)->pnpId.c_str()); - setIfNotEmpty(item, "locationId", (*it)->locationId.c_str()); - setIfNotEmpty(item, "vendorId", (*it)->vendorId.c_str()); - setIfNotEmpty(item, "productId", (*it)->productId.c_str()); - - Nan::Set(results, i, item); - } - argv[0] = Nan::Null(); - argv[1] = results; - } - data->callback.Call(2, argv); - - for (std::list::iterator it = data->results.begin(); it != data->results.end(); ++it) { - delete *it; - } - delete data; - delete req; -} - -NAN_METHOD(Flush) { - // file descriptor - if (!info[0]->IsInt32()) { - Nan::ThrowTypeError("First argument must be an int"); - return; - } - int fd; - #if NODE_MAJOR_VERSION >= 10 - fd = info[0]->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - fd = info[0]->ToInt32()->Int32Value(); - #endif - - // callback - if (!info[1]->IsFunction()) { - Nan::ThrowTypeError("Second argument must be a function"); - return; - } - v8::Local callback = info[1].As(); - - FlushBaton* baton = new FlushBaton(); - memset(baton, 0, sizeof(FlushBaton)); - baton->fd = fd; - baton->callback.Reset(callback); - - uv_work_t* req = new uv_work_t(); - req->data = baton; - uv_queue_work(uv_default_loop(), req, EIO_Flush, (uv_after_work_cb)EIO_AfterFlush); - - return; -} - -void EIO_AfterFlush(uv_work_t* req) { - Nan::HandleScope scope; - - FlushBaton* data = static_cast(req->data); - - v8::Local argv[2]; - - if (data->errorString[0]) { - argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); - argv[1] = Nan::Undefined(); - } else { - argv[0] = Nan::Undefined(); - argv[1] = Nan::New(data->result); - } - - data->callback.Call(2, argv); - - delete data; - delete req; -} - -NAN_METHOD(Set) { - // file descriptor - if (!info[0]->IsInt32()) { - Nan::ThrowTypeError("First argument must be an int"); - return; - } - int fd; - #if NODE_MAJOR_VERSION >= 10 - fd = info[0]->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - fd = info[0]->ToInt32()->Int32Value(); - #endif - - // options - if (!info[1]->IsObject()) { - Nan::ThrowTypeError("Second argument must be an object"); - return; - } - v8::Local options = info[1]->ToObject(); - - // callback - if (!info[2]->IsFunction()) { - Nan::ThrowTypeError("Third argument must be a function"); - return; - } - v8::Local callback = info[2].As(); - - SetBaton* baton = new SetBaton(); - memset(baton, 0, sizeof(SetBaton)); - baton->fd = fd; - baton->callback.Reset(callback); - baton->brk = getBoolFromObject(options, "brk"); - baton->rts = getBoolFromObject(options, "rts"); - baton->cts = getBoolFromObject(options, "cts"); - baton->dtr = getBoolFromObject(options, "dtr"); - baton->dsr = getBoolFromObject(options, "dsr"); - - uv_work_t* req = new uv_work_t(); - req->data = baton; - uv_queue_work(uv_default_loop(), req, EIO_Set, (uv_after_work_cb)EIO_AfterSet); - - return; -} - -void EIO_AfterSet(uv_work_t* req) { - Nan::HandleScope scope; - - SetBaton* data = static_cast(req->data); - - v8::Local argv[1]; - - if (data->errorString[0]) { - argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); - } else { - argv[0] = Nan::Null(); - } - data->callback.Call(1, argv); - - delete data; - delete req; -} - -NAN_METHOD(Drain) { - // file descriptor - if (!info[0]->IsInt32()) { - Nan::ThrowTypeError("First argument must be an int"); - return; - } - int fd; - #if NODE_MAJOR_VERSION >= 10 - fd = info[0]->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - fd = info[0]->ToInt32()->Int32Value(); - #endif - - // callback - if (!info[1]->IsFunction()) { - Nan::ThrowTypeError("Second argument must be a function"); - return; - } - - DrainBaton* baton = new DrainBaton(); - memset(baton, 0, sizeof(DrainBaton)); - baton->fd = fd; - baton->callback.Reset(info[1].As()); - - uv_work_t* req = new uv_work_t(); - req->data = baton; - uv_queue_work(uv_default_loop(), req, EIO_Drain, (uv_after_work_cb)EIO_AfterDrain); - - return; -} - -void EIO_AfterDrain(uv_work_t* req) { - Nan::HandleScope scope; - - DrainBaton* data = static_cast(req->data); - - v8::Local argv[1]; - - if (data->errorString[0]) { - argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); - } else { - argv[0] = Nan::Null(); - } - data->callback.Call(1, argv); - - delete data; - delete req; -} - -SerialPortParity NAN_INLINE(ToParityEnum(const v8::Local& v8str)) { - Nan::HandleScope scope; - Nan::Utf8String str(v8str); - size_t count = strlen(*str); - SerialPortParity parity = SERIALPORT_PARITY_NONE; - if (!strncasecmp(*str, "none", count)) { - parity = SERIALPORT_PARITY_NONE; - } else if (!strncasecmp(*str, "even", count)) { - parity = SERIALPORT_PARITY_EVEN; - } else if (!strncasecmp(*str, "mark", count)) { - parity = SERIALPORT_PARITY_MARK; - } else if (!strncasecmp(*str, "odd", count)) { - parity = SERIALPORT_PARITY_ODD; - } else if (!strncasecmp(*str, "space", count)) { - parity = SERIALPORT_PARITY_SPACE; - } - return parity; -} - -SerialPortStopBits NAN_INLINE(ToStopBitEnum(double stopBits)) { - if (stopBits > 1.4 && stopBits < 1.6) { - return SERIALPORT_STOPBITS_ONE_FIVE; - } - if (stopBits == 2) { - return SERIALPORT_STOPBITS_TWO; - } - return SERIALPORT_STOPBITS_ONE; -} - -extern "C" { - void init_serialport(v8::Handle target) { - Nan::HandleScope scope; - Nan::SetMethod(target, "set", Set); - Nan::SetMethod(target, "open", Open); - Nan::SetMethod(target, "update", Update); - Nan::SetMethod(target, "write", Write); - Nan::SetMethod(target, "close", Close); - Nan::SetMethod(target, "list", List); - Nan::SetMethod(target, "flush", Flush); - Nan::SetMethod(target, "drain", Drain); - -#ifndef WIN32 - SerialportPoller::Init(target); -#endif - } -} - -//NODE_MODULE(serialport, init); +#include "./serialport.h" + +#ifdef WIN32 +#define strncasecmp strnicmp +#else +#include "./serialport_poller.h" +#endif + +struct _WriteQueue { + const int _fd; // the fd that is associated with this write queue + QueuedWrite _write_queue; + uv_mutex_t _write_queue_mutex; + _WriteQueue *_next; + + _WriteQueue(const int fd) : _fd(fd), _write_queue(), _next(NULL) { + uv_mutex_init(&_write_queue_mutex); + } + + void lock() { uv_mutex_lock(&_write_queue_mutex); } + void unlock() { uv_mutex_unlock(&_write_queue_mutex); } + + QueuedWrite &get() { return _write_queue; } +}; + +static _WriteQueue *write_queues = NULL; + +static _WriteQueue *qForFD(const int fd) { + _WriteQueue *q = write_queues; + while (q != NULL) { + if (q->_fd == fd) { + return q; + } + q = q->_next; + } + return NULL; +} + +static _WriteQueue *newQForFD(const int fd) { + _WriteQueue *q = qForFD(fd); + + if (q == NULL) { + if (write_queues == NULL) { + write_queues = new _WriteQueue(fd); + return write_queues; + } else { + q = write_queues; + while (q->_next != NULL) { + q = q->_next; + } + q->_next = new _WriteQueue(fd); + return q->_next; + } + } + + return q; +} + +static void deleteQForFD(const int fd) { + if (write_queues == NULL) + return; + + _WriteQueue *q = write_queues; + if (write_queues->_fd == fd) { + write_queues = write_queues->_next; + delete q; + + return; + } + + while (q->_next != NULL) { + if (q->_next->_fd == fd) { + _WriteQueue *out_q = q->_next; + q->_next = q->_next->_next; + delete out_q; + + return; + } + q = q->_next; + } + + // It wasn't found... +} + +v8::Local getValueFromObject(v8::Local options, std::string key) { + v8::Local v8str = Nan::New(key).ToLocalChecked(); + return Nan::Get(options, v8str).ToLocalChecked(); +} + +int getIntFromObject(v8::Local options, std::string key) { + #if NODE_MAJOR_VERSION >= 10 + return Nan::To(getValueFromObject(options, key)).ToLocalChecked()->Value(); + #else + return getValueFromObject(options, key)->ToInt32()->Int32Value(); + #endif +} + +bool getBoolFromObject(v8::Local options, std::string key) { + return getValueFromObject(options, key)->ToBoolean()->BooleanValue(); +} + +v8::Local getStringFromObj(v8::Local options, std::string key) { + return getValueFromObject(options, key)->ToString(); +} + +double getDoubleFromObject(v8::Local options, std::string key) { + #if NODE_MAJOR_VERSION >= 10 + return Nan::To(getValueFromObject(options, key)).FromMaybe(0); + #else + return getValueFromObject(options, key)->ToNumber()->NumberValue(); + #endif +} + +NAN_METHOD(Open) { + // path + if (!info[0]->IsString()) { + Nan::ThrowTypeError("First argument must be a string"); + return; + } + v8::String::Utf8Value path(info[0]->ToString()); + + // options + if (!info[1]->IsObject()) { + Nan::ThrowTypeError("Second argument must be an object"); + return; + } + v8::Local options = info[1]->ToObject(); + + // callback + if (!info[2]->IsFunction()) { + Nan::ThrowTypeError("Third argument must be a function"); + return; + } + + OpenBaton* baton = new OpenBaton(); + memset(baton, 0, sizeof(OpenBaton)); + strcpy(baton->path, *path); + baton->baudRate = getIntFromObject(options, "baudRate"); + baton->dataBits = getIntFromObject(options, "dataBits"); + baton->bufferSize = getIntFromObject(options, "bufferSize"); + baton->parity = ToParityEnum(getStringFromObj(options, "parity")); + baton->stopBits = ToStopBitEnum(getDoubleFromObject(options, "stopBits")); + baton->rtscts = getBoolFromObject(options, "rtscts"); + baton->xon = getBoolFromObject(options, "xon"); + baton->xoff = getBoolFromObject(options, "xoff"); + baton->xany = getBoolFromObject(options, "xany"); + baton->hupcl = getBoolFromObject(options, "hupcl"); + baton->lock = getBoolFromObject(options, "lock"); + + v8::Local platformOptions = getValueFromObject(options, "platformOptions")->ToObject(); + baton->platformOptions = ParsePlatformOptions(platformOptions); + + baton->callback.Reset(info[2].As()); + baton->dataCallback = new Nan::Callback(getValueFromObject(options, "dataCallback").As()); + baton->disconnectedCallback = new Nan::Callback(getValueFromObject(options, "disconnectedCallback").As()); + baton->errorCallback = new Nan::Callback(getValueFromObject(options, "errorCallback").As()); + + uv_work_t* req = new uv_work_t(); + req->data = baton; + + uv_queue_work(uv_default_loop(), req, EIO_Open, (uv_after_work_cb)EIO_AfterOpen); + + return; +} + +void EIO_AfterOpen(uv_work_t* req) { + Nan::HandleScope scope; + + OpenBaton* data = static_cast(req->data); + + v8::Local argv[2]; + if (data->errorString[0]) { + argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); + argv[1] = Nan::Undefined(); + // not needed because we're not calling AfterOpenSuccess + delete data->dataCallback; + delete data->errorCallback; + delete data->disconnectedCallback; + } else { + argv[0] = Nan::Null(); + argv[1] = Nan::New(data->result); + + int fd; + #if NODE_MAJOR_VERSION >= 10 + fd = argv[1]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + #else + fd = argv[1]->ToInt32()->Int32Value(); + #endif + newQForFD(fd); + + AfterOpenSuccess(data->result, data->dataCallback, data->disconnectedCallback, data->errorCallback); + } + + data->callback.Call(2, argv); + + delete data->platformOptions; + delete data; + delete req; +} + +NAN_METHOD(Update) { + // file descriptor + if (!info[0]->IsInt32()) { + Nan::ThrowTypeError("First argument must be an int"); + return; + } + int fd; + #if NODE_MAJOR_VERSION >= 10 + fd = info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + #else + fd = info[0]->ToInt32()->Int32Value(); + #endif + + // options + if (!info[1]->IsObject()) { + Nan::ThrowTypeError("Second argument must be an object"); + return; + } + v8::Local options = info[1]->ToObject(); + + if (!Nan::Has(options, Nan::New("baudRate").ToLocalChecked()).FromMaybe(false)) { + Nan::ThrowTypeError("baudRate must be set on options object"); + return; + } + + // callback + if (!info[2]->IsFunction()) { + Nan::ThrowTypeError("Third argument must be a function"); + return; + } + + ConnectionOptionsBaton* baton = new ConnectionOptionsBaton(); + memset(baton, 0, sizeof(ConnectionOptionsBaton)); + + baton->fd = fd; + #if NODE_MAJOR_VERSION >= 10 + baton->baudRate = Nan::Get(options, Nan::New("baudRate").ToLocalChecked()).ToLocalChecked()->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + #else + baton->baudRate = Nan::Get(options, Nan::New("baudRate").ToLocalChecked()).ToLocalChecked()->ToInt32()->Int32Value(); + #endif + baton->callback.Reset(info[2].As()); + + uv_work_t* req = new uv_work_t(); + req->data = baton; + + uv_queue_work(uv_default_loop(), req, EIO_Update, (uv_after_work_cb)EIO_AfterUpdate); + + return; +} + +void EIO_AfterUpdate(uv_work_t* req) { + Nan::HandleScope scope; + + ConnectionOptionsBaton* data = static_cast(req->data); + + v8::Local argv[1]; + if (data->errorString[0]) { + argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); + } else { + argv[0] = Nan::Null(); + } + + data->callback.Call(1, argv); + + delete data; + delete req; +} + +NAN_METHOD(Write) { + // file descriptor + if (!info[0]->IsInt32()) { + Nan::ThrowTypeError("First argument must be an int"); + return; + } + int fd; + #if NODE_MAJOR_VERSION >= 10 + fd = info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + #else + fd = info[0]->ToInt32()->Int32Value(); + #endif + + // buffer + if (!info[1]->IsObject() || !node::Buffer::HasInstance(info[1])) { + Nan::ThrowTypeError("Second argument must be a buffer"); + return; + } + v8::Local buffer = info[1]->ToObject(); + char* bufferData = node::Buffer::Data(buffer); + size_t bufferLength = node::Buffer::Length(buffer); + + // callback + if (!info[2]->IsFunction()) { + Nan::ThrowTypeError("Third argument must be a function"); + return; + } + + WriteBaton* baton = new WriteBaton(); + memset(baton, 0, sizeof(WriteBaton)); + baton->fd = fd; + baton->buffer.Reset(buffer); + baton->bufferData = bufferData; + baton->bufferLength = bufferLength; + baton->offset = 0; + baton->callback.Reset(info[2].As()); + + QueuedWrite* queuedWrite = new QueuedWrite(); + memset(queuedWrite, 0, sizeof(QueuedWrite)); + queuedWrite->baton = baton; + queuedWrite->req.data = queuedWrite; + + _WriteQueue *q = qForFD(fd); + if (!q) { + Nan::ThrowTypeError("There's no write queue for that file descriptor (write)!"); + return; + } + + q->lock(); + QueuedWrite &write_queue = q->get(); + bool empty = write_queue.empty(); + + write_queue.insert_tail(queuedWrite); + + if (empty) { + uv_queue_work(uv_default_loop(), &queuedWrite->req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); + } + q->unlock(); + + return; +} + +void EIO_AfterWrite(uv_work_t* req) { + Nan::HandleScope scope; + + QueuedWrite* queuedWrite = static_cast(req->data); + WriteBaton* data = static_cast(queuedWrite->baton); + + v8::Local argv[1]; + if (data->errorString[0]) { + argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); + } else { + argv[0] = Nan::Null(); + } + + if (data->offset < data->bufferLength && !data->errorString[0]) { + // We're not done with this baton, so throw it right back onto the queue. + // Don't re-push the write in the event loop if there was an error; because same error could occur again! + // TODO: Add a uv_poll here for unix... + // fprintf(stderr, "Write again...\n"); + uv_queue_work(uv_default_loop(), req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); + return; + } + + // throwing errors instead of returning them at this point is rude + int fd = data->fd; + _WriteQueue *q = qForFD(fd); + if (!q) { + Nan::ThrowTypeError("There's no write queue for that file descriptor (after write)!"); + return; + } + + q->lock(); + QueuedWrite &write_queue = q->get(); + + // remove this one from the list + queuedWrite->remove(); + + data->callback.Call(1, argv); + + // If there are any left, start a new thread to write the next one. + if (!write_queue.empty()) { + // Always pull the next work item from the head of the queue + QueuedWrite* nextQueuedWrite = write_queue.next; + uv_queue_work(uv_default_loop(), &nextQueuedWrite->req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); + } + q->unlock(); + + data->buffer.Reset(); + delete data; + delete queuedWrite; +} + +NAN_METHOD(Close) { + // file descriptor + if (!info[0]->IsInt32()) { + Nan::ThrowTypeError("First argument must be an int"); + return; + } + + // callback + if (!info[1]->IsFunction()) { + Nan::ThrowTypeError("Second argument must be a function"); + return; + } + + CloseBaton* baton = new CloseBaton(); + memset(baton, 0, sizeof(CloseBaton)); + #if NODE_MAJOR_VERSION >= 10 + baton->fd = info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + #else + baton->fd = info[0]->ToInt32()->Int32Value(); + #endif + + baton->callback.Reset(info[1].As()); + + uv_work_t* req = new uv_work_t(); + req->data = baton; + uv_queue_work(uv_default_loop(), req, EIO_Close, (uv_after_work_cb)EIO_AfterClose); + + return; +} + +void EIO_AfterClose(uv_work_t* req) { + Nan::HandleScope scope; + CloseBaton* data = static_cast(req->data); + + v8::Local argv[1]; + if (data->errorString[0]) { + argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); + } else { + argv[0] = Nan::Null(); + + // We don't have an error, so clean up the write queue for that fd + _WriteQueue *q = qForFD(data->fd); + if (q) { + q->lock(); + QueuedWrite &write_queue = q->get(); + while (!write_queue.empty()) { + QueuedWrite *del_q = write_queue.next; + del_q->baton->buffer.Reset(); + del_q->remove(); + } + q->unlock(); + deleteQForFD(data->fd); + } + } + data->callback.Call(1, argv); + + delete data; + delete req; +} + +NAN_METHOD(List) { + // callback + if (!info[0]->IsFunction()) { + Nan::ThrowTypeError("First argument must be a function"); + return; + } + + ListBaton* baton = new ListBaton(); + strcpy(baton->errorString, ""); + baton->callback.Reset(info[0].As()); + + uv_work_t* req = new uv_work_t(); + req->data = baton; + uv_queue_work(uv_default_loop(), req, EIO_List, (uv_after_work_cb)EIO_AfterList); + + return; +} + +void setIfNotEmpty(v8::Local item, std::string key, const char *value) { + v8::Local v8key = Nan::New(key).ToLocalChecked(); + if (strlen(value) > 0) { + Nan::Set(item, v8key, Nan::New(value).ToLocalChecked()); + } else { + Nan::Set(item, v8key, Nan::Undefined()); + } + +} + +void EIO_AfterList(uv_work_t* req) { + Nan::HandleScope scope; + + ListBaton* data = static_cast(req->data); + + v8::Local argv[2]; + if (data->errorString[0]) { + argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); + argv[1] = Nan::Undefined(); + } else { + v8::Local results = Nan::New(); + int i = 0; + for (std::list::iterator it = data->results.begin(); it != data->results.end(); ++it, i++) { + v8::Local item = Nan::New(); + + setIfNotEmpty(item, "comName", (*it)->comName.c_str()); + setIfNotEmpty(item, "manufacturer", (*it)->manufacturer.c_str()); + setIfNotEmpty(item, "serialNumber", (*it)->serialNumber.c_str()); + setIfNotEmpty(item, "pnpId", (*it)->pnpId.c_str()); + setIfNotEmpty(item, "locationId", (*it)->locationId.c_str()); + setIfNotEmpty(item, "vendorId", (*it)->vendorId.c_str()); + setIfNotEmpty(item, "productId", (*it)->productId.c_str()); + + Nan::Set(results, i, item); + } + argv[0] = Nan::Null(); + argv[1] = results; + } + data->callback.Call(2, argv); + + for (std::list::iterator it = data->results.begin(); it != data->results.end(); ++it) { + delete *it; + } + delete data; + delete req; +} + +NAN_METHOD(Flush) { + // file descriptor + if (!info[0]->IsInt32()) { + Nan::ThrowTypeError("First argument must be an int"); + return; + } + int fd; + #if NODE_MAJOR_VERSION >= 10 + fd = info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + #else + fd = info[0]->ToInt32()->Int32Value(); + #endif + + // callback + if (!info[1]->IsFunction()) { + Nan::ThrowTypeError("Second argument must be a function"); + return; + } + v8::Local callback = info[1].As(); + + FlushBaton* baton = new FlushBaton(); + memset(baton, 0, sizeof(FlushBaton)); + baton->fd = fd; + baton->callback.Reset(callback); + + uv_work_t* req = new uv_work_t(); + req->data = baton; + uv_queue_work(uv_default_loop(), req, EIO_Flush, (uv_after_work_cb)EIO_AfterFlush); + + return; +} + +void EIO_AfterFlush(uv_work_t* req) { + Nan::HandleScope scope; + + FlushBaton* data = static_cast(req->data); + + v8::Local argv[2]; + + if (data->errorString[0]) { + argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); + argv[1] = Nan::Undefined(); + } else { + argv[0] = Nan::Undefined(); + argv[1] = Nan::New(data->result); + } + + data->callback.Call(2, argv); + + delete data; + delete req; +} + +NAN_METHOD(Set) { + // file descriptor + if (!info[0]->IsInt32()) { + Nan::ThrowTypeError("First argument must be an int"); + return; + } + int fd; + #if NODE_MAJOR_VERSION >= 10 + fd = info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + #else + fd = info[0]->ToInt32()->Int32Value(); + #endif + + // options + if (!info[1]->IsObject()) { + Nan::ThrowTypeError("Second argument must be an object"); + return; + } + v8::Local options = info[1]->ToObject(); + + // callback + if (!info[2]->IsFunction()) { + Nan::ThrowTypeError("Third argument must be a function"); + return; + } + v8::Local callback = info[2].As(); + + SetBaton* baton = new SetBaton(); + memset(baton, 0, sizeof(SetBaton)); + baton->fd = fd; + baton->callback.Reset(callback); + baton->brk = getBoolFromObject(options, "brk"); + baton->rts = getBoolFromObject(options, "rts"); + baton->cts = getBoolFromObject(options, "cts"); + baton->dtr = getBoolFromObject(options, "dtr"); + baton->dsr = getBoolFromObject(options, "dsr"); + + uv_work_t* req = new uv_work_t(); + req->data = baton; + uv_queue_work(uv_default_loop(), req, EIO_Set, (uv_after_work_cb)EIO_AfterSet); + + return; +} + +void EIO_AfterSet(uv_work_t* req) { + Nan::HandleScope scope; + + SetBaton* data = static_cast(req->data); + + v8::Local argv[1]; + + if (data->errorString[0]) { + argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); + } else { + argv[0] = Nan::Null(); + } + data->callback.Call(1, argv); + + delete data; + delete req; +} + +NAN_METHOD(Drain) { + // file descriptor + if (!info[0]->IsInt32()) { + Nan::ThrowTypeError("First argument must be an int"); + return; + } + int fd; + #if NODE_MAJOR_VERSION >= 10 + fd = info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + #else + fd = info[0]->ToInt32()->Int32Value(); + #endif + + // callback + if (!info[1]->IsFunction()) { + Nan::ThrowTypeError("Second argument must be a function"); + return; + } + + DrainBaton* baton = new DrainBaton(); + memset(baton, 0, sizeof(DrainBaton)); + baton->fd = fd; + baton->callback.Reset(info[1].As()); + + uv_work_t* req = new uv_work_t(); + req->data = baton; + uv_queue_work(uv_default_loop(), req, EIO_Drain, (uv_after_work_cb)EIO_AfterDrain); + + return; +} + +void EIO_AfterDrain(uv_work_t* req) { + Nan::HandleScope scope; + + DrainBaton* data = static_cast(req->data); + + v8::Local argv[1]; + + if (data->errorString[0]) { + argv[0] = v8::Exception::Error(Nan::New(data->errorString).ToLocalChecked()); + } else { + argv[0] = Nan::Null(); + } + data->callback.Call(1, argv); + + delete data; + delete req; +} + +SerialPortParity NAN_INLINE(ToParityEnum(const v8::Local& v8str)) { + Nan::HandleScope scope; + Nan::Utf8String str(v8str); + size_t count = strlen(*str); + SerialPortParity parity = SERIALPORT_PARITY_NONE; + if (!strncasecmp(*str, "none", count)) { + parity = SERIALPORT_PARITY_NONE; + } else if (!strncasecmp(*str, "even", count)) { + parity = SERIALPORT_PARITY_EVEN; + } else if (!strncasecmp(*str, "mark", count)) { + parity = SERIALPORT_PARITY_MARK; + } else if (!strncasecmp(*str, "odd", count)) { + parity = SERIALPORT_PARITY_ODD; + } else if (!strncasecmp(*str, "space", count)) { + parity = SERIALPORT_PARITY_SPACE; + } + return parity; +} + +SerialPortStopBits NAN_INLINE(ToStopBitEnum(double stopBits)) { + if (stopBits > 1.4 && stopBits < 1.6) { + return SERIALPORT_STOPBITS_ONE_FIVE; + } + if (stopBits == 2) { + return SERIALPORT_STOPBITS_TWO; + } + return SERIALPORT_STOPBITS_ONE; +} + +extern "C" { + void init_serialport( v8::Local target) { + Nan::HandleScope scope; + Nan::SetMethod(target, "set", Set); + Nan::SetMethod(target, "open", Open); + Nan::SetMethod(target, "update", Update); + Nan::SetMethod(target, "write", Write); + Nan::SetMethod(target, "close", Close); + Nan::SetMethod(target, "list", List); + Nan::SetMethod(target, "flush", Flush); + Nan::SetMethod(target, "drain", Drain); + +#ifndef WIN32 + SerialportPoller::Init(target); +#endif + } +} + +//NODE_MODULE(serialport, init); diff --git a/vendor/node-usb-native/src/serialport.h b/vendor/node-usb-native/src/serialport.h index 392fc2017..883ef9b05 100644 --- a/vendor/node-usb-native/src/serialport.h +++ b/vendor/node-usb-native/src/serialport.h @@ -1,195 +1,195 @@ -#ifndef SRC_SERIALPORT_H_ -#define SRC_SERIALPORT_H_ - -#include -#include -#include -#include -#include -#include - -#define ERROR_STRING_SIZE 1024 - -NAN_METHOD(List); -void EIO_List(uv_work_t* req); -void EIO_AfterList(uv_work_t* req); - -NAN_METHOD(Open); -void EIO_Open(uv_work_t* req); -void EIO_AfterOpen(uv_work_t* req); -void AfterOpenSuccess(int fd, Nan::Callback* dataCallback, Nan::Callback* disconnectedCallback, Nan::Callback* errorCallback); - -NAN_METHOD(Update); -void EIO_Update(uv_work_t* req); -void EIO_AfterUpdate(uv_work_t* req); - -NAN_METHOD(Write); -void EIO_Write(uv_work_t* req); -void EIO_AfterWrite(uv_work_t* req); - -NAN_METHOD(Close); -void EIO_Close(uv_work_t* req); -void EIO_AfterClose(uv_work_t* req); - -NAN_METHOD(Flush); -void EIO_Flush(uv_work_t* req); -void EIO_AfterFlush(uv_work_t* req); - -NAN_METHOD(Set); -void EIO_Set(uv_work_t* req); -void EIO_AfterSet(uv_work_t* req); - -NAN_METHOD(Drain); -void EIO_Drain(uv_work_t* req); -void EIO_AfterDrain(uv_work_t* req); - -enum SerialPortParity { - SERIALPORT_PARITY_NONE = 1, - SERIALPORT_PARITY_MARK = 2, - SERIALPORT_PARITY_EVEN = 3, - SERIALPORT_PARITY_ODD = 4, - SERIALPORT_PARITY_SPACE = 5 -}; - -enum SerialPortStopBits { - SERIALPORT_STOPBITS_ONE = 1, - SERIALPORT_STOPBITS_ONE_FIVE = 2, - SERIALPORT_STOPBITS_TWO = 3 -}; - -SerialPortParity ToParityEnum(const v8::Local& str); -SerialPortStopBits ToStopBitEnum(double stopBits); - -struct OpenBatonPlatformOptions { }; -OpenBatonPlatformOptions* ParsePlatformOptions(const v8::Local& options); - -struct OpenBaton { - char errorString[ERROR_STRING_SIZE]; - Nan::Callback callback; - char path[1024]; - int fd; - int result; - int baudRate; - int dataBits; - int bufferSize; - bool rtscts; - bool xon; - bool xoff; - bool xany; - bool dsrdtr; - bool hupcl; - bool lock; - Nan::Callback* dataCallback; - Nan::Callback* disconnectedCallback; - Nan::Callback* errorCallback; - SerialPortParity parity; - SerialPortStopBits stopBits; - OpenBatonPlatformOptions* platformOptions; -}; - -struct ConnectionOptionsBaton { - char errorString[ERROR_STRING_SIZE]; - Nan::Callback callback; - int fd; - int baudRate; -}; - -struct WriteBaton { - int fd; - char* bufferData; - size_t bufferLength; - size_t offset; - Nan::Persistent buffer; - Nan::Callback callback; - int result; - char errorString[ERROR_STRING_SIZE]; -}; - -struct QueuedWrite { - uv_work_t req; - QueuedWrite *prev; - QueuedWrite *next; - WriteBaton* baton; - - QueuedWrite() { - prev = this; - next = this; - - baton = 0; - } - - ~QueuedWrite() { - remove(); - } - - void remove() { - prev->next = next; - next->prev = prev; - - next = this; - prev = this; - } - - void insert_tail(QueuedWrite *qw) { - qw->next = this; - qw->prev = this->prev; - qw->prev->next = qw; - this->prev = qw; - } - - bool empty() { - return next == this; - } -}; - -struct CloseBaton { - int fd; - Nan::Callback callback; - char errorString[ERROR_STRING_SIZE]; -}; - -struct ListResultItem { - std::string comName; - std::string manufacturer; - std::string serialNumber; - std::string pnpId; - std::string locationId; - std::string vendorId; - std::string productId; -}; - -struct ListBaton { - Nan::Callback callback; - std::list results; - char errorString[ERROR_STRING_SIZE]; -}; - -struct FlushBaton { - int fd; - Nan::Callback callback; - int result; - char errorString[ERROR_STRING_SIZE]; -}; - -struct SetBaton { - int fd; - Nan::Callback callback; - int result; - char errorString[ERROR_STRING_SIZE]; - bool rts; - bool cts; - bool dtr; - bool dsr; - bool brk; -}; - -struct DrainBaton { - int fd; - Nan::Callback callback; - int result; - char errorString[ERROR_STRING_SIZE]; -}; - -int setup(int fd, OpenBaton *data); -int setBaudRate(ConnectionOptionsBaton *data); -#endif // SRC_SERIALPORT_H_ +#ifndef SRC_SERIALPORT_H_ +#define SRC_SERIALPORT_H_ + +#include +#include +#include +#include +#include +#include + +#define ERROR_STRING_SIZE 1024 + +NAN_METHOD(List); +void EIO_List(uv_work_t* req); +void EIO_AfterList(uv_work_t* req); + +NAN_METHOD(Open); +void EIO_Open(uv_work_t* req); +void EIO_AfterOpen(uv_work_t* req); +void AfterOpenSuccess(int fd, Nan::Callback* dataCallback, Nan::Callback* disconnectedCallback, Nan::Callback* errorCallback); + +NAN_METHOD(Update); +void EIO_Update(uv_work_t* req); +void EIO_AfterUpdate(uv_work_t* req); + +NAN_METHOD(Write); +void EIO_Write(uv_work_t* req); +void EIO_AfterWrite(uv_work_t* req); + +NAN_METHOD(Close); +void EIO_Close(uv_work_t* req); +void EIO_AfterClose(uv_work_t* req); + +NAN_METHOD(Flush); +void EIO_Flush(uv_work_t* req); +void EIO_AfterFlush(uv_work_t* req); + +NAN_METHOD(Set); +void EIO_Set(uv_work_t* req); +void EIO_AfterSet(uv_work_t* req); + +NAN_METHOD(Drain); +void EIO_Drain(uv_work_t* req); +void EIO_AfterDrain(uv_work_t* req); + +enum SerialPortParity { + SERIALPORT_PARITY_NONE = 1, + SERIALPORT_PARITY_MARK = 2, + SERIALPORT_PARITY_EVEN = 3, + SERIALPORT_PARITY_ODD = 4, + SERIALPORT_PARITY_SPACE = 5 +}; + +enum SerialPortStopBits { + SERIALPORT_STOPBITS_ONE = 1, + SERIALPORT_STOPBITS_ONE_FIVE = 2, + SERIALPORT_STOPBITS_TWO = 3 +}; + +SerialPortParity ToParityEnum(const v8::Local& str); +SerialPortStopBits ToStopBitEnum(double stopBits); + +struct OpenBatonPlatformOptions { }; +OpenBatonPlatformOptions* ParsePlatformOptions(const v8::Local& options); + +struct OpenBaton { + char errorString[ERROR_STRING_SIZE]; + Nan::Callback callback; + char path[1024]; + int fd; + int result; + int baudRate; + int dataBits; + int bufferSize; + bool rtscts; + bool xon; + bool xoff; + bool xany; + bool dsrdtr; + bool hupcl; + bool lock; + Nan::Callback* dataCallback; + Nan::Callback* disconnectedCallback; + Nan::Callback* errorCallback; + SerialPortParity parity; + SerialPortStopBits stopBits; + OpenBatonPlatformOptions* platformOptions; +}; + +struct ConnectionOptionsBaton { + char errorString[ERROR_STRING_SIZE]; + Nan::Callback callback; + int fd; + int baudRate; +}; + +struct WriteBaton { + int fd; + char* bufferData; + size_t bufferLength; + size_t offset; + Nan::Persistent buffer; + Nan::Callback callback; + int result; + char errorString[ERROR_STRING_SIZE]; +}; + +struct QueuedWrite { + uv_work_t req; + QueuedWrite *prev; + QueuedWrite *next; + WriteBaton* baton; + + QueuedWrite() { + prev = this; + next = this; + + baton = 0; + } + + ~QueuedWrite() { + remove(); + } + + void remove() { + prev->next = next; + next->prev = prev; + + next = this; + prev = this; + } + + void insert_tail(QueuedWrite *qw) { + qw->next = this; + qw->prev = this->prev; + qw->prev->next = qw; + this->prev = qw; + } + + bool empty() { + return next == this; + } +}; + +struct CloseBaton { + int fd; + Nan::Callback callback; + char errorString[ERROR_STRING_SIZE]; +}; + +struct ListResultItem { + std::string comName; + std::string manufacturer; + std::string serialNumber; + std::string pnpId; + std::string locationId; + std::string vendorId; + std::string productId; +}; + +struct ListBaton { + Nan::Callback callback; + std::list results; + char errorString[ERROR_STRING_SIZE]; +}; + +struct FlushBaton { + int fd; + Nan::Callback callback; + int result; + char errorString[ERROR_STRING_SIZE]; +}; + +struct SetBaton { + int fd; + Nan::Callback callback; + int result; + char errorString[ERROR_STRING_SIZE]; + bool rts; + bool cts; + bool dtr; + bool dsr; + bool brk; +}; + +struct DrainBaton { + int fd; + Nan::Callback callback; + int result; + char errorString[ERROR_STRING_SIZE]; +}; + +int setup(int fd, OpenBaton *data); +int setBaudRate(ConnectionOptionsBaton *data); +#endif // SRC_SERIALPORT_H_ diff --git a/vendor/node-usb-native/src/serialport_poller.cpp b/vendor/node-usb-native/src/serialport_poller.cpp index 7471f2a38..b7db5af67 100644 --- a/vendor/node-usb-native/src/serialport_poller.cpp +++ b/vendor/node-usb-native/src/serialport_poller.cpp @@ -1,128 +1,128 @@ -// Copyright (C) 2013 Robert Giseburt -// serialport_poller.cpp Written as a part of https://github.com/voodootikigod/node-serialport -// License to use this is the same as that of node-serialport. - -#include -#include "./serialport_poller.h" - -using namespace v8; - -static Nan::Persistent serialportpoller_constructor; - -SerialportPoller::SerialportPoller() : Nan::ObjectWrap() {} -SerialportPoller::~SerialportPoller() { - // printf("~SerialportPoller\n"); - delete callback_; -} - -void _serialportReadable(uv_poll_t *req, int status, int events) { - SerialportPoller* sp = (SerialportPoller*) req->data; - // We can stop polling until we have read all of the data... - sp->_stop(); - sp->callCallback(status); -} - -void SerialportPoller::callCallback(int status) { - Nan::HandleScope scope; - // uv_work_t* req = new uv_work_t; - - // Call the callback to go read more data... - - v8::Local argv[1]; - if (status != 0) { - // error handling changed in libuv, see: - // https://github.com/joyent/libuv/commit/3ee4d3f183331 - #ifdef UV_ERRNO_H_ - const char* err_string = uv_strerror(status); - #else - uv_err_t errno = uv_last_error(uv_default_loop()); - const char* err_string = uv_strerror(errno); - #endif - snprintf(this->errorString, sizeof(this->errorString), "Error %s on polling", err_string); - argv[0] = v8::Exception::Error(Nan::New(this->errorString).ToLocalChecked()); - } else { - argv[0] = Nan::Undefined(); - } - - callback_->Call(1, argv); -} - - - -void SerialportPoller::Init(Handle target) { - Nan::HandleScope scope; - - // Prepare constructor template - Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("SerialportPoller").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - - // Prototype - - // SerialportPoller.close() - Nan::SetPrototypeMethod(tpl, "close", Close); - - // SerialportPoller.start() - Nan::SetPrototypeMethod(tpl, "start", Start); - - serialportpoller_constructor.Reset(tpl); - - Nan::Set(target, Nan::New("SerialportPoller").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked()); -} - -NAN_METHOD(SerialportPoller::New) { - if (!info[0]->IsInt32()) { - Nan::ThrowTypeError("First argument must be an fd"); - return; - } - - if (!info[1]->IsFunction()) { - Nan::ThrowTypeError("Third argument must be a function"); - return; - } - - SerialportPoller* obj = new SerialportPoller(); - #if NODE_MAJOR_VERSION >= 10 - obj->fd_ = info[0]->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - obj->fd_ = info[0]->ToInt32()->Int32Value(); - #endif - obj->callback_ = new Nan::Callback(info[1].As()); - // obj->callCallback(); - - obj->Wrap(info.This()); - - obj->poll_handle_.data = obj; - - uv_poll_init(uv_default_loop(), &obj->poll_handle_, obj->fd_); - - uv_poll_start(&obj->poll_handle_, UV_READABLE, _serialportReadable); - - info.GetReturnValue().Set(info.This()); -} - -void SerialportPoller::_start() { - uv_poll_start(&poll_handle_, UV_READABLE, _serialportReadable); -} - -void SerialportPoller::_stop() { - uv_poll_stop(&poll_handle_); -} - - -NAN_METHOD(SerialportPoller::Start) { - SerialportPoller* obj = Nan::ObjectWrap::Unwrap(info.This()); - obj->_start(); - - return; -} - -NAN_METHOD(SerialportPoller::Close) { - SerialportPoller* obj = Nan::ObjectWrap::Unwrap(info.This()); - obj->_stop(); - - // DO SOMETHING! - - return; -} +// Copyright (C) 2013 Robert Giseburt +// serialport_poller.cpp Written as a part of https://github.com/voodootikigod/node-serialport +// License to use this is the same as that of node-serialport. + +#include +#include "./serialport_poller.h" + +using namespace v8; + +static Nan::Persistent serialportpoller_constructor; + +SerialportPoller::SerialportPoller() : Nan::ObjectWrap() {} +SerialportPoller::~SerialportPoller() { + // printf("~SerialportPoller\n"); + delete callback_; +} + +void _serialportReadable(uv_poll_t *req, int status, int events) { + SerialportPoller* sp = (SerialportPoller*) req->data; + // We can stop polling until we have read all of the data... + sp->_stop(); + sp->callCallback(status); +} + +void SerialportPoller::callCallback(int status) { + Nan::HandleScope scope; + // uv_work_t* req = new uv_work_t; + + // Call the callback to go read more data... + + v8::Local argv[1]; + if (status != 0) { + // error handling changed in libuv, see: + // https://github.com/joyent/libuv/commit/3ee4d3f183331 + #ifdef UV_ERRNO_H_ + const char* err_string = uv_strerror(status); + #else + uv_err_t errno = uv_last_error(uv_default_loop()); + const char* err_string = uv_strerror(errno); + #endif + snprintf(this->errorString, sizeof(this->errorString), "Error %s on polling", err_string); + argv[0] = v8::Exception::Error(Nan::New(this->errorString).ToLocalChecked()); + } else { + argv[0] = Nan::Undefined(); + } + + callback_->Call(1, argv); +} + + + +void SerialportPoller::Init(Local target) { + Nan::HandleScope scope; + + // Prepare constructor template + Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("SerialportPoller").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + + // Prototype + + // SerialportPoller.close() + Nan::SetPrototypeMethod(tpl, "close", Close); + + // SerialportPoller.start() + Nan::SetPrototypeMethod(tpl, "start", Start); + + serialportpoller_constructor.Reset(tpl); + + Nan::Set(target, Nan::New("SerialportPoller").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked()); +} + +NAN_METHOD(SerialportPoller::New) { + if (!info[0]->IsInt32()) { + Nan::ThrowTypeError("First argument must be an fd"); + return; + } + + if (!info[1]->IsFunction()) { + Nan::ThrowTypeError("Third argument must be a function"); + return; + } + + SerialportPoller* obj = new SerialportPoller(); + #if NODE_MAJOR_VERSION >= 10 + obj->fd_ = info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + #else + obj->fd_ = info[0]->ToInt32()->Int32Value(); + #endif + obj->callback_ = new Nan::Callback(info[1].As()); + // obj->callCallback(); + + obj->Wrap(info.This()); + + obj->poll_handle_.data = obj; + + uv_poll_init(uv_default_loop(), &obj->poll_handle_, obj->fd_); + + uv_poll_start(&obj->poll_handle_, UV_READABLE, _serialportReadable); + + info.GetReturnValue().Set(info.This()); +} + +void SerialportPoller::_start() { + uv_poll_start(&poll_handle_, UV_READABLE, _serialportReadable); +} + +void SerialportPoller::_stop() { + uv_poll_stop(&poll_handle_); +} + + +NAN_METHOD(SerialportPoller::Start) { + SerialportPoller* obj = Nan::ObjectWrap::Unwrap(info.This()); + obj->_start(); + + return; +} + +NAN_METHOD(SerialportPoller::Close) { + SerialportPoller* obj = Nan::ObjectWrap::Unwrap(info.This()); + obj->_stop(); + + // DO SOMETHING! + + return; +} diff --git a/vendor/node-usb-native/src/serialport_poller.h b/vendor/node-usb-native/src/serialport_poller.h index 4d20b07d6..1f4cc37c2 100644 --- a/vendor/node-usb-native/src/serialport_poller.h +++ b/vendor/node-usb-native/src/serialport_poller.h @@ -1,35 +1,35 @@ -// Copyright (C) 2013 Robert Giseburt -// serialport_poller.h Written as a part of https://github.com/voodootikigod/node-serialport -// License to use this is the same as that of node-serialport. - -#ifndef SERIALPORT_POLLER_H -#define SERIALPORT_POLLER_H - -#include -#include "./serialport.h" - -class SerialportPoller : public Nan::ObjectWrap { - public: - static void Init(v8::Handle target); - - void callCallback(int status); - - void _start(); - void _stop(); - - private: - SerialportPoller(); - ~SerialportPoller(); - - static NAN_METHOD(New); - static NAN_METHOD(Close); - static NAN_METHOD(Start); - - uv_poll_t poll_handle_; - int fd_; - char errorString[ERROR_STRING_SIZE]; - - Nan::Callback* callback_; -}; - -#endif +// Copyright (C) 2013 Robert Giseburt +// serialport_poller.h Written as a part of https://github.com/voodootikigod/node-serialport +// License to use this is the same as that of node-serialport. + +#ifndef SERIALPORT_POLLER_H +#define SERIALPORT_POLLER_H + +#include +#include "./serialport.h" + +class SerialportPoller : public Nan::ObjectWrap { + public: + static void Init( v8::Local target); + + void callCallback(int status); + + void _start(); + void _stop(); + + private: + SerialportPoller(); + ~SerialportPoller(); + + static NAN_METHOD(New); + static NAN_METHOD(Close); + static NAN_METHOD(Start); + + uv_poll_t poll_handle_; + int fd_; + char errorString[ERROR_STRING_SIZE]; + + Nan::Callback* callback_; +}; + +#endif diff --git a/vendor/node-usb-native/src/serialport_unix.cpp b/vendor/node-usb-native/src/serialport_unix.cpp index cd27b40c6..41cbe7710 100644 --- a/vendor/node-usb-native/src/serialport_unix.cpp +++ b/vendor/node-usb-native/src/serialport_unix.cpp @@ -1,740 +1,740 @@ -#include "./serialport.h" -#include "./serialport_poller.h" -#include -#include -#include -#include -#include - -#ifdef __APPLE__ -#include -#include -#include -#include -#include -#include - -uv_mutex_t list_mutex; -Boolean lockInitialised = FALSE; -#endif - -#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) -#include -#include -#endif - -#if defined(__OpenBSD__) -#include -#endif - -#if defined(__linux__) -#include -#include -#endif - -struct UnixPlatformOptions : OpenBatonPlatformOptions { - uint8_t vmin; - uint8_t vtime; -}; - -OpenBatonPlatformOptions* ParsePlatformOptions(const v8::Local& options) { - Nan::HandleScope scope; - - UnixPlatformOptions* result = new UnixPlatformOptions(); - #if NODE_MAJOR_VERSION >= 10 - result->vmin = Nan::Get(options, Nan::New("vmin").ToLocalChecked()).ToLocalChecked()->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - result->vtime = Nan::Get(options, Nan::New("vtime").ToLocalChecked()).ToLocalChecked()->ToInt32(v8::Isolate::GetCurrent())->Int32Value(); - #else - result->vmin = Nan::Get(options, Nan::New("vmin").ToLocalChecked()).ToLocalChecked()->ToInt32()->Int32Value(); - result->vtime = Nan::Get(options, Nan::New("vtime").ToLocalChecked()).ToLocalChecked()->ToInt32()->Int32Value(); - #endif - - return result; -} - -int ToBaudConstant(int baudRate); -int ToDataBitsConstant(int dataBits); -int ToStopBitsConstant(SerialPortStopBits stopBits); - -void AfterOpenSuccess(int fd, Nan::Callback* dataCallback, Nan::Callback* disconnectedCallback, Nan::Callback* errorCallback) { - delete dataCallback; - delete errorCallback; - delete disconnectedCallback; -} - -int ToBaudConstant(int baudRate) { - switch (baudRate) { - case 0: return B0; - case 50: return B50; - case 75: return B75; - case 110: return B110; - case 134: return B134; - case 150: return B150; - case 200: return B200; - case 300: return B300; - case 600: return B600; - case 1200: return B1200; - case 1800: return B1800; - case 2400: return B2400; - case 4800: return B4800; - case 9600: return B9600; - case 19200: return B19200; - case 38400: return B38400; - case 57600: return B57600; - case 115200: return B115200; - case 230400: return B230400; -#if defined(__linux__) - case 460800: return B460800; - case 500000: return B500000; - case 576000: return B576000; - case 921600: return B921600; - case 1000000: return B1000000; - case 1152000: return B1152000; - case 1500000: return B1500000; - case 2000000: return B2000000; - case 2500000: return B2500000; - case 3000000: return B3000000; - case 3500000: return B3500000; - case 4000000: return B4000000; -#endif - } - return -1; -} - -#ifdef __APPLE__ -typedef struct SerialDevice { - char port[MAXPATHLEN]; - char locationId[MAXPATHLEN]; - char vendorId[MAXPATHLEN]; - char productId[MAXPATHLEN]; - char manufacturer[MAXPATHLEN]; - char serialNumber[MAXPATHLEN]; -} stSerialDevice; - -typedef struct DeviceListItem { - struct SerialDevice value; - struct DeviceListItem *next; - int* length; -} stDeviceListItem; -#endif - -int ToDataBitsConstant(int dataBits) { - switch (dataBits) { - case 8: default: return CS8; - case 7: return CS7; - case 6: return CS6; - case 5: return CS5; - } - return -1; -} - -void EIO_Open(uv_work_t* req) { - OpenBaton* data = static_cast(req->data); - - int flags = (O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC | O_SYNC); - int fd = open(data->path, flags); - - if (-1 == fd) { - snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot open %s", strerror(errno), data->path); - return; - } - - if (-1 == setup(fd, data)) { - close(fd); - return; - } - - data->result = fd; -} - -int setBaudRate(ConnectionOptionsBaton *data) { - // lookup the standard baudrates from the table - int baudRate = ToBaudConstant(data->baudRate); - int fd = data->fd; - - // get port options - struct termios options; - if (tcgetattr(fd, &options)) { - snprintf(data->errorString, sizeof(data->errorString), "Error: tcgetattr encountering %s", strerror(errno)); - return -1; - } - - // If there is a custom baud rate on linux you can do the following trick with B38400 - #if defined(__linux__) && defined(ASYNC_SPD_CUST) - if (baudRate == -1) { - struct serial_struct serinfo; - serinfo.reserved_char[0] = 0; - if (-1 != ioctl(fd, TIOCGSERIAL, &serinfo)) { - serinfo.flags &= ~ASYNC_SPD_MASK; - serinfo.flags |= ASYNC_SPD_CUST; - serinfo.custom_divisor = (serinfo.baud_base + (data->baudRate / 2)) / data->baudRate; - if (serinfo.custom_divisor < 1) - serinfo.custom_divisor = 1; - - ioctl(fd, TIOCSSERIAL, &serinfo); - ioctl(fd, TIOCGSERIAL, &serinfo); - } else { - snprintf(data->errorString, sizeof(data->errorString), "Error: %s setting custom baud rate of %d", strerror(errno), data->baudRate); - return -1; - } - - // Now we use "B38400" to trigger the special baud rate. - baudRate = B38400; - } - #endif - - // On OS X, starting with Tiger, we can set a custom baud rate with ioctl - #if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) - if (-1 == baudRate) { - speed_t speed = data->baudRate; - if (-1 == ioctl(fd, IOSSIOSPEED, &speed)) { - snprintf(data->errorString, sizeof(data->errorString), "Error: %s calling ioctl(.., IOSSIOSPEED, %ld )", strerror(errno), speed ); - return -1; - } else { - return 1; - } - } - #endif - - // If we have a good baud rate set it and lets go - if (-1 != baudRate) { - cfsetospeed(&options, baudRate); - cfsetispeed(&options, baudRate); - tcflush(fd, TCIFLUSH); - tcsetattr(fd, TCSANOW, &options); - return 1; - } - - snprintf(data->errorString, sizeof(data->errorString), "Error baud rate of %d is not supported on your platform", data->baudRate); - return -1; -} - -void EIO_Update(uv_work_t* req) { - ConnectionOptionsBaton* data = static_cast(req->data); - setBaudRate(data); -} - -int setup(int fd, OpenBaton *data) { - UnixPlatformOptions* platformOptions = static_cast(data->platformOptions); - - int dataBits = ToDataBitsConstant(data->dataBits); - if (-1 == dataBits) { - snprintf(data->errorString, sizeof(data->errorString), "Invalid data bits setting %d", data->dataBits); - return -1; - } - - // Snow Leopard doesn't have O_CLOEXEC - if (-1 == fcntl(fd, F_SETFD, FD_CLOEXEC)) { - snprintf(data->errorString, sizeof(data->errorString), "Error %s Cannot open %s", strerror(errno), data->path); - return -1; - } - - // Copy the connection options into the ConnectionOptionsBaton to set the baud rate - ConnectionOptionsBaton* connectionOptions = new ConnectionOptionsBaton(); - memset(connectionOptions, 0, sizeof(ConnectionOptionsBaton)); - connectionOptions->fd = fd; - connectionOptions->baudRate = data->baudRate; - - if (-1 == setBaudRate(connectionOptions)) { - strncpy(data->errorString, connectionOptions->errorString, sizeof(data->errorString)); - delete(connectionOptions); - return -1; - } - delete(connectionOptions); - - // Get port configuration for modification - struct termios options; - if (tcgetattr(fd, &options)) { - snprintf(data->errorString, sizeof(data->errorString), "Error: tcgetattr encountering %s", strerror(errno)); - return -1; - } - - // IGNPAR: ignore bytes with parity errors - options.c_iflag = IGNPAR; - - // ICRNL: map CR to NL (otherwise a CR input on the other computer will not terminate input) - // Future potential option - // options.c_iflag = ICRNL; - // otherwise make device raw (no other input processing) - - // Specify data bits - options.c_cflag &= ~CSIZE; - options.c_cflag |= dataBits; - - options.c_cflag &= ~(CRTSCTS); - - if (data->rtscts) { - options.c_cflag |= CRTSCTS; - // evaluate specific flow control options - } - - options.c_iflag &= ~(IXON | IXOFF | IXANY); - - if (data->xon) { - options.c_iflag |= IXON; - } - - if (data->xoff) { - options.c_iflag |= IXOFF; - } - - if (data->xany) { - options.c_iflag |= IXANY; - } - - switch (data->parity) { - case SERIALPORT_PARITY_NONE: - options.c_cflag &= ~PARENB; - // options.c_cflag &= ~CSTOPB; - // options.c_cflag &= ~CSIZE; - // options.c_cflag |= CS8; - break; - case SERIALPORT_PARITY_ODD: - options.c_cflag |= PARENB; - options.c_cflag |= PARODD; - // options.c_cflag &= ~CSTOPB; - // options.c_cflag &= ~CSIZE; - // options.c_cflag |= CS7; - break; - case SERIALPORT_PARITY_EVEN: - options.c_cflag |= PARENB; - options.c_cflag &= ~PARODD; - // options.c_cflag &= ~CSTOPB; - // options.c_cflag &= ~CSIZE; - // options.c_cflag |= CS7; - break; - default: - snprintf(data->errorString, sizeof(data->errorString), "Invalid parity setting %d", data->parity); - return -1; - } - - switch (data->stopBits) { - case SERIALPORT_STOPBITS_ONE: - options.c_cflag &= ~CSTOPB; - break; - case SERIALPORT_STOPBITS_TWO: - options.c_cflag |= CSTOPB; - break; - default: - snprintf(data->errorString, sizeof(data->errorString), "Invalid stop bits setting %d", data->stopBits); - return -1; - } - - options.c_cflag |= CLOCAL; // ignore status lines - options.c_cflag |= CREAD; // enable receiver - if (data->hupcl) { - options.c_cflag |= HUPCL; // drop DTR (i.e. hangup) on close - } - - // Raw output - options.c_oflag = 0; - - // ICANON makes partial lines not readable. It should be optional. - // It works with ICRNL. - options.c_lflag = 0; // ICANON; - - options.c_cc[VMIN]= platformOptions->vmin; - options.c_cc[VTIME]= platformOptions->vtime; - - // why? - tcflush(fd, TCIFLUSH); - - // check for error? - tcsetattr(fd, TCSANOW, &options); - - if (data->lock){ - if (-1 == flock(fd, LOCK_EX | LOCK_NB)) { - snprintf(data->errorString, sizeof(data->errorString), "Error %s Cannot lock port", strerror(errno)); - return -1; - } - } - - return 1; -} - -void EIO_Write(uv_work_t* req) { - QueuedWrite* queuedWrite = static_cast(req->data); - WriteBaton* data = static_cast(queuedWrite->baton); - int bytesWritten = 0; - - do { - errno = 0; // probably don't need this - bytesWritten = write(data->fd, data->bufferData + data->offset, data->bufferLength - data->offset); - if (-1 != bytesWritten) { - // there wasn't an error, do the math on what we actually wrote and keep writing until finished - data->offset += bytesWritten; - continue; - } - - // The write call was interrupted before anything was written, try again immediately. - if (errno == EINTR) { - // why try again right away instead of in another event loop? - continue; - } - - // Try again in another event loop - if (errno == EAGAIN || errno == EWOULDBLOCK){ - return; - } - - // EBAD would mean we're "disconnected" - - // a real error so lets bail - snprintf(data->errorString, sizeof(data->errorString), "Error: %s, calling write", strerror(errno)); - return; - } while (data->bufferLength > data->offset); -} - -void EIO_Close(uv_work_t* req) { - CloseBaton* data = static_cast(req->data); - if (-1 == close(data->fd)) { - snprintf(data->errorString, sizeof(data->errorString), "Error: %s, unable to close fd %d", strerror(errno), data->fd); - } -} - -#ifdef __APPLE__ - -// Function prototypes -static kern_return_t FindModems(io_iterator_t *matchingServices); -static io_service_t GetUsbDevice(io_service_t service); -static stDeviceListItem* GetSerialDevices(); - - -static kern_return_t FindModems(io_iterator_t *matchingServices) { - kern_return_t kernResult; - CFMutableDictionaryRef classesToMatch; - classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); - if (classesToMatch != NULL) { - CFDictionarySetValue(classesToMatch, - CFSTR(kIOSerialBSDTypeKey), - CFSTR(kIOSerialBSDAllTypes)); - } - - kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices); - - return kernResult; -} - -static io_service_t GetUsbDevice(io_service_t service) { - IOReturn status; - io_iterator_t iterator = 0; - io_service_t device = 0; - - if (!service) { - return device; - } - - status = IORegistryEntryCreateIterator(service, - kIOServicePlane, - (kIORegistryIterateParents | kIORegistryIterateRecursively), - &iterator); - - if (status == kIOReturnSuccess) { - io_service_t currentService; - while ((currentService = IOIteratorNext(iterator)) && device == 0) { - io_name_t serviceName; - status = IORegistryEntryGetNameInPlane(currentService, kIOServicePlane, serviceName); - if (status == kIOReturnSuccess && IOObjectConformsTo(currentService, kIOUSBDeviceClassName)) { - device = currentService; - } else { - // Release the service object which is no longer needed - (void) IOObjectRelease(currentService); - } - } - - // Release the iterator - (void) IOObjectRelease(iterator); - } - - return device; -} - -static void ExtractUsbInformation(stSerialDevice *serialDevice, IOUSBDeviceInterface **deviceInterface) { - kern_return_t kernResult; - UInt32 locationID; - kernResult = (*deviceInterface)->GetLocationID(deviceInterface, &locationID); - if (KERN_SUCCESS == kernResult) { - snprintf(serialDevice->locationId, 11, "0x%08x", locationID); - } - - UInt16 vendorID; - kernResult = (*deviceInterface)->GetDeviceVendor(deviceInterface, &vendorID); - if (KERN_SUCCESS == kernResult) { - snprintf(serialDevice->vendorId, 7, "0x%04x", vendorID); - } - - UInt16 productID; - kernResult = (*deviceInterface)->GetDeviceProduct(deviceInterface, &productID); - if (KERN_SUCCESS == kernResult) { - snprintf(serialDevice->productId, 7, "0x%04x", productID); - } -} - -static stDeviceListItem* GetSerialDevices() { - kern_return_t kernResult; - io_iterator_t serialPortIterator; - char bsdPath[MAXPATHLEN]; - - FindModems(&serialPortIterator); - - io_service_t modemService; - kernResult = KERN_FAILURE; - Boolean modemFound = false; - - // Initialize the returned path - *bsdPath = '\0'; - - stDeviceListItem* devices = NULL; - stDeviceListItem* lastDevice = NULL; - int length = 0; - - while ((modemService = IOIteratorNext(serialPortIterator))) { - CFTypeRef bsdPathAsCFString; - bsdPathAsCFString = IORegistryEntrySearchCFProperty( - modemService, - kIOServicePlane, - CFSTR(kIOCalloutDeviceKey), - kCFAllocatorDefault, - kIORegistryIterateRecursively); - - if (bsdPathAsCFString) { - Boolean result; - - // Convert the path from a CFString to a C (NUL-terminated) - result = CFStringGetCString((CFStringRef) bsdPathAsCFString, - bsdPath, - sizeof(bsdPath), - kCFStringEncodingUTF8); - CFRelease(bsdPathAsCFString); - - if (result) { - stDeviceListItem *deviceListItem = (stDeviceListItem*) malloc(sizeof(stDeviceListItem)); - stSerialDevice *serialDevice = &(deviceListItem->value); - strcpy(serialDevice->port, bsdPath); - memset(serialDevice->locationId, 0, sizeof(serialDevice->locationId)); - memset(serialDevice->vendorId, 0, sizeof(serialDevice->vendorId)); - memset(serialDevice->productId, 0, sizeof(serialDevice->productId)); - serialDevice->manufacturer[0] = '\0'; - serialDevice->serialNumber[0] = '\0'; - deviceListItem->next = NULL; - deviceListItem->length = &length; - - if (devices == NULL) { - devices = deviceListItem; - } else { - lastDevice->next = deviceListItem; - } - - lastDevice = deviceListItem; - length++; - - modemFound = true; - kernResult = KERN_SUCCESS; - - uv_mutex_lock(&list_mutex); - - io_service_t device = GetUsbDevice(modemService); - - if (device) { - CFStringRef manufacturerAsCFString = (CFStringRef) IORegistryEntryCreateCFProperty(device, - CFSTR(kUSBVendorString), - kCFAllocatorDefault, - 0); - - if (manufacturerAsCFString) { - Boolean result; - char manufacturer[MAXPATHLEN]; - - // Convert from a CFString to a C (NUL-terminated) - result = CFStringGetCString(manufacturerAsCFString, - manufacturer, - sizeof(manufacturer), - kCFStringEncodingUTF8); - - if (result) { - strcpy(serialDevice->manufacturer, manufacturer); - } - - CFRelease(manufacturerAsCFString); - } - - CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(device, - kIOServicePlane, - CFSTR(kUSBSerialNumberString), - kCFAllocatorDefault, - kIORegistryIterateRecursively); - - if (serialNumberAsCFString) { - Boolean result; - char serialNumber[MAXPATHLEN]; - - // Convert from a CFString to a C (NUL-terminated) - result = CFStringGetCString(serialNumberAsCFString, - serialNumber, - sizeof(serialNumber), - kCFStringEncodingUTF8); - - if (result) { - strcpy(serialDevice->serialNumber, serialNumber); - } - - CFRelease(serialNumberAsCFString); - } - - IOCFPlugInInterface **plugInInterface = NULL; - SInt32 score; - HRESULT res; - - IOUSBDeviceInterface **deviceInterface = NULL; - - kernResult = IOCreatePlugInInterfaceForService(device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, - &plugInInterface, &score); - - if ((kIOReturnSuccess != kernResult) || !plugInInterface) { - continue; - } - - // Use the plugin interface to retrieve the device interface. - res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), - (LPVOID*) &deviceInterface); - - // Now done with the plugin interface. - (*plugInInterface)->Release(plugInInterface); - - if (res || deviceInterface == NULL) { - continue; - } - - // Extract the desired Information - ExtractUsbInformation(serialDevice, deviceInterface); - - // Release the Interface - (*deviceInterface)->Release(deviceInterface); - - // Release the device - (void) IOObjectRelease(device); - } - - uv_mutex_unlock(&list_mutex); - } - } - - // Release the io_service_t now that we are done with it. - (void) IOObjectRelease(modemService); - } - - IOObjectRelease(serialPortIterator); // Release the iterator. - - return devices; -} - -#endif - -void EIO_List(uv_work_t* req) { - ListBaton* data = static_cast(req->data); - -#ifndef __APPLE__ - // This code exists in javascript for other unix platforms - snprintf(data->errorString, sizeof(data->errorString), "List is not Implemented"); - return; -# else - if (!lockInitialised) { - uv_mutex_init(&list_mutex); - lockInitialised = TRUE; - } - - stDeviceListItem* devices = GetSerialDevices(); - if (*(devices->length) > 0) { - stDeviceListItem* next = devices; - - for (int i = 0, len = *(devices->length); i < len; i++) { - stSerialDevice device = (* next).value; - - ListResultItem* resultItem = new ListResultItem(); - resultItem->comName = device.port; - - if (*device.locationId) { - resultItem->locationId = device.locationId; - } - if (*device.vendorId) { - resultItem->vendorId = device.vendorId; - } - if (*device.productId) { - resultItem->productId = device.productId; - } - if (*device.manufacturer) { - resultItem->manufacturer = device.manufacturer; - } - if (*device.serialNumber) { - resultItem->serialNumber = device.serialNumber; - } - data->results.push_back(resultItem); - - stDeviceListItem* current = next; - - if (next->next != NULL) { - next = next->next; - } - - free(current); - } - } -#endif -} - -void EIO_Flush(uv_work_t* req) { - FlushBaton* data = static_cast(req->data); - - data->result = tcflush(data->fd, TCIFLUSH); -} - -void EIO_Set(uv_work_t* req) { - SetBaton* data = static_cast(req->data); - - int bits; - ioctl(data->fd, TIOCMGET, &bits); - - bits &= ~(TIOCM_RTS | TIOCM_CTS | TIOCM_DTR | TIOCM_DSR); - - if (data->rts) { - bits |= TIOCM_RTS; - } - - if (data->cts) { - bits |= TIOCM_CTS; - } - - if (data->dtr) { - bits |= TIOCM_DTR; - } - - if (data->dsr) { - bits |= TIOCM_DSR; - } - - int result = 0; - if (data->brk) { - result = ioctl(data->fd, TIOCSBRK, NULL); - } else { - result = ioctl(data->fd, TIOCCBRK, NULL); - } - - if (-1 == result) { - snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot drain", strerror(errno)); - return; - } - - if (-1 == ioctl(data->fd, TIOCMSET, &bits)) { - snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot drain", strerror(errno)); - return; - } -} - -void EIO_Drain(uv_work_t* req) { - DrainBaton* data = static_cast(req->data); - - if (-1 == tcdrain(data->fd)) { - snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot drain", strerror(errno)); - return; - } -} +#include "./serialport.h" +#include "./serialport_poller.h" +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#include +#include +#include +#include +#include + +uv_mutex_t list_mutex; +Boolean lockInitialised = FALSE; +#endif + +#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) +#include +#include +#endif + +#if defined(__OpenBSD__) +#include +#endif + +#if defined(__linux__) +#include +#include +#endif + +struct UnixPlatformOptions : OpenBatonPlatformOptions { + uint8_t vmin; + uint8_t vtime; +}; + +OpenBatonPlatformOptions* ParsePlatformOptions(const v8::Local& options) { + Nan::HandleScope scope; + + UnixPlatformOptions* result = new UnixPlatformOptions(); + #if NODE_MAJOR_VERSION >= 10 + result->vmin = Nan::Get(options, Nan::New("vmin").ToLocalChecked()).ToLocalChecked()->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + result->vtime = Nan::Get(options, Nan::New("vtime").ToLocalChecked()).ToLocalChecked()->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(); + #else + result->vmin = Nan::Get(options, Nan::New("vmin").ToLocalChecked()).ToLocalChecked()->ToInt32()->Int32Value(); + result->vtime = Nan::Get(options, Nan::New("vtime").ToLocalChecked()).ToLocalChecked()->ToInt32()->Int32Value(); + #endif + + return result; +} + +int ToBaudConstant(int baudRate); +int ToDataBitsConstant(int dataBits); +int ToStopBitsConstant(SerialPortStopBits stopBits); + +void AfterOpenSuccess(int fd, Nan::Callback* dataCallback, Nan::Callback* disconnectedCallback, Nan::Callback* errorCallback) { + delete dataCallback; + delete errorCallback; + delete disconnectedCallback; +} + +int ToBaudConstant(int baudRate) { + switch (baudRate) { + case 0: return B0; + case 50: return B50; + case 75: return B75; + case 110: return B110; + case 134: return B134; + case 150: return B150; + case 200: return B200; + case 300: return B300; + case 600: return B600; + case 1200: return B1200; + case 1800: return B1800; + case 2400: return B2400; + case 4800: return B4800; + case 9600: return B9600; + case 19200: return B19200; + case 38400: return B38400; + case 57600: return B57600; + case 115200: return B115200; + case 230400: return B230400; +#if defined(__linux__) + case 460800: return B460800; + case 500000: return B500000; + case 576000: return B576000; + case 921600: return B921600; + case 1000000: return B1000000; + case 1152000: return B1152000; + case 1500000: return B1500000; + case 2000000: return B2000000; + case 2500000: return B2500000; + case 3000000: return B3000000; + case 3500000: return B3500000; + case 4000000: return B4000000; +#endif + } + return -1; +} + +#ifdef __APPLE__ +typedef struct SerialDevice { + char port[MAXPATHLEN]; + char locationId[MAXPATHLEN]; + char vendorId[MAXPATHLEN]; + char productId[MAXPATHLEN]; + char manufacturer[MAXPATHLEN]; + char serialNumber[MAXPATHLEN]; +} stSerialDevice; + +typedef struct DeviceListItem { + struct SerialDevice value; + struct DeviceListItem *next; + int* length; +} stDeviceListItem; +#endif + +int ToDataBitsConstant(int dataBits) { + switch (dataBits) { + case 8: default: return CS8; + case 7: return CS7; + case 6: return CS6; + case 5: return CS5; + } + return -1; +} + +void EIO_Open(uv_work_t* req) { + OpenBaton* data = static_cast(req->data); + + int flags = (O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC | O_SYNC); + int fd = open(data->path, flags); + + if (-1 == fd) { + snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot open %s", strerror(errno), data->path); + return; + } + + if (-1 == setup(fd, data)) { + close(fd); + return; + } + + data->result = fd; +} + +int setBaudRate(ConnectionOptionsBaton *data) { + // lookup the standard baudrates from the table + int baudRate = ToBaudConstant(data->baudRate); + int fd = data->fd; + + // get port options + struct termios options; + if (tcgetattr(fd, &options)) { + snprintf(data->errorString, sizeof(data->errorString), "Error: tcgetattr encountering %s", strerror(errno)); + return -1; + } + + // If there is a custom baud rate on linux you can do the following trick with B38400 + #if defined(__linux__) && defined(ASYNC_SPD_CUST) + if (baudRate == -1) { + struct serial_struct serinfo; + serinfo.reserved_char[0] = 0; + if (-1 != ioctl(fd, TIOCGSERIAL, &serinfo)) { + serinfo.flags &= ~ASYNC_SPD_MASK; + serinfo.flags |= ASYNC_SPD_CUST; + serinfo.custom_divisor = (serinfo.baud_base + (data->baudRate / 2)) / data->baudRate; + if (serinfo.custom_divisor < 1) + serinfo.custom_divisor = 1; + + ioctl(fd, TIOCSSERIAL, &serinfo); + ioctl(fd, TIOCGSERIAL, &serinfo); + } else { + snprintf(data->errorString, sizeof(data->errorString), "Error: %s setting custom baud rate of %d", strerror(errno), data->baudRate); + return -1; + } + + // Now we use "B38400" to trigger the special baud rate. + baudRate = B38400; + } + #endif + + // On OS X, starting with Tiger, we can set a custom baud rate with ioctl + #if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) + if (-1 == baudRate) { + speed_t speed = data->baudRate; + if (-1 == ioctl(fd, IOSSIOSPEED, &speed)) { + snprintf(data->errorString, sizeof(data->errorString), "Error: %s calling ioctl(.., IOSSIOSPEED, %ld )", strerror(errno), speed ); + return -1; + } else { + return 1; + } + } + #endif + + // If we have a good baud rate set it and lets go + if (-1 != baudRate) { + cfsetospeed(&options, baudRate); + cfsetispeed(&options, baudRate); + tcflush(fd, TCIFLUSH); + tcsetattr(fd, TCSANOW, &options); + return 1; + } + + snprintf(data->errorString, sizeof(data->errorString), "Error baud rate of %d is not supported on your platform", data->baudRate); + return -1; +} + +void EIO_Update(uv_work_t* req) { + ConnectionOptionsBaton* data = static_cast(req->data); + setBaudRate(data); +} + +int setup(int fd, OpenBaton *data) { + UnixPlatformOptions* platformOptions = static_cast(data->platformOptions); + + int dataBits = ToDataBitsConstant(data->dataBits); + if (-1 == dataBits) { + snprintf(data->errorString, sizeof(data->errorString), "Invalid data bits setting %d", data->dataBits); + return -1; + } + + // Snow Leopard doesn't have O_CLOEXEC + if (-1 == fcntl(fd, F_SETFD, FD_CLOEXEC)) { + snprintf(data->errorString, sizeof(data->errorString), "Error %s Cannot open %s", strerror(errno), data->path); + return -1; + } + + // Copy the connection options into the ConnectionOptionsBaton to set the baud rate + ConnectionOptionsBaton* connectionOptions = new ConnectionOptionsBaton(); + memset(connectionOptions, 0, sizeof(ConnectionOptionsBaton)); + connectionOptions->fd = fd; + connectionOptions->baudRate = data->baudRate; + + if (-1 == setBaudRate(connectionOptions)) { + strncpy(data->errorString, connectionOptions->errorString, sizeof(data->errorString)); + delete(connectionOptions); + return -1; + } + delete(connectionOptions); + + // Get port configuration for modification + struct termios options; + if (tcgetattr(fd, &options)) { + snprintf(data->errorString, sizeof(data->errorString), "Error: tcgetattr encountering %s", strerror(errno)); + return -1; + } + + // IGNPAR: ignore bytes with parity errors + options.c_iflag = IGNPAR; + + // ICRNL: map CR to NL (otherwise a CR input on the other computer will not terminate input) + // Future potential option + // options.c_iflag = ICRNL; + // otherwise make device raw (no other input processing) + + // Specify data bits + options.c_cflag &= ~CSIZE; + options.c_cflag |= dataBits; + + options.c_cflag &= ~(CRTSCTS); + + if (data->rtscts) { + options.c_cflag |= CRTSCTS; + // evaluate specific flow control options + } + + options.c_iflag &= ~(IXON | IXOFF | IXANY); + + if (data->xon) { + options.c_iflag |= IXON; + } + + if (data->xoff) { + options.c_iflag |= IXOFF; + } + + if (data->xany) { + options.c_iflag |= IXANY; + } + + switch (data->parity) { + case SERIALPORT_PARITY_NONE: + options.c_cflag &= ~PARENB; + // options.c_cflag &= ~CSTOPB; + // options.c_cflag &= ~CSIZE; + // options.c_cflag |= CS8; + break; + case SERIALPORT_PARITY_ODD: + options.c_cflag |= PARENB; + options.c_cflag |= PARODD; + // options.c_cflag &= ~CSTOPB; + // options.c_cflag &= ~CSIZE; + // options.c_cflag |= CS7; + break; + case SERIALPORT_PARITY_EVEN: + options.c_cflag |= PARENB; + options.c_cflag &= ~PARODD; + // options.c_cflag &= ~CSTOPB; + // options.c_cflag &= ~CSIZE; + // options.c_cflag |= CS7; + break; + default: + snprintf(data->errorString, sizeof(data->errorString), "Invalid parity setting %d", data->parity); + return -1; + } + + switch (data->stopBits) { + case SERIALPORT_STOPBITS_ONE: + options.c_cflag &= ~CSTOPB; + break; + case SERIALPORT_STOPBITS_TWO: + options.c_cflag |= CSTOPB; + break; + default: + snprintf(data->errorString, sizeof(data->errorString), "Invalid stop bits setting %d", data->stopBits); + return -1; + } + + options.c_cflag |= CLOCAL; // ignore status lines + options.c_cflag |= CREAD; // enable receiver + if (data->hupcl) { + options.c_cflag |= HUPCL; // drop DTR (i.e. hangup) on close + } + + // Raw output + options.c_oflag = 0; + + // ICANON makes partial lines not readable. It should be optional. + // It works with ICRNL. + options.c_lflag = 0; // ICANON; + + options.c_cc[VMIN]= platformOptions->vmin; + options.c_cc[VTIME]= platformOptions->vtime; + + // why? + tcflush(fd, TCIFLUSH); + + // check for error? + tcsetattr(fd, TCSANOW, &options); + + if (data->lock){ + if (-1 == flock(fd, LOCK_EX | LOCK_NB)) { + snprintf(data->errorString, sizeof(data->errorString), "Error %s Cannot lock port", strerror(errno)); + return -1; + } + } + + return 1; +} + +void EIO_Write(uv_work_t* req) { + QueuedWrite* queuedWrite = static_cast(req->data); + WriteBaton* data = static_cast(queuedWrite->baton); + int bytesWritten = 0; + + do { + errno = 0; // probably don't need this + bytesWritten = write(data->fd, data->bufferData + data->offset, data->bufferLength - data->offset); + if (-1 != bytesWritten) { + // there wasn't an error, do the math on what we actually wrote and keep writing until finished + data->offset += bytesWritten; + continue; + } + + // The write call was interrupted before anything was written, try again immediately. + if (errno == EINTR) { + // why try again right away instead of in another event loop? + continue; + } + + // Try again in another event loop + if (errno == EAGAIN || errno == EWOULDBLOCK){ + return; + } + + // EBAD would mean we're "disconnected" + + // a real error so lets bail + snprintf(data->errorString, sizeof(data->errorString), "Error: %s, calling write", strerror(errno)); + return; + } while (data->bufferLength > data->offset); +} + +void EIO_Close(uv_work_t* req) { + CloseBaton* data = static_cast(req->data); + if (-1 == close(data->fd)) { + snprintf(data->errorString, sizeof(data->errorString), "Error: %s, unable to close fd %d", strerror(errno), data->fd); + } +} + +#ifdef __APPLE__ + +// Function prototypes +static kern_return_t FindModems(io_iterator_t *matchingServices); +static io_service_t GetUsbDevice(io_service_t service); +static stDeviceListItem* GetSerialDevices(); + + +static kern_return_t FindModems(io_iterator_t *matchingServices) { + kern_return_t kernResult; + CFMutableDictionaryRef classesToMatch; + classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); + if (classesToMatch != NULL) { + CFDictionarySetValue(classesToMatch, + CFSTR(kIOSerialBSDTypeKey), + CFSTR(kIOSerialBSDAllTypes)); + } + + kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices); + + return kernResult; +} + +static io_service_t GetUsbDevice(io_service_t service) { + IOReturn status; + io_iterator_t iterator = 0; + io_service_t device = 0; + + if (!service) { + return device; + } + + status = IORegistryEntryCreateIterator(service, + kIOServicePlane, + (kIORegistryIterateParents | kIORegistryIterateRecursively), + &iterator); + + if (status == kIOReturnSuccess) { + io_service_t currentService; + while ((currentService = IOIteratorNext(iterator)) && device == 0) { + io_name_t serviceName; + status = IORegistryEntryGetNameInPlane(currentService, kIOServicePlane, serviceName); + if (status == kIOReturnSuccess && IOObjectConformsTo(currentService, kIOUSBDeviceClassName)) { + device = currentService; + } else { + // Release the service object which is no longer needed + (void) IOObjectRelease(currentService); + } + } + + // Release the iterator + (void) IOObjectRelease(iterator); + } + + return device; +} + +static void ExtractUsbInformation(stSerialDevice *serialDevice, IOUSBDeviceInterface **deviceInterface) { + kern_return_t kernResult; + UInt32 locationID; + kernResult = (*deviceInterface)->GetLocationID(deviceInterface, &locationID); + if (KERN_SUCCESS == kernResult) { + snprintf(serialDevice->locationId, 11, "0x%08x", locationID); + } + + UInt16 vendorID; + kernResult = (*deviceInterface)->GetDeviceVendor(deviceInterface, &vendorID); + if (KERN_SUCCESS == kernResult) { + snprintf(serialDevice->vendorId, 7, "0x%04x", vendorID); + } + + UInt16 productID; + kernResult = (*deviceInterface)->GetDeviceProduct(deviceInterface, &productID); + if (KERN_SUCCESS == kernResult) { + snprintf(serialDevice->productId, 7, "0x%04x", productID); + } +} + +static stDeviceListItem* GetSerialDevices() { + kern_return_t kernResult; + io_iterator_t serialPortIterator; + char bsdPath[MAXPATHLEN]; + + FindModems(&serialPortIterator); + + io_service_t modemService; + kernResult = KERN_FAILURE; + Boolean modemFound = false; + + // Initialize the returned path + *bsdPath = '\0'; + + stDeviceListItem* devices = NULL; + stDeviceListItem* lastDevice = NULL; + int length = 0; + + while ((modemService = IOIteratorNext(serialPortIterator))) { + CFTypeRef bsdPathAsCFString; + bsdPathAsCFString = IORegistryEntrySearchCFProperty( + modemService, + kIOServicePlane, + CFSTR(kIOCalloutDeviceKey), + kCFAllocatorDefault, + kIORegistryIterateRecursively); + + if (bsdPathAsCFString) { + Boolean result; + + // Convert the path from a CFString to a C (NUL-terminated) + result = CFStringGetCString((CFStringRef) bsdPathAsCFString, + bsdPath, + sizeof(bsdPath), + kCFStringEncodingUTF8); + CFRelease(bsdPathAsCFString); + + if (result) { + stDeviceListItem *deviceListItem = (stDeviceListItem*) malloc(sizeof(stDeviceListItem)); + stSerialDevice *serialDevice = &(deviceListItem->value); + strcpy(serialDevice->port, bsdPath); + memset(serialDevice->locationId, 0, sizeof(serialDevice->locationId)); + memset(serialDevice->vendorId, 0, sizeof(serialDevice->vendorId)); + memset(serialDevice->productId, 0, sizeof(serialDevice->productId)); + serialDevice->manufacturer[0] = '\0'; + serialDevice->serialNumber[0] = '\0'; + deviceListItem->next = NULL; + deviceListItem->length = &length; + + if (devices == NULL) { + devices = deviceListItem; + } else { + lastDevice->next = deviceListItem; + } + + lastDevice = deviceListItem; + length++; + + modemFound = true; + kernResult = KERN_SUCCESS; + + uv_mutex_lock(&list_mutex); + + io_service_t device = GetUsbDevice(modemService); + + if (device) { + CFStringRef manufacturerAsCFString = (CFStringRef) IORegistryEntryCreateCFProperty(device, + CFSTR(kUSBVendorString), + kCFAllocatorDefault, + 0); + + if (manufacturerAsCFString) { + Boolean result; + char manufacturer[MAXPATHLEN]; + + // Convert from a CFString to a C (NUL-terminated) + result = CFStringGetCString(manufacturerAsCFString, + manufacturer, + sizeof(manufacturer), + kCFStringEncodingUTF8); + + if (result) { + strcpy(serialDevice->manufacturer, manufacturer); + } + + CFRelease(manufacturerAsCFString); + } + + CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(device, + kIOServicePlane, + CFSTR(kUSBSerialNumberString), + kCFAllocatorDefault, + kIORegistryIterateRecursively); + + if (serialNumberAsCFString) { + Boolean result; + char serialNumber[MAXPATHLEN]; + + // Convert from a CFString to a C (NUL-terminated) + result = CFStringGetCString(serialNumberAsCFString, + serialNumber, + sizeof(serialNumber), + kCFStringEncodingUTF8); + + if (result) { + strcpy(serialDevice->serialNumber, serialNumber); + } + + CFRelease(serialNumberAsCFString); + } + + IOCFPlugInInterface **plugInInterface = NULL; + SInt32 score; + HRESULT res; + + IOUSBDeviceInterface **deviceInterface = NULL; + + kernResult = IOCreatePlugInInterfaceForService(device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, + &plugInInterface, &score); + + if ((kIOReturnSuccess != kernResult) || !plugInInterface) { + continue; + } + + // Use the plugin interface to retrieve the device interface. + res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), + (LPVOID*) &deviceInterface); + + // Now done with the plugin interface. + (*plugInInterface)->Release(plugInInterface); + + if (res || deviceInterface == NULL) { + continue; + } + + // Extract the desired Information + ExtractUsbInformation(serialDevice, deviceInterface); + + // Release the Interface + (*deviceInterface)->Release(deviceInterface); + + // Release the device + (void) IOObjectRelease(device); + } + + uv_mutex_unlock(&list_mutex); + } + } + + // Release the io_service_t now that we are done with it. + (void) IOObjectRelease(modemService); + } + + IOObjectRelease(serialPortIterator); // Release the iterator. + + return devices; +} + +#endif + +void EIO_List(uv_work_t* req) { + ListBaton* data = static_cast(req->data); + +#ifndef __APPLE__ + // This code exists in javascript for other unix platforms + snprintf(data->errorString, sizeof(data->errorString), "List is not Implemented"); + return; +# else + if (!lockInitialised) { + uv_mutex_init(&list_mutex); + lockInitialised = TRUE; + } + + stDeviceListItem* devices = GetSerialDevices(); + if (*(devices->length) > 0) { + stDeviceListItem* next = devices; + + for (int i = 0, len = *(devices->length); i < len; i++) { + stSerialDevice device = (* next).value; + + ListResultItem* resultItem = new ListResultItem(); + resultItem->comName = device.port; + + if (*device.locationId) { + resultItem->locationId = device.locationId; + } + if (*device.vendorId) { + resultItem->vendorId = device.vendorId; + } + if (*device.productId) { + resultItem->productId = device.productId; + } + if (*device.manufacturer) { + resultItem->manufacturer = device.manufacturer; + } + if (*device.serialNumber) { + resultItem->serialNumber = device.serialNumber; + } + data->results.push_back(resultItem); + + stDeviceListItem* current = next; + + if (next->next != NULL) { + next = next->next; + } + + free(current); + } + } +#endif +} + +void EIO_Flush(uv_work_t* req) { + FlushBaton* data = static_cast(req->data); + + data->result = tcflush(data->fd, TCIFLUSH); +} + +void EIO_Set(uv_work_t* req) { + SetBaton* data = static_cast(req->data); + + int bits; + ioctl(data->fd, TIOCMGET, &bits); + + bits &= ~(TIOCM_RTS | TIOCM_CTS | TIOCM_DTR | TIOCM_DSR); + + if (data->rts) { + bits |= TIOCM_RTS; + } + + if (data->cts) { + bits |= TIOCM_CTS; + } + + if (data->dtr) { + bits |= TIOCM_DTR; + } + + if (data->dsr) { + bits |= TIOCM_DSR; + } + + int result = 0; + if (data->brk) { + result = ioctl(data->fd, TIOCSBRK, NULL); + } else { + result = ioctl(data->fd, TIOCCBRK, NULL); + } + + if (-1 == result) { + snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot drain", strerror(errno)); + return; + } + + if (-1 == ioctl(data->fd, TIOCMSET, &bits)) { + snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot drain", strerror(errno)); + return; + } +} + +void EIO_Drain(uv_work_t* req) { + DrainBaton* data = static_cast(req->data); + + if (-1 == tcdrain(data->fd)) { + snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot drain", strerror(errno)); + return; + } +} diff --git a/vendor/node-usb-native/src/serialport_win.cpp b/vendor/node-usb-native/src/serialport_win.cpp index 0440da987..340f72beb 100644 --- a/vendor/node-usb-native/src/serialport_win.cpp +++ b/vendor/node-usb-native/src/serialport_win.cpp @@ -1,582 +1,582 @@ -#include -#include -#include -#include "./serialport.h" -#include -#include -#include -#include -#pragma comment (lib, "setupapi.lib") - -#ifdef WIN32 - -#define MAX_BUFFER_SIZE 1000 - -struct WindowsPlatformOptions : OpenBatonPlatformOptions { -}; - -OpenBatonPlatformOptions* ParsePlatformOptions(const v8::Local& options) { - // currently none - return new WindowsPlatformOptions(); -} - -// Declare type of pointer to CancelIoEx function -typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped); - -std::list g_closingHandles; -int bufferSize; -void ErrorCodeToString(const char* prefix, int errorCode, char *errorStr) { - switch (errorCode) { - case ERROR_FILE_NOT_FOUND: - _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: File not found", prefix); - break; - case ERROR_INVALID_HANDLE: - _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Invalid handle", prefix); - break; - case ERROR_ACCESS_DENIED: - _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Access denied", prefix); - break; - case ERROR_OPERATION_ABORTED: - _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: operation aborted", prefix); - break; - default: - _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Unknown error code %d", prefix, errorCode); - break; - } -} - -void EIO_Open(uv_work_t* req) { - OpenBaton* data = static_cast(req->data); - - char originalPath[1024]; - strncpy_s(originalPath, sizeof(originalPath), data->path, _TRUNCATE); - // data->path is char[1024] but on Windows it has the form "COMx\0" or "COMxx\0" - // We want to prepend "\\\\.\\" to it before we call CreateFile - strncpy(data->path + 20, data->path, 10); - strncpy(data->path, "\\\\.\\", 4); - strncpy(data->path + 4, data->path + 20, 10); - - int shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - if (data->lock) { - shareMode = 0; - } - - HANDLE file = CreateFile( - data->path, - GENERIC_READ | GENERIC_WRITE, - shareMode, // dwShareMode 0 Prevents other processes from opening if they request delete, read, or write access - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, // allows for reading and writing at the same time and sets the handle for asynchronous I/O - NULL - ); - - if (file == INVALID_HANDLE_VALUE) { - DWORD errorCode = GetLastError(); - char temp[100]; - _snprintf_s(temp, sizeof(temp), _TRUNCATE, "Opening %s", originalPath); - ErrorCodeToString(temp, errorCode, data->errorString); - return; - } - - bufferSize = data->bufferSize; - if (bufferSize > MAX_BUFFER_SIZE) { - bufferSize = MAX_BUFFER_SIZE; - } - - DCB dcb = { 0 }; - SecureZeroMemory(&dcb, sizeof(DCB)); - dcb.DCBlength = sizeof(DCB); - - if (!GetCommState(file, &dcb)) { - ErrorCodeToString("Open (GetCommState)", GetLastError(), data->errorString); - CloseHandle(file); - return; - } - - if (data->hupcl) { - dcb.fDtrControl = DTR_CONTROL_ENABLE; - } else { - dcb.fDtrControl = DTR_CONTROL_DISABLE; // disable DTR to avoid reset - } - - dcb.Parity = NOPARITY; - dcb.ByteSize = 8; - dcb.StopBits = ONESTOPBIT; - dcb.fInX = FALSE; - dcb.fOutX = FALSE; - dcb.fOutxDsrFlow = FALSE; - dcb.fOutxCtsFlow = FALSE; - dcb.fRtsControl = RTS_CONTROL_ENABLE; - - dcb.fBinary = true; - dcb.BaudRate = data->baudRate; - dcb.ByteSize = data->dataBits; - - switch (data->parity) { - case SERIALPORT_PARITY_NONE: - dcb.Parity = NOPARITY; - break; - case SERIALPORT_PARITY_MARK: - dcb.Parity = MARKPARITY; - break; - case SERIALPORT_PARITY_EVEN: - dcb.Parity = EVENPARITY; - break; - case SERIALPORT_PARITY_ODD: - dcb.Parity = ODDPARITY; - break; - case SERIALPORT_PARITY_SPACE: - dcb.Parity = SPACEPARITY; - break; - } - - switch (data->stopBits) { - case SERIALPORT_STOPBITS_ONE: - dcb.StopBits = ONESTOPBIT; - break; - case SERIALPORT_STOPBITS_ONE_FIVE: - dcb.StopBits = ONE5STOPBITS; - break; - case SERIALPORT_STOPBITS_TWO: - dcb.StopBits = TWOSTOPBITS; - break; - } - - if (!SetCommState(file, &dcb)) { - ErrorCodeToString("Open (SetCommState)", GetLastError(), data->errorString); - CloseHandle(file); - return; - } - - // Set the com port read/write timeouts - DWORD serialBitsPerByte = 8/*std data bits*/ + 1/*start bit*/; - serialBitsPerByte += (data->parity == SERIALPORT_PARITY_NONE) ? 0 : 1; - serialBitsPerByte += (data->stopBits == SERIALPORT_STOPBITS_ONE) ? 1 : 2; - DWORD msPerByte = (data->baudRate > 0) ? - ((1000 * serialBitsPerByte + data->baudRate - 1) / data->baudRate) : - 1; - if (msPerByte < 1) { - msPerByte = 1; - } - COMMTIMEOUTS commTimeouts = {0}; - commTimeouts.ReadIntervalTimeout = msPerByte; // Minimize chance of concatenating of separate serial port packets on read - commTimeouts.ReadTotalTimeoutMultiplier = 0; // Do not allow big read timeout when big read buffer used - commTimeouts.ReadTotalTimeoutConstant = 1000; // Total read timeout (period of read loop) - commTimeouts.WriteTotalTimeoutConstant = 1000; // Const part of write timeout - commTimeouts.WriteTotalTimeoutMultiplier = msPerByte; // Variable part of write timeout (per byte) - if (!SetCommTimeouts(file, &commTimeouts)) { - ErrorCodeToString("Open (SetCommTimeouts)", GetLastError(), data->errorString); - CloseHandle(file); - return; - } - - // Remove garbage data in RX/TX queues - PurgeComm(file, PURGE_RXCLEAR); - PurgeComm(file, PURGE_TXCLEAR); - - data->result = (int)file; -} - -struct WatchPortBaton { - HANDLE fd; - DWORD bytesRead; - char buffer[MAX_BUFFER_SIZE]; - char errorString[ERROR_STRING_SIZE]; - DWORD errorCode; - bool disconnected; - Nan::Callback* dataCallback; - Nan::Callback* errorCallback; - Nan::Callback* disconnectedCallback; -}; - -void EIO_Update(uv_work_t* req) { - ConnectionOptionsBaton* data = static_cast(req->data); - - DCB dcb = { 0 }; - SecureZeroMemory(&dcb, sizeof(DCB)); - dcb.DCBlength = sizeof(DCB); - - if (!GetCommState((HANDLE)data->fd, &dcb)) { - ErrorCodeToString("GetCommState", GetLastError(), data->errorString); - return; - } - - dcb.BaudRate = data->baudRate; - - if (!SetCommState((HANDLE)data->fd, &dcb)) { - ErrorCodeToString("SetCommState", GetLastError(), data->errorString); - return; - } -} - -void EIO_Set(uv_work_t* req) { - SetBaton* data = static_cast(req->data); - - if (data->rts) { - EscapeCommFunction((HANDLE)data->fd, SETRTS); - } else { - EscapeCommFunction((HANDLE)data->fd, CLRRTS); - } - - if (data->dtr) { - EscapeCommFunction((HANDLE)data->fd, SETDTR); - } else { - EscapeCommFunction((HANDLE)data->fd, CLRDTR); - } - - if (data->brk) { - EscapeCommFunction((HANDLE)data->fd, SETBREAK); - } else { - EscapeCommFunction((HANDLE)data->fd, CLRBREAK); - } - - DWORD bits = 0; - - GetCommMask((HANDLE)data->fd, &bits); - - bits &= ~(EV_CTS | EV_DSR); - - if (data->cts) { - bits |= EV_CTS; - } - - if (data->dsr) { - bits |= EV_DSR; - } - - if (!SetCommMask((HANDLE)data->fd, bits)) { - ErrorCodeToString("Setting options on COM port (SetCommMask)", GetLastError(), data->errorString); - return; - } -} - - -void EIO_WatchPort(uv_work_t* req) { - WatchPortBaton* data = static_cast(req->data); - data->bytesRead = 0; - data->disconnected = false; - - // Event used by GetOverlappedResult(..., TRUE) to wait for incoming data or timeout - // Event MUST be used if program has several simultaneous asynchronous operations - // on the same handle (i.e. ReadFile and WriteFile) - HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - while (true) { - OVERLAPPED ov = {0}; - ov.hEvent = hEvent; - - // Start read operation - synchrounous or asynchronous - DWORD bytesReadSync = 0; - if (!ReadFile((HANDLE)data->fd, data->buffer, bufferSize, &bytesReadSync, &ov)) { - data->errorCode = GetLastError(); - if (data->errorCode != ERROR_IO_PENDING) { - // Read operation error - if (data->errorCode == ERROR_OPERATION_ABORTED) { - data->disconnected = true; - } else { - ErrorCodeToString("Reading from COM port (ReadFile)", data->errorCode, data->errorString); - CloseHandle(hEvent); - return; - } - break; - } - - // Read operation is asynchronous and is pending - // We MUST wait for operation completion before deallocation of OVERLAPPED struct - // or read data buffer - - // Wait for async read operation completion or timeout - DWORD bytesReadAsync = 0; - if (!GetOverlappedResult((HANDLE)data->fd, &ov, &bytesReadAsync, TRUE)) { - // Read operation error - data->errorCode = GetLastError(); - if (data->errorCode == ERROR_OPERATION_ABORTED) { - data->disconnected = true; - } else { - ErrorCodeToString("Reading from COM port (GetOverlappedResult)", data->errorCode, data->errorString); - CloseHandle(hEvent); - return; - } - break; - } else { - // Read operation completed asynchronously - data->bytesRead = bytesReadAsync; - } - } else { - // Read operation completed synchronously - data->bytesRead = bytesReadSync; - } - - // Return data received if any - if (data->bytesRead > 0) { - break; - } - } - - CloseHandle(hEvent); -} - -bool IsClosingHandle(int fd) { - for (std::list::iterator it = g_closingHandles.begin(); it != g_closingHandles.end(); ++it) { - if (fd == *it) { - g_closingHandles.remove(fd); - return true; - } - } - return false; -} - -void DisposeWatchPortCallbacks(WatchPortBaton* data) { - delete data->dataCallback; - delete data->errorCallback; - delete data->disconnectedCallback; -} - -// FinalizerCallback will prevent WatchPortBaton::buffer from getting -// collected by gc while finalizing v8::ArrayBuffer. The buffer will -// get cleaned up through this callback. -static void FinalizerCallback(char* data, void* hint) { - uv_work_t* req = reinterpret_cast(hint); - WatchPortBaton* wpb = static_cast(req->data); - delete wpb; - delete req; -} - -void EIO_AfterWatchPort(uv_work_t* req) { - Nan::HandleScope scope; - - WatchPortBaton* data = static_cast(req->data); - if (data->disconnected) { - data->disconnectedCallback->Call(0, NULL); - DisposeWatchPortCallbacks(data); - goto cleanup; - } - - bool skipCleanup = false; - if (data->bytesRead > 0) { - v8::Local argv[1]; - argv[0] = Nan::NewBuffer(data->buffer, data->bytesRead, FinalizerCallback, req).ToLocalChecked(); - skipCleanup = true; - data->dataCallback->Call(1, argv); - } else if (data->errorCode > 0) { - if (data->errorCode == ERROR_INVALID_HANDLE && IsClosingHandle((int)data->fd)) { - DisposeWatchPortCallbacks(data); - goto cleanup; - } else { - v8::Local argv[1]; - argv[0] = Nan::Error(data->errorString); - data->errorCallback->Call(1, argv); - Sleep(100); // prevent the errors from occurring too fast - } - } - AfterOpenSuccess((int)data->fd, data->dataCallback, data->disconnectedCallback, data->errorCallback); - -cleanup: - if (!skipCleanup) { - delete data; - delete req; - } -} - -void AfterOpenSuccess(int fd, Nan::Callback* dataCallback, Nan::Callback* disconnectedCallback, Nan::Callback* errorCallback) { - WatchPortBaton* baton = new WatchPortBaton(); - memset(baton, 0, sizeof(WatchPortBaton)); - baton->fd = (HANDLE)fd; - baton->dataCallback = dataCallback; - baton->errorCallback = errorCallback; - baton->disconnectedCallback = disconnectedCallback; - - uv_work_t* req = new uv_work_t(); - req->data = baton; - - uv_queue_work(uv_default_loop(), req, EIO_WatchPort, (uv_after_work_cb)EIO_AfterWatchPort); -} - -void EIO_Write(uv_work_t* req) { - QueuedWrite* queuedWrite = static_cast(req->data); - WriteBaton* data = static_cast(queuedWrite->baton); - data->result = 0; - - do { - OVERLAPPED ov = {0}; - // Event used by GetOverlappedResult(..., TRUE) to wait for outgoing data or timeout - // Event MUST be used if program has several simultaneous asynchronous operations - // on the same handle (i.e. ReadFile and WriteFile) - ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - // Start write operation - synchronous or asynchronous - DWORD bytesWritten = 0; - if (!WriteFile((HANDLE)data->fd, data->bufferData, static_cast(data->bufferLength), &bytesWritten, &ov)) { - DWORD lastError = GetLastError(); - if (lastError != ERROR_IO_PENDING) { - // Write operation error - ErrorCodeToString("Writing to COM port (WriteFile)", lastError, data->errorString); - CloseHandle(ov.hEvent); - return; - } - // Write operation is completing asynchronously - // We MUST wait for the operation completion before deallocation of OVERLAPPED struct - // or write data buffer - - // block for async write operation completion - bytesWritten = 0; - if (!GetOverlappedResult((HANDLE)data->fd, &ov, &bytesWritten, TRUE)) { - // Write operation error - DWORD lastError = GetLastError(); - ErrorCodeToString("Writing to COM port (GetOverlappedResult)", lastError, data->errorString); - CloseHandle(ov.hEvent); - return; - } - } - // Write operation completed synchronously - data->result = bytesWritten; - data->offset += data->result; - CloseHandle(ov.hEvent); - } while (data->bufferLength > data->offset); -} - -void EIO_Close(uv_work_t* req) { - CloseBaton* data = static_cast(req->data); - - g_closingHandles.push_back(data->fd); - - HMODULE hKernel32 = LoadLibrary("kernel32.dll"); - // Look up function address - CancelIoExType pCancelIoEx = (CancelIoExType)GetProcAddress(hKernel32, "CancelIoEx"); - // Do something with it - if (pCancelIoEx) { - // Function exists so call it - // Cancel all pending IO Requests for the current device - pCancelIoEx((HANDLE)data->fd, NULL); - } - if (!CloseHandle((HANDLE)data->fd)) { - ErrorCodeToString("closing connection", GetLastError(), data->errorString); - return; - } -} - -char *copySubstring(char *someString, int n) -{ - char *new_ = (char*)malloc(sizeof(char)*n + 1); - strncpy_s(new_, n + 1, someString, n); - new_[n] = '\0'; - return new_; -} - -void EIO_List(uv_work_t* req) { - ListBaton* data = static_cast(req->data); - - GUID *guidDev = (GUID*)& GUID_DEVCLASS_PORTS; - HDEVINFO hDevInfo = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE); - SP_DEVINFO_DATA deviceInfoData; - - int memberIndex = 0; - DWORD dwSize, dwPropertyRegDataType; - char szBuffer[400]; - char *pnpId; - char *vendorId; - char *productId; - char *name; - char *manufacturer; - char *locationId; - bool isCom; - while (true) { - pnpId = NULL; - vendorId = NULL; - productId = NULL; - name = NULL; - manufacturer = NULL; - locationId = NULL; - - ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA)); - deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - - if (SetupDiEnumDeviceInfo(hDevInfo, memberIndex, &deviceInfoData) == FALSE) { - if (GetLastError() == ERROR_NO_MORE_ITEMS) { - break; - } - } - - dwSize = sizeof(szBuffer); - SetupDiGetDeviceInstanceId(hDevInfo, &deviceInfoData, szBuffer, dwSize, &dwSize); - szBuffer[dwSize] = '\0'; - pnpId = strdup(szBuffer); - - vendorId = strstr(szBuffer, "VID_"); - if (vendorId) { - vendorId += 4; - vendorId = copySubstring(vendorId, 4); - } - productId = strstr(szBuffer, "PID_"); - if (productId) { - productId += 4; - productId = copySubstring(productId, 4); - } - - if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_LOCATION_INFORMATION, &dwPropertyRegDataType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize)) { - locationId = strdup(szBuffer); - } - if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_MFG, &dwPropertyRegDataType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize)) { - manufacturer = strdup(szBuffer); - } - - HKEY hkey = SetupDiOpenDevRegKey(hDevInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); - if (hkey != INVALID_HANDLE_VALUE) { - dwSize = sizeof(szBuffer); - if (RegQueryValueEx(hkey, "PortName", NULL, NULL, (LPBYTE)&szBuffer, &dwSize) == ERROR_SUCCESS) { - szBuffer[dwSize] = '\0'; - name = strdup(szBuffer); - isCom = strstr(szBuffer, "COM") != NULL; - } - } - if (isCom) { - ListResultItem* resultItem = new ListResultItem(); - resultItem->comName = name; - resultItem->manufacturer = manufacturer; - resultItem->pnpId = pnpId; - if (vendorId) { - resultItem->vendorId = vendorId; - } - if (productId) { - resultItem->productId = productId; - } - if (locationId) { - resultItem->locationId = locationId; - } - data->results.push_back(resultItem); - } - free(pnpId); - free(vendorId); - free(productId); - free(locationId); - free(manufacturer); - free(name); - - RegCloseKey(hkey); - memberIndex++; - } - if (hDevInfo) { - SetupDiDestroyDeviceInfoList(hDevInfo); - } -} - -void EIO_Flush(uv_work_t* req) { - FlushBaton* data = static_cast(req->data); - - if (!FlushFileBuffers((HANDLE)data->fd)) { - ErrorCodeToString("flushing connection (FlushFileBuffers)", GetLastError(), data->errorString); - return; - } -} - -void EIO_Drain(uv_work_t* req) { - DrainBaton* data = static_cast(req->data); - - if (!FlushFileBuffers((HANDLE)data->fd)) { - ErrorCodeToString("draining connection (FlushFileBuffers)", GetLastError(), data->errorString); - return; - } -} - -#endif +#include +#include +#include +#include "./serialport.h" +#include +#include +#include +#include +#pragma comment (lib, "setupapi.lib") + +#ifdef WIN32 + +#define MAX_BUFFER_SIZE 1000 + +struct WindowsPlatformOptions : OpenBatonPlatformOptions { +}; + +OpenBatonPlatformOptions* ParsePlatformOptions(const v8::Local& options) { + // currently none + return new WindowsPlatformOptions(); +} + +// Declare type of pointer to CancelIoEx function +typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped); + +std::list g_closingHandles; +int bufferSize; +void ErrorCodeToString(const char* prefix, int errorCode, char *errorStr) { + switch (errorCode) { + case ERROR_FILE_NOT_FOUND: + _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: File not found", prefix); + break; + case ERROR_INVALID_HANDLE: + _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Invalid handle", prefix); + break; + case ERROR_ACCESS_DENIED: + _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Access denied", prefix); + break; + case ERROR_OPERATION_ABORTED: + _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: operation aborted", prefix); + break; + default: + _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Unknown error code %d", prefix, errorCode); + break; + } +} + +void EIO_Open(uv_work_t* req) { + OpenBaton* data = static_cast(req->data); + + char originalPath[1024]; + strncpy_s(originalPath, sizeof(originalPath), data->path, _TRUNCATE); + // data->path is char[1024] but on Windows it has the form "COMx\0" or "COMxx\0" + // We want to prepend "\\\\.\\" to it before we call CreateFile + strncpy(data->path + 20, data->path, 10); + strncpy(data->path, "\\\\.\\", 4); + strncpy(data->path + 4, data->path + 20, 10); + + int shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + if (data->lock) { + shareMode = 0; + } + + HANDLE file = CreateFile( + data->path, + GENERIC_READ | GENERIC_WRITE, + shareMode, // dwShareMode 0 Prevents other processes from opening if they request delete, read, or write access + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, // allows for reading and writing at the same time and sets the handle for asynchronous I/O + NULL + ); + + if (file == INVALID_HANDLE_VALUE) { + DWORD errorCode = GetLastError(); + char temp[100]; + _snprintf_s(temp, sizeof(temp), _TRUNCATE, "Opening %s", originalPath); + ErrorCodeToString(temp, errorCode, data->errorString); + return; + } + + bufferSize = data->bufferSize; + if (bufferSize > MAX_BUFFER_SIZE) { + bufferSize = MAX_BUFFER_SIZE; + } + + DCB dcb = { 0 }; + SecureZeroMemory(&dcb, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + + if (!GetCommState(file, &dcb)) { + ErrorCodeToString("Open (GetCommState)", GetLastError(), data->errorString); + CloseHandle(file); + return; + } + + if (data->hupcl) { + dcb.fDtrControl = DTR_CONTROL_ENABLE; + } else { + dcb.fDtrControl = DTR_CONTROL_DISABLE; // disable DTR to avoid reset + } + + dcb.Parity = NOPARITY; + dcb.ByteSize = 8; + dcb.StopBits = ONESTOPBIT; + dcb.fInX = FALSE; + dcb.fOutX = FALSE; + dcb.fOutxDsrFlow = FALSE; + dcb.fOutxCtsFlow = FALSE; + dcb.fRtsControl = RTS_CONTROL_ENABLE; + + dcb.fBinary = true; + dcb.BaudRate = data->baudRate; + dcb.ByteSize = data->dataBits; + + switch (data->parity) { + case SERIALPORT_PARITY_NONE: + dcb.Parity = NOPARITY; + break; + case SERIALPORT_PARITY_MARK: + dcb.Parity = MARKPARITY; + break; + case SERIALPORT_PARITY_EVEN: + dcb.Parity = EVENPARITY; + break; + case SERIALPORT_PARITY_ODD: + dcb.Parity = ODDPARITY; + break; + case SERIALPORT_PARITY_SPACE: + dcb.Parity = SPACEPARITY; + break; + } + + switch (data->stopBits) { + case SERIALPORT_STOPBITS_ONE: + dcb.StopBits = ONESTOPBIT; + break; + case SERIALPORT_STOPBITS_ONE_FIVE: + dcb.StopBits = ONE5STOPBITS; + break; + case SERIALPORT_STOPBITS_TWO: + dcb.StopBits = TWOSTOPBITS; + break; + } + + if (!SetCommState(file, &dcb)) { + ErrorCodeToString("Open (SetCommState)", GetLastError(), data->errorString); + CloseHandle(file); + return; + } + + // Set the com port read/write timeouts + DWORD serialBitsPerByte = 8/*std data bits*/ + 1/*start bit*/; + serialBitsPerByte += (data->parity == SERIALPORT_PARITY_NONE) ? 0 : 1; + serialBitsPerByte += (data->stopBits == SERIALPORT_STOPBITS_ONE) ? 1 : 2; + DWORD msPerByte = (data->baudRate > 0) ? + ((1000 * serialBitsPerByte + data->baudRate - 1) / data->baudRate) : + 1; + if (msPerByte < 1) { + msPerByte = 1; + } + COMMTIMEOUTS commTimeouts = {0}; + commTimeouts.ReadIntervalTimeout = msPerByte; // Minimize chance of concatenating of separate serial port packets on read + commTimeouts.ReadTotalTimeoutMultiplier = 0; // Do not allow big read timeout when big read buffer used + commTimeouts.ReadTotalTimeoutConstant = 1000; // Total read timeout (period of read loop) + commTimeouts.WriteTotalTimeoutConstant = 1000; // Const part of write timeout + commTimeouts.WriteTotalTimeoutMultiplier = msPerByte; // Variable part of write timeout (per byte) + if (!SetCommTimeouts(file, &commTimeouts)) { + ErrorCodeToString("Open (SetCommTimeouts)", GetLastError(), data->errorString); + CloseHandle(file); + return; + } + + // Remove garbage data in RX/TX queues + PurgeComm(file, PURGE_RXCLEAR); + PurgeComm(file, PURGE_TXCLEAR); + + data->result = (int)file; +} + +struct WatchPortBaton { + HANDLE fd; + DWORD bytesRead; + char buffer[MAX_BUFFER_SIZE]; + char errorString[ERROR_STRING_SIZE]; + DWORD errorCode; + bool disconnected; + Nan::Callback* dataCallback; + Nan::Callback* errorCallback; + Nan::Callback* disconnectedCallback; +}; + +void EIO_Update(uv_work_t* req) { + ConnectionOptionsBaton* data = static_cast(req->data); + + DCB dcb = { 0 }; + SecureZeroMemory(&dcb, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + + if (!GetCommState((HANDLE)data->fd, &dcb)) { + ErrorCodeToString("GetCommState", GetLastError(), data->errorString); + return; + } + + dcb.BaudRate = data->baudRate; + + if (!SetCommState((HANDLE)data->fd, &dcb)) { + ErrorCodeToString("SetCommState", GetLastError(), data->errorString); + return; + } +} + +void EIO_Set(uv_work_t* req) { + SetBaton* data = static_cast(req->data); + + if (data->rts) { + EscapeCommFunction((HANDLE)data->fd, SETRTS); + } else { + EscapeCommFunction((HANDLE)data->fd, CLRRTS); + } + + if (data->dtr) { + EscapeCommFunction((HANDLE)data->fd, SETDTR); + } else { + EscapeCommFunction((HANDLE)data->fd, CLRDTR); + } + + if (data->brk) { + EscapeCommFunction((HANDLE)data->fd, SETBREAK); + } else { + EscapeCommFunction((HANDLE)data->fd, CLRBREAK); + } + + DWORD bits = 0; + + GetCommMask((HANDLE)data->fd, &bits); + + bits &= ~(EV_CTS | EV_DSR); + + if (data->cts) { + bits |= EV_CTS; + } + + if (data->dsr) { + bits |= EV_DSR; + } + + if (!SetCommMask((HANDLE)data->fd, bits)) { + ErrorCodeToString("Setting options on COM port (SetCommMask)", GetLastError(), data->errorString); + return; + } +} + + +void EIO_WatchPort(uv_work_t* req) { + WatchPortBaton* data = static_cast(req->data); + data->bytesRead = 0; + data->disconnected = false; + + // Event used by GetOverlappedResult(..., TRUE) to wait for incoming data or timeout + // Event MUST be used if program has several simultaneous asynchronous operations + // on the same handle (i.e. ReadFile and WriteFile) + HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + while (true) { + OVERLAPPED ov = {0}; + ov.hEvent = hEvent; + + // Start read operation - synchrounous or asynchronous + DWORD bytesReadSync = 0; + if (!ReadFile((HANDLE)data->fd, data->buffer, bufferSize, &bytesReadSync, &ov)) { + data->errorCode = GetLastError(); + if (data->errorCode != ERROR_IO_PENDING) { + // Read operation error + if (data->errorCode == ERROR_OPERATION_ABORTED) { + data->disconnected = true; + } else { + ErrorCodeToString("Reading from COM port (ReadFile)", data->errorCode, data->errorString); + CloseHandle(hEvent); + return; + } + break; + } + + // Read operation is asynchronous and is pending + // We MUST wait for operation completion before deallocation of OVERLAPPED struct + // or read data buffer + + // Wait for async read operation completion or timeout + DWORD bytesReadAsync = 0; + if (!GetOverlappedResult((HANDLE)data->fd, &ov, &bytesReadAsync, TRUE)) { + // Read operation error + data->errorCode = GetLastError(); + if (data->errorCode == ERROR_OPERATION_ABORTED) { + data->disconnected = true; + } else { + ErrorCodeToString("Reading from COM port (GetOverlappedResult)", data->errorCode, data->errorString); + CloseHandle(hEvent); + return; + } + break; + } else { + // Read operation completed asynchronously + data->bytesRead = bytesReadAsync; + } + } else { + // Read operation completed synchronously + data->bytesRead = bytesReadSync; + } + + // Return data received if any + if (data->bytesRead > 0) { + break; + } + } + + CloseHandle(hEvent); +} + +bool IsClosingHandle(int fd) { + for (std::list::iterator it = g_closingHandles.begin(); it != g_closingHandles.end(); ++it) { + if (fd == *it) { + g_closingHandles.remove(fd); + return true; + } + } + return false; +} + +void DisposeWatchPortCallbacks(WatchPortBaton* data) { + delete data->dataCallback; + delete data->errorCallback; + delete data->disconnectedCallback; +} + +// FinalizerCallback will prevent WatchPortBaton::buffer from getting +// collected by gc while finalizing v8::ArrayBuffer. The buffer will +// get cleaned up through this callback. +static void FinalizerCallback(char* data, void* hint) { + uv_work_t* req = reinterpret_cast(hint); + WatchPortBaton* wpb = static_cast(req->data); + delete wpb; + delete req; +} + +void EIO_AfterWatchPort(uv_work_t* req) { + Nan::HandleScope scope; + + WatchPortBaton* data = static_cast(req->data); + if (data->disconnected) { + data->disconnectedCallback->Call(0, NULL); + DisposeWatchPortCallbacks(data); + goto cleanup; + } + + bool skipCleanup = false; + if (data->bytesRead > 0) { + v8::Local argv[1]; + argv[0] = Nan::NewBuffer(data->buffer, data->bytesRead, FinalizerCallback, req).ToLocalChecked(); + skipCleanup = true; + data->dataCallback->Call(1, argv); + } else if (data->errorCode > 0) { + if (data->errorCode == ERROR_INVALID_HANDLE && IsClosingHandle((int)data->fd)) { + DisposeWatchPortCallbacks(data); + goto cleanup; + } else { + v8::Local argv[1]; + argv[0] = Nan::Error(data->errorString); + data->errorCallback->Call(1, argv); + Sleep(100); // prevent the errors from occurring too fast + } + } + AfterOpenSuccess((int)data->fd, data->dataCallback, data->disconnectedCallback, data->errorCallback); + +cleanup: + if (!skipCleanup) { + delete data; + delete req; + } +} + +void AfterOpenSuccess(int fd, Nan::Callback* dataCallback, Nan::Callback* disconnectedCallback, Nan::Callback* errorCallback) { + WatchPortBaton* baton = new WatchPortBaton(); + memset(baton, 0, sizeof(WatchPortBaton)); + baton->fd = (HANDLE)fd; + baton->dataCallback = dataCallback; + baton->errorCallback = errorCallback; + baton->disconnectedCallback = disconnectedCallback; + + uv_work_t* req = new uv_work_t(); + req->data = baton; + + uv_queue_work(uv_default_loop(), req, EIO_WatchPort, (uv_after_work_cb)EIO_AfterWatchPort); +} + +void EIO_Write(uv_work_t* req) { + QueuedWrite* queuedWrite = static_cast(req->data); + WriteBaton* data = static_cast(queuedWrite->baton); + data->result = 0; + + do { + OVERLAPPED ov = {0}; + // Event used by GetOverlappedResult(..., TRUE) to wait for outgoing data or timeout + // Event MUST be used if program has several simultaneous asynchronous operations + // on the same handle (i.e. ReadFile and WriteFile) + ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + // Start write operation - synchronous or asynchronous + DWORD bytesWritten = 0; + if (!WriteFile((HANDLE)data->fd, data->bufferData, static_cast(data->bufferLength), &bytesWritten, &ov)) { + DWORD lastError = GetLastError(); + if (lastError != ERROR_IO_PENDING) { + // Write operation error + ErrorCodeToString("Writing to COM port (WriteFile)", lastError, data->errorString); + CloseHandle(ov.hEvent); + return; + } + // Write operation is completing asynchronously + // We MUST wait for the operation completion before deallocation of OVERLAPPED struct + // or write data buffer + + // block for async write operation completion + bytesWritten = 0; + if (!GetOverlappedResult((HANDLE)data->fd, &ov, &bytesWritten, TRUE)) { + // Write operation error + DWORD lastError = GetLastError(); + ErrorCodeToString("Writing to COM port (GetOverlappedResult)", lastError, data->errorString); + CloseHandle(ov.hEvent); + return; + } + } + // Write operation completed synchronously + data->result = bytesWritten; + data->offset += data->result; + CloseHandle(ov.hEvent); + } while (data->bufferLength > data->offset); +} + +void EIO_Close(uv_work_t* req) { + CloseBaton* data = static_cast(req->data); + + g_closingHandles.push_back(data->fd); + + HMODULE hKernel32 = LoadLibrary("kernel32.dll"); + // Look up function address + CancelIoExType pCancelIoEx = (CancelIoExType)GetProcAddress(hKernel32, "CancelIoEx"); + // Do something with it + if (pCancelIoEx) { + // Function exists so call it + // Cancel all pending IO Requests for the current device + pCancelIoEx((HANDLE)data->fd, NULL); + } + if (!CloseHandle((HANDLE)data->fd)) { + ErrorCodeToString("closing connection", GetLastError(), data->errorString); + return; + } +} + +char *copySubstring(char *someString, int n) +{ + char *new_ = (char*)malloc(sizeof(char)*n + 1); + strncpy_s(new_, n + 1, someString, n); + new_[n] = '\0'; + return new_; +} + +void EIO_List(uv_work_t* req) { + ListBaton* data = static_cast(req->data); + + GUID *guidDev = (GUID*)& GUID_DEVCLASS_PORTS; + HDEVINFO hDevInfo = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE); + SP_DEVINFO_DATA deviceInfoData; + + int memberIndex = 0; + DWORD dwSize, dwPropertyRegDataType; + char szBuffer[400]; + char *pnpId; + char *vendorId; + char *productId; + char *name; + char *manufacturer; + char *locationId; + bool isCom; + while (true) { + pnpId = NULL; + vendorId = NULL; + productId = NULL; + name = NULL; + manufacturer = NULL; + locationId = NULL; + + ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA)); + deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + + if (SetupDiEnumDeviceInfo(hDevInfo, memberIndex, &deviceInfoData) == FALSE) { + if (GetLastError() == ERROR_NO_MORE_ITEMS) { + break; + } + } + + dwSize = sizeof(szBuffer); + SetupDiGetDeviceInstanceId(hDevInfo, &deviceInfoData, szBuffer, dwSize, &dwSize); + szBuffer[dwSize] = '\0'; + pnpId = strdup(szBuffer); + + vendorId = strstr(szBuffer, "VID_"); + if (vendorId) { + vendorId += 4; + vendorId = copySubstring(vendorId, 4); + } + productId = strstr(szBuffer, "PID_"); + if (productId) { + productId += 4; + productId = copySubstring(productId, 4); + } + + if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_LOCATION_INFORMATION, &dwPropertyRegDataType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize)) { + locationId = strdup(szBuffer); + } + if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_MFG, &dwPropertyRegDataType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize)) { + manufacturer = strdup(szBuffer); + } + + HKEY hkey = SetupDiOpenDevRegKey(hDevInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); + if (hkey != INVALID_HANDLE_VALUE) { + dwSize = sizeof(szBuffer); + if (RegQueryValueEx(hkey, "PortName", NULL, NULL, (LPBYTE)&szBuffer, &dwSize) == ERROR_SUCCESS) { + szBuffer[dwSize] = '\0'; + name = strdup(szBuffer); + isCom = strstr(szBuffer, "COM") != NULL; + } + } + if (isCom) { + ListResultItem* resultItem = new ListResultItem(); + resultItem->comName = name; + resultItem->manufacturer = manufacturer; + resultItem->pnpId = pnpId; + if (vendorId) { + resultItem->vendorId = vendorId; + } + if (productId) { + resultItem->productId = productId; + } + if (locationId) { + resultItem->locationId = locationId; + } + data->results.push_back(resultItem); + } + free(pnpId); + free(vendorId); + free(productId); + free(locationId); + free(manufacturer); + free(name); + + RegCloseKey(hkey); + memberIndex++; + } + if (hDevInfo) { + SetupDiDestroyDeviceInfoList(hDevInfo); + } +} + +void EIO_Flush(uv_work_t* req) { + FlushBaton* data = static_cast(req->data); + + if (!FlushFileBuffers((HANDLE)data->fd)) { + ErrorCodeToString("flushing connection (FlushFileBuffers)", GetLastError(), data->errorString); + return; + } +} + +void EIO_Drain(uv_work_t* req) { + DrainBaton* data = static_cast(req->data); + + if (!FlushFileBuffers((HANDLE)data->fd)) { + ErrorCodeToString("draining connection (FlushFileBuffers)", GetLastError(), data->errorString); + return; + } +} + +#endif From bd17618695d9b409d45208be1bfa4dbc433f35aa Mon Sep 17 00:00:00 2001 From: Andrea Mah <31675041+andreamah@users.noreply.github.com> Date: Mon, 2 Mar 2020 09:38:45 -0800 Subject: [PATCH 2/5] removed readme badges and changed date on release note (#234) removed readme badges and updated release note --- README.md | 12 ------------ src/latest_release_note.ts | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/README.md b/README.md index f52084c69..d675ab0a5 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,11 @@ # Device Simulator Express, a Microsoft Garage project -Python versions: 3.7+ Project Status: Active – The project has reached a stable, usable state and is being actively developed. License: We are using the MIT License We are welcoming PRS! Platforms Supported: Windows, MacOSX - -Azure DevOps Board Badge - Make without limit! Device Simulator Express, a Microsoft Garage project, allows you to code microcontrollers without the hardware on hand! You can program your Circuit Playground Express (CPX) or your BBC micro:bit! Test and debug your code on the device simulator and see the same result when you plug in your actual microcontroller. Curious about the output of the device, the serial monitor allows you to observe the device output. CircuitPlayground Express -## Build Status - -| Branch | Build Status | -| :------ | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| dev | [![Build Status](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_apis/build/status/Adafruit/Pacifica-CI?branchName=dev)](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_build/latest?definitionId=304&branchName=dev) | -| staging | [![Build Status](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_apis/build/status/Adafruit/Pacifica-CI?branchName=staging)](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_build/latest?definitionId=304&branchName=staging) | -| master | [![Build Status](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_apis/build/status/Adafruit/Pacifica-CI?branchName=master)](https://microsoftgarage.visualstudio.com/Intern%20GitHub/_build/latest?definitionId=304&branchName=master) | - ## Prerequisites diff --git a/src/latest_release_note.ts b/src/latest_release_note.ts index a4e1ddabd..33e292154 100644 --- a/src/latest_release_note.ts +++ b/src/latest_release_note.ts @@ -1,5 +1,5 @@ // TODO: find a better way of loading html into a string -export const LATEST_RELEASE_NOTE = `

Device Simulator Express Release Notes 👩🏾‍💻 👨🏾‍💻 (Feb. 27, 2020)

+export const LATEST_RELEASE_NOTE = `

Device Simulator Express Release Notes 👩🏾‍💻 👨🏾‍💻 (Mar. 2, 2020)

Welcome to the first update to the Device Simulator Express! Please feel free to enable our feature flag in Settings From ce0552c3c5e1a95a500ef68d1c8ed58e1ccbebb2 Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Mon, 2 Mar 2020 14:35:35 -0800 Subject: [PATCH 3/5] Fix issue on mac os when using track_event --- src/common/telemetry.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/telemetry.py b/src/common/telemetry.py index 44a22d058..fd4a8537c 100644 --- a/src/common/telemetry.py +++ b/src/common/telemetry.py @@ -1,4 +1,7 @@ +import sys + from applicationinsights import TelemetryClient +from common import constants as CONSTANTS from .telemetry_events import TelemetryEvent @@ -17,6 +20,7 @@ def send_telemetry(self, event_name: TelemetryEvent): self.__enable_telemetry and self.telemetry_available() and not self.telemetry_state[event_name.name] + and not sys.platform.startswith(CONSTANTS.MAC_OS) ): self.telemetry_client.track_event( f"{self.extension_name}/{event_name.value}" From c0505c72b3a543348c8c2cd1b0637c95c455b1b4 Mon Sep 17 00:00:00 2001 From: Andrea Mah <31675041+andreamah@users.noreply.github.com> Date: Tue, 3 Mar 2020 08:44:06 -0800 Subject: [PATCH 4/5] changed date on release note (#239) Changed release date on release note --- src/latest_release_note.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/latest_release_note.ts b/src/latest_release_note.ts index 33e292154..569e1f3c5 100644 --- a/src/latest_release_note.ts +++ b/src/latest_release_note.ts @@ -1,5 +1,5 @@ // TODO: find a better way of loading html into a string -export const LATEST_RELEASE_NOTE = `

Device Simulator Express Release Notes 👩🏾‍💻 👨🏾‍💻 (Mar. 2, 2020)

+export const LATEST_RELEASE_NOTE = `

Device Simulator Express Release Notes 👩🏾‍💻 👨🏾‍💻 (Mar. 3, 2020)

Welcome to the first update to the Device Simulator Express! Please feel free to enable our feature flag in Settings From 1b79fbf51206e1036425b83187f0095f9fa8f389 Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Mon, 9 Mar 2020 14:16:32 -0700 Subject: [PATCH 5/5] Remove duplicate --- package-lock.json | 16 ++++++++++++---- package.json | 1 - src/constants.ts | 5 +---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index b0702e597..7b8613ef0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26317,7 +26317,8 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -26477,6 +26478,7 @@ "version": "2.9.0", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -26495,6 +26497,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -26597,6 +26600,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -26682,7 +26686,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -26718,6 +26723,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -26781,12 +26787,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true } } } diff --git a/package.json b/package.json index 59e9b4417..4c18fe24a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "category": "%deviceSimulatorExpressExtension.commands.common.label%" }, { - "command": "deviceSimulatorExpress.common.openSerialMonitor", "title": "%deviceSimulatorExpressExtension.commands.common.openSerialMonitor%", "category": "%deviceSimulatorExpressExtension.commands.common.label%" diff --git a/src/constants.ts b/src/constants.ts index e200f2a19..5d30b3602 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -69,10 +69,7 @@ export const CONSTANTS = { "error.installationError", "Installation Error" ), - INSTALLATION_ERROR: localize( - "error.installationError", - "Installation Error" - ), + INVALID_FILE_EXTENSION_DEBUG: localize( "error.invalidFileExtensionDebug", "The file you tried to run isn't a Python file."