diff --git a/.build/pre-release.sh b/.build/pre-release.sh index fe44496a..1f515ee3 100644 --- a/.build/pre-release.sh +++ b/.build/pre-release.sh @@ -1,13 +1,8 @@ #!/usr/bin/env bash set -ex -echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc -npm whoami - -npm ci patchVersion=$(npm --no-git-tag version patch) nextVersion=${patchVersion}-next."$(date +%Y%m%d%H%M%S)" echo "${nextVersion:1}" -npm version --no-git-tag -f "${nextVersion:1}" -npm run publish-next \ No newline at end of file +npm version --no-git-tag -f "${nextVersion:1}" \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index eef4ab05..fe1d11cf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -43,7 +43,7 @@ jobs: npm run coverage:merge npm run coverage:merge-report - name: Send results to SonarCloud - uses: SonarSource/sonarcloud-github-action@v1.4 + uses: SonarSource/sonarcloud-github-action@v1.6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} @@ -53,11 +53,8 @@ jobs: - sonar strategy: matrix: - os: [ ubuntu-latest, windows-latest, macos-latest ] - node: [ 12, 14, 16 ] - exclude: - - os: ubuntu-latest - node: 14 + os: [ windows-latest, macos-latest ] + node: [ 14 ] runs-on: ${{matrix.os}} steps: - name: Set up Git repository diff --git a/.github/workflows/snapshot_release.yaml b/.github/workflows/snapshot_release.yaml index e7dd13dc..816061cc 100644 --- a/.github/workflows/snapshot_release.yaml +++ b/.github/workflows/snapshot_release.yaml @@ -12,7 +12,7 @@ jobs: strategy: matrix: os: [ ubuntu-latest, windows-latest, macos-latest ] - node: [ 12, 14, 16 ] + node: [ 14 ] runs-on: ${{matrix.os}} steps: - name: Set up Git repository @@ -58,9 +58,21 @@ jobs: uses: actions/setup-node@v2 with: node-version: 14 + registry-url: 'https://registry.npmjs.org' + - name: Install + run: npm ci - name: Install @nut-tree/libnut@next run: npm i @nut-tree/libnut@next - - name: Publish snapshot release + - name: Create snapshot release run: bash ./.build/pre-release.sh + - name: Publish snapshot release to npm + run: npm run publish-next + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - uses: actions/setup-node@v2 + with: + registry-url: 'https://npm.pkg.github.com' + - name: Publish snapshot release to GPR + run: npm run publish-next env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tagged_release.yaml b/.github/workflows/tagged_release.yaml index 2dfc280f..fc32a9d9 100644 --- a/.github/workflows/tagged_release.yaml +++ b/.github/workflows/tagged_release.yaml @@ -9,7 +9,7 @@ jobs: strategy: matrix: os: [ ubuntu-latest, windows-latest, macos-latest ] - node: [ 12, 14, 16 ] + node: [ 14 ] runs-on: ${{matrix.os}} steps: - name: Set up Git repository @@ -52,6 +52,7 @@ jobs: uses: actions/setup-node@v2 with: node-version: 14 + registry-url: 'https://registry.npmjs.org' - name: Install run: npm ci - name: Run typedoc @@ -62,7 +63,14 @@ jobs: deploy_key: ${{ secrets.API_DOC_DEPLOY_KEY }} external_repository: nut-tree/apidoc publish_dir: ./docs - - name: Publish tagged release - uses: JS-DevTools/npm-publish@v1 + - name: Publish tagged release to npm + run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - uses: actions/setup-node@v2 with: - token: ${{ secrets.NPM_TOKEN }} + registry-url: 'https://npm.pkg.github.com' + - name: Publish tagged release to GPR + run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/README.md b/README.md index 5bc2932d..7b5430b7 100644 --- a/README.md +++ b/README.md @@ -5,23 +5,15 @@ |Master |![Create tagged release](https://github.com/nut-tree/nut.js/workflows/Create%20tagged%20release/badge.svg)| |Develop|![Create snapshot release](https://github.com/nut-tree/nut.js/workflows/Create%20snapshot%20release/badge.svg)| -![Supported node LTS versions](https://img.shields.io/badge/node%40lts-erbium%2C%20fermium-green) -![Supported node versions](https://img.shields.io/badge/node-16.x.x-green) -![Supported Electron versions](https://img.shields.io/badge/electron-8.x.x%20--%2013.x.x-green) - [![SonarCloud badge](https://sonarcloud.io/api/project_badges/measure?project=nut-tree%3Anut.js&metric=alert_status)](https://sonarcloud.io/dashboard?id=nut-tree%3Anut.js) [![SonarCloud Coverage](https://sonarcloud.io/api/project_badges/measure?project=nut-tree%3Anut.js&metric=coverage)](https://sonarcloud.io/component_measures?id=nut-tree%3Anut.js&metric=coverage) [![Downloads per month](https://img.shields.io/npm/dm/@nut-tree/nut-js)](https://www.npmjs.com/package/@nut-tree/nut-js) -

+

Native UI testing / automation with node.js


-

- - Built with opencv4nodejs -

# About @@ -34,10 +26,30 @@ Native UI testing / automation with node.js It allows for native UI interactions via keyboard and / or mouse, but additionally gives you the possibility to navigate the screen based on image matching. +# Sponsoring + +`nut.js` is developed with community in mind. + +A huge **"Thank you!"** goes out to all sponsors who make open source a bit more sustainable! + +[Reiss Cashmore](https://github.com/Reiss-Cashmore) +[Chet Corcos](https://github.com/ccorcos) +[Stephan Petzl](https://github.com/stoefln) + +# Demo + +Check out this demo video to get a first impression of what nut.js is capable of. + +[![nut.js demo video](https://img.youtube.com/vi/MpIyUJnU_Bk/1.jpg)](https://www.youtube.com/watch?v=MpIyUJnU_Bk) + # Examples [nut-tree/trailmix](https://github.com/nut-tree/trailmix) contains a set of ready to use examples which demo the usage ot nut.js. +# API Docs + +nut.js provides [public API documentation](https://nut-tree.github.io/apidoc/) auto-generated by [TypeDoc](https://typedoc.org). + # Discussion In [nut-tree/rfc](https://github.com/nut-tree/rfc) documents regarding larger design / implementation changes in nut.js are up for discussion. @@ -59,7 +71,7 @@ It's work in progress and will undergo constant modification. ## Keyboard - [x] Support for standard US keyboard layout -- [x] Support for German special characters +- [x] Support for multimedia keys ## Mouse @@ -77,8 +89,10 @@ It's work in progress and will undergo constant modification. ## Screen -- [x] findOnScreen -- [x] waitFor +- [x] Find an image on screen +- [x] Find all image occurrences on screen +- [x] Wait for an image to appear on screen +- [x] Retrieve RGBA color information on screen - [x] Hooks to trigger actions based on images - [x] Highlighting screen regions @@ -201,96 +215,3 @@ will install the most recent development release of `nut.js`. **Attention**: While snapshot releases are great to work with upcoming features before a new stable release, it is still a snapshot release. Please bear in mind that things might change and / or break on snapshot releases, so it is not recommended using them in production. - -### Usage with Electron - -`nut.js` in combination with Electron requires bindings built for use with Electron. -`nut.js` does provide such bindings and e.g. [electron-rebuild](https://www.npmjs.com/package/electron-rebuild) makes installation a breeze. - -Besides installing `nut.js` via - -```bash -npm i @nut-tree/nut-js -``` - -or - -```bash -yarn add @nut-tree/nut-js -``` - -we also install `electron-rebuild` as a `devDependency`: - -```bash -npm i -D electron-rebuild -``` - -or - -```bash -yarn add -D electron-rebuild -``` - -Next, we add a `rebuild` script to our `package.json`: - -```json -{ - ... - "scripts": { - ... - "start": "electron app.js", - "rebuild": "electron-rebuild" - }, - ..., -} -``` - -Now all we have to do is run `npm run rebuild` and `electron-rebuild` will fetch the appropriate bindings for our Electron version. -Currently `nut.js` provides bindings for all ABI version to work with Electron v4.x up to 8.x - -### Manual build - -As a fallback, `nut.js` is able to build all required dependencies by itself. -To do so, some setup is required on the respective target platform. - -#### Windows - -In order to install `nut.js` on Windows, [Windows Build Tools](https://www.microsoft.com/en-us/download/details.aspx?id=48159) and [Python 2](https://www.python.org/downloads/windows/) are required. -You can either set them up manually, or install them via npm: - -```bash -npm install --global windows-build-tools -``` - -or - -```bash -yarn global add windows-build-tools -``` - -#### macOS - -On macOS, Xcode command line tools are required. -You can install them by running -```bash -xcode-select --install -``` - -#### Linux - -Depending on your distribution, Linux setups may differ. - -In general, `nut.js` requires - -- Python 2 -- g++ -- make -- libXtst -- libPng - -Installation on `*buntu` distributions: -```bash -sudo apt-get install build-essential python libxtst-dev libpng++-dev -``` - -Setups on other distributions might differ. diff --git a/e2e/assets/checkers.png b/e2e/assets/checkers.png new file mode 100644 index 00000000..07cde4f0 Binary files /dev/null and b/e2e/assets/checkers.png differ diff --git a/e2e/electron-test/package-lock.json b/e2e/electron-test/package-lock.json index abc08134..52c29e6e 100644 --- a/e2e/electron-test/package-lock.json +++ b/e2e/electron-test/package-lock.json @@ -1,6 +1,6 @@ { "name": "electron-test", - "version": "1.6.0", + "version": "1.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -35,9 +35,8 @@ "dev": true, "requires": { "@nut-tree/libnut": "2.1.2", - "clipboardy": "2.0.0", - "node-abort-controller": "2.0.0", - "opencv4nodejs-prebuilt": "5.3.3" + "clipboardy": "2.3.0", + "node-abort-controller": "2.0.0" }, "dependencies": { "@babel/code-frame": { @@ -845,7 +844,6 @@ "version": "16.3.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.2.tgz", "integrity": "sha512-jJs9ErFLP403I+hMLGnqDRWT0RYKSvArxuBVh2veudHV7ifEC1WAmjJADacZ7mRbA2nWgHtn8xyECMAot0SkAw==", - "dev": true, "optional": true }, "@types/normalize-package-data": { @@ -975,8 +973,7 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, "arch": { "version": "2.1.1", @@ -1241,8 +1238,7 @@ "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -1281,7 +1277,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, "requires": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -1291,14 +1286,12 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "readable-stream": { "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", "string_decoder": "^1.1.1", @@ -1308,14 +1301,12 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "requires": { "safe-buffer": "~5.2.0" } @@ -1385,7 +1376,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -1500,8 +1490,7 @@ "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "ci-info": { "version": "2.0.0", @@ -1742,8 +1731,7 @@ "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "convert-source-map": { "version": "1.7.0", @@ -1766,7 +1754,7 @@ "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -1835,7 +1823,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dev": true, "requires": { "mimic-response": "^2.0.0" } @@ -1843,8 +1830,7 @@ "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "deep-is": { "version": "0.1.3", @@ -1909,8 +1895,7 @@ "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "detect-indent": { "version": "6.0.0", @@ -1920,8 +1905,7 @@ "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, "detect-newline": { "version": "3.1.0", @@ -2064,7 +2048,7 @@ "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "requires": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", @@ -2128,8 +2112,7 @@ "expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" }, "expect": { "version": "25.4.0", @@ -2441,8 +2424,7 @@ "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { "version": "5.0.0", @@ -2529,7 +2511,7 @@ "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "requires": { "pump": "^3.0.0" }, @@ -2561,8 +2543,7 @@ "github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" }, "glob": { "version": "7.1.3", @@ -2648,8 +2629,7 @@ "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "has-value": { "version": "1.0.0", @@ -2768,8 +2748,7 @@ "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { "version": "5.1.4", @@ -2812,8 +2791,7 @@ "ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "inquirer": { "version": "7.1.0", @@ -4804,8 +4782,7 @@ "mimic-response": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" }, "minimatch": { "version": "3.0.4", @@ -4869,8 +4846,7 @@ "mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "ms": { "version": "2.1.2", @@ -4885,8 +4861,7 @@ "nan": { "version": "2.14.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", - "dev": true + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" }, "nanomatch": { "version": "1.2.13", @@ -4909,14 +4884,12 @@ "napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" }, "native-node-utils": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/native-node-utils/-/native-node-utils-0.2.7.tgz", "integrity": "sha512-61v0G3uVxWlXHppSZGwZi+ZEIgGUKI8QvEkEJLb1GVePI7P8SBe+G747z+QMXSt4TxfgbVZP0DyobbRKYVIjdw==", - "dev": true, "requires": { "nan": "^2.13.2" } @@ -4934,13 +4907,12 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=" + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, "node-abi": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.0.tgz", "integrity": "sha512-g6bZh3YCKQRdwuO/tSZZYJAw622SjsRfJ2X0Iy4sSOHZ34/sPPdVBn8fev2tj7njzLwuqPw9uMtGsGkO5kIQvg==", - "dev": true, "requires": { "semver": "^5.4.1" } @@ -5098,8 +5070,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-copy": { "version": "0.1.0", @@ -5165,7 +5136,6 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/opencv4nodejs-prebuilt/-/opencv4nodejs-prebuilt-5.3.3.tgz", "integrity": "sha512-c9n4bLoamHLwafqCR6W4Xh5O/35IJ2A01pWbW/4SVgYJDAhGAW/FrZw0q4VwUPxEe1cXZgr+Wy5HZUQIotkZdg==", - "dev": true, "requires": { "@types/node": ">6", "nan": "^2.14.2", @@ -5178,7 +5148,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -5188,7 +5157,6 @@ "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", @@ -5204,7 +5172,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -5216,7 +5183,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5231,7 +5197,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -5418,7 +5383,6 @@ "version": "6.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.3.tgz", "integrity": "sha512-iqqSR84tNYQUQHRXalSKdIaM8Ov1QxOVuBNWI7+BzZWv6Ih9k75wOnH1rGQ9WWTaaLkTpxWKIciOF0KyfM74+Q==", - "dev": true, "requires": { "detect-libc": "^1.0.3", "expand-template": "^2.0.3", @@ -5439,7 +5403,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -5449,7 +5412,6 @@ "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", @@ -5465,7 +5427,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -5477,7 +5438,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5492,7 +5452,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -5525,8 +5484,7 @@ "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "process-on-spawn": { "version": "1.0.0", @@ -5569,7 +5527,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, "requires": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -6073,14 +6030,12 @@ "simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "dev": true, "requires": { "decompress-response": "^4.2.0", "once": "^1.3.1", @@ -6434,8 +6389,7 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "supports-color": { "version": "7.1.0", @@ -6460,25 +6414,32 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", "dev": true, "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } } }, "tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, "requires": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -6490,7 +6451,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, "requires": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -6503,7 +6463,6 @@ "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", "string_decoder": "^1.1.1", @@ -6513,14 +6472,12 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "requires": { "safe-buffer": "~5.2.0" } @@ -6975,8 +6932,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "3.3.2", @@ -7120,7 +7076,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, "requires": { "string-width": "^1.0.2 || 2" } @@ -8733,6 +8688,12 @@ "tar": "^4" }, "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -8740,18 +8701,18 @@ "dev": true }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", "dev": true, "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" } }, "yallist": { @@ -9132,12 +9093,6 @@ "sprintf-js": "^1.1.2" } }, - "run-script-os": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz", - "integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==", - "dev": true - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -9284,9 +9239,9 @@ } }, "tar": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", - "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", "dev": true, "requires": { "chownr": "^2.0.0", diff --git a/e2e/electron-test/package.json b/e2e/electron-test/package.json index a09cfd92..e5fb52c4 100644 --- a/e2e/electron-test/package.json +++ b/e2e/electron-test/package.json @@ -1,6 +1,6 @@ { "name": "electron-test", - "version": "1.6.0", + "version": "1.7.0", "description": "A test to verify usage with Electron", "main": "main.js", "author": { diff --git a/e2e/window-test/package-lock.json b/e2e/window-test/package-lock.json index fcbb1c5b..dc8817c1 100644 --- a/e2e/window-test/package-lock.json +++ b/e2e/window-test/package-lock.json @@ -1,6 +1,6 @@ { "name": "window-integration-tests", - "version": "1.6.0", + "version": "1.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -680,9 +680,8 @@ "dev": true, "requires": { "@nut-tree/libnut": "2.1.2", - "clipboardy": "2.0.0", - "node-abort-controller": "2.0.0", - "opencv4nodejs-prebuilt": "5.3.3" + "clipboardy": "2.3.0", + "node-abort-controller": "2.0.0" }, "dependencies": { "@babel/code-frame": { @@ -1490,7 +1489,6 @@ "version": "16.3.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.2.tgz", "integrity": "sha512-jJs9ErFLP403I+hMLGnqDRWT0RYKSvArxuBVh2veudHV7ifEC1WAmjJADacZ7mRbA2nWgHtn8xyECMAot0SkAw==", - "dev": true, "optional": true }, "@types/normalize-package-data": { @@ -1620,13 +1618,12 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, "arch": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.1.tgz", - "integrity": "sha1-j1wnMao1owkpIhuwZA7tZRdeyE4=" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==" }, "archy": { "version": "1.0.0", @@ -1886,8 +1883,7 @@ "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -1926,7 +1922,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, "requires": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -1936,14 +1931,12 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "readable-stream": { "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", "string_decoder": "^1.1.1", @@ -1953,14 +1946,12 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "requires": { "safe-buffer": "~5.2.0" } @@ -2030,7 +2021,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -2145,8 +2135,7 @@ "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "ci-info": { "version": "2.0.0", @@ -2193,12 +2182,13 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" }, "clipboardy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.0.0.tgz", - "integrity": "sha1-P87kIf3spOamLOcrZvPrDEIWWs0=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", "requires": { "arch": "^2.1.1", - "execa": "^1.0.0" + "execa": "^1.0.0", + "is-wsl": "^2.1.1" } }, "cliui": { @@ -2387,8 +2377,7 @@ "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "convert-source-map": { "version": "1.7.0", @@ -2411,7 +2400,7 @@ "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -2480,7 +2469,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dev": true, "requires": { "mimic-response": "^2.0.0" } @@ -2488,8 +2476,7 @@ "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "deep-is": { "version": "0.1.3", @@ -2554,8 +2541,7 @@ "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "detect-indent": { "version": "6.0.0", @@ -2565,8 +2551,7 @@ "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, "detect-newline": { "version": "3.1.0", @@ -2649,9 +2634,9 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "requires": { "once": "^1.4.0" } @@ -2709,7 +2694,7 @@ "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "requires": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", @@ -2773,8 +2758,7 @@ "expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" }, "expect": { "version": "25.4.0", @@ -3086,8 +3070,7 @@ "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { "version": "5.0.0", @@ -3174,20 +3157,9 @@ "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "requires": { "pump": "^3.0.0" - }, - "dependencies": { - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } } }, "get-value": { @@ -3206,8 +3178,7 @@ "github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" }, "glob": { "version": "7.1.3", @@ -3293,8 +3264,7 @@ "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "has-value": { "version": "1.0.0", @@ -3413,8 +3383,7 @@ "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { "version": "5.1.4", @@ -3457,8 +3426,7 @@ "ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "inquirer": { "version": "7.1.0", @@ -3674,8 +3642,7 @@ "is-wsl": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", - "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", - "optional": true + "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==" }, "isarray": { "version": "1.0.0", @@ -5449,8 +5416,7 @@ "mimic-response": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" }, "minimatch": { "version": "3.0.4", @@ -5514,8 +5480,7 @@ "mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "ms": { "version": "2.1.2", @@ -5530,8 +5495,7 @@ "nan": { "version": "2.14.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", - "dev": true + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" }, "nanomatch": { "version": "1.2.13", @@ -5554,14 +5518,12 @@ "napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" }, "native-node-utils": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/native-node-utils/-/native-node-utils-0.2.7.tgz", "integrity": "sha512-61v0G3uVxWlXHppSZGwZi+ZEIgGUKI8QvEkEJLb1GVePI7P8SBe+G747z+QMXSt4TxfgbVZP0DyobbRKYVIjdw==", - "dev": true, "requires": { "nan": "^2.13.2" } @@ -5579,13 +5541,12 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=" + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, "node-abi": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.0.tgz", "integrity": "sha512-g6bZh3YCKQRdwuO/tSZZYJAw622SjsRfJ2X0Iy4sSOHZ34/sPPdVBn8fev2tj7njzLwuqPw9uMtGsGkO5kIQvg==", - "dev": true, "requires": { "semver": "^5.4.1" } @@ -5743,8 +5704,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-copy": { "version": "0.1.0", @@ -5810,7 +5770,6 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/opencv4nodejs-prebuilt/-/opencv4nodejs-prebuilt-5.3.3.tgz", "integrity": "sha512-c9n4bLoamHLwafqCR6W4Xh5O/35IJ2A01pWbW/4SVgYJDAhGAW/FrZw0q4VwUPxEe1cXZgr+Wy5HZUQIotkZdg==", - "dev": true, "requires": { "@types/node": ">6", "nan": "^2.14.2", @@ -5823,7 +5782,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -5833,7 +5791,6 @@ "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", @@ -5849,7 +5806,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -5861,7 +5817,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5876,7 +5831,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -6063,7 +6017,6 @@ "version": "6.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.3.tgz", "integrity": "sha512-iqqSR84tNYQUQHRXalSKdIaM8Ov1QxOVuBNWI7+BzZWv6Ih9k75wOnH1rGQ9WWTaaLkTpxWKIciOF0KyfM74+Q==", - "dev": true, "requires": { "detect-libc": "^1.0.3", "expand-template": "^2.0.3", @@ -6084,7 +6037,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -6094,7 +6046,6 @@ "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", @@ -6110,7 +6061,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -6122,7 +6072,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -6137,7 +6086,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -6170,8 +6118,7 @@ "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "process-on-spawn": { "version": "1.0.0", @@ -6214,7 +6161,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, "requires": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -6711,21 +6657,19 @@ "optional": true }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", + "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" }, "simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "dev": true, "requires": { "decompress-response": "^4.2.0", "once": "^1.3.1", @@ -7079,8 +7023,7 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "supports-color": { "version": "7.1.0", @@ -7106,8 +7049,7 @@ }, "tar": { "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "resolved": "", "dev": true, "requires": { "chownr": "^1.1.1", @@ -7123,7 +7065,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, "requires": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -7135,7 +7076,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, "requires": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -7148,7 +7088,6 @@ "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", "string_decoder": "^1.1.1", @@ -7158,14 +7097,12 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "requires": { "safe-buffer": "~5.2.0" } @@ -7620,8 +7557,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "3.3.2", @@ -7765,7 +7701,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, "requires": { "string-width": "^1.0.2 || 2" } @@ -8239,9 +8174,9 @@ } }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { @@ -11636,9 +11571,9 @@ "dev": true }, "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, "to-fast-properties": { diff --git a/e2e/window-test/package.json b/e2e/window-test/package.json index 79a3c5cb..22162342 100644 --- a/e2e/window-test/package.json +++ b/e2e/window-test/package.json @@ -1,6 +1,6 @@ { "name": "window-integration-tests", - "version": "1.6.0", + "version": "1.7.0", "description": "Integration tests to verify window handling", "main": "main.js", "author": { diff --git a/e2e/window-test/test.js b/e2e/window-test/test.js index fdb92d3c..e76cc23c 100644 --- a/e2e/window-test/test.js +++ b/e2e/window-test/test.js @@ -68,7 +68,7 @@ describe("getActiveWindow", () => { it("should determine correct coordinates for our application after moving the window", async () => { // GIVEN const xPosition = 42; - const yPosition = 23; + const yPosition = 25; await app.browserWindow.setPosition(xPosition, yPosition); await sleep(1000); diff --git a/index.e2e.spec.ts b/index.e2e.spec.ts deleted file mode 100644 index 7e48cab2..00000000 --- a/index.e2e.spec.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { - assert, - centerOf, - down, - Key, - keyboard, - mouse, - Region, - right, - screen, - sleep, - straightTo, -} from "./index"; - -const openXfceMenu = async () => { - await mouse.move(straightTo(centerOf(screen.find("menu.png")))); - await mouse.leftClick(); - await mouse.leftClick(); -}; - -const run = async (cmd: string) => { - await keyboard.type(Key.LeftAlt, Key.F2); - await keyboard.type(cmd); - await keyboard.type(Key.Enter); -}; - -const calculate = async () => { - await mouse.move(straightTo(centerOf(screen.find("plus.png")))); - await mouse.leftClick(); - await mouse.move(straightTo(centerOf(screen.find("one.png")))); - await mouse.leftClick(); - await mouse.move(straightTo(centerOf(screen.find("zero.png")))); - await mouse.leftClick(); - await mouse.leftClick(); - await mouse.move(straightTo(centerOf(screen.find("equals.png")))); - await mouse.leftClick(); -}; - -const close = async () => { - await mouse.move(straightTo(centerOf(screen.find("close.png")))); - await mouse.leftClick(); -}; - -describe("E2E tests", () => { - afterEach(async () => { - await keyboard.type(Key.LeftControl, Key.LeftAlt, Key.Left); - }); - - it("should throw on invalid images", async () => { - jest.setTimeout(30000); - await expect(screen.find("mouse.png")).rejects.toContain("Failed to load image"); - }); - - it("should perform some calculations", async () => { - jest.setTimeout(30000); - screen.config.resourceDirectory = "./e2e/assets"; - await assert.isVisible("mouse.png"); - await assert.isVisible("desktop.png"); - await openXfceMenu(); - await run("gnome-calculator"); - await sleep(1500); - await assert.isVisible("calculator.png"); - await keyboard.type("525"); - await calculate(); - await screen.waitFor("result.png"); - await close(); - }); - - it("drag & drop", async () => { - jest.setTimeout(60000); - screen.config.resourceDirectory = "./e2e/assets"; - - const expected = new Region(38, 585, 70, 86); - const maxDiff = 1; - - await assert.isVisible("trash.png"); - await mouse.move(straightTo(centerOf(screen.find("trash.png")))); - await mouse.drag(down(500)); - await mouse.move(right(100)); - await mouse.leftClick(); - const dest = await screen.waitFor("moved_trash.png"); - expect(Math.abs(dest.left - expected.left)).toBeLessThanOrEqual(maxDiff); - expect(Math.abs(dest.top - expected.top)).toBeLessThanOrEqual(maxDiff); - expect(Math.abs(dest.width - expected.width)).toBeLessThanOrEqual(maxDiff); - expect(Math.abs(dest.height - expected.height)).toBeLessThanOrEqual(maxDiff); - }); -}); diff --git a/index.ts b/index.ts index 6b3df65a..db8b6d43 100644 --- a/index.ts +++ b/index.ts @@ -1,51 +1,72 @@ -import { NativeAdapter } from "./lib/adapter/native.adapter.class"; -import { VisionAdapter } from "./lib/adapter/vision.adapter.class"; -import { Assert } from "./lib/assert.class"; -import { Clipboard } from "./lib/clipboard.class"; -import { Keyboard } from "./lib/keyboard.class"; -import { Mouse } from "./lib/mouse.class"; -import { createMovementApi } from "./lib/movement.function"; -import { Screen } from "./lib/screen.class"; -import { LineHelper } from "./lib/util/linehelper.class"; -import { createWindowApi } from "./lib/window.function"; - -export { jestMatchers } from "./lib/expect/jest.matcher.function"; -export { sleep } from "./lib/sleep.function"; -export { Image } from "./lib/image.class"; -export { Key } from "./lib/key.enum"; -export { Button } from "./lib/button.enum"; -export { centerOf, randomPointIn } from "./lib/location.function"; -export { LocationParameters } from "./lib/locationparameters.class"; -export { OptionalSearchParameters } from "./lib/optionalsearchparameters.class"; -export { linear } from "./lib/movementtype.function"; -export { Point } from "./lib/point.class"; -export { Region } from "./lib/region.class"; -export { Window } from "./lib/window.class"; - -const screenActions = new VisionAdapter(); -const nativeActions = new NativeAdapter(); +import {AssertClass} from "./lib/assert.class"; +import {ClipboardClass} from "./lib/clipboard.class"; +import {KeyboardClass} from "./lib/keyboard.class"; +import {MouseClass} from "./lib/mouse.class"; +import {createMovementApi} from "./lib/movement.function"; +import {ScreenClass} from "./lib/screen.class"; +import {LineHelper} from "./lib/util/linehelper.class"; +import {createWindowApi} from "./lib/window.function"; +import providerRegistry from "./lib/provider/provider-registry.class"; +import {loadImageResource} from "./lib/imageResources.function"; + +export { + AssertClass, + ClipboardClass, + KeyboardClass, + MouseClass, + ScreenClass, + providerRegistry +} + +export {MatchRequest} from "./lib/match-request.class"; +export {MatchResult} from "./lib/match-result.class"; +export * from "./lib/provider"; + +export {jestMatchers} from "./lib/expect/jest.matcher.function"; +export {sleep} from "./lib/sleep.function"; +export {Image} from "./lib/image.class"; +export {RGBA} from "./lib/rgba.class"; +export {Key} from "./lib/key.enum"; +export {Button} from "./lib/button.enum"; +export {centerOf, randomPointIn} from "./lib/location.function"; +export {OptionalSearchParameters} from "./lib/optionalsearchparameters.class"; +export {EasingFunction, linear} from "./lib/mouse-movement.function"; +export {Point} from "./lib/point.class"; +export {Region} from "./lib/region.class"; +export {Window} from "./lib/window.class"; +export {FileType} from "./lib/file-type.enum"; +export {ColorMode} from "./lib/colormode.enum"; + const lineHelper = new LineHelper(); -const clipboard = new Clipboard(nativeActions); -const keyboard = new Keyboard(nativeActions); -const mouse = new Mouse(nativeActions); -const screen = new Screen(screenActions); -const assert = new Assert(screen); +const clipboard = new ClipboardClass(providerRegistry); +const keyboard = new KeyboardClass(providerRegistry); +const mouse = new MouseClass(providerRegistry); +const screen = new ScreenClass(providerRegistry); +const assert = new AssertClass(screen); + +const {straightTo, up, down, left, right} = createMovementApi(providerRegistry, lineHelper); +const {getWindows, getActiveWindow} = createWindowApi(providerRegistry); + +const loadImage = providerRegistry.getImageReader().load; +const saveImage = providerRegistry.getImageWriter().store; -const {straightTo, up, down, left, right} = createMovementApi(nativeActions, lineHelper); -const {getWindows, getActiveWindow } = createWindowApi(nativeActions); +const imageResource = (fileName: string) => loadImageResource(providerRegistry, screen.config.resourceDirectory, fileName); export { - clipboard, - keyboard, - mouse, - screen, - assert, - straightTo, - up, - down, - left, - right, - getWindows, - getActiveWindow, + clipboard, + keyboard, + mouse, + screen, + assert, + straightTo, + up, + down, + left, + right, + getWindows, + getActiveWindow, + loadImage, + saveImage, + imageResource }; diff --git a/lib/adapter/native.adapter.class.spec.ts b/lib/adapter/native.adapter.class.spec.ts deleted file mode 100644 index ab0da5a4..00000000 --- a/lib/adapter/native.adapter.class.spec.ts +++ /dev/null @@ -1,313 +0,0 @@ -import { Button } from "../button.enum"; -import { Key } from "../key.enum"; -import { Point } from "../point.class"; -import { NativeAdapter } from "./native.adapter.class"; -import ClipboardAction from "../provider/native/clipboardy-clipboard-action.class"; -import KeyboardAction from "../provider/native/libnut-keyboard-action.class"; -import MouseAction from "../provider/native/libnut-mouse-action.class"; -import WindowAction from "../provider/native/libnut-window-action.class"; - -jest.mock("../provider/native/clipboardy-clipboard-action.class"); -jest.mock("../provider/native/libnut-mouse-action.class"); -jest.mock("../provider/native/libnut-keyboard-action.class"); -jest.mock("../provider/native/libnut-window-action.class"); - -describe("NativeAdapter class", () => { - describe("MouseAction", () => { - it("should delegate calls to setMouseDelay", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const delay = 5; - - // WHEN - SUT.setMouseDelay(delay); - - // THEN - expect(mouseMock.setMouseDelay).toBeCalledTimes(1); - expect(mouseMock.setMouseDelay).toBeCalledWith(delay); - }); - - it("should delegate calls to setMousePosition", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const newPosition = new Point(10, 10); - - // WHEN - await SUT.setMousePosition(newPosition); - - // THEN - expect(mouseMock.setMousePosition).toBeCalledTimes(1); - expect(mouseMock.setMousePosition).toBeCalledWith(newPosition); - }); - - it("should delegate calls to currentMousePosition", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - - // WHEN - await SUT.currentMousePosition(); - - // THEN - expect(mouseMock.currentMousePosition).toBeCalledTimes(1); - }); - - it("should delegate calls to leftClick", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - - // WHEN - await SUT.leftClick(); - - // THEN - expect(mouseMock.leftClick).toBeCalledTimes(1); - }); - - it("should delegate calls to rightClick", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - - // WHEN - await SUT.rightClick(); - - // THEN - expect(mouseMock.rightClick).toBeCalledTimes(1); - }); - - it("should delegate calls to middleClick", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - - // WHEN - await SUT.middleClick(); - - // THEN - expect(mouseMock.middleClick).toBeCalledTimes(1); - }); - - it("should delegate calls to pressButton", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const buttonToPress = Button.LEFT; - - // WHEN - await SUT.pressButton(buttonToPress); - - // THEN - expect(mouseMock.pressButton).toBeCalledTimes(1); - expect(mouseMock.pressButton).toBeCalledWith(buttonToPress); - }); - - it("should delegate calls to releaseButton", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const buttonToRelease = Button.LEFT; - - // WHEN - await SUT.releaseButton(buttonToRelease); - - // THEN - expect(mouseMock.releaseButton).toBeCalledTimes(1); - expect(mouseMock.releaseButton).toBeCalledWith(buttonToRelease); - }); - }); - - describe("KeyboardAction", () => { - it("should delegate calls to pressKey", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const keyToPress = Key.A; - - // WHEN - await SUT.pressKey(keyToPress); - - // THEN - expect(keyboardMock.pressKey).toBeCalledTimes(1); - expect(keyboardMock.pressKey).toBeCalledWith(keyToPress); - }); - - it("should delegate calls to releaseButton", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const keyToRelease = Key.A; - - // WHEN - await SUT.releaseKey(keyToRelease); - - // THEN - expect(keyboardMock.releaseKey).toBeCalledTimes(1); - expect(keyboardMock.releaseKey).toBeCalledWith(keyToRelease); - }); - - it("should delegate calls to click", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const keyToClick = Key.A; - - // WHEN - await SUT.click(keyToClick); - - // THEN - expect(keyboardMock.click).toBeCalledTimes(1); - expect(keyboardMock.click).toBeCalledWith(keyToClick); - }); - - it("should delegate calls to type", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const stringToType = "testString"; - - // WHEN - await SUT.type(stringToType); - - // THEN - expect(keyboardMock.type).toBeCalledTimes(1); - expect(keyboardMock.type).toBeCalledWith(stringToType); - }); - }); - - describe("ClipboardAction", () => { - it("should delegate calls to copy", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const stringToCopy = "testString"; - - // WHEN - await SUT.copy(stringToCopy); - - // THEN - expect(clipboardMock.copy).toBeCalledTimes(1); - expect(clipboardMock.copy).toBeCalledWith(stringToCopy); - }); - - it("should delegate calls to paste", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - - // WHEN - await SUT.paste(); - - // THEN - expect(clipboardMock.paste).toBeCalledTimes(1); - }); - }); - - describe("WindowAction", () => { - it("should delegate calls to getActiveWindow", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - - // WHEN - await SUT.getActiveWindow(); - - // THEN - expect(windowMock.getActiveWindow).toBeCalledTimes(1); - }); - - it("should delegate calls to getWindows", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - - // WHEN - await SUT.getWindows(); - - // THEN - expect(windowMock.getWindows).toBeCalledTimes(1); - }); - - it("should delegate calls to getWindowTitle", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const windowHandle = 123; - - // WHEN - await SUT.getWindowTitle(windowHandle); - - // THEN - expect(windowMock.getWindowTitle).toBeCalledTimes(1); - }); - - it("should delegate calls to getWindowRegion", async () => { - // GIVEN - const clipboardMock = new ClipboardAction(); - const keyboardMock = new KeyboardAction(); - const mouseMock = new MouseAction(); - const windowMock = new WindowAction(); - const SUT = new NativeAdapter(clipboardMock, keyboardMock, mouseMock, windowMock); - const windowHandle = 123; - - // WHEN - await SUT.getWindowRegion(windowHandle); - - // THEN - expect(windowMock.getWindowRegion).toBeCalledTimes(1); - }); - }); -}); diff --git a/lib/adapter/native.adapter.class.ts b/lib/adapter/native.adapter.class.ts deleted file mode 100644 index 67122d97..00000000 --- a/lib/adapter/native.adapter.class.ts +++ /dev/null @@ -1,231 +0,0 @@ -import { Button } from "../button.enum"; -import { Key } from "../key.enum"; -import { Point } from "../point.class"; -import { ClipboardActionProvider } from "../provider/native/clipboard-action-provider.interface"; -import { KeyboardActionProvider } from "../provider/native/keyboard-action-provider.interface"; -import { MouseActionProvider } from "../provider/native/mouse-action-provider.interface"; -import { Region } from "../region.class"; -import { WindowActionProvider } from "../provider/native/window-action-provider.interface"; -import ClipboardAction from "../provider/native/clipboardy-clipboard-action.class"; -import KeyboardAction from "../provider/native/libnut-keyboard-action.class"; -import MouseAction from "../provider/native/libnut-mouse-action.class"; -import WindowAction from "../provider/native/libnut-window-action.class"; - -/** - * {@link NativeAdapter} serves as an abstraction layer for all OS level interactions. - * - * This allows to provide a high level interface for native actions, - * without having to spread (possibly) multiple dependencies all over the code. - * All actions which involve the OS are bundled in this adapter. - */ -export class NativeAdapter { - /** - * {@link NativeAdapter} class constructor - * @param clipboard {@link ClipboardActionProvider} instance used to interact with a systems clipboard (Default: {@link ClipboardAction}) - * @param keyboard {@link KeyboardActionProvider} instance used to interact with a systems keybaord (Default: {@link KeyboardAction}) - * @param mouse {@link MouseActionProvider} instance used to interact with a systems mouse (Default: {@link MouseAction}) - * @param window {@link WindowActionProvider} instance used to interact with a systems windows (Default: {@link WindowAction}) - */ - constructor( - private clipboard: ClipboardActionProvider = new ClipboardAction(), - private keyboard: KeyboardActionProvider = new KeyboardAction(), - private mouse: MouseActionProvider = new MouseAction(), - private window: WindowActionProvider = new WindowAction(), - ) {} - - /** - * {@link setMouseDelay} configures mouse speed for movement - * - * @param delay Mouse delay in milliseconds - */ - public setMouseDelay(delay: number): void { - this.mouse.setMouseDelay(delay); - } - - /** - * {@link setKeyboardDelay} configures keyboard delay between key presses - * - * @param delay The keyboard delay in milliseconds - */ - public setKeyboardDelay(delay: number): void { - this.keyboard.setKeyboardDelay(delay); - } - - /** - * {@link setMousePosition} changes the current mouse cursor position to a given {@link Point} - * - * @param p The new cursor position at {@link Point} p - */ - public setMousePosition(p: Point): Promise { - return this.mouse.setMousePosition(p); - } - - /** - * {@link currentMousePosition} returns the current mouse position - * - * @returns Current cursor position at a certain {@link Point} - */ - public currentMousePosition(): Promise { - return this.mouse.currentMousePosition(); - } - - /** - * {@link leftClick} triggers a native left-click event via OS API - */ - public leftClick(): Promise { - return this.mouse.leftClick(); - } - - /** - * {@link rightClick} triggers a native right-click event via OS API - */ - public rightClick(): Promise { - return this.mouse.rightClick(); - } - - /** - * {@link middleClick} triggers a native middle-click event via OS API - */ - public middleClick(): Promise { - return this.mouse.middleClick(); - } - - /** - * {@link pressButton} presses and holds a mouse {@link Button} - * - * @param btn The mouse {@link Button} to press - */ - public pressButton(btn: Button): Promise { - return this.mouse.pressButton(btn); - } - - /** - * {@link releaseButton} releases a mouse {@link Button} previously clicked via {@link pressButton} - * - * @param btn The mouse {@link Button} to release - */ - public releaseButton(btn: Button): Promise { - return this.mouse.releaseButton(btn); - } - - /** - * {@link type} types a given string via native keyboard events - * - * @param input The text to type - */ - public type(input: string): Promise { - return this.keyboard.type(input); - } - - /** - * {@link click} clicks a {@link Key} via native keyboard event - * - * @param keys Array of {@link Key}s to click - */ - public click(...keys: Key[]): Promise { - return this.keyboard.click(...keys); - } - - /** - * {@link pressKey} presses and holds a given {@link Key} - * - * @param keys Array of {@link Key}s to press and hold - */ - public pressKey(...keys: Key[]): Promise { - return this.keyboard.pressKey(...keys); - } - - /** - * {@link releaseKey} releases a {@link Key} previously presses via {@link pressKey} - * - * @param keys Array of {@link Key}s to release - */ - public releaseKey(...keys: Key[]): Promise { - return this.keyboard.releaseKey(...keys); - } - - /** - * {@link scrollUp} triggers an upwards mouse wheel scroll - * - * @param amount The amount of 'ticks' to scroll - */ - public scrollUp(amount: number): Promise { - return this.mouse.scrollUp(amount); - } - - /** - * {@link scrollDown} triggers a downward mouse wheel scroll - * - * @param amount The amount of 'ticks' to scroll - */ - public scrollDown(amount: number): Promise { - return this.mouse.scrollDown(amount); - } - - /** - * {@link scrollLeft} triggers a left mouse scroll - * - * @param amount The amount of 'ticks' to scroll - */ - public scrollLeft(amount: number): Promise { - return this.mouse.scrollLeft(amount); - } - - /** - * {@link scrollRight} triggers a right mouse scroll - * - * @param amount The amount of 'ticks' to scroll - */ - public scrollRight(amount: number): Promise { - return this.mouse.scrollRight(amount); - } - - /** - * {@link copy} copies a given text to the system clipboard - * - * @param text The text to copy - */ - public copy(text: string): Promise { - return this.clipboard.copy(text); - } - - /** - * {@link paste} pastes the current text on the system clipboard - * - * @returns The clipboard text - */ - public paste(): Promise { - return this.clipboard.paste(); - } - - public getWindows(): Promise { - return this.window.getWindows(); - } - - /** - * {@link getActiveWindow} returns the window handle of the currently active foreground window - * - * @returns The handle to the currently active foreground window - */ - public getActiveWindow(): Promise { - return this.window.getActiveWindow(); - } - - /** - * {@link getWindowTitle} returns the title of a window addressed via its window handle - * - * @returns A string representing the title of a window addressed via its window handle - */ - public getWindowTitle(windowHandle: number): Promise { - return this.window.getWindowTitle(windowHandle); - } - - /** - * {@link getWindowRegion} returns a {@link Region} object representing the size and position of the window addressed via its window handle - * - * @returns The {@link Region} occupied by the window addressed via its window handle - */ - public getWindowRegion(windowHandle: number): Promise { - return this.window.getWindowRegion(windowHandle); - } -} diff --git a/lib/adapter/vision.adapter.class.spec.ts b/lib/adapter/vision.adapter.class.spec.ts deleted file mode 100644 index df79ce7e..00000000 --- a/lib/adapter/vision.adapter.class.spec.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { Image } from "../image.class"; -import { MatchRequest } from "../match-request.class"; -import ScreenAction from "../provider/native/libnut-screen-action.class"; -import TemplateMatchingFinder from "../provider/opencv/template-matching-finder.class"; -import { Region } from "../region.class"; -import { VisionAdapter } from "./vision.adapter.class"; - -jest.mock("../provider/opencv/template-matching-finder.class"); -jest.mock("../provider/native/libnut-screen-action.class"); - -describe("VisionAdapter class", () => { - it("should delegate calls to grabScreen", () => { - // GIVEN - const finderMock = new TemplateMatchingFinder(); - const screenMock = new ScreenAction(); - const SUT = new VisionAdapter(finderMock, screenMock); - - // WHEN - SUT.grabScreen(); - - // THEN - expect(screenMock.grabScreen).toBeCalledTimes(1); - }); - - it("should delegate calls to grabScreenRegion", async () => { - // GIVEN - const finderMock = new TemplateMatchingFinder(); - const screenMock = new ScreenAction(); - const SUT = new VisionAdapter(finderMock, screenMock); - const screenRegion = new Region(0, 0, 100, 100); - - // WHEN - await SUT.grabScreenRegion(screenRegion); - - // THEN - expect(screenMock.grabScreenRegion).toBeCalledTimes(1); - expect(screenMock.grabScreenRegion).toBeCalledWith(screenRegion); - }); - - it("should delegate calls to highlightScreenRegion", async () => { - // GIVEN - const finderMock = new TemplateMatchingFinder(); - const screenMock = new ScreenAction(); - const SUT = new VisionAdapter(finderMock, screenMock); - const screenRegion = new Region(0, 0, 100, 100); - const opacity = 0.25; - const duration = 1; - - // WHEN - await SUT.highlightScreenRegion(screenRegion, duration, opacity); - - // THEN - expect(screenMock.highlightScreenRegion).toBeCalledTimes(1); - expect(screenMock.highlightScreenRegion).toBeCalledWith(screenRegion, duration, opacity); - }); - - it("should delegate calls to screenWidth", async () => { - // GIVEN - const finderMock = new TemplateMatchingFinder(); - const screenMock = new ScreenAction(); - const SUT = new VisionAdapter(finderMock, screenMock); - - // WHEN - await SUT.screenWidth(); - - // THEN - expect(screenMock.screenWidth).toBeCalledTimes(1); - }); - - it("should delegate calls to screenHeight", async () => { - // GIVEN - const finderMock = new TemplateMatchingFinder(); - const screenMock = new ScreenAction(); - const SUT = new VisionAdapter(finderMock, screenMock); - - // WHEN - await SUT.screenHeight(); - - // THEN - expect(screenMock.screenHeight).toBeCalledTimes(1); - }); - - it("should delegate calls to screenSize", async () => { - // GIVEN - const finderMock = new TemplateMatchingFinder(); - const screenMock = new ScreenAction(); - const SUT = new VisionAdapter(finderMock, screenMock); - - // WHEN - await SUT.screenSize(); - - // THEN - expect(screenMock.screenSize).toBeCalledTimes(1); - }); - - it("should delegate calls to findImage", async () => { - // GIVEN - const finderMock = new TemplateMatchingFinder(); - const SUT = new VisionAdapter(finderMock); - const request = new MatchRequest( - new Image(100, 100, new ArrayBuffer(0), 3), - "foo", - new Region(0, 0, 100, 100), - 0.99, - true); - - // WHEN - await SUT.findOnScreenRegion(request); - - expect(finderMock.findMatch).toBeCalledTimes(1); - expect(finderMock.findMatch).toBeCalledWith(request); - }); -}); diff --git a/lib/adapter/vision.adapter.class.ts b/lib/adapter/vision.adapter.class.ts deleted file mode 100644 index ad5f51ae..00000000 --- a/lib/adapter/vision.adapter.class.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { Image } from "../image.class"; -import { MatchRequest } from "../match-request.class"; -import { MatchResult } from "../match-result.class"; -import ScreenAction from "../provider/native/libnut-screen-action.class"; -import { ScreenActionProvider } from "../provider/native/screen-action-provider.interface"; -import { DataSink } from "../provider/opencv/data-sink.interface"; -import { FinderInterface } from "../provider/opencv/finder.interface"; -import { ImageWriter } from "../provider/opencv/image-writer.class"; -import TemplateMatchingFinder from "../provider/opencv/template-matching-finder.class"; -import { Region } from "../region.class"; - -/** - * {@link VisionAdapter} serves as an abstraction layer for all image based interactions. - * - * This allows to provide a high level interface for image based actions, - * without having to spread (possibly) multiple dependencies all over the code. - * All actions which involve screenshots / images are bundled in this adapter. - */ -export class VisionAdapter { - /** - * {@link VisionAdapter} class constructor - * @param finder A {@link FinderInterface} instance used for on-screen image detection (Default: {@link TemplateMatchingFinder}) - * @param screen A {@link ScreenActionProvider} instance used to retrieve screen data (Default: {@link ScreenAction}) - * @param dataSink A {@link DataSink} instance used to write output data to disk (Default: {@link ImageWriter}) - */ - constructor( - private finder: FinderInterface = new TemplateMatchingFinder(), - private screen: ScreenActionProvider = new ScreenAction(), - private dataSink: DataSink = new ImageWriter() - ) { - } - - /** - * {@link grabScreen} will return an {@link Image} containing the current screen image - * - * @returns An {@link Image} which will contain screenshot data as well as dimensions - */ - public grabScreen(): Promise { - return this.screen.grabScreen(); - } - - /** - * {@link grabScreenRegion} essentially does the same as grabScreen, but only returns a specified {@link Region} - * - * @param region The screen {@link Region} we want to grab - * @returns An {@link Image} which will contain screenshot data of the specified {@link Region} as well as dimensions - */ - public grabScreenRegion(region: Region): Promise { - return this.screen.grabScreenRegion(region); - } - - /** - * {@link highlightScreenRegion} highlights a screen {@link Region} for a given duration by overlaying it with an opaque window - * - * @param region The {@link Region} to highlight - * @param duration The highlight duration - * @param opacity Overlay opacity - */ - public highlightScreenRegion(region: Region, duration: number, opacity: number): Promise { - return this.screen.highlightScreenRegion(region, duration, opacity); - } - - /** - * {@link findOnScreenRegion} will search for a given pattern inside a {@link Region} of the main screen - * If multiple possible occurrences are found, the one with the highest probability is returned. - * For matchProbability < 0.99 the search will be performed on grayscale images. - * - * @param matchRequest A {@link MatchRequest} which holds all required matching data - * @returns {@link MatchResult} containing location and probability of a possible match - */ - public async findOnScreenRegion( - matchRequest: MatchRequest, - ): Promise { - return new Promise(async (resolve, reject) => { - try { - const matchResult = await this.finder.findMatch(matchRequest); - resolve(matchResult); - } catch (e) { - reject(e); - } - }); - } - - /** - * {@link screenWidth} returns the main screens width as reported by the OS. - * Please notice that on e.g. Apples Retina display the reported width - * and the actual pixel size may differ - * - * @returns The main screens width as reported by the OS - */ - public screenWidth(): Promise { - return this.screen.screenWidth(); - } - - /** - * {@link screenHeight} returns the main screens height as reported by the OS. - * Please notice that on e.g. Apples Retina display the reported width - * and the actual pixel size may differ - * - * @returns The main screens height as reported by the OS - */ - public screenHeight(): Promise { - return this.screen.screenHeight(); - } - - /** - * {@link screenSize} returns a {@link Region} object with the main screens size. - * Please note that on e.g. Apples Retina display the reported width - * and the actual pixel size may differ - * - * @returns A {@link Region} object representing the size of a systems main screen - */ - public screenSize(): Promise { - return this.screen.screenSize(); - } - - /** - * {@link saveImage} saves an {@link Image} to a given path on disk. - * - * @param image The {@link Image} to store - * @param path The path where to store the image - */ - public saveImage(image: Image, path: string): Promise { - return (this.dataSink as ImageWriter).store(image, path); - } -} diff --git a/lib/assert.class.spec.ts b/lib/assert.class.spec.ts index 3a022346..8f3b1e0b 100644 --- a/lib/assert.class.spec.ts +++ b/lib/assert.class.spec.ts @@ -1,79 +1,93 @@ -import { VisionAdapter } from "./adapter/vision.adapter.class"; -import { Assert } from "./assert.class"; -import { Region } from "./region.class"; -import { Screen } from "./screen.class"; - -jest.mock("./adapter/native.adapter.class"); -jest.mock("./adapter/vision.adapter.class"); +import {AssertClass} from "./assert.class"; +import {Region} from "./region.class"; +import {ScreenClass} from "./screen.class"; +import providerRegistry from "./provider/provider-registry.class"; +import {Image} from "../index"; +import {mockPartial} from "sneer"; + +jest.mock('jimp', () => { +}); jest.mock("./screen.class"); +const needleId = "needleId"; + describe("Assert", () => { - it("isVisible should not throw if a match is found.", async () => { - // GIVEN - Screen.prototype.find = jest.fn(() => Promise.resolve(new Region(0, 0, 100, 100))); - const screenMock = new Screen(new VisionAdapter()); - const SUT = new Assert(screenMock); - const needle = "foo"; - - // WHEN - - // THEN - await expect(SUT.isVisible(needle)).resolves.not.toThrowError(); - }); - - it("isVisible should throw if a match is found.", async () => { - // GIVEN - Screen.prototype.find = jest.fn(() => Promise.reject("foo")); - const screenMock = new Screen(new VisionAdapter()); - const SUT = new Assert(screenMock); - const needle = "foo"; - - // WHEN - - // THEN - await expect(SUT.isVisible(needle)).rejects.toThrowError(`Element '${needle}' not found`); - }); - - it("isVisible should throw if a match is found.", async () => { - // GIVEN - Screen.prototype.find = jest.fn(() => Promise.reject("foo")); - const screenMock = new Screen(new VisionAdapter()); - const SUT = new Assert(screenMock); - const searchRegion = new Region(10, 10, 10, 10); - const needle = "foo"; - - // WHEN - - // THEN - await expect(SUT - .isVisible(needle, searchRegion)) - .rejects.toThrowError(`Element '${needle}' not found in region ${searchRegion.toString()}` - ); - }); - - it("isNotVisible should throw if a match is found.", async () => { - // GIVEN - Screen.prototype.find = jest.fn(() => Promise.resolve(new Region(0, 0, 100, 100))); - const screenMock = new Screen(new VisionAdapter()); - const SUT = new Assert(screenMock); - const needle = "foo"; - - // WHEN - - // THEN - await expect(SUT.notVisible(needle)).rejects.toThrowError(`'${needle}' is visible`); - }); - - it("isVisible should throw if a match is found.", async () => { - // GIVEN - Screen.prototype.find = jest.fn(() => Promise.reject("foo")); - const screenMock = new Screen(new VisionAdapter()); - const SUT = new Assert(screenMock); - const needle = "foo"; - - // WHEN - - // THEN - await expect(SUT.notVisible(needle)).resolves.not.toThrowError(); - }); + it("isVisible should not throw if a match is found.", async () => { + // GIVEN + ScreenClass.prototype.find = jest.fn(() => Promise.resolve(new Region(0, 0, 100, 100))); + const screenMock = new ScreenClass(providerRegistry); + const SUT = new AssertClass(screenMock); + const needle = mockPartial({ + id: needleId + }); + + // WHEN + + // THEN + await expect(SUT.isVisible(needle)).resolves.not.toThrowError(); + }); + + it("isVisible should throw if a match is found.", async () => { + // GIVEN + ScreenClass.prototype.find = jest.fn(() => Promise.reject("foo")); + const screenMock = new ScreenClass(providerRegistry); + const SUT = new AssertClass(screenMock); + const needle = mockPartial({ + id: needleId + }); + + // WHEN + + // THEN + await expect(SUT.isVisible(needle)).rejects.toThrowError(`Element '${needle.id}' not found`); + }); + + it("isVisible should throw if a match is found.", async () => { + // GIVEN + ScreenClass.prototype.find = jest.fn(() => Promise.reject("foo")); + const screenMock = new ScreenClass(providerRegistry); + const SUT = new AssertClass(screenMock); + const searchRegion = new Region(10, 10, 10, 10); + const needle = mockPartial({ + id: needleId + }); + + // WHEN + + // THEN + await expect(SUT + .isVisible(needle, searchRegion)) + .rejects.toThrowError(`Element '${needle.id}' not found in region ${searchRegion.toString()}` + ); + }); + + it("isNotVisible should throw if a match is found.", async () => { + // GIVEN + ScreenClass.prototype.find = jest.fn(() => Promise.resolve(new Region(0, 0, 100, 100))); + const screenMock = new ScreenClass(providerRegistry); + const SUT = new AssertClass(screenMock); + const needle = mockPartial({ + id: needleId + }); + + // WHEN + + // THEN + await expect(SUT.notVisible(needle)).rejects.toThrowError(`'${needle.id}' is visible`); + }); + + it("isVisible should throw if a match is found.", async () => { + // GIVEN + ScreenClass.prototype.find = jest.fn(() => Promise.reject("foo")); + const screenMock = new ScreenClass(providerRegistry); + const SUT = new AssertClass(screenMock); + const needle = mockPartial({ + id: needleId + }); + + // WHEN + + // THEN + await expect(SUT.notVisible(needle)).resolves.not.toThrowError(); + }); }); diff --git a/lib/assert.class.ts b/lib/assert.class.ts index 14cb0cd2..6409e791 100644 --- a/lib/assert.class.ts +++ b/lib/assert.class.ts @@ -1,36 +1,42 @@ -import { LocationParameters } from "./locationparameters.class"; -import { Region } from "./region.class"; -import { Screen } from "./screen.class"; +import {Region} from "./region.class"; +import {ScreenClass} from "./screen.class"; +import {FirstArgumentType} from "./typings"; +import {OptionalSearchParameters} from "./optionalsearchparameters.class"; -export class Assert { - constructor(private screen: Screen) {} +export class AssertClass { + constructor(private screen: ScreenClass) { + } + + public async isVisible(needle: FirstArgumentType, searchRegion?: Region, confidence?: number) { + const identifier = (await needle).id; - public async isVisible(pathToNeedle: string, searchRegion?: Region, confidence?: number) { - try { - await this.screen.find( - pathToNeedle, - {searchRegion, confidence} as LocationParameters, - ); - } catch (err) { - if (searchRegion !== undefined) { - throw new Error( - `Element '${pathToNeedle}' not found in region ${searchRegion.toString()}`, - ); - } else { - throw new Error(`Element '${pathToNeedle}' not found`); - } + try { + await this.screen.find( + needle, + {searchRegion, confidence} as OptionalSearchParameters, + ); + } catch (err) { + if (searchRegion !== undefined) { + throw new Error( + `Element '${identifier}' not found in region ${searchRegion.toString()}. Reason: ${err}`, + ); + } else { + throw new Error(`Element '${identifier}' not found. Reason: ${err}`); + } + } } - } - public async notVisible(pathToNeedle: string, searchRegion?: Region, confidence?: number) { - try { - await this.screen.find( - pathToNeedle, - {searchRegion, confidence} as LocationParameters, - ); - } catch (err) { - return; + public async notVisible(needle: FirstArgumentType, searchRegion?: Region, confidence?: number) { + const identifier = (await needle).id; + + try { + await this.screen.find( + needle, + {searchRegion, confidence} as OptionalSearchParameters, + ); + } catch (err) { + return; + } + throw new Error(`'${identifier}' is visible`); } - throw new Error(`'${pathToNeedle}' is visible`); - } } diff --git a/lib/clipboard.class.e2e.spec.ts b/lib/clipboard.class.e2e.spec.ts index 5545ba3b..d4e35f1d 100644 --- a/lib/clipboard.class.e2e.spec.ts +++ b/lib/clipboard.class.e2e.spec.ts @@ -1,10 +1,9 @@ -import {NativeAdapter} from "./adapter/native.adapter.class"; -import {Clipboard} from "./clipboard.class"; +import {ClipboardClass} from "./clipboard.class"; +import providerRegistry from "./provider/provider-registry.class"; describe("Clipboard class", () => { it("should paste copied input from system clipboard.", async () => { - const adapterMock = new NativeAdapter(); - const SUT = new Clipboard(adapterMock); + const SUT = new ClipboardClass(providerRegistry); const textToCopy = "bar"; diff --git a/lib/clipboard.class.spec.ts b/lib/clipboard.class.spec.ts index f957a56a..c0119bc0 100644 --- a/lib/clipboard.class.spec.ts +++ b/lib/clipboard.class.spec.ts @@ -1,29 +1,47 @@ -import {NativeAdapter} from "./adapter/native.adapter.class"; -import {Clipboard} from "./clipboard.class"; +import {ClipboardClass} from "./clipboard.class"; +import {ProviderRegistry} from "./provider/provider-registry.class"; +import {mockPartial} from "sneer"; +import {ClipboardProviderInterface} from "./provider"; -jest.mock("./adapter/native.adapter.class"); +jest.mock('jimp', () => { +}); beforeEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); }); -describe("Clipboard class", () => { - it("should call the native adapters copy method.", () => { - const adapterMock = new NativeAdapter(); - const SUT = new Clipboard(adapterMock); +const providerRegistryMock = mockPartial({}) +describe("Clipboard class", () => { + it("should call providers copy method.", () => { + // GIVEN + const SUT = new ClipboardClass(providerRegistryMock); + const copyMock = jest.fn(); + providerRegistryMock.getClipboard = jest.fn(() => mockPartial({ + copy: copyMock + })); const textToCopy = "bar"; + // WHEN SUT.copy(textToCopy); - expect(adapterMock.copy).toHaveBeenCalledTimes(1); - expect(adapterMock.copy).toHaveBeenCalledWith(textToCopy); + + // THEN + expect(copyMock).toHaveBeenCalledTimes(1); + expect(copyMock).toHaveBeenCalledWith(textToCopy); }); - it("should call the native adapters paste method.", () => { - const adapterMock = new NativeAdapter(); - const SUT = new Clipboard(adapterMock); + it("should call providers paste method.", () => { + // GIVEN + const SUT = new ClipboardClass(providerRegistryMock); + const pasteMock = jest.fn(); + providerRegistryMock.getClipboard = jest.fn(() => mockPartial({ + paste: pasteMock + })); + // WHEN SUT.paste(); - expect(adapterMock.paste).toHaveBeenCalledTimes(1); + + // THEN + expect(pasteMock).toHaveBeenCalledTimes(1); }); }); diff --git a/lib/clipboard.class.ts b/lib/clipboard.class.ts index c116c523..67aa3744 100644 --- a/lib/clipboard.class.ts +++ b/lib/clipboard.class.ts @@ -1,14 +1,14 @@ -import { NativeAdapter } from "./adapter/native.adapter.class"; - /** - * {@link Clipboard} class gives access to a systems clipboard + * {@link ClipboardClass} class gives access to a systems clipboard */ -export class Clipboard { +import {ProviderRegistry} from "./provider/provider-registry.class"; + +export class ClipboardClass { /** - * {@link Clipboard} class constructor - * @param nativeAdapter {@link NativeAdapter} instance used to access OS API + * {@link ClipboardClass} class constructor + * @param providerRegistry */ - constructor(private nativeAdapter: NativeAdapter) { + constructor(private providerRegistry: ProviderRegistry) { } /** @@ -16,13 +16,13 @@ export class Clipboard { * @param text The text to copy */ public copy(text: string): Promise { - return this.nativeAdapter.copy(text); + return this.providerRegistry.getClipboard().copy(text); } /** * {@link paste} returns the current content of the system clipboard (limited to text) */ public paste(): Promise { - return this.nativeAdapter.paste(); + return this.providerRegistry.getClipboard().paste(); } } diff --git a/lib/colormode.enum.ts b/lib/colormode.enum.ts new file mode 100644 index 00000000..ce0b0434 --- /dev/null +++ b/lib/colormode.enum.ts @@ -0,0 +1,7 @@ +/** + * The {@link ColorMode} enum is used to specify the color mode of an {@link Image} + */ +export enum ColorMode { + BGR, + RGB +} \ No newline at end of file diff --git a/lib/expect/jest.matcher.function.ts b/lib/expect/jest.matcher.function.ts index 32690746..9477f27d 100644 --- a/lib/expect/jest.matcher.function.ts +++ b/lib/expect/jest.matcher.function.ts @@ -1,21 +1,23 @@ -import { Point } from "../point.class"; -import { Region } from "../region.class"; -import { toBeAt } from "./matchers/toBeAt.function"; -import { toBeIn } from "./matchers/toBeIn.function"; -import { toShow } from "./matchers/toShow.function"; +import {Point} from "../point.class"; +import {Region} from "../region.class"; +import {toBeAt} from "./matchers/toBeAt.function"; +import {toBeIn} from "./matchers/toBeIn.function"; +import {toShow} from "./matchers/toShow.function"; +import {FirstArgumentType} from "../typings"; +import {ScreenClass} from "../screen.class"; declare global { - namespace jest { - interface Matchers { - toBeAt: (position: Point) => {}; - toBeIn: (region: Region) => {}; - toShow: (needle: string, confidence?: number) => {}; + namespace jest { + interface Matchers { + toBeAt: (position: Point) => {}; + toBeIn: (region: Region) => {}; + toShow: (needle: FirstArgumentType, confidence?: number) => {}; + } } - } } export const jestMatchers = { - toBeAt, - toBeIn, - toShow, + toBeAt, + toBeIn, + toShow, }; diff --git a/lib/expect/matchers/toBeAt.function.e2e.spec.ts b/lib/expect/matchers/toBeAt.function.e2e.spec.ts index ef4f2dcf..c40ebb63 100644 --- a/lib/expect/matchers/toBeAt.function.e2e.spec.ts +++ b/lib/expect/matchers/toBeAt.function.e2e.spec.ts @@ -2,6 +2,8 @@ import { mouse } from "../../../index"; import { Point } from "../../point.class"; import { toBeAt } from "./toBeAt.function"; +jest.mock('jimp', () => {}); + const targetPoint = new Point(100, 100); describe(".toBeAt", () => { diff --git a/lib/expect/matchers/toBeAt.function.ts b/lib/expect/matchers/toBeAt.function.ts index 25fe4785..e0bd7cd4 100644 --- a/lib/expect/matchers/toBeAt.function.ts +++ b/lib/expect/matchers/toBeAt.function.ts @@ -1,7 +1,7 @@ -import { Mouse } from "../../mouse.class"; +import { MouseClass } from "../../mouse.class"; import { Point } from "../../point.class"; -export const toBeAt = async (received: Mouse, position: Point) => { +export const toBeAt = async (received: MouseClass, position: Point) => { const currentPosition = await received.getPosition(); const success = diff --git a/lib/expect/matchers/toBeIn.function.e2e.spec.ts b/lib/expect/matchers/toBeIn.function.e2e.spec.ts index 19d0144f..ba3f2501 100644 --- a/lib/expect/matchers/toBeIn.function.e2e.spec.ts +++ b/lib/expect/matchers/toBeIn.function.e2e.spec.ts @@ -3,6 +3,8 @@ import { Point } from "../../point.class"; import { Region } from "../../region.class"; import { toBeIn } from "./toBeIn.function"; +jest.mock('jimp', () => {}); + const targetPoint = new Point(400, 400); describe(".toBeIn", () => { diff --git a/lib/expect/matchers/toBeIn.function.ts b/lib/expect/matchers/toBeIn.function.ts index 5fc3b3e8..372ec64e 100644 --- a/lib/expect/matchers/toBeIn.function.ts +++ b/lib/expect/matchers/toBeIn.function.ts @@ -1,7 +1,7 @@ -import { Mouse } from "../../mouse.class"; +import { MouseClass } from "../../mouse.class"; import { Region } from "../../region.class"; -export const toBeIn = async (received: Mouse, region: Region) => { +export const toBeIn = async (received: MouseClass, region: Region) => { const currentPosition = await received.getPosition(); const inX = diff --git a/lib/expect/matchers/toShow.function.ts b/lib/expect/matchers/toShow.function.ts index d50da7f4..3b3c3848 100644 --- a/lib/expect/matchers/toShow.function.ts +++ b/lib/expect/matchers/toShow.function.ts @@ -1,26 +1,28 @@ -import { LocationParameters } from "../../locationparameters.class"; -import { Screen } from "../../screen.class"; +import {ScreenClass} from "../../screen.class"; +import {FirstArgumentType} from "../../typings"; +import {OptionalSearchParameters} from "../../optionalsearchparameters.class"; export const toShow = async ( - received: Screen, - needle: string, - confidence?: number, + received: ScreenClass, + needle: FirstArgumentType, + confidence?: number, ) => { - let locationParams; - if (confidence) { - locationParams = new LocationParameters(); - locationParams.confidence = confidence; - } - try { - await received.find(needle, locationParams); - return { - message: () => `Expected screen to not show ${needle}`, - pass: true, - }; - } catch (err) { - return { - message: () => `Screen is not showing ${needle}: ${err}`, - pass: false, - }; - } + let locationParams; + if (confidence) { + locationParams = new OptionalSearchParameters(); + locationParams.confidence = confidence; + } + const identifier = (await needle).id; + try { + await received.find(needle, locationParams); + return { + message: () => `Expected screen to not show ${identifier}`, + pass: true, + }; + } catch (err) { + return { + message: () => `Screen is not showing ${identifier}: ${err}`, + pass: false, + }; + } }; diff --git a/lib/image.class.spec.ts b/lib/image.class.spec.ts index 0b7740c6..78823179 100644 --- a/lib/image.class.spec.ts +++ b/lib/image.class.spec.ts @@ -1,30 +1,68 @@ -import { Image } from "./image.class"; +import {Image} from "./image.class"; +import {imageToJimp} from "./provider/io/imageToJimp.function"; +import {ColorMode} from "./colormode.enum"; + +jest.mock("./provider/io/imageToJimp.function", () => { + return { + imageToJimp: jest.fn() + } +}); + +afterEach(() => { + jest.resetAllMocks(); +}); describe("Image class", () => { - it("should return alphachannel = true for > 3 channels", () => { - const SUT = new Image(200, 200, 123, 4); - expect(SUT.hasAlphaChannel).toBeTruthy(); - }); - - it("should return alphachannel = false for <= 3 channels", () => { - const SUT = new Image(200, 200, 123, 3); - expect(SUT.hasAlphaChannel).toBeFalsy(); - }); - it("should return alphachannel = false for <= 3 channels", () => { - const SUT = new Image(200, 200, 123, 2); - expect(SUT.hasAlphaChannel).toBeFalsy(); - }); - it("should return alphachannel = false for <= 3 channels", () => { - const SUT = new Image(200, 200, 123, 1); - expect(SUT.hasAlphaChannel).toBeFalsy(); - }); - - it("should throw for <= 0 channels", () => { - expect(() => new Image(200, 200, 123, 0)).toThrowError("Channel <= 0"); - }); - - it("should have a default pixel density of 1.0", () => { - const SUT = new Image(200, 200, 123, 1); - expect(SUT.pixelDensity).toEqual({ scaleX: 1.0, scaleY: 1.0 }); - }); + it("should return alphachannel = true for > 3 channels", () => { + const SUT = new Image(200, 200, Buffer.from([123]), 4, "id"); + expect(SUT.hasAlphaChannel).toBeTruthy(); + }); + + it("should return alphachannel = false for <= 3 channels", () => { + const SUT = new Image(200, 200, Buffer.from([123]), 3, "id"); + expect(SUT.hasAlphaChannel).toBeFalsy(); + }); + it("should return alphachannel = false for <= 3 channels", () => { + const SUT = new Image(200, 200, Buffer.from([123]), 2, "id"); + expect(SUT.hasAlphaChannel).toBeFalsy(); + }); + it("should return alphachannel = false for <= 3 channels", () => { + const SUT = new Image(200, 200, Buffer.from([123]), 1, "id"); + expect(SUT.hasAlphaChannel).toBeFalsy(); + }); + + it("should throw for <= 0 channels", () => { + expect(() => new Image(200, 200, Buffer.from([123]), 0, "id")).toThrowError("Channel <= 0"); + }); + + it("should have a default pixel density of 1.0", () => { + const SUT = new Image(200, 200, Buffer.from([123]), 1, "id"); + expect(SUT.pixelDensity).toEqual({scaleX: 1.0, scaleY: 1.0}); + }); + + describe("Colormode", () => { + it("should not try to convert an image to BGR if it already has the correct color mode", async () => { + // GIVEN + const bgrImage = new Image(100, 100, Buffer.from([]), 3, "testImage"); + + // WHEN + const convertedImage = await bgrImage.toBGR(); + + // THEN + expect(convertedImage).toBe(bgrImage); + expect(imageToJimp).not.toBeCalledTimes(1) + }); + + it("should not try to convert an image to RGB if it already has the correct color mode", async () => { + // GIVEN + const rgbImage = new Image(100, 100, Buffer.from([]), 3, "testImage", ColorMode.RGB); + + // WHEN + const convertedImage = await rgbImage.toRGB(); + + // THEN + expect(convertedImage).toBe(rgbImage); + expect(imageToJimp).not.toBeCalledTimes(1) + }); + }); }); diff --git a/lib/image.class.ts b/lib/image.class.ts index 1e511335..4fc1a154 100644 --- a/lib/image.class.ts +++ b/lib/image.class.ts @@ -1,34 +1,72 @@ +import {imageToJimp} from "./provider/io/imageToJimp.function"; +import {ColorMode} from "./colormode.enum"; + /** * The {@link Image} class represents generic image data */ export class Image { - /** - * {@link Image} class constructor - * @param width {@link Image} width in pixels - * @param height {@link Image} height in pixels - * @param data Generic {@link Image} data - * @param channels Amount of {@link Image} channels - * @param pixelDensity Object containing scale info to work with e.g. Retina display data where the reported display size and pixel size differ (Default: {scaleX: 1.0, scaleY: 1.0}) - */ - constructor( - public readonly width: number, - public readonly height: number, - public readonly data: any, - public readonly channels: number, - public readonly pixelDensity: { scaleX: number; scaleY: number } = { - scaleX: 1.0, - scaleY: 1.0, - }, - ) { - if (channels <= 0) { - throw new Error("Channel <= 0"); + /** + * {@link Image} class constructor + * @param width {@link Image} width in pixels + * @param height {@link Image} height in pixels + * @param data Generic {@link Image} data + * @param channels Amount of {@link Image} channels + * @param id Image identifier + * @param colorMode An images color mode, defaults to {@link ColorMode.BGR} + * @param pixelDensity Object containing scale info to work with e.g. Retina display data where the reported display size and pixel size differ (Default: {scaleX: 1.0, scaleY: 1.0}) + */ + constructor( + public readonly width: number, + public readonly height: number, + public readonly data: Buffer, + public readonly channels: number, + public readonly id: string, + public readonly colorMode: ColorMode = ColorMode.BGR, + public readonly pixelDensity: { scaleX: number; scaleY: number } = { + scaleX: 1.0, + scaleY: 1.0, + }, + ) { + if (channels <= 0) { + throw new Error("Channel <= 0"); + } + } + + /** + * {@link hasAlphaChannel} return true if an {@link Image} has an additional (fourth) alpha channel + */ + public get hasAlphaChannel() { + return this.channels > 3; + } + + /** + * {@link toRGB} converts an {@link Image} from BGR color mode (default within nut.js) to RGB + */ + public async toRGB(): Promise { + if (this.colorMode === ColorMode.RGB) { + return this; + } + const rgbImage = imageToJimp(this); + return new Image(this.width, this.height, rgbImage.bitmap.data, this.channels, this.id, ColorMode.RGB, this.pixelDensity); + } + + /** + * {@link toBGR} converts an {@link Image} from RGB color mode to RGB + */ + public async toBGR(): Promise { + if (this.colorMode === ColorMode.BGR) { + return this; + } + const rgbImage = imageToJimp(this); + return new Image(this.width, this.height, rgbImage.bitmap.data, this.channels, this.id, ColorMode.BGR, this.pixelDensity); } - } - /** - * {@link hasAlphaChannel} return true if an {@link Image} has an additional (fourth) alpha channel - */ - public get hasAlphaChannel() { - return this.channels > 3; - } + /** + * {@link fromRGBData} creates an {@link Image} from provided RGB data + */ + public static fromRGBData(width: number, height: number, data: Buffer, channels: number, id: string): Image { + const rgbImage = new Image(width, height, data, channels, id); + const jimpImage = imageToJimp(rgbImage); + return new Image(width, height, jimpImage.bitmap.data, channels, id); + } } diff --git a/lib/imageResources.function.spec.ts b/lib/imageResources.function.spec.ts new file mode 100644 index 00000000..a64600aa --- /dev/null +++ b/lib/imageResources.function.spec.ts @@ -0,0 +1,28 @@ +import {loadImageResource} from "./imageResources.function"; +import {mockPartial} from "sneer"; +import {ProviderRegistry} from "./provider/provider-registry.class"; +import {ImageReader} from "./provider"; +import {join} from "path"; + +const loadMock = jest.fn(); +const providerRegistryMock = mockPartial({ + getImageReader(): ImageReader { + return mockPartial({ + load: loadMock + }); + } +}); + +describe('imageResources', () => { + it('should retrieve an ImageReader via providerRegistry and load an image relative to the provided resourceDirectory', async () => { + // GIVEN + const resourceDirectoryPath = '/foo/bar'; + const imageFileName = "image.png"; + + // WHEN + await loadImageResource(providerRegistryMock, resourceDirectoryPath, imageFileName); + + // THEN + expect(loadMock).toBeCalledWith(join(resourceDirectoryPath, imageFileName)); + }); +}); \ No newline at end of file diff --git a/lib/imageResources.function.ts b/lib/imageResources.function.ts new file mode 100644 index 00000000..96ce588e --- /dev/null +++ b/lib/imageResources.function.ts @@ -0,0 +1,7 @@ +import {join, normalize} from "path"; +import {ProviderRegistry} from "./provider/provider-registry.class"; + +export function loadImageResource(providerRegistry: ProviderRegistry, resourceDirectory: string, fileName: string) { + const fullPath = normalize(join(resourceDirectory, fileName)); + return providerRegistry.getImageReader().load(fullPath); +} \ No newline at end of file diff --git a/lib/key.enum.ts b/lib/key.enum.ts index fab519c0..f6f6ef0b 100644 --- a/lib/key.enum.ts +++ b/lib/key.enum.ts @@ -28,6 +28,18 @@ export enum Key { F10, F11, F12, + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, Num0, Num1, @@ -116,4 +128,17 @@ export enum Key { CapsLock, ScrollLock, NumLock, + + AudioMute, + AudioVolDown, + AudioVolUp, + AudioPlay, + AudioStop, + AudioPause, + AudioPrev, + AudioNext, + AudioRewind, + AudioForward, + AudioRepeat, + AudioRandom } diff --git a/lib/keyboard.class.e2e.spec.ts b/lib/keyboard.class.e2e.spec.ts deleted file mode 100644 index 0f9fed58..00000000 --- a/lib/keyboard.class.e2e.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { jestMatchers, Key, keyboard, screen } from "../index"; - -expect.extend(jestMatchers); - -const run = async (cmd: string) => { - await keyboard.type(Key.LeftAlt, Key.F2); - await keyboard.type(cmd); - await keyboard.type(Key.Enter); -}; - -const confirm = async () => { - await keyboard.type(Key.Enter); -}; - -const close = async () => { - await keyboard.type(Key.LeftAlt, Key.F4); -}; - -describe("Keyboard e2e class", () => { - it("should open gnome calculator via keyboard.", async () => { - // GIVEN - jest.setTimeout(30000); - screen.config.resourceDirectory = "./e2e/assets"; - screen.config.confidence = 0.97; - await run("gnome-calculator"); - await confirm(); - - // WHEN - - // THEN - await expect(screen).toShow("calculator.png"); - await close(); - }); -}); diff --git a/lib/keyboard.class.spec.ts b/lib/keyboard.class.spec.ts index bd4e4e80..1406561e 100644 --- a/lib/keyboard.class.spec.ts +++ b/lib/keyboard.class.spec.ts @@ -1,114 +1,152 @@ -import { NativeAdapter } from "./adapter/native.adapter.class"; -import { Key } from "./key.enum"; -import { Keyboard } from "./keyboard.class"; +import {Key} from "./key.enum"; +import {KeyboardClass} from "./keyboard.class"; +import {ProviderRegistry} from "./provider/provider-registry.class"; +import {mockPartial} from "sneer"; +import {KeyboardProviderInterface} from "./provider"; -jest.mock("./adapter/native.adapter.class"); +jest.setTimeout(10000); beforeEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); }); -describe("Keyboard", () => { - it("should have a default delay of 300 ms", () => { - // GIVEN - const adapterMock = new NativeAdapter(); - const SUT = new Keyboard(adapterMock); - - // WHEN - - // THEN - expect(SUT.config.autoDelayMs).toEqual(300); - }); - - it("should pass input strings down to the type call.", async () => { - // GIVEN - const adapterMock = new NativeAdapter(); - const SUT = new Keyboard(adapterMock); - const payload = "Test input!"; - - // WHEN - await SUT.type(payload); - - // THEN - expect(adapterMock.type).toHaveBeenCalledTimes(payload.length); - for (const char of payload.split("")) { - expect(adapterMock.type).toHaveBeenCalledWith(char); - } - }); - - it("should pass multiple input strings down to the type call.", async () => { - // GIVEN - jest.setTimeout(10000); - const adapterMock = new NativeAdapter(); - const SUT = new Keyboard(adapterMock); - const payload = ["Test input!", "Array test2"]; - - // WHEN - await SUT.type(...payload); - - // THEN - expect(adapterMock.type).toHaveBeenCalledTimes(payload.join(" ").length); - for (const char of payload.join(" ").split("")) { - expect(adapterMock.type).toHaveBeenCalledWith(char); - } - }); - - it("should pass input keys down to the click call.", async () => { - // GIVEN - const adapterMock = new NativeAdapter(); - const SUT = new Keyboard(adapterMock); - const payload = [Key.A, Key.S, Key.D, Key.F]; - - // WHEN - await SUT.type(...payload); - - // THEN - expect(adapterMock.click).toHaveBeenCalledTimes(1); - expect(adapterMock.click).toHaveBeenCalledWith(...payload); - }); - - it("should pass a list of input keys down to the click call.", async () => { - // GIVEN - const adapterMock = new NativeAdapter(); - const SUT = new Keyboard(adapterMock); - const payload = [Key.A, Key.S, Key.D, Key.F]; - - // WHEN - for (const key of payload) { - await SUT.type(key); - } - - // THEN - expect(adapterMock.click).toHaveBeenCalledTimes(payload.length); - }); - - it("should pass a list of input keys down to the pressKey call.", async () => { - // GIVEN - const adapterMock = new NativeAdapter(); - const SUT = new Keyboard(adapterMock); - const payload = [Key.A, Key.S, Key.D, Key.F]; - - // WHEN - for (const key of payload) { - await SUT.pressKey(key); - } - - // THEN - expect(adapterMock.pressKey).toHaveBeenCalledTimes(payload.length); - }); - - it("should pass a list of input keys down to the releaseKey call.", async () => { - // GIVEN - const adapterMock = new NativeAdapter(); - const SUT = new Keyboard(adapterMock); - const payload = [Key.A, Key.S, Key.D, Key.F]; - - // WHEN - for (const key of payload) { - await SUT.releaseKey(key); +const providerRegistryMock = mockPartial({ + getKeyboard(): KeyboardProviderInterface { + return mockPartial({ + setKeyboardDelay: jest.fn(), + }) } +}) - // THEN - expect(adapterMock.releaseKey).toHaveBeenCalledTimes(payload.length); - }); +describe("Keyboard", () => { + it("should have a default delay of 300 ms", () => { + // GIVEN + const SUT = new KeyboardClass(providerRegistryMock); + + // WHEN + + // THEN + expect(SUT.config.autoDelayMs).toEqual(300); + }); + + it("should pass input strings down to the type call.", async () => { + // GIVEN + const SUT = new KeyboardClass(providerRegistryMock); + const payload = "Test input!"; + + const typeMock = jest.fn(); + providerRegistryMock.getKeyboard = jest.fn(() => mockPartial({ + setKeyboardDelay: jest.fn(), + type: typeMock + })); + + // WHEN + await SUT.type(payload); + + // THEN + expect(typeMock).toHaveBeenCalledTimes(payload.length); + for (const char of payload.split("")) { + expect(typeMock).toHaveBeenCalledWith(char); + } + }); + + it("should pass multiple input strings down to the type call.", async () => { + // GIVEN + const SUT = new KeyboardClass(providerRegistryMock); + const payload = ["Test input!", "Array test2"]; + + const typeMock = jest.fn(); + providerRegistryMock.getKeyboard = jest.fn(() => mockPartial({ + setKeyboardDelay: jest.fn(), + type: typeMock + })); + + // WHEN + await SUT.type(...payload); + + // THEN + expect(typeMock).toHaveBeenCalledTimes(payload.join(" ").length); + for (const char of payload.join(" ").split("")) { + expect(typeMock).toHaveBeenCalledWith(char); + } + }); + + it("should pass input keys down to the click call.", async () => { + // GIVEN + const SUT = new KeyboardClass(providerRegistryMock); + const payload = [Key.A, Key.S, Key.D, Key.F]; + + const clickMock = jest.fn(); + providerRegistryMock.getKeyboard = jest.fn(() => mockPartial({ + setKeyboardDelay: jest.fn(), + click: clickMock + })); + + // WHEN + await SUT.type(...payload); + + // THEN + expect(clickMock).toHaveBeenCalledTimes(1); + expect(clickMock).toHaveBeenCalledWith(...payload); + }); + + it("should pass a list of input keys down to the click call.", async () => { + // GIVEN + const SUT = new KeyboardClass(providerRegistryMock); + const payload = [Key.A, Key.S, Key.D, Key.F]; + + const clickMock = jest.fn(); + providerRegistryMock.getKeyboard = jest.fn(() => mockPartial({ + setKeyboardDelay: jest.fn(), + click: clickMock + })); + + // WHEN + for (const key of payload) { + await SUT.type(key); + } + + // THEN + expect(clickMock).toHaveBeenCalledTimes(payload.length); + }); + + it("should pass a list of input keys down to the pressKey call.", async () => { + // GIVEN + const SUT = new KeyboardClass(providerRegistryMock); + const payload = [Key.A, Key.S, Key.D, Key.F]; + + const keyMock = jest.fn(); + providerRegistryMock.getKeyboard = jest.fn(() => mockPartial({ + setKeyboardDelay: jest.fn(), + pressKey: keyMock + })); + + // WHEN + for (const key of payload) { + await SUT.pressKey(key); + } + + // THEN + expect(keyMock).toHaveBeenCalledTimes(payload.length); + }); + + it("should pass a list of input keys down to the releaseKey call.", async () => { + // GIVEN + const SUT = new KeyboardClass(providerRegistryMock); + const payload = [Key.A, Key.S, Key.D, Key.F]; + + const keyMock = jest.fn(); + providerRegistryMock.getKeyboard = jest.fn(() => mockPartial({ + setKeyboardDelay: jest.fn(), + releaseKey: keyMock + })); + + // WHEN + for (const key of payload) { + await SUT.releaseKey(key); + } + + // THEN + expect(keyMock).toHaveBeenCalledTimes(payload.length); + }); }); diff --git a/lib/keyboard.class.ts b/lib/keyboard.class.ts index 0a155c97..669e722b 100644 --- a/lib/keyboard.class.ts +++ b/lib/keyboard.class.ts @@ -1,105 +1,105 @@ -import { NativeAdapter } from "./adapter/native.adapter.class"; -import { Key } from "./key.enum"; -import { sleep } from "./sleep.function"; +import {Key} from "./key.enum"; +import {sleep} from "./sleep.function"; +import {ProviderRegistry} from "./provider/provider-registry.class"; type StringOrKey = string[] | Key[]; -const inputIsString = (input: string[] | Key[]): input is string[] => { - return input.every((elem: string | Key) => typeof elem === "string"); +const inputIsString = (input: (string | Key)[]): input is string[] => { + return input.every((elem: string | Key) => typeof elem === "string"); }; /** - * {@link Keyboard} class provides methods to emulate keyboard input + * {@link KeyboardClass} class provides methods to emulate keyboard input */ -export class Keyboard { +export class KeyboardClass { - /** - * Config object for {@link Keyboard} class - */ - public config = { /** - * Configures the delay between single key events + * Config object for {@link KeyboardClass} class */ - autoDelayMs: 300, - }; + public config = { + /** + * Configures the delay between single key events + */ + autoDelayMs: 300, + }; - /** - * {@link Keyboard} class constructor - * @param nativeAdapter {@link NativeAdapter} instance which bundles access to mouse, keyboard and clipboard - */ - constructor(private nativeAdapter: NativeAdapter) { - this.nativeAdapter.setKeyboardDelay(this.config.autoDelayMs); - } + /** + * {@link KeyboardClass} class constructor + * @param providerRegistry + */ + constructor(private providerRegistry: ProviderRegistry) { + this.providerRegistry.getKeyboard().setKeyboardDelay(this.config.autoDelayMs); + } - /** - * {@link type} types a sequence of {@link String} or single {@link Key}s via system keyboard - * @example - * ```typescript - * await keyboard.type(Key.A, Key.S, Key.D, Key.F); - * await keyboard.type("Hello, world!"); - * ``` - * - * @param input Sequence of {@link String} or {@link Key} to type - */ - public type(...input: StringOrKey): Promise { - return new Promise(async (resolve, reject) => { - try { - if (inputIsString(input)) { - for (const char of input.join(" ").split("")) { - await sleep(this.config.autoDelayMs); - await this.nativeAdapter.type(char); - } - } else { - await this.nativeAdapter.click(...input as Key[]); - } - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link type} types a sequence of {@link String} or single {@link Key}s via system keyboard + * @example + * ```typescript + * await keyboard.type(Key.A, Key.S, Key.D, Key.F); + * await keyboard.type("Hello, world!"); + * ``` + * + * @param input Sequence of {@link String} or {@link Key} to type + */ + public type(...input: StringOrKey): Promise { + return new Promise(async (resolve, reject) => { + try { + if (inputIsString(input)) { + for (const char of input.join(" ").split("")) { + await sleep(this.config.autoDelayMs); + await this.providerRegistry.getKeyboard().type(char); + } + } else { + await this.providerRegistry.getKeyboard().click(...input as Key[]); + } + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link pressKey} presses and holds a single {@link Key} for {@link Key} combinations - * Modifier {@link Key}s are to be given in "natural" ordering, so first modifier {@link Key}s, followed by the {@link Key} to press - * @example - * ```typescript - * // Will press and hold key combination STRG + V - * await keyboard.pressKey(Key.STRG, Key.A); - * ``` - * - * @param keys Array of {@link Key}s to press and hold - */ - public pressKey(...keys: Key[]): Promise { - return new Promise(async (resolve, reject) => { - try { - await this.nativeAdapter.pressKey(...keys); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link pressKey} presses and holds a single {@link Key} for {@link Key} combinations + * Modifier {@link Key}s are to be given in "natural" ordering, so first modifier {@link Key}s, followed by the {@link Key} to press + * @example + * ```typescript + * // Will press and hold key combination STRG + V + * await keyboard.pressKey(Key.STRG, Key.A); + * ``` + * + * @param keys Array of {@link Key}s to press and hold + */ + public pressKey(...keys: Key[]): Promise { + return new Promise(async (resolve, reject) => { + try { + await this.providerRegistry.getKeyboard().pressKey(...keys); + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link pressKey} releases a single {@link Key} for {@link Key} combinations - * Modifier {@link Key}s are to be given in "natural" ordering, so first modifier {@link Key}s, followed by the {@link Key} to press - * @example - * ```typescript - * // Will release key combination STRG + V - * await keyboard.releaseKey(Key.STRG, Key.A); - * ``` - * - * @param keys Array of {@link Key}s to release - */ - public releaseKey(...keys: Key[]): Promise { - return new Promise(async (resolve, reject) => { - try { - await this.nativeAdapter.releaseKey(...keys); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link pressKey} releases a single {@link Key} for {@link Key} combinations + * Modifier {@link Key}s are to be given in "natural" ordering, so first modifier {@link Key}s, followed by the {@link Key} to press + * @example + * ```typescript + * // Will release key combination STRG + V + * await keyboard.releaseKey(Key.STRG, Key.A); + * ``` + * + * @param keys Array of {@link Key}s to release + */ + public releaseKey(...keys: Key[]): Promise { + return new Promise(async (resolve, reject) => { + try { + await this.providerRegistry.getKeyboard().releaseKey(...keys); + resolve(this); + } catch (e) { + reject(e); + } + }); + } } diff --git a/lib/locationparameters.class.ts b/lib/locationparameters.class.ts deleted file mode 100644 index 0febeb5f..00000000 --- a/lib/locationparameters.class.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {OptionalSearchParameters} from "./optionalsearchparameters.class"; - -/** - * {@deprecated This module serves as a polyfill to not break existing pre v1.5 code. Will be removed in v2.0.0} - * Use {@link OptionalSearchParameters} instead - */ -export { - OptionalSearchParameters as LocationParameters -} \ No newline at end of file diff --git a/lib/match-request.class.spec.ts b/lib/match-request.class.spec.ts index df509638..d2eaaa76 100644 --- a/lib/match-request.class.spec.ts +++ b/lib/match-request.class.spec.ts @@ -1,21 +1,27 @@ -import { Image } from "./image.class"; -import { MatchRequest } from "./match-request.class"; -import { Region } from "./region.class"; +import {Image} from "./image.class"; +import {MatchRequest} from "./match-request.class"; + +jest.mock('jimp', () => {}); describe("MatchRequest", () => { - it("should default to multi-scale matching", () => { - const SUT = new MatchRequest( - new Image(100, 100, - new ArrayBuffer(0), 3 - ), - "foo", - new Region( - 0, - 0, - 100, - 100), - 0.99); + it("should default to multi-scale matching", () => { + const SUT = new MatchRequest( + new Image( + 100, + 100, + Buffer.from([]), + 3, + "haystack_image" + ), + new Image( + 100, + 100, + Buffer.from([]), + 3, + "needle_image" + ), + 0.99); - expect(SUT.searchMultipleScales).toBeTruthy(); - }); + expect(SUT.searchMultipleScales).toBeTruthy(); + }); }); diff --git a/lib/match-request.class.ts b/lib/match-request.class.ts index 78601102..d09d026a 100644 --- a/lib/match-request.class.ts +++ b/lib/match-request.class.ts @@ -1,11 +1,9 @@ import { Image } from "./image.class"; -import { Region } from "./region.class"; export class MatchRequest { constructor( public readonly haystack: Image, - public readonly pathToNeedle: string, - public readonly searchRegion: Region, + public readonly needle: Image, public readonly confidence: number, public readonly searchMultipleScales: boolean = true, ) {} diff --git a/lib/mouse-movement.function.spec.ts b/lib/mouse-movement.function.spec.ts new file mode 100644 index 00000000..abb5274a --- /dev/null +++ b/lib/mouse-movement.function.spec.ts @@ -0,0 +1,80 @@ +import { + calculateStepDuration, + linear, + calculateMovementTimesteps, EasingFunction +} from "./mouse-movement.function"; + +describe("MovementType", () => { + describe("baseStepDuration", () => { + it("should calculate the base step duration in nanoseconds", () => { + // GIVEN + const speedInPixelsPerSecond = 1000; + const expectedBaseStepDuration = 1_000_000; + + // WHEN + const result = calculateStepDuration(speedInPixelsPerSecond); + + // THEN + expect(result).toBe(expectedBaseStepDuration); + }); + }); + + describe("stepDuration", () => { + it("should call easing function progress to calculate current step duration", () => { + // GIVEN + const amountOfSteps = 100; + const speedInPixelsPerSecond = 1000; + const easingFunction = jest.fn(() => 0); + + // WHEN + calculateMovementTimesteps(amountOfSteps, speedInPixelsPerSecond, easingFunction); + + // THEN + expect(easingFunction).toBeCalledTimes(amountOfSteps); + }) + }); + + describe('linear', () => { + it("should return a set of linear timesteps, 1000000 nanosecond per step.", () => { + // GIVEN + const expected = [1000000, 1000000, 1000000, 1000000, 1000000, 1000000]; + + // WHEN + const result = calculateMovementTimesteps(6, 1000, linear); + + // THEN + expect(result).toEqual(expected); + }); + + it("should should return a set of linear timesteps, 2000000 nanoseconds per step.", () => { + // GIVEN + const expected = [2000000, 2000000, 2000000, 2000000, 2000000, 2000000]; + + // WHEN + const result = calculateMovementTimesteps(6, 500, linear); + + // THEN + expect(result).toEqual(expected); + }); + }); + + describe('non-linear', () => { + it("should return progress slowly in the first half, 2000000 nanoseconds per step, then continue with normal speed, 1000000 nanoseconds per step", () => { + // GIVEN + const mouseSpeed = 1000; + const easingFunction: EasingFunction = (p: number) => { + if (p < 0.5) { + return -0.5 * mouseSpeed; + } + return 0; + }; + const expected = [2000000, 2000000, 2000000, 1000000, 1000000, 1000000]; + + // WHEN + const result = calculateMovementTimesteps(6, mouseSpeed, easingFunction); + + // THEN + expect(result).toEqual(expected); + }); + }); +}); \ No newline at end of file diff --git a/lib/mouse-movement.function.ts b/lib/mouse-movement.function.ts new file mode 100644 index 00000000..3d435850 --- /dev/null +++ b/lib/mouse-movement.function.ts @@ -0,0 +1,31 @@ +/** + * {@link EasingFunction}s are used to modify movement behaviour. + * + * See https://easings.net/ for reference + */ +export interface EasingFunction { + (progressPercentage: number): number; +} + +export const calculateStepDuration = (speedInPixelsPerSecond: number) => (1 / speedInPixelsPerSecond) * 1_000_000_000; + +export const calculateMovementTimesteps = ( + amountOfSteps: number, + speedInPixelsPerSecond: number, + easingFunction: EasingFunction = linear +): number[] => { + return Array(amountOfSteps) + .fill(speedInPixelsPerSecond) + .map((speed: number, idx: number) => { + let speedInPixels = speed; + if (typeof easingFunction === "function") { + speedInPixels += easingFunction(idx / amountOfSteps); + } + const stepDuration = calculateStepDuration(speedInPixels); + return (isFinite(stepDuration) && stepDuration > 0) ? stepDuration : 0; + }); +}; + +export const linear: EasingFunction = (_: number): number => { + return 0; +}; diff --git a/lib/mouse.class.spec.ts b/lib/mouse.class.spec.ts index 8133507e..6302afb3 100644 --- a/lib/mouse.class.spec.ts +++ b/lib/mouse.class.spec.ts @@ -1,155 +1,217 @@ -import { NativeAdapter } from "./adapter/native.adapter.class"; -import { Button } from "./button.enum"; -import { Mouse } from "./mouse.class"; -import { Point } from "./point.class"; -import { LineHelper } from "./util/linehelper.class"; - -jest.mock("./adapter/native.adapter.class"); +import {Button} from "./button.enum"; +import {MouseClass} from "./mouse.class"; +import {Point} from "./point.class"; +import {LineHelper} from "./util/linehelper.class"; +import {ProviderRegistry} from "./provider/provider-registry.class"; +import {mockPartial} from "sneer"; +import {MouseProviderInterface} from "./provider"; beforeEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); }); const linehelper = new LineHelper(); +const providerRegistryMock = mockPartial({ + getMouse(): MouseProviderInterface { + return mockPartial({ + setMouseDelay: jest.fn() + }) + } +}); + describe("Mouse class", () => { - it("should have a default delay of 500 ms", () => { - // GIVEN - const adapterMock = new NativeAdapter(); - const SUT = new Mouse(adapterMock); - - // WHEN - - // THEN - expect(SUT.config.autoDelayMs).toEqual(100); - }); - - it("should forward scrollLeft to the native adapter class", async () => { - // GIVEN - const nativeAdapterMock = new NativeAdapter(); - const SUT = new Mouse(nativeAdapterMock); - const scrollAmount = 5; - - // WHEN - const result = await SUT.scrollLeft(scrollAmount); - - // THEN - expect(nativeAdapterMock.scrollLeft).toBeCalledWith(scrollAmount); - expect(result).toBe(SUT); - }); - - it("should forward scrollRight to the native adapter class", async () => { - // GIVEN - const nativeAdapterMock = new NativeAdapter(); - const SUT = new Mouse(nativeAdapterMock); - const scrollAmount = 5; - - // WHEN - const result = await SUT.scrollRight(scrollAmount); - - // THEN - expect(nativeAdapterMock.scrollRight).toBeCalledWith(scrollAmount); - expect(result).toBe(SUT); - }); - - it("should forward scrollDown to the native adapter class", async () => { - // GIVEN - const nativeAdapterMock = new NativeAdapter(); - const SUT = new Mouse(nativeAdapterMock); - const scrollAmount = 5; - - // WHEN - const result = await SUT.scrollDown(scrollAmount); - - // THEN - expect(nativeAdapterMock.scrollDown).toBeCalledWith(scrollAmount); - expect(result).toBe(SUT); - }); - - it("should forward scrollUp to the native adapter class", async () => { - // GIVEN - const nativeAdapterMock = new NativeAdapter(); - const SUT = new Mouse(nativeAdapterMock); - const scrollAmount = 5; - - // WHEN - const result = await SUT.scrollUp(scrollAmount); - - // THEN - expect(nativeAdapterMock.scrollUp).toBeCalledWith(scrollAmount); - expect(result).toBe(SUT); - }); - - it("should forward leftClick to the native adapter class", async () => { - // GIVEN - const nativeAdapterMock = new NativeAdapter(); - const SUT = new Mouse(nativeAdapterMock); - - // WHEN - const result = await SUT.leftClick(); - - // THEN - expect(nativeAdapterMock.leftClick).toBeCalled(); - expect(result).toBe(SUT); - }); - - it("should forward rightClick to the native adapter class", async () => { - // GIVEN - const nativeAdapterMock = new NativeAdapter(); - const SUT = new Mouse(nativeAdapterMock); - - // WHEN - const result = await SUT.rightClick(); - - // THEN - expect(nativeAdapterMock.rightClick).toBeCalled(); - expect(result).toBe(SUT); - }); - - it("update mouse position along path on move", async () => { - // GIVEN - const nativeAdapterMock = new NativeAdapter(); - const SUT = new Mouse(nativeAdapterMock); - const path = linehelper.straightLine(new Point(0, 0), new Point(10, 10)); - - // WHEN - const result = await SUT.move(path); - - // THEN - expect(nativeAdapterMock.setMousePosition).toBeCalledTimes(path.length); - expect(result).toBe(SUT); - }); - - it("should press and hold left mouse button, move and release left mouse button on drag", async () => { - // GIVEN - const nativeAdapterMock = new NativeAdapter(); - const SUT = new Mouse(nativeAdapterMock); - const path = linehelper.straightLine(new Point(0, 0), new Point(10, 10)); - - // WHEN - const result = await SUT.drag(path); - - // THEN - expect(nativeAdapterMock.pressButton).toBeCalledWith(Button.LEFT); - expect(nativeAdapterMock.setMousePosition).toBeCalledTimes(path.length); - expect(nativeAdapterMock.releaseButton).toBeCalledWith(Button.LEFT); - expect(result).toBe(SUT); - }); + it("should have a default delay of 500 ms", () => { + // GIVEN + const SUT = new MouseClass(providerRegistryMock); + + // WHEN + + // THEN + expect(SUT.config.autoDelayMs).toEqual(100); + }); + + it("should forward scrollLeft to the provider", async () => { + // GIVEN + const SUT = new MouseClass(providerRegistryMock); + const scrollAmount = 5; + + const scrollMock = jest.fn(); + providerRegistryMock.getMouse = jest.fn(() => mockPartial({ + setMouseDelay: jest.fn(), + scrollLeft: scrollMock + })); + + // WHEN + const result = await SUT.scrollLeft(scrollAmount); + + // THEN + expect(scrollMock).toBeCalledWith(scrollAmount); + expect(result).toBe(SUT); + }); + + it("should forward scrollRight to the provider", async () => { + // GIVEN + const SUT = new MouseClass(providerRegistryMock); + const scrollAmount = 5; + + const scrollMock = jest.fn(); + providerRegistryMock.getMouse = jest.fn(() => mockPartial({ + setMouseDelay: jest.fn(), + scrollRight: scrollMock + })); + + // WHEN + const result = await SUT.scrollRight(scrollAmount); + + // THEN + expect(scrollMock).toBeCalledWith(scrollAmount); + expect(result).toBe(SUT); + }); + + it("should forward scrollDown to the provider", async () => { + // GIVEN + const SUT = new MouseClass(providerRegistryMock); + const scrollAmount = 5; + + const scrollMock = jest.fn(); + providerRegistryMock.getMouse = jest.fn(() => mockPartial({ + setMouseDelay: jest.fn(), + scrollDown: scrollMock + })); + + // WHEN + const result = await SUT.scrollDown(scrollAmount); + + // THEN + expect(scrollMock).toBeCalledWith(scrollAmount); + expect(result).toBe(SUT); + }); + + it("should forward scrollUp to the provider", async () => { + // GIVEN + const SUT = new MouseClass(providerRegistryMock); + const scrollAmount = 5; + + const scrollMock = jest.fn(); + providerRegistryMock.getMouse = jest.fn(() => mockPartial({ + setMouseDelay: jest.fn(), + scrollUp: scrollMock + })); + + // WHEN + const result = await SUT.scrollUp(scrollAmount); + + // THEN + expect(scrollMock).toBeCalledWith(scrollAmount); + expect(result).toBe(SUT); + }); + + it("should forward leftClick to the provider", async () => { + // GIVEN + const SUT = new MouseClass(providerRegistryMock); + + const clickMock = jest.fn(); + providerRegistryMock.getMouse = jest.fn(() => mockPartial({ + setMouseDelay: jest.fn(), + leftClick: clickMock + })); + + // WHEN + const result = await SUT.leftClick(); + + // THEN + expect(clickMock).toBeCalled(); + expect(result).toBe(SUT); + }); + + it("should forward rightClick to the provider", async () => { + // GIVEN + const SUT = new MouseClass(providerRegistryMock); + + const clickMock = jest.fn(); + providerRegistryMock.getMouse = jest.fn(() => mockPartial({ + setMouseDelay: jest.fn(), + rightClick: clickMock + })); + + // WHEN + const result = await SUT.rightClick(); + + // THEN + expect(clickMock).toBeCalled(); + expect(result).toBe(SUT); + }); + + it("update mouse position along path on move", async () => { + // GIVEN + const SUT = new MouseClass(providerRegistryMock); + const path = linehelper.straightLine(new Point(0, 0), new Point(10, 10)); + + const setPositionMock = jest.fn(); + providerRegistryMock.getMouse = jest.fn(() => mockPartial({ + setMouseDelay: jest.fn(), + setMousePosition: setPositionMock + })); + + // WHEN + const result = await SUT.move(path); + + // THEN + expect(setPositionMock).toBeCalledTimes(path.length); + expect(result).toBe(SUT); + }); + + it("should press and hold left mouse button, move and release left mouse button on drag", async () => { + // GIVEN + const SUT = new MouseClass(providerRegistryMock); + const path = linehelper.straightLine(new Point(0, 0), new Point(10, 10)); + + const setPositionMock = jest.fn(); + const pressButtonMock = jest.fn(); + const releaseButtonMock = jest.fn(); + providerRegistryMock.getMouse = jest.fn(() => mockPartial({ + setMouseDelay: jest.fn(), + setMousePosition: setPositionMock, + pressButton: pressButtonMock, + releaseButton: releaseButtonMock + })); + + // WHEN + const result = await SUT.drag(path); + + // THEN + expect(pressButtonMock).toBeCalledWith(Button.LEFT); + expect(setPositionMock).toBeCalledTimes(path.length); + expect(releaseButtonMock).toBeCalledWith(Button.LEFT); + expect(result).toBe(SUT); + }); }); describe("Mousebuttons", () => { - it.each([ - [Button.LEFT, Button.LEFT], - [Button.MIDDLE, Button.MIDDLE], - [Button.RIGHT, Button.RIGHT], - ] as Array<[Button, Button]>)("should be pressed and released", async (input: Button, expected: Button) => { - const nativeAdapterMock = new NativeAdapter(); - const SUT = new Mouse(nativeAdapterMock); - const pressed = await SUT.pressButton(input); - const released = await SUT.releaseButton(input); - expect(nativeAdapterMock.pressButton).toBeCalledWith(expected); - expect(nativeAdapterMock.releaseButton).toBeCalledWith(expected); - expect(pressed).toBe(SUT); - expect(released).toBe(SUT); - }); + it.each([ + [Button.LEFT, Button.LEFT], + [Button.MIDDLE, Button.MIDDLE], + [Button.RIGHT, Button.RIGHT], + ] as Array<[Button, Button]>)("should be pressed and released", async (input: Button, expected: Button) => { + // GIVEN + const SUT = new MouseClass(providerRegistryMock); + const pressButtonMock = jest.fn(); + const releaseButtonMock = jest.fn(); + providerRegistryMock.getMouse = jest.fn(() => mockPartial({ + setMouseDelay: jest.fn(), + pressButton: pressButtonMock, + releaseButton: releaseButtonMock + })); + + // WHEN + const pressed = await SUT.pressButton(input); + const released = await SUT.releaseButton(input); + + // THEN + expect(pressButtonMock).toBeCalledWith(expected); + expect(releaseButtonMock).toBeCalledWith(expected); + expect(pressed).toBe(SUT); + expect(released).toBe(SUT); + }); }); diff --git a/lib/mouse.class.ts b/lib/mouse.class.ts index f03e62cf..39c902ba 100644 --- a/lib/mouse.class.ts +++ b/lib/mouse.class.ts @@ -1,221 +1,221 @@ -import { NativeAdapter } from "./adapter/native.adapter.class"; -import { Button } from "./button.enum"; -import { linear } from "./movementtype.function"; -import { Point } from "./point.class"; -import { busyWaitForNanoSeconds, sleep } from "./sleep.function"; +import {Button} from "./button.enum"; +import {Point} from "./point.class"; +import {busyWaitForNanoSeconds, sleep} from "./sleep.function"; +import {calculateMovementTimesteps, EasingFunction, linear} from "./mouse-movement.function"; +import {ProviderRegistry} from "./provider/provider-registry.class"; /** - * {@link Mouse} class provides methods to emulate mouse input + * {@link MouseClass} class provides methods to emulate mouse input */ -export class Mouse { - /** - * Config object for {@link Mouse} class - */ - public config = { +export class MouseClass { /** - * Configures the delay between single mouse events + * Config object for {@link MouseClass} class */ - autoDelayMs: 100, + public config = { + /** + * Configures the delay between single mouse events + */ + autoDelayMs: 100, + + /** + * Configures the speed in pixels/second for mouse movement + */ + mouseSpeed: 1000, + }; /** - * Configures the speed in pixels/second for mouse movement + * {@link MouseClass} class constructor + * @param providerRegistry */ - mouseSpeed: 1000, - }; - - /** - * {@link Mouse} class constructor - * @param native {@link NativeAdapter} instance which bundles access to mouse, keyboard and clipboard - */ - constructor(private native: NativeAdapter) { - this.native.setMouseDelay(0); - } + constructor(private providerRegistry: ProviderRegistry) { + this.providerRegistry.getMouse().setMouseDelay(0); + } - /** - * {@link setPosition} instantly moves the mouse cursor to a given {@link Point} - * @param target {@link Point} to move the cursor to - */ - public async setPosition(target: Point): Promise { - return new Promise(async (resolve, reject) => { - try { - await this.native.setMousePosition(target); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link setPosition} instantly moves the mouse cursor to a given {@link Point} + * @param target {@link Point} to move the cursor to + */ + public async setPosition(target: Point): Promise { + return new Promise(async (resolve, reject) => { + try { + await this.providerRegistry.getMouse().setMousePosition(target); + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link getPosition} returns a {@link Point} representing the current mouse position - */ - public getPosition(): Promise { - return this.native.currentMousePosition(); - } + /** + * {@link getPosition} returns a {@link Point} representing the current mouse position + */ + public getPosition(): Promise { + return this.providerRegistry.getMouse().currentMousePosition(); + } - /** - * {@link move} moves the mouse cursor along a given path of {@link Point}s, according to a movement type - * @param path Array of {@link Point}s to follow - * @param movementType Defines the type of mouse movement. Would allow to configured acceleration etc. (Default: {@link linear}, no acceleration) - */ - public async move(path: Point[] | Promise, movementType = linear): Promise { - return new Promise(async (resolve, reject) => { - try { - const pathSteps = await path; - const timeSteps = movementType(pathSteps.length, this.config.mouseSpeed); - for (let idx = 0; idx < pathSteps.length; ++idx) { - const node = pathSteps[idx]; - const minTime = timeSteps[idx]; - await busyWaitForNanoSeconds(minTime); - await this.native.setMousePosition(node); - } - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link move} moves the mouse cursor along a given path of {@link Point}s, according to a movement type + * @param path Array of {@link Point}s to follow + * @param movementType Defines the type of mouse movement. Would allow to configured acceleration etc. (Default: {@link linear}, no acceleration) + */ + public async move(path: Point[] | Promise, movementType: EasingFunction = linear): Promise { + return new Promise(async (resolve, reject) => { + try { + const pathSteps = await path; + const timeSteps = calculateMovementTimesteps(pathSteps.length, this.config.mouseSpeed, movementType); + for (let idx = 0; idx < pathSteps.length; ++idx) { + const node = pathSteps[idx]; + const minTime = timeSteps[idx]; + await busyWaitForNanoSeconds(minTime); + await this.providerRegistry.getMouse().setMousePosition(node); + } + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link leftClick} performs a click with the left mouse button - */ - public async leftClick(): Promise { - return new Promise(async resolve => { - await sleep(this.config.autoDelayMs); - await this.native.leftClick(); - resolve(this); - }); - } + /** + * {@link leftClick} performs a click with the left mouse button + */ + public async leftClick(): Promise { + return new Promise(async resolve => { + await sleep(this.config.autoDelayMs); + await this.providerRegistry.getMouse().leftClick(); + resolve(this); + }); + } - /** - * {@link rightClick} performs a click with the right mouse button - */ - public async rightClick(): Promise { - return new Promise(async (resolve, reject) => { - try { - await sleep(this.config.autoDelayMs); - await this.native.rightClick(); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link rightClick} performs a click with the right mouse button + */ + public async rightClick(): Promise { + return new Promise(async (resolve, reject) => { + try { + await sleep(this.config.autoDelayMs); + await this.providerRegistry.getMouse().rightClick(); + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link scrollDown} scrolls down for a given amount of "steps" - * Please note that the actual scroll distance of a single "step" is OS dependent - * @param amount The amount of "steps" to scroll - */ - public async scrollDown(amount: number): Promise { - return new Promise(async (resolve, reject) => { - try { - await sleep(this.config.autoDelayMs); - await this.native.scrollDown(amount); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link scrollDown} scrolls down for a given amount of "steps" + * Please note that the actual scroll distance of a single "step" is OS dependent + * @param amount The amount of "steps" to scroll + */ + public async scrollDown(amount: number): Promise { + return new Promise(async (resolve, reject) => { + try { + await sleep(this.config.autoDelayMs); + await this.providerRegistry.getMouse().scrollDown(amount); + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link scrollUp} scrolls up for a given amount of "steps" - * Please note that the actual scroll distance of a single "step" is OS dependent - * @param amount The amount of "steps" to scroll - */ - public async scrollUp(amount: number): Promise { - return new Promise(async (resolve, reject) => { - try { - await sleep(this.config.autoDelayMs); - await this.native.scrollUp(amount); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link scrollUp} scrolls up for a given amount of "steps" + * Please note that the actual scroll distance of a single "step" is OS dependent + * @param amount The amount of "steps" to scroll + */ + public async scrollUp(amount: number): Promise { + return new Promise(async (resolve, reject) => { + try { + await sleep(this.config.autoDelayMs); + await this.providerRegistry.getMouse().scrollUp(amount); + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link scrollLeft} scrolls left for a given amount of "steps" - * Please note that the actual scroll distance of a single "step" is OS dependent - * @param amount The amount of "steps" to scroll - */ - public async scrollLeft(amount: number): Promise { - return new Promise(async (resolve, reject) => { - try { - await sleep(this.config.autoDelayMs); - await this.native.scrollLeft(amount); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link scrollLeft} scrolls left for a given amount of "steps" + * Please note that the actual scroll distance of a single "step" is OS dependent + * @param amount The amount of "steps" to scroll + */ + public async scrollLeft(amount: number): Promise { + return new Promise(async (resolve, reject) => { + try { + await sleep(this.config.autoDelayMs); + await this.providerRegistry.getMouse().scrollLeft(amount); + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link scrollRight} scrolls right for a given amount of "steps" - * Please note that the actual scroll distance of a single "step" is OS dependent - * @param amount The amount of "steps" to scroll - */ - public async scrollRight(amount: number): Promise { - return new Promise(async (resolve, reject) => { - try { - await sleep(this.config.autoDelayMs); - await this.native.scrollRight(amount); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link scrollRight} scrolls right for a given amount of "steps" + * Please note that the actual scroll distance of a single "step" is OS dependent + * @param amount The amount of "steps" to scroll + */ + public async scrollRight(amount: number): Promise { + return new Promise(async (resolve, reject) => { + try { + await sleep(this.config.autoDelayMs); + await this.providerRegistry.getMouse().scrollRight(amount); + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link drag} drags the mouse along a certain path - * In summary, {@link drag} presses and holds the left mouse button, moves the mouse and releases the left button - * @param path The path of {@link Point}s to drag along - */ - public async drag(path: Point[] | Promise): Promise { - return new Promise(async (resolve, reject) => { - try { - await sleep(this.config.autoDelayMs); - await this.native.pressButton(Button.LEFT); - await this.move(path); - await this.native.releaseButton(Button.LEFT); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link drag} drags the mouse along a certain path + * In summary, {@link drag} presses and holds the left mouse button, moves the mouse and releases the left button + * @param path The path of {@link Point}s to drag along + */ + public async drag(path: Point[] | Promise): Promise { + return new Promise(async (resolve, reject) => { + try { + await sleep(this.config.autoDelayMs); + await this.providerRegistry.getMouse().pressButton(Button.LEFT); + await this.move(path); + await this.providerRegistry.getMouse().releaseButton(Button.LEFT); + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link pressButton} presses and holds a mouse button - * @param btn The {@link Button} to press and hold - */ - public async pressButton(btn: Button): Promise { - return new Promise(async (resolve, reject) => { - try { - await this.native.pressButton(btn); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link pressButton} presses and holds a mouse button + * @param btn The {@link Button} to press and hold + */ + public async pressButton(btn: Button): Promise { + return new Promise(async (resolve, reject) => { + try { + await this.providerRegistry.getMouse().pressButton(btn); + resolve(this); + } catch (e) { + reject(e); + } + }); + } - /** - * {@link releaseButton} releases a mouse button previously pressed via {@link pressButton} - * @param btn The {@link Button} to release - */ - public async releaseButton(btn: Button): Promise { - return new Promise(async (resolve, reject) => { - try { - await this.native.releaseButton(btn); - resolve(this); - } catch (e) { - reject(e); - } - }); - } + /** + * {@link releaseButton} releases a mouse button previously pressed via {@link pressButton} + * @param btn The {@link Button} to release + */ + public async releaseButton(btn: Button): Promise { + return new Promise(async (resolve, reject) => { + try { + await this.providerRegistry.getMouse().releaseButton(btn); + resolve(this); + } catch (e) { + reject(e); + } + }); + } } diff --git a/lib/movement.function.ts b/lib/movement.function.ts index 5c3feb1d..be8b2adf 100644 --- a/lib/movement.function.ts +++ b/lib/movement.function.ts @@ -1,30 +1,30 @@ -import { NativeAdapter } from "./adapter/native.adapter.class"; -import { MovementApi } from "./movement-api.interface"; -import { Point } from "./point.class"; -import { LineHelper } from "./util/linehelper.class"; +import {MovementApi} from "./movement-api.interface"; +import {Point} from "./point.class"; +import {LineHelper} from "./util/linehelper.class"; +import {ProviderRegistry} from "./provider/provider-registry.class"; -export const createMovementApi = (native: NativeAdapter, lineHelper: LineHelper): MovementApi => { - return ({ - down: async (px: number): Promise => { - const pos = await native.currentMousePosition(); - return lineHelper.straightLine(pos, new Point(pos.x, pos.y + px)); - }, - left: async (px: number): Promise => { - const pos = await native.currentMousePosition(); - return lineHelper.straightLine(pos, new Point(pos.x - px, pos.y)); - }, - right: async (px: number): Promise => { - const pos = await native.currentMousePosition(); - return lineHelper.straightLine(pos, new Point(pos.x + px, pos.y)); - }, - straightTo: async (target: Point | Promise): Promise => { - const targetPoint = await target; - const origin = await native.currentMousePosition(); - return lineHelper.straightLine(origin, targetPoint); - }, - up: async (px: number): Promise => { - const pos = await native.currentMousePosition(); - return lineHelper.straightLine(pos, new Point(pos.x, pos.y - px)); - }, - }); +export const createMovementApi = (providerRegistry: ProviderRegistry, lineHelper: LineHelper): MovementApi => { + return ({ + down: async (px: number): Promise => { + const pos = await providerRegistry.getMouse().currentMousePosition(); + return lineHelper.straightLine(pos, new Point(pos.x, pos.y + px)); + }, + left: async (px: number): Promise => { + const pos = await providerRegistry.getMouse().currentMousePosition(); + return lineHelper.straightLine(pos, new Point(pos.x - px, pos.y)); + }, + right: async (px: number): Promise => { + const pos = await providerRegistry.getMouse().currentMousePosition(); + return lineHelper.straightLine(pos, new Point(pos.x + px, pos.y)); + }, + straightTo: async (target: Point | Promise): Promise => { + const targetPoint = await target; + const origin = await providerRegistry.getMouse().currentMousePosition(); + return lineHelper.straightLine(origin, targetPoint); + }, + up: async (px: number): Promise => { + const pos = await providerRegistry.getMouse().currentMousePosition(); + return lineHelper.straightLine(pos, new Point(pos.x, pos.y - px)); + }, + }); }; diff --git a/lib/movementtype.function.spec.ts b/lib/movementtype.function.spec.ts deleted file mode 100644 index cf1220e1..00000000 --- a/lib/movementtype.function.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { linear } from "./movementtype.function"; - -describe("MovementType", () => { - it("should return a set of linear timesteps, 1000000 nanosecond per step.", () => { - const expected = [1000000, 1000000, 1000000, 1000000, 1000000, 1000000]; - expect(linear(6, 1000)).toEqual(expected); - }); - - it("should should return a set of linear timesteps, 2000000 nanoseconds per step.", () => { - const expected = [2000000, 2000000, 2000000, 2000000, 2000000, 2000000]; - expect(linear(6, 500)).toEqual(expected); - }); -}); diff --git a/lib/movementtype.function.ts b/lib/movementtype.function.ts deleted file mode 100644 index dd99acb6..00000000 --- a/lib/movementtype.function.ts +++ /dev/null @@ -1,15 +0,0 @@ -export const linear = ( - amountOfSteps: number, - speedInPixelsPerSecond: number, -): number[] => { - const timeSteps = []; - // Duration per movement step in nanoseconds - let stepDuration = (1 / speedInPixelsPerSecond) * 1_000_000_000; - if (stepDuration <= 0) { - stepDuration = 0; - } - for (let idx = 0; idx < amountOfSteps; ++idx) { - timeSteps.push(stepDuration); - } - return timeSteps; -}; diff --git a/lib/provider/native/clipboard-action-provider.interface.ts b/lib/provider/clipboard-provider.interface.ts similarity index 94% rename from lib/provider/native/clipboard-action-provider.interface.ts rename to lib/provider/clipboard-provider.interface.ts index f451b669..17c6637a 100644 --- a/lib/provider/native/clipboard-action-provider.interface.ts +++ b/lib/provider/clipboard-provider.interface.ts @@ -1,7 +1,7 @@ /** * A ClipboardActionProvider should allow access to the system clipboard */ -export interface ClipboardActionProvider { +export interface ClipboardProviderInterface { /** * hasText should return whether the system clipboard currently holds text or not * diff --git a/lib/provider/data-sink.interface.ts b/lib/provider/data-sink.interface.ts new file mode 100644 index 00000000..47a0d0e8 --- /dev/null +++ b/lib/provider/data-sink.interface.ts @@ -0,0 +1,12 @@ +/** + * A DataSink should provide methods to store data + * + * @interface DataSinkInterface + */ +export interface DataSinkInterface { + /** + * store will store data to disk + * @param parameters Required parameters + */ + store(parameters: PARAMETER_TYPE): Promise; +} diff --git a/lib/provider/data-source.interface.ts b/lib/provider/data-source.interface.ts new file mode 100644 index 00000000..e2d57f7b --- /dev/null +++ b/lib/provider/data-source.interface.ts @@ -0,0 +1,12 @@ +/** + * A DataSource should provide methods to load data + * + * @interface DataSourceInterface + */ +export interface DataSourceInterface { + /** + * load will load data from disk + * @param parameters Required parameters + */ + load(parameters: PARAMETER_TYPE): Promise; +} diff --git a/lib/provider/image-finder.interface.ts b/lib/provider/image-finder.interface.ts new file mode 100644 index 00000000..07bb496b --- /dev/null +++ b/lib/provider/image-finder.interface.ts @@ -0,0 +1,29 @@ +import { MatchRequest } from "../match-request.class"; +import { MatchResult } from "../match-result.class"; + +/** + * An ImageFinder should provide an abstraction layer to perform image matching + * + * @interface ImageFinderInterface + */ +export interface ImageFinderInterface { + /** + * findMatch should provide an abstraction to search for an image needle + * in another image haystack + * + * @param {MatchRequest} matchRequest A {@link MatchRequest} containing needed matching data + * @returns {Promise} A {@link MatchResult} holding the match probability and location + * @memberof ImageFinderInterface + */ + findMatch(matchRequest: MatchRequest): Promise; + + /** + * findMatches should provide an abstraction to search for an image needle + * in another image haystack + * + * @param {MatchRequest} matchRequest A matchrequest containing needed matching data + * @returns {Promise} A list of {@link MatchResult}s holding the match probability and location + * @memberof ImageFinderInterface + */ + findMatches(matchRequest: MatchRequest): Promise; +} diff --git a/lib/provider/image-processor.interface.ts b/lib/provider/image-processor.interface.ts new file mode 100644 index 00000000..1eca6ffb --- /dev/null +++ b/lib/provider/image-processor.interface.ts @@ -0,0 +1,19 @@ +import {Point} from "../point.class"; +import {RGBA} from "../rgba.class"; +import {Image} from "../image.class"; + +/** + * An ImageProcessor should provide an abstraction layer to perform + * image processing via a 3rd part library + * + * @interface ImageFinderInterface + */ +export interface ImageProcessor { + + /** + * {@link colorAt} returns a pixels {@link RGBA} value + * @param image The {@link Image} to query color information from + * @param location The {@link Point} where to query color information + */ + colorAt(image: Image | Promise, location: Point | Promise): Promise; +} \ No newline at end of file diff --git a/lib/provider/image-reader.type.ts b/lib/provider/image-reader.type.ts new file mode 100644 index 00000000..04b8c4f1 --- /dev/null +++ b/lib/provider/image-reader.type.ts @@ -0,0 +1,4 @@ +import {DataSourceInterface} from "./data-source.interface"; +import {Image} from "../image.class"; + +export type ImageReader = DataSourceInterface; diff --git a/lib/provider/image-writer.type.ts b/lib/provider/image-writer.type.ts new file mode 100644 index 00000000..0d063fee --- /dev/null +++ b/lib/provider/image-writer.type.ts @@ -0,0 +1,9 @@ +import {Image} from "../image.class"; +import {DataSinkInterface} from "./data-sink.interface"; + +export interface ImageWriterParameters { + image: Image, + path: string +} + +export type ImageWriter = DataSinkInterface; diff --git a/lib/provider/image/jimp-image-processor.class.ts b/lib/provider/image/jimp-image-processor.class.ts new file mode 100644 index 00000000..832f71fe --- /dev/null +++ b/lib/provider/image/jimp-image-processor.class.ts @@ -0,0 +1,24 @@ +import Jimp from 'jimp'; +import {Image} from "../../image.class"; +import {Point} from "../../point.class"; +import {ImageProcessor} from "../image-processor.interface"; +import {imageToJimp} from "../io/imageToJimp.function"; +import {RGBA} from "../../rgba.class"; + +export default class implements ImageProcessor { + colorAt(image: Image | Promise, point: Point | Promise): Promise { + return new Promise(async (resolve, reject) => { + const location = await point; + const img = await image; + if (location.x < 0 || location.x >= img.width) { + reject(`Query location out of bounds. Should be in range 0 <= x < image.width, is ${location.x}`); + } + if (location.y < 0 || location.y >= img.height) { + reject(`Query location out of bounds. Should be in range 0 <= y < image.height, is ${location.y}`); + } + const jimpImage = imageToJimp(img); + const rgba = Jimp.intToRGBA(jimpImage.getPixelColor(location.x, location.y)); + resolve(new RGBA(rgba.r, rgba.g, rgba.b, rgba.a)); + }); + } +} diff --git a/lib/provider/index.ts b/lib/provider/index.ts new file mode 100644 index 00000000..f20d3799 --- /dev/null +++ b/lib/provider/index.ts @@ -0,0 +1,10 @@ +export {ClipboardProviderInterface} from "./clipboard-provider.interface"; +export {DataSinkInterface} from "./data-sink.interface"; +export {DataSourceInterface} from "./data-source.interface"; +export {ImageFinderInterface} from "./image-finder.interface"; +export {ImageReader} from "./image-reader.type"; +export {ImageWriter, ImageWriterParameters} from "./image-writer.type"; +export {KeyboardProviderInterface} from "./keyboard-provider.interface"; +export {MouseProviderInterface} from "./mouse-provider.interface"; +export {ScreenProviderInterface} from "./screen-provider.interface"; +export {WindowProviderInterface} from "./window-provider.interface"; \ No newline at end of file diff --git a/lib/provider/io/__mocks__/calculator.png b/lib/provider/io/__mocks__/calculator.png new file mode 100644 index 00000000..8f6cf3cb Binary files /dev/null and b/lib/provider/io/__mocks__/calculator.png differ diff --git a/lib/provider/io/imageToJimp.function.spec.ts b/lib/provider/io/imageToJimp.function.spec.ts new file mode 100644 index 00000000..30c527c1 --- /dev/null +++ b/lib/provider/io/imageToJimp.function.spec.ts @@ -0,0 +1,38 @@ +import {Image} from "../../image.class"; +import {imageToJimp} from "./imageToJimp.function"; +import Jimp from "jimp"; + +jest.mock('jimp', () => { + class JimpMock { + bitmap = { + width: 100, + height: 100, + data: Buffer.from([]), + } + hasAlpha = () => false + static read = jest.fn(() => Promise.resolve(new JimpMock())) + } + + return ({ + __esModule: true, + default: JimpMock + }) +}); + +afterEach(() => jest.resetAllMocks()); + +describe('imageToJimp', () => { + it('should successfully convert an Image to a Jimp instance', async () => { + // GIVEN + const scanMock = jest.fn(); + Jimp.prototype.scan = scanMock; + const inputImage = new Image(1, 1, Buffer.from([0, 0, 0]),3, "input_image"); + + // WHEN + const result = await imageToJimp(inputImage); + + // THEN + expect(result).toBeInstanceOf(Jimp); + expect(scanMock).toHaveBeenCalledTimes(1); + }); +}); \ No newline at end of file diff --git a/lib/provider/io/imageToJimp.function.ts b/lib/provider/io/imageToJimp.function.ts new file mode 100644 index 00000000..b91cdff4 --- /dev/null +++ b/lib/provider/io/imageToJimp.function.ts @@ -0,0 +1,20 @@ +import Jimp from "jimp"; +import {Image} from "../../image.class"; +import {ColorMode} from "../../colormode.enum"; + +export function imageToJimp(image: Image): Jimp { + const jimpImage = new Jimp({ + data: image.data, + width: image.width, + height: image.height + }); + if (image.colorMode === ColorMode.BGR) { + // Image treats data in BGR format, so we have to switch red and blue color channels + jimpImage.scan(0, 0, jimpImage.bitmap.width, jimpImage.bitmap.height, function (_, __, idx) { + const red = this.bitmap.data[idx]; + this.bitmap.data[idx] = this.bitmap.data[idx + 2]; + this.bitmap.data[idx + 2] = red; + }); + } + return jimpImage; +} \ No newline at end of file diff --git a/lib/provider/io/jimp-image-reader.class.spec.ts b/lib/provider/io/jimp-image-reader.class.spec.ts new file mode 100644 index 00000000..837b6d5c --- /dev/null +++ b/lib/provider/io/jimp-image-reader.class.spec.ts @@ -0,0 +1,58 @@ +import ImageReader from "./jimp-image-reader.class"; +import {join} from "path"; +import Jimp from "jimp"; + +jest.mock('jimp', () => { + class JimpMock { + bitmap = { + width: 100, + height: 100, + data: Buffer.from([]), + } + hasAlpha = () => false + static read = jest.fn(() => Promise.resolve(new JimpMock())) + } + + return ({ + __esModule: true, + default: JimpMock + }) +}); + +afterEach(() => jest.resetAllMocks()); + +describe('Jimp image reader', () => { + it('should return an Image object', async () => { + // GIVEN + const inputPath = join(__dirname, "__mocks__", "calculator.png"); + const scanMock = jest.fn(); + Jimp.prototype.scan = scanMock; + const SUT = new ImageReader(); + + // WHEN + await SUT.load(inputPath); + + // THEN + expect(scanMock).toHaveBeenCalledTimes(1); + expect(Jimp.read).toBeCalledTimes(1); + expect(Jimp.read).toBeCalledWith(inputPath); + }); + + it('should reject on loading failures', async () => { + // GIVEN + const inputPath = "/some/path/to/file"; + const expectedError = "Error during load"; + const SUT = new ImageReader(); + Jimp.read = jest.fn(() => { + throw new Error(expectedError); + }) + + // WHEN + try { + await SUT.load(inputPath); + } catch (err) { + // THEN + expect(err).toStrictEqual(Error(expectedError)); + } + }); +}); \ No newline at end of file diff --git a/lib/provider/io/jimp-image-reader.class.ts b/lib/provider/io/jimp-image-reader.class.ts new file mode 100644 index 00000000..f33089be --- /dev/null +++ b/lib/provider/io/jimp-image-reader.class.ts @@ -0,0 +1,28 @@ +import Jimp from 'jimp'; +import {ImageReader} from "../image-reader.type"; +import {Image} from "../../image.class"; +import {ColorMode} from "../../colormode.enum"; + +export default class implements ImageReader { + load(parameters: string): Promise { + return new Promise((resolve, reject) => { + Jimp.read(parameters) + .then(jimpImage => { + // stay consistent with images retrieved from libnut which uses BGR format + jimpImage.scan(0, 0, jimpImage.bitmap.width, jimpImage.bitmap.height, function (_, __, idx) { + const red = this.bitmap.data[idx]; + this.bitmap.data[idx] = this.bitmap.data[idx + 2]; + this.bitmap.data[idx + 2] = red; + }); + resolve(new Image( + jimpImage.bitmap.width, + jimpImage.bitmap.height, + jimpImage.bitmap.data, + jimpImage.hasAlpha() ? 4 : 3, + parameters, + ColorMode.BGR + )); + }).catch(err => reject(`Failed to load image from '${parameters}'. Reason: ${err}`)); + }) + } +} diff --git a/lib/provider/io/jimp-image-writer.class.spec.ts b/lib/provider/io/jimp-image-writer.class.spec.ts new file mode 100644 index 00000000..480cae06 --- /dev/null +++ b/lib/provider/io/jimp-image-writer.class.spec.ts @@ -0,0 +1,43 @@ +import ImageWriter from "./jimp-image-writer.class"; +import {Image} from "../../image.class"; +import Jimp from "jimp"; + +jest.mock('jimp', () => { + class JimpMock { + bitmap = { + width: 100, + height: 100, + data: Buffer.from([]), + } + hasAlpha = () => false + static read = jest.fn(() => Promise.resolve(new JimpMock())) + } + + return ({ + __esModule: true, + default: JimpMock + }) +}); + +afterEach(() => jest.resetAllMocks()); + +describe('Jimp image writer', () => { + it('should reject on writing failures', async () => { + // GIVEN + const outputFileName = "/does/not/compute.png" + const outputFile = new Image(100, 200, Buffer.from([]), 3, outputFileName); + const writeMock = jest.fn(() => Promise.resolve(new Jimp())); + const scanMock = jest.fn(); + Jimp.prototype.scan = scanMock; + Jimp.prototype.writeAsync = writeMock; + const SUT = new ImageWriter(); + + // WHEN + await SUT.store({image: outputFile, path: outputFileName}); + + // THEN + expect(scanMock).toHaveBeenCalledTimes(1) + expect(writeMock).toHaveBeenCalledTimes(1) + expect(writeMock).toHaveBeenCalledWith(outputFileName) + }); +}); \ No newline at end of file diff --git a/lib/provider/io/jimp-image-writer.class.ts b/lib/provider/io/jimp-image-writer.class.ts new file mode 100644 index 00000000..664b7794 --- /dev/null +++ b/lib/provider/io/jimp-image-writer.class.ts @@ -0,0 +1,14 @@ +import {ImageWriter, ImageWriterParameters} from "../image-writer.type"; +import {imageToJimp} from "./imageToJimp.function"; + +export default class implements ImageWriter { + store(parameters: ImageWriterParameters): Promise { + return new Promise((resolve, reject) => { + const jimpImage = imageToJimp(parameters.image); + jimpImage + .writeAsync(parameters.path) + .then(_ => resolve()) + .catch(err => reject(err)); + }); + } +} diff --git a/lib/provider/native/keyboard-action-provider.interface.ts b/lib/provider/keyboard-provider.interface.ts similarity index 92% rename from lib/provider/native/keyboard-action-provider.interface.ts rename to lib/provider/keyboard-provider.interface.ts index 6cedae6f..ea4305b9 100644 --- a/lib/provider/native/keyboard-action-provider.interface.ts +++ b/lib/provider/keyboard-provider.interface.ts @@ -1,9 +1,9 @@ -import { Key } from "../../key.enum"; +import { Key } from "../key.enum"; /** * A KeyboardActionProvider should provide access to a systems keyboard */ -export interface KeyboardActionProvider { +export interface KeyboardProviderInterface { /** * setKeyboardDelay should allow to configure a delay between key presses * diff --git a/lib/provider/native/mouse-action-provider.interface.ts b/lib/provider/mouse-provider.interface.ts similarity index 93% rename from lib/provider/native/mouse-action-provider.interface.ts rename to lib/provider/mouse-provider.interface.ts index 7240dbce..bc58d6dd 100644 --- a/lib/provider/native/mouse-action-provider.interface.ts +++ b/lib/provider/mouse-provider.interface.ts @@ -1,10 +1,10 @@ -import { Button } from "../../button.enum"; -import { Point } from "../../point.class"; +import { Button } from "../button.enum"; +import { Point } from "../point.class"; /** * A MouseActionProvider should provide access to a systems mouse input */ -export interface MouseActionProvider { +export interface MouseProviderInterface { /** * setMouseDelay should allow to configure mouse movement speed * diff --git a/lib/provider/native/clipboardy-clipboard-action.class.spec.ts b/lib/provider/native/clipboardy-clipboard.class.spec.ts similarity index 71% rename from lib/provider/native/clipboardy-clipboard-action.class.spec.ts rename to lib/provider/native/clipboardy-clipboard.class.spec.ts index ff368d51..9e96a795 100644 --- a/lib/provider/native/clipboardy-clipboard-action.class.spec.ts +++ b/lib/provider/native/clipboardy-clipboard.class.spec.ts @@ -1,4 +1,6 @@ -import ClipboardAction from "./clipboardy-clipboard-action.class"; +import ClipboardAction from "./clipboardy-clipboard.class"; + +jest.mock('jimp', () => {}); beforeEach(() => { jest.resetAllMocks(); @@ -6,7 +8,7 @@ beforeEach(() => { describe("clipboardy action", () => { describe("copy", () => { - it("should resolve", async done => { + it("should resolve", async () => { // GIVEN const SUT = new ClipboardAction(); const testText = "test"; @@ -15,11 +17,10 @@ describe("clipboardy action", () => { // THEN await SUT.copy(testText); - done(); }); }); describe("hasText", () => { - it("should return true when text has been copied", async done => { + it("should return true when text has been copied", async () => { // GIVEN const SUT = new ClipboardAction(); const testText = "test"; @@ -29,7 +30,6 @@ describe("clipboardy action", () => { // THEN await expect(SUT.hasText()).resolves.toBeTruthy(); - done(); }); }); }); diff --git a/lib/provider/native/clipboardy-clipboard-action.class.ts b/lib/provider/native/clipboardy-clipboard.class.ts similarity index 83% rename from lib/provider/native/clipboardy-clipboard-action.class.ts rename to lib/provider/native/clipboardy-clipboard.class.ts index 03ee2f18..a8ab2747 100644 --- a/lib/provider/native/clipboardy-clipboard-action.class.ts +++ b/lib/provider/native/clipboardy-clipboard.class.ts @@ -1,7 +1,7 @@ import clippy from "clipboardy"; -import { ClipboardActionProvider } from "./clipboard-action-provider.interface"; +import { ClipboardProviderInterface } from "../clipboard-provider.interface"; -export default class implements ClipboardActionProvider { +export default class implements ClipboardProviderInterface { constructor() { } diff --git a/lib/provider/native/libnut-keyboard-action.class.ts b/lib/provider/native/libnut-keyboard-action.class.ts deleted file mode 100644 index a71cef5f..00000000 --- a/lib/provider/native/libnut-keyboard-action.class.ts +++ /dev/null @@ -1,207 +0,0 @@ -import libnut = require("@nut-tree/libnut"); -import { Key } from "../../key.enum"; -import { KeyboardActionProvider } from "./keyboard-action-provider.interface"; - -export default class KeyboardAction implements KeyboardActionProvider { - - public static KeyLookupMap = new Map([ - [Key.A, "a"], - [Key.B, "b"], - [Key.C, "c"], - [Key.D, "d"], - [Key.E, "e"], - [Key.F, "f"], - [Key.G, "g"], - [Key.H, "h"], - [Key.I, "i"], - [Key.J, "j"], - [Key.K, "k"], - [Key.L, "l"], - [Key.M, "m"], - [Key.N, "n"], - [Key.O, "o"], - [Key.P, "p"], - [Key.Q, "q"], - [Key.R, "r"], - [Key.S, "s"], - [Key.T, "t"], - [Key.U, "u"], - [Key.V, "v"], - [Key.W, "w"], - [Key.X, "x"], - [Key.Y, "y"], - [Key.Z, "z"], - - [Key.F1, "f1"], - [Key.F2, "f2"], - [Key.F3, "f3"], - [Key.F4, "f4"], - [Key.F5, "f5"], - [Key.F6, "f6"], - [Key.F7, "f7"], - [Key.F8, "f8"], - [Key.F9, "f9"], - [Key.F10, "f10"], - [Key.F11, "f11"], - [Key.F12, "f12"], - - [Key.Num0, "0"], - [Key.Num1, "1"], - [Key.Num2, "2"], - [Key.Num3, "3"], - [Key.Num4, "4"], - [Key.Num5, "5"], - [Key.Num6, "6"], - [Key.Num7, "7"], - [Key.Num8, "8"], - [Key.Num9, "9"], - [Key.NumPad0, "numpad_0"], - [Key.NumPad1, "numpad_1"], - [Key.NumPad2, "numpad_2"], - [Key.NumPad3, "numpad_3"], - [Key.NumPad4, "numpad_4"], - [Key.NumPad5, "numpad_5"], - [Key.NumPad6, "numpad_6"], - [Key.NumPad7, "numpad_7"], - [Key.NumPad8, "numpad_8"], - [Key.NumPad9, "numpad_9"], - - [Key.Space, "space"], - [Key.Escape, "escape"], - [Key.Tab, "tab"], - [Key.LeftAlt, "alt"], - [Key.LeftControl, "control"], - [Key.RightAlt, "alt"], - [Key.RightControl, "control"], - - [Key.LeftShift, "shift"], - [Key.LeftSuper, "command"], - [Key.RightShift, "space"], - [Key.RightSuper, "command"], - - [Key.Grave, "~"], - [Key.Minus, "-"], - [Key.Equal, "="], - [Key.Backspace, "backspace"], - [Key.LeftBracket, "["], - [Key.RightBracket, "]"], - [Key.Backslash, "\\"], - [Key.Semicolon, ";"], - [Key.Quote, "'"], - [Key.Return, "enter"], - [Key.Comma, ","], - [Key.Period, "."], - [Key.Slash, "/"], - - [Key.Left, "left"], - [Key.Up, "up"], - [Key.Right, "right"], - [Key.Down, "down"], - - [Key.Print, "printscreen"], - [Key.Pause, null], - [Key.Insert, "insert"], - [Key.Delete, null], - [Key.Home, "home"], - [Key.End, "end"], - [Key.PageUp, "pageup"], - [Key.PageDown, "pagedown"], - - [Key.Add, null], - [Key.Subtract, null], - [Key.Multiply, null], - [Key.Divide, null], - [Key.Decimal, null], - [Key.Enter, "enter"], - - [Key.CapsLock, null], - [Key.ScrollLock, null], - [Key.NumLock, null], - ]); - - public static keyLookup(key: Key): any { - return this.KeyLookupMap.get(key); - } - - private static mapModifierKeys(...keys: Key[]): string[] { - return keys - .map(modifier => KeyboardAction.keyLookup(modifier)) - .filter(modifierKey => modifierKey != null && modifierKey.length > 1); - } - - private static key(key: Key, event: "up" | "down", ...modifiers: Key[]): Promise { - return new Promise((resolve, reject) => { - try { - const nativeKey = KeyboardAction.keyLookup(key); - const modifierKeys = this.mapModifierKeys(...modifiers); - if (nativeKey) { - libnut.keyToggle(nativeKey, event, modifierKeys); - } - resolve(); - } catch (e) { - reject(e); - } - }); - } - - constructor() { - } - - public type(input: string): Promise { - return new Promise((resolve, reject) => { - try { - libnut.typeString(input); - resolve(); - } catch (e) { - reject(e); - } - }); - } - - public click(...keys: Key[]): Promise { - return new Promise((resolve, reject) => { - try { - keys.reverse(); - const [key, ...modifiers] = keys; - const nativeKey = KeyboardAction.keyLookup(key); - const modifierKeys = KeyboardAction.mapModifierKeys(...modifiers); - if (nativeKey) { - libnut.keyTap(nativeKey, modifierKeys); - } - resolve(); - } catch (e) { - reject(e); - } - }); - } - - public pressKey(...keys: Key[]): Promise { - return new Promise(async (resolve, reject) => { - try { - keys.reverse(); - const [key, ...modifiers] = keys; - await KeyboardAction.key(key, "down", ...modifiers); - resolve(); - } catch (e) { - reject(e); - } - }); - } - - public releaseKey(...keys: Key[]): Promise { - return new Promise(async (resolve, reject) => { - try { - keys.reverse(); - const [key, ...modifiers] = keys; - await KeyboardAction.key(key, "up", ...modifiers); - resolve(); - } catch (e) { - reject(e); - } - }); - } - - public setKeyboardDelay(delay: number): void { - libnut.setKeyboardDelay(delay); - } -} diff --git a/lib/provider/native/libnut-keyboard.action.class.spec.ts b/lib/provider/native/libnut-keyboard.class.spec.ts similarity index 85% rename from lib/provider/native/libnut-keyboard.action.class.spec.ts rename to lib/provider/native/libnut-keyboard.class.spec.ts index f4f1e124..d1cedfcf 100644 --- a/lib/provider/native/libnut-keyboard.action.class.spec.ts +++ b/lib/provider/native/libnut-keyboard.class.spec.ts @@ -1,6 +1,6 @@ import libnut = require("@nut-tree/libnut"); import { Key } from "../../key.enum"; -import KeyboardAction from "./libnut-keyboard-action.class"; +import KeyboardAction from "./libnut-keyboard.class"; jest.mock("@nut-tree/libnut"); @@ -175,4 +175,30 @@ describe("libnut keyboard action", () => { expect(SUT.releaseKey(Key.A)).rejects.toThrowError("Test error"); }); }); + + describe("bugfix #260", () => { + it("should forward the pressKey call to libnut for 'delete'", () => { + // GIVEN + const SUT = new KeyboardAction(); + + // WHEN + SUT.pressKey(Key.Delete); + + // THEN + expect(libnut.keyToggle).toBeCalledTimes(1); + expect(libnut.keyToggle).toBeCalledWith("delete", "down", []); + }); + + it("should forward the releaseKey call to libnut for 'delete'", () => { + // GIVEN + const SUT = new KeyboardAction(); + + // WHEN + SUT.releaseKey(Key.Delete); + + // THEN + expect(libnut.keyToggle).toBeCalledTimes(1); + expect(libnut.keyToggle).toBeCalledWith("delete", "up", []); + }); + }); }); diff --git a/lib/provider/native/libnut-keyboard.class.ts b/lib/provider/native/libnut-keyboard.class.ts new file mode 100644 index 00000000..60846bc1 --- /dev/null +++ b/lib/provider/native/libnut-keyboard.class.ts @@ -0,0 +1,232 @@ +import libnut = require("@nut-tree/libnut"); +import {Key} from "../../key.enum"; +import {KeyboardProviderInterface} from "../keyboard-provider.interface"; + +export default class KeyboardAction implements KeyboardProviderInterface { + + public static KeyLookupMap = new Map([ + [Key.A, "a"], + [Key.B, "b"], + [Key.C, "c"], + [Key.D, "d"], + [Key.E, "e"], + [Key.F, "f"], + [Key.G, "g"], + [Key.H, "h"], + [Key.I, "i"], + [Key.J, "j"], + [Key.K, "k"], + [Key.L, "l"], + [Key.M, "m"], + [Key.N, "n"], + [Key.O, "o"], + [Key.P, "p"], + [Key.Q, "q"], + [Key.R, "r"], + [Key.S, "s"], + [Key.T, "t"], + [Key.U, "u"], + [Key.V, "v"], + [Key.W, "w"], + [Key.X, "x"], + [Key.Y, "y"], + [Key.Z, "z"], + + [Key.F1, "f1"], + [Key.F2, "f2"], + [Key.F3, "f3"], + [Key.F4, "f4"], + [Key.F5, "f5"], + [Key.F6, "f6"], + [Key.F7, "f7"], + [Key.F8, "f8"], + [Key.F9, "f9"], + [Key.F10, "f10"], + [Key.F11, "f11"], + [Key.F12, "f12"], + [Key.F13, "f13"], + [Key.F14, "f14"], + [Key.F15, "f15"], + [Key.F16, "f16"], + [Key.F17, "f17"], + [Key.F18, "f18"], + [Key.F19, "f19"], + [Key.F20, "f20"], + [Key.F21, "f21"], + [Key.F22, "f22"], + [Key.F23, "f23"], + [Key.F24, "f24"], + + [Key.Num0, "0"], + [Key.Num1, "1"], + [Key.Num2, "2"], + [Key.Num3, "3"], + [Key.Num4, "4"], + [Key.Num5, "5"], + [Key.Num6, "6"], + [Key.Num7, "7"], + [Key.Num8, "8"], + [Key.Num9, "9"], + [Key.NumPad0, "numpad_0"], + [Key.NumPad1, "numpad_1"], + [Key.NumPad2, "numpad_2"], + [Key.NumPad3, "numpad_3"], + [Key.NumPad4, "numpad_4"], + [Key.NumPad5, "numpad_5"], + [Key.NumPad6, "numpad_6"], + [Key.NumPad7, "numpad_7"], + [Key.NumPad8, "numpad_8"], + [Key.NumPad9, "numpad_9"], + + [Key.Space, "space"], + [Key.Escape, "escape"], + [Key.Tab, "tab"], + [Key.LeftAlt, "alt"], + [Key.LeftControl, "control"], + [Key.RightAlt, "alt"], + [Key.RightControl, "control"], + + [Key.LeftShift, "shift"], + [Key.LeftSuper, "command"], + [Key.RightShift, "space"], + [Key.RightSuper, "command"], + + [Key.Grave, "~"], + [Key.Minus, "-"], + [Key.Equal, "="], + [Key.Backspace, "backspace"], + [Key.LeftBracket, "["], + [Key.RightBracket, "]"], + [Key.Backslash, "\\"], + [Key.Semicolon, ";"], + [Key.Quote, "'"], + [Key.Return, "enter"], + [Key.Comma, ","], + [Key.Period, "."], + [Key.Slash, "/"], + + [Key.Left, "left"], + [Key.Up, "up"], + [Key.Right, "right"], + [Key.Down, "down"], + + [Key.Print, "printscreen"], + [Key.Pause, null], + [Key.Insert, "insert"], + [Key.Delete, "delete"], + [Key.Home, "home"], + [Key.End, "end"], + [Key.PageUp, "pageup"], + [Key.PageDown, "pagedown"], + + [Key.Add, null], + [Key.Subtract, null], + [Key.Multiply, null], + [Key.Divide, null], + [Key.Decimal, null], + [Key.Enter, "enter"], + + [Key.CapsLock, null], + [Key.ScrollLock, null], + [Key.NumLock, null], + + [Key.AudioMute, "audio_mute"], + [Key.AudioVolDown, "audio_vol_down"], + [Key.AudioVolUp, "audio_vol_up"], + [Key.AudioPlay, "audio_play"], + [Key.AudioStop, "audio_stop"], + [Key.AudioPause, "audio_pause"], + [Key.AudioPrev, "audio_prev"], + [Key.AudioNext, "audio_next"], + [Key.AudioRewind, "audio_rewind"], + [Key.AudioForward, "audio_forward"], + [Key.AudioRepeat, "audio_repeat"], + [Key.AudioRandom, "audio_random"] + ]); + + public static keyLookup(key: Key): any { + return this.KeyLookupMap.get(key); + } + + private static mapModifierKeys(...keys: Key[]): string[] { + return keys + .map(modifier => KeyboardAction.keyLookup(modifier)) + .filter(modifierKey => modifierKey != null && modifierKey.length > 1); + } + + private static key(key: Key, event: "up" | "down", ...modifiers: Key[]): Promise { + return new Promise((resolve, reject) => { + try { + const nativeKey = KeyboardAction.keyLookup(key); + const modifierKeys = this.mapModifierKeys(...modifiers); + if (nativeKey) { + libnut.keyToggle(nativeKey, event, modifierKeys); + } + resolve(); + } catch (e) { + reject(e); + } + }); + } + + constructor() { + } + + public type(input: string): Promise { + return new Promise((resolve, reject) => { + try { + libnut.typeString(input); + resolve(); + } catch (e) { + reject(e); + } + }); + } + + public click(...keys: Key[]): Promise { + return new Promise((resolve, reject) => { + try { + keys.reverse(); + const [key, ...modifiers] = keys; + const nativeKey = KeyboardAction.keyLookup(key); + const modifierKeys = KeyboardAction.mapModifierKeys(...modifiers); + if (nativeKey) { + libnut.keyTap(nativeKey, modifierKeys); + } + resolve(); + } catch (e) { + reject(e); + } + }); + } + + public pressKey(...keys: Key[]): Promise { + return new Promise(async (resolve, reject) => { + try { + keys.reverse(); + const [key, ...modifiers] = keys; + await KeyboardAction.key(key, "down", ...modifiers); + resolve(); + } catch (e) { + reject(e); + } + }); + } + + public releaseKey(...keys: Key[]): Promise { + return new Promise(async (resolve, reject) => { + try { + keys.reverse(); + const [key, ...modifiers] = keys; + await KeyboardAction.key(key, "up", ...modifiers); + resolve(); + } catch (e) { + reject(e); + } + }); + } + + public setKeyboardDelay(delay: number): void { + libnut.setKeyboardDelay(delay); + } +} diff --git a/lib/provider/native/libnut-mouse-action.class.spec.ts b/lib/provider/native/libnut-mouse.class.spec.ts similarity index 99% rename from lib/provider/native/libnut-mouse-action.class.spec.ts rename to lib/provider/native/libnut-mouse.class.spec.ts index 4ceaa0e3..cd74c31e 100644 --- a/lib/provider/native/libnut-mouse-action.class.spec.ts +++ b/lib/provider/native/libnut-mouse.class.spec.ts @@ -1,7 +1,7 @@ import libnut = require("@nut-tree/libnut"); import { Button } from "../../button.enum"; import { Point } from "../../point.class"; -import MouseAction from "./libnut-mouse-action.class"; +import MouseAction from "./libnut-mouse.class"; jest.mock("@nut-tree/libnut"); diff --git a/lib/provider/native/libnut-mouse-action.class.ts b/lib/provider/native/libnut-mouse.class.ts similarity index 95% rename from lib/provider/native/libnut-mouse-action.class.ts rename to lib/provider/native/libnut-mouse.class.ts index 81d05cb9..c47bdbea 100644 --- a/lib/provider/native/libnut-mouse-action.class.ts +++ b/lib/provider/native/libnut-mouse.class.ts @@ -1,9 +1,9 @@ import libnut = require("@nut-tree/libnut"); import { Button } from "../../button.enum"; import { Point } from "../../point.class"; -import { MouseActionProvider } from "./mouse-action-provider.interface"; +import { MouseProviderInterface } from "../mouse-provider.interface"; -export default class MouseAction implements MouseActionProvider { +export default class MouseAction implements MouseProviderInterface { public static buttonLookup(btn: Button): any { return this.ButtonLookupMap.get(btn); } diff --git a/lib/provider/native/libnut-screen-action.class.spec.ts b/lib/provider/native/libnut-screen.class.spec.ts similarity index 98% rename from lib/provider/native/libnut-screen-action.class.spec.ts rename to lib/provider/native/libnut-screen.class.spec.ts index a29df6a8..2e1aaa89 100644 --- a/lib/provider/native/libnut-screen-action.class.spec.ts +++ b/lib/provider/native/libnut-screen.class.spec.ts @@ -1,7 +1,8 @@ import libnut = require("@nut-tree/libnut"); import { Region } from "../../region.class"; -import ScreenAction from "./libnut-screen-action.class"; +import ScreenAction from "./libnut-screen.class"; +jest.mock("jimp", () => {}); jest.mock("@nut-tree/libnut"); beforeEach(() => { diff --git a/lib/provider/native/libnut-screen-action.class.ts b/lib/provider/native/libnut-screen.class.ts similarity index 87% rename from lib/provider/native/libnut-screen-action.class.ts rename to lib/provider/native/libnut-screen.class.ts index a21b5359..1ab716a5 100644 --- a/lib/provider/native/libnut-screen-action.class.ts +++ b/lib/provider/native/libnut-screen.class.ts @@ -1,9 +1,10 @@ import libnut = require("@nut-tree/libnut"); -import { Image } from "../../image.class"; -import { Region } from "../../region.class"; -import { ScreenActionProvider } from "./screen-action-provider.interface"; +import {Image} from "../../image.class"; +import {Region} from "../../region.class"; +import {ScreenProviderInterface} from "../screen-provider.interface"; +import {ColorMode} from "../../colormode.enum"; -export default class ScreenAction implements ScreenActionProvider { +export default class ScreenAction implements ScreenProviderInterface { private static determinePixelDensity( screen: Region, @@ -33,6 +34,8 @@ export default class ScreenAction implements ScreenActionProvider { screenShot.height, screenShot.image, 4, + "grabScreenResult", + ColorMode.BGR, pixelScaling, ), ); @@ -58,6 +61,8 @@ export default class ScreenAction implements ScreenActionProvider { screenShot.height, screenShot.image, 4, + "grabScreenRegionResult", + ColorMode.BGR, pixelScaling, ), ); diff --git a/lib/provider/native/libnut-window-action.class.spec.ts b/lib/provider/native/libnut-window.class.spec.ts similarity index 98% rename from lib/provider/native/libnut-window-action.class.spec.ts rename to lib/provider/native/libnut-window.class.spec.ts index 93d4115b..a89a9deb 100644 --- a/lib/provider/native/libnut-window-action.class.spec.ts +++ b/lib/provider/native/libnut-window.class.spec.ts @@ -1,5 +1,5 @@ import libnut = require("@nut-tree/libnut"); -import WindowAction from "./libnut-window-action.class"; +import WindowAction from "./libnut-window.class"; import {Region} from "../../region.class"; jest.mock("@nut-tree/libnut"); diff --git a/lib/provider/native/libnut-window-action.class.ts b/lib/provider/native/libnut-window.class.ts similarity index 88% rename from lib/provider/native/libnut-window-action.class.ts rename to lib/provider/native/libnut-window.class.ts index 1352f682..40804364 100644 --- a/lib/provider/native/libnut-window-action.class.ts +++ b/lib/provider/native/libnut-window.class.ts @@ -1,8 +1,8 @@ import libnut = require("@nut-tree/libnut"); import { Region } from "../../region.class"; -import { WindowActionProvider } from "./window-action-provider.interface"; +import { WindowProviderInterface } from "../window-provider.interface"; -export default class WindowAction implements WindowActionProvider { +export default class WindowAction implements WindowProviderInterface { public getWindows(): Promise { return new Promise((resolve, reject) => { try { diff --git a/lib/provider/opencv/__mocks__/alpha_channel.png b/lib/provider/opencv/__mocks__/alpha_channel.png deleted file mode 100644 index 5214843c..00000000 Binary files a/lib/provider/opencv/__mocks__/alpha_channel.png and /dev/null differ diff --git a/lib/provider/opencv/__mocks__/coverage.png b/lib/provider/opencv/__mocks__/coverage.png deleted file mode 100644 index e23cd669..00000000 Binary files a/lib/provider/opencv/__mocks__/coverage.png and /dev/null differ diff --git a/lib/provider/opencv/__mocks__/downloads.png b/lib/provider/opencv/__mocks__/downloads.png deleted file mode 100644 index d8542250..00000000 Binary files a/lib/provider/opencv/__mocks__/downloads.png and /dev/null differ diff --git a/lib/provider/opencv/__mocks__/fat-needle.png b/lib/provider/opencv/__mocks__/fat-needle.png deleted file mode 100644 index 87533253..00000000 Binary files a/lib/provider/opencv/__mocks__/fat-needle.png and /dev/null differ diff --git a/lib/provider/opencv/__mocks__/mouse.png b/lib/provider/opencv/__mocks__/mouse.png deleted file mode 100644 index b3468b75..00000000 Binary files a/lib/provider/opencv/__mocks__/mouse.png and /dev/null differ diff --git a/lib/provider/opencv/__mocks__/needle.png b/lib/provider/opencv/__mocks__/needle.png deleted file mode 100644 index a9b012f0..00000000 Binary files a/lib/provider/opencv/__mocks__/needle.png and /dev/null differ diff --git a/lib/provider/opencv/bound-value.function.spec.ts b/lib/provider/opencv/bound-value.function.spec.ts deleted file mode 100644 index fc5f9323..00000000 --- a/lib/provider/opencv/bound-value.function.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { lowerBound, upperBound } from "./bound-value.function"; - -describe("lowerBound function", () => { - it.each([ - [5, 10, 1, 1], - [5, 5, 10, 10], - [5, 1, 10, 5], - [0, 0, 0, 0] - ])("Input: %f, Boundary: %f, minValue: %f, Expected: %f", - (input: number, boundary: number, minValue: number, expected: number) => { - // WHEN - const result = lowerBound(input, boundary, minValue); - - // THEN - expect(result).toBe(expected); - }); -}); - -describe("upperBound function", () => { - it.each([ - [5, 10, 1, 5], - [5, 5, 10, 10], - [5, 1, 10, 10], - [5, 5, 5, 5] - ])("Input: %f, Boundary: %f, maxValue: %f, Expected: %f", - (input: number, boundary: number, maxValue: number, expected: number) => { - // WHEN - const result = upperBound(input, boundary, maxValue); - - // THEN - expect(result).toBe(expected); - }); -}); diff --git a/lib/provider/opencv/bound-value.function.ts b/lib/provider/opencv/bound-value.function.ts deleted file mode 100644 index e6e6b308..00000000 --- a/lib/provider/opencv/bound-value.function.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function lowerBound(value: number, boundary: number, minValue: number): number { - return (value <= boundary) ? minValue : value; -} - -export function upperBound(value: number, boundary: number, maxValue: number): number { - return (value >= boundary) ? maxValue : value; -} diff --git a/lib/provider/opencv/data-sink.interface.ts b/lib/provider/opencv/data-sink.interface.ts deleted file mode 100644 index 79f15b1c..00000000 --- a/lib/provider/opencv/data-sink.interface.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * A DataSink should provide methods to store data - * - * @interface DataSink - */ -export interface DataSink { - /** - * store will write data to disk - * @param data Data to write - * @param path Absolute output file path - */ - store(data: any, path: string): Promise; -} diff --git a/lib/provider/opencv/data-source.interface.ts b/lib/provider/opencv/data-source.interface.ts deleted file mode 100644 index f59d06b7..00000000 --- a/lib/provider/opencv/data-source.interface.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * A DataSource should provide methods to load data - * - * @interface DataSource - */ -export interface DataSource { - /** - * load will load image data from disk - * @param path Absolute path to output file - */ - load(path: string): Promise; -} diff --git a/lib/provider/opencv/determine-searchregion.function.spec.ts b/lib/provider/opencv/determine-searchregion.function.spec.ts deleted file mode 100644 index 9885aec8..00000000 --- a/lib/provider/opencv/determine-searchregion.function.spec.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { mockPartial } from "sneer"; -import { Image } from "../../image.class"; -import { MatchRequest } from "../../match-request.class"; -import { Region } from "../../region.class"; -import { determineScaledSearchRegion } from "./determine-searchregion.function"; - -describe("determineSearchRegion", () => { - it("should return a search region adopted to pixel density", () => { - // GIVEN - const imageMock = mockPartial({ - pixelDensity: { - scaleX: 1.5, - scaleY: 2.0 - } - }); - const needlePath = "/path/to/needle"; - const inputSearchRegion = new Region(0, 0, 100, 100); - const expectedSearchRegion = new Region(0, 0, 150, 200); - - const matchRequest = new MatchRequest( - imageMock, - needlePath, - inputSearchRegion, - 0.99 - ); - - // WHEN - const result = determineScaledSearchRegion(matchRequest); - - // THEN - expect(result).toEqual(expectedSearchRegion); - }); - - it.each([[0, 1], [1, 0]])("should not adjust searchregion for factor 0: scaleX: %i scaleY: %i", - (scaleX: number, scaleY: number) => { - // GIVEN - const imageMock = mockPartial({ - pixelDensity: { - scaleX, - scaleY - } - }); - const needlePath = "/path/to/needle"; - const inputSearchRegion = new Region(0, 0, 100, 100); - const expectedSearchRegion = new Region(0, 0, 100, 100); - - const matchRequest = new MatchRequest( - imageMock, - needlePath, - inputSearchRegion, - 0.99 - ); - - // WHEN - const result = determineScaledSearchRegion(matchRequest); - - // THEN - expect(result).toEqual(expectedSearchRegion); - }); -}); diff --git a/lib/provider/opencv/determine-searchregion.function.ts b/lib/provider/opencv/determine-searchregion.function.ts deleted file mode 100644 index 84226b1d..00000000 --- a/lib/provider/opencv/determine-searchregion.function.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { MatchRequest } from "../../match-request.class"; -import { Region } from "../../region.class"; - -export function determineScaledSearchRegion(matchRequest: MatchRequest): Region { - const searchRegion = matchRequest.searchRegion; - const scaleX = matchRequest.haystack.pixelDensity.scaleX || 1.0; - const scaleY = matchRequest.haystack.pixelDensity.scaleY || 1.0; - searchRegion.width *= scaleX; - searchRegion.height *= scaleY; - return searchRegion; -} diff --git a/lib/provider/opencv/finder.interface.ts b/lib/provider/opencv/finder.interface.ts deleted file mode 100644 index 83da0d00..00000000 --- a/lib/provider/opencv/finder.interface.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { MatchRequest } from "../../match-request.class"; -import { MatchResult } from "../../match-result.class"; - -/** - * A Finder should provide an abstraction layer to perform - * image processing and matching via a 3rd part library - * - * @interface FinderInterface - */ -export interface FinderInterface { - /** - * findMatch should provide an abstraction to search for an image needle - * in another image haystack - * - * @param {MatchRequest} matchRequest A matchrequest containing needed matching data - * @returns {Promise} A matchresult containing the match probability and location - * @memberof FinderInterface - */ - findMatch(matchRequest: MatchRequest): Promise; - - /** - * findMatches should provide an abstraction to search for an image needle - * in another image haystack - * - * @param {MatchRequest} matchRequest A matchrequest containing needed matching data - * @returns {Promise} A list of matchresults containing the match probability and location - * @memberof FinderInterface - */ - findMatches(matchRequest: MatchRequest): Promise; -} diff --git a/lib/provider/opencv/image-processor.class.spec.ts b/lib/provider/opencv/image-processor.class.spec.ts deleted file mode 100644 index 19651f7d..00000000 --- a/lib/provider/opencv/image-processor.class.spec.ts +++ /dev/null @@ -1,82 +0,0 @@ -import {resolve} from "path"; -import {Region} from "../../region.class"; -import {ImageReader} from "./image-reader.class"; -import {fromImageWithAlphaChannel, fromImageWithoutAlphaChannel} from "./image-processor.class"; - -describe("ImageProcessor", () => { - it("should allow to create a cv.Mat from an Image with alpha channel, alpha channel is dropped", async () => { - // GIVEN - const imageReader = new ImageReader(); - const imagePath = resolve(__dirname, "./__mocks__/alpha_channel.png"); - const image = await imageReader.load(imagePath); - - // WHEN - const mat = await fromImageWithAlphaChannel(image); - - // THEN - expect(image.hasAlphaChannel).toBeTruthy(); - expect(mat.channels).toEqual(3); - expect(mat.rows).toEqual(image.height); - expect(mat.cols).toEqual(image.width); - expect(mat.empty).toBeFalsy(); - }); - - it("should allow to create a cv.Mat from an Image without alpha channel", async () => { - // GIVEN - const imageReader = new ImageReader(); - const imagePath = resolve(__dirname, "./__mocks__/mouse.png"); - const image = await imageReader.load(imagePath); - - // WHEN - const mat = await fromImageWithoutAlphaChannel(image); - - // THEN - expect(image.hasAlphaChannel).toBeFalsy(); - expect(mat.channels).toEqual(3); - expect(mat.rows).toEqual(image.height); - expect(mat.cols).toEqual(image.width); - expect(mat.empty).toBeFalsy(); - }); -}); - -describe("ImageProcessor with ROI", () => { - it("negative left or top values are updated to 0", async () => { - // GIVEN - const imageReader = new ImageReader(); - const imagePath = resolve(__dirname, "./__mocks__/mouse.png"); - const image = await imageReader.load(imagePath); - - // WHEN - const mat = await fromImageWithoutAlphaChannel( - image, - new Region(-100, -100, 10, 10) - ); - - // THEN - expect(image.hasAlphaChannel).toBeFalsy(); - expect(mat.channels).toEqual(3); - expect(mat.rows).toEqual(10); - expect(mat.cols).toEqual(10); - expect(mat.empty).toBeFalsy(); - }); - - it("values bigger than the input are updated to width and height", async () => { - // GIVEN - const imageReader = new ImageReader(); - const imagePath = resolve(__dirname, "./__mocks__/mouse.png"); - const image = await imageReader.load(imagePath); - - // WHEN - const mat = await fromImageWithoutAlphaChannel( - image, - new Region(10, 10, image.width * 2, image.height * 2) - ); - - // THEN - expect(image.hasAlphaChannel).toBeFalsy(); - expect(mat.channels).toEqual(3); - expect(mat.rows).toEqual(image.height - 10); - expect(mat.cols).toEqual(image.width - 10); - expect(mat.empty).toBeFalsy(); - }); -}); diff --git a/lib/provider/opencv/image-processor.class.ts b/lib/provider/opencv/image-processor.class.ts deleted file mode 100644 index 7b0a3ab6..00000000 --- a/lib/provider/opencv/image-processor.class.ts +++ /dev/null @@ -1,53 +0,0 @@ -import * as cv from "opencv4nodejs-prebuilt"; -import {Image} from "../../image.class"; -import {Region} from "../../region.class"; - -function determineROI(img: Image, roi: Region): cv.Rect { - return new cv.Rect( - Math.min(Math.max(roi.left, 0), img.width), - Math.min(Math.max(roi.top, 0), img.height), - Math.min(roi.width, img.width - roi.left), - Math.min(roi.height, img.height - roi.top)); -} - -/** - * fromImageWithAlphaChannel should provide a way to create a library specific - * image with alpha channel from an abstract Image object holding raw data and image dimension - * - * @param {Image} img The input Image - * @param {Region} [roi] An optional Region to specify a ROI - * @returns {Promise} An image - * @memberof VisionProviderInterface - */ -export const fromImageWithAlphaChannel = async ( - img: Image, - roi?: Region, -): Promise => { - const mat = await new cv.Mat(img.data, img.height, img.width, cv.CV_8UC4).cvtColorAsync(cv.COLOR_BGRA2BGR); - if (roi) { - return mat.getRegion(determineROI(img, roi)); - } else { - return mat; - } -}; - -/** - * fromImageWithoutAlphaChannel should provide a way to create a library specific - * image without alpha channel from an abstract Image object holding raw data and image dimension - * - * @param {Image} img The input Image - * @param {Region} [roi] An optional Region to specify a ROI - * @returns {Promise} An image - * @memberof VisionProviderInterface - */ -export const fromImageWithoutAlphaChannel = async ( - img: Image, - roi?: Region, -): Promise => { - const mat = new cv.Mat(img.data, img.height, img.width, cv.CV_8UC3); - if (roi) { - return mat.getRegion(determineROI(img, roi)); - } else { - return mat; - } -}; diff --git a/lib/provider/opencv/image-reader.class.spec.ts b/lib/provider/opencv/image-reader.class.spec.ts deleted file mode 100644 index f51d93bb..00000000 --- a/lib/provider/opencv/image-reader.class.spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as path from "path"; -import { ImageReader } from "./image-reader.class"; - -describe("Image loader", () => { - it("should resolve to a non-empty Mat on successful load", async () => { - // GIVEN - const SUT = new ImageReader(); - const imagePath = path.resolve(__dirname, "./__mocks__/mouse.png"); - - // WHEN - const result = await SUT.load(imagePath); - - // THEN - expect(result.height).toBeGreaterThan(0); - expect(result.width).toBeGreaterThan(0); - }); - - it("loadImage should reject on unsuccessful load", async () => { - // GIVEN - const SUT = new ImageReader(); - const imagePath = "./__mocks__/foo.png"; - - // WHEN - const call = SUT.load; - - // THEN - await expect(call(imagePath)).rejects.toEqual(`Failed to load image from '${imagePath}'`); - }); -}); diff --git a/lib/provider/opencv/image-reader.class.ts b/lib/provider/opencv/image-reader.class.ts deleted file mode 100644 index 73d90c34..00000000 --- a/lib/provider/opencv/image-reader.class.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as cv from "opencv4nodejs-prebuilt"; -import { Image } from "../../image.class"; -import { DataSource } from "./data-source.interface"; - -export class ImageReader implements DataSource { - public async load(path: string): Promise { - return new Promise(async (resolve, reject) => { - try { - const image = await cv.imreadAsync(path, cv.IMREAD_UNCHANGED); - resolve(new Image(image.cols, image.rows, image.getData(), image.channels)); - } catch (e) { - reject(`Failed to load image from '${path}'`); - } - }); - } -} diff --git a/lib/provider/opencv/image-writer.class.spec.ts b/lib/provider/opencv/image-writer.class.spec.ts deleted file mode 100644 index d672ed9a..00000000 --- a/lib/provider/opencv/image-writer.class.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { existsSync, unlinkSync } from "fs"; -import { resolve } from "path"; -import { ImageReader } from "./image-reader.class"; -import { ImageWriter } from "./image-writer.class"; - -const INPUT_PATH = resolve(__dirname, "./__mocks__/mouse.png"); -const OUTPUT_PATH_PNG = resolve(__dirname, "./__mocks__/output.png"); -const OUTPUT_PATH_JPG = resolve(__dirname, "./__mocks__/output.jpg"); - -beforeEach(() => { - for (const file of [OUTPUT_PATH_JPG, OUTPUT_PATH_PNG]) { - if (existsSync(file)) { - unlinkSync(file); - } - } -}); - -describe.each([[OUTPUT_PATH_PNG], [OUTPUT_PATH_JPG]])( - "Image writer", (outputPath) => { - test("should allow to store image data to disk", async () => { - // GIVEN - const imageReader = new ImageReader(); - const image = await imageReader.load(INPUT_PATH); - const imageWriter = new ImageWriter(); - - // WHEN - await imageWriter.store(image, outputPath); - - // THEN - expect(existsSync(outputPath)).toBeTruthy(); - }); - }); diff --git a/lib/provider/opencv/image-writer.class.ts b/lib/provider/opencv/image-writer.class.ts deleted file mode 100644 index 6ae6b90c..00000000 --- a/lib/provider/opencv/image-writer.class.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as cv from "opencv4nodejs-prebuilt"; -import {Image} from "../../image.class"; -import {DataSink} from "./data-sink.interface"; -import {fromImageWithAlphaChannel, fromImageWithoutAlphaChannel} from "./image-processor.class"; - -export class ImageWriter implements DataSink { - public async store(data: Image, path: string): Promise { - let outputMat: cv.Mat; - if (data.hasAlphaChannel) { - outputMat = await fromImageWithAlphaChannel(data); - } else { - outputMat = await fromImageWithoutAlphaChannel(data); - } - return cv.imwriteAsync(path, outputMat); - } -} diff --git a/lib/provider/opencv/match-image.function.spec.ts b/lib/provider/opencv/match-image.function.spec.ts deleted file mode 100644 index 41baa7e1..00000000 --- a/lib/provider/opencv/match-image.function.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as cv from "opencv4nodejs-prebuilt"; -import { mockPartial } from "sneer"; -import { matchImages } from "./match-image.function"; - -describe("matchImages", () => { - it("should return minLoc position and needle size", async () => { - // GIVEN - const minLocX = 100; - const minLocY = 1000; - const matchMock = mockPartial({ - minMaxLocAsync: jest.fn(() => Promise.resolve({ - maxLoc: new cv.Point2( - 200, - 2000 - ), - maxVal: 100, - minLoc: new cv.Point2( - minLocX, - minLocY - ), - minVal: 0, - })) - }); - const haystackMock = mockPartial({ - matchTemplateAsync: jest.fn(() => Promise.resolve(matchMock)) - }); - const needleMock = mockPartial({ - cols: 123, - rows: 456 - }); - - // WHEN - const result = await matchImages(haystackMock, needleMock); - - // THEN - expect(result.location.left).toEqual(minLocX); - expect(result.location.top).toEqual(minLocY); - expect(result.location.width).toEqual(needleMock.cols); - expect(result.location.height).toEqual(needleMock.rows); - }); -}); diff --git a/lib/provider/opencv/match-image.function.ts b/lib/provider/opencv/match-image.function.ts deleted file mode 100644 index c49e422a..00000000 --- a/lib/provider/opencv/match-image.function.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as cv from "opencv4nodejs-prebuilt"; -import { MatchResult } from "../../match-result.class"; -import { Region } from "../../region.class"; - -export async function matchImages(haystack: cv.Mat, needle: cv.Mat): Promise { - const match = await haystack.matchTemplateAsync( - needle, - cv.TM_SQDIFF_NORMED, - ); - const minMax = await match.minMaxLocAsync(); - return new MatchResult( - 1.0 - minMax.minVal, - new Region( - minMax.minLoc.x, - minMax.minLoc.y, - needle.cols, - needle.rows, - ), - ); -} diff --git a/lib/provider/opencv/scale-image.function.spec.ts b/lib/provider/opencv/scale-image.function.spec.ts deleted file mode 100644 index c25f4dee..00000000 --- a/lib/provider/opencv/scale-image.function.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import * as path from "path"; -import {ImageReader} from "./image-reader.class"; -import {scaleImage} from "./scale-image.function"; -import {fromImageWithoutAlphaChannel} from "./image-processor.class"; - -describe("scaleImage", () => { - it.each([[0.5], [1.5]])("should scale an image correctly by factor %f", async (scaleFactor) => { - // GIVEN - const imageLoader = new ImageReader(); - const pathToinput = path.resolve(__dirname, "./__mocks__/mouse.png"); - const inputImage = await imageLoader.load(pathToinput); - const inputMat = await fromImageWithoutAlphaChannel(inputImage); - const expectedWidth = Math.floor(inputMat.cols * scaleFactor); - const expectedHeight = Math.floor(inputMat.rows * scaleFactor); - - // WHEN - const result = await scaleImage(inputMat, scaleFactor); - - // THEN - expect(result.rows).toBe(expectedHeight); - expect(result.cols).toBe(expectedWidth); - }); - - it.each([[0], [-0.25]])("should keep scale if factor <= 0: Scale %f", async (scaleFactor) => { - // GIVEN - const imageLoader = new ImageReader(); - const pathToinput = path.resolve(__dirname, "./__mocks__/mouse.png"); - const inputImage = await imageLoader.load(pathToinput); - const inputMat = await fromImageWithoutAlphaChannel(inputImage); - const expectedWidth = inputMat.cols; - const expectedHeight = inputMat.rows; - - // WHEN - const result = await scaleImage(inputMat, scaleFactor); - - // THEN - expect(result.rows).toBe(expectedHeight); - expect(result.cols).toBe(expectedWidth); - }); -}); diff --git a/lib/provider/opencv/scale-image.function.ts b/lib/provider/opencv/scale-image.function.ts deleted file mode 100644 index b5fbd21d..00000000 --- a/lib/provider/opencv/scale-image.function.ts +++ /dev/null @@ -1,9 +0,0 @@ -import * as cv from "opencv4nodejs-prebuilt"; -import { lowerBound } from "./bound-value.function"; - -export async function scaleImage(image: cv.Mat, scaleFactor: number): Promise { - const boundScaleFactor = lowerBound(scaleFactor, 0.0, 1.0); - const scaledRows = Math.floor(image.rows * boundScaleFactor); - const scaledCols = Math.floor(image.cols * boundScaleFactor); - return image.resizeAsync(scaledRows, scaledCols, 0, 0, cv.INTER_AREA); -} diff --git a/lib/provider/opencv/scale-location.function.spec.ts b/lib/provider/opencv/scale-location.function.spec.ts deleted file mode 100644 index dfdf3e8a..00000000 --- a/lib/provider/opencv/scale-location.function.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Region } from "../../region.class"; -import { scaleLocation } from "./scale-location.function"; - -describe("scaleLocation", () => { - it("should scale location of a Region for valid scale factors", () => { - // GIVEN - const scaleFactor = 0.5; - const inputRegion = new Region(100, 100, 10, 10); - const expectedRegion = new Region(200, 200, 10, 10); - - // WHEN - const result = scaleLocation(inputRegion, scaleFactor); - - // THEN - expect(result).toEqual(expectedRegion); - }); - - it("should not scale location of a Region for invalid scale factors", () => { - // GIVEN - const scaleFactor = 0.0; - const inputRegion = new Region(100, 100, 10, 10); - const expectedRegion = new Region(100, 100, 10, 10); - - // WHEN - const result = scaleLocation(inputRegion, scaleFactor); - - // THEN - expect(result).toEqual(expectedRegion); - }); -}); diff --git a/lib/provider/opencv/scale-location.function.ts b/lib/provider/opencv/scale-location.function.ts deleted file mode 100644 index 814160c0..00000000 --- a/lib/provider/opencv/scale-location.function.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Region } from "../../region.class"; -import { lowerBound } from "./bound-value.function"; - -export function scaleLocation( - result: Region, - scaleFactor: number, -): Region { - const boundScaleFactor = lowerBound(scaleFactor, 0.0, 1.0); - return new Region( - result.left / boundScaleFactor, - result.top / boundScaleFactor, - result.width, - result.height, - ); -} diff --git a/lib/provider/opencv/template-matching-finder.class.spec.ts b/lib/provider/opencv/template-matching-finder.class.spec.ts deleted file mode 100644 index 974dc897..00000000 --- a/lib/provider/opencv/template-matching-finder.class.spec.ts +++ /dev/null @@ -1,110 +0,0 @@ -import * as path from "path"; -import {Image} from "../../image.class"; -import {MatchRequest} from "../../match-request.class"; -import {Region} from "../../region.class"; -import {ImageReader} from "./image-reader.class"; -import TemplateMatchingFinder from "./template-matching-finder.class"; - -describe("Template-matching finder", () => { - it("findMatch should return a match when present in image", async () => { - // GIVEN - const imageLoader = new ImageReader(); - const SUT = new TemplateMatchingFinder(); - const haystackPath = path.resolve(__dirname, "./__mocks__/mouse.png"); - const needlePath = path.resolve(__dirname, "./__mocks__/needle.png"); - const haystack = await imageLoader.load(haystackPath); - const needle = await imageLoader.load(needlePath); - const minConfidence = 0.99; - const searchRegion = new Region(0, 0, haystack.width, haystack.height); - const matchRequest = new MatchRequest(haystack, needlePath, searchRegion, minConfidence); - const expectedResult = new Region(16, 31, needle.width, needle.height); - - // WHEN - const result = await SUT.findMatch(matchRequest); - - // THEN - expect(result.confidence).toBeGreaterThanOrEqual(minConfidence); - expect(result.location).toEqual(expectedResult); - }); - - it("findMatch should return a match within a search region when present in image", async () => { - // GIVEN - const imageLoader = new ImageReader(); - const SUT = new TemplateMatchingFinder(); - const haystackPath = path.resolve(__dirname, "./__mocks__/mouse.png"); - const needlePath = path.resolve(__dirname, "./__mocks__/needle.png"); - const haystack = await imageLoader.load(haystackPath); - const needle = await imageLoader.load(needlePath); - const minConfidence = 0.99; - const searchRegion = new Region(10, 20, 140, 100); - const matchRequest = new MatchRequest(haystack, needlePath, searchRegion, minConfidence); - const expectedResult = new Region(6, 11, needle.width, needle.height); - - // WHEN - const result = await SUT.findMatch(matchRequest); - - // THEN - expect(result.confidence).toBeGreaterThanOrEqual(minConfidence); - expect(result.location).toEqual(expectedResult); - }); - - it("findMatch should return confidence and location of best match if no match with sufficient confidence is found", async () => { - // GIVEN - const imageLoader = new ImageReader(); - const SUT = new TemplateMatchingFinder(); - const haystackPath = path.resolve(__dirname, "./__mocks__/downloads.png"); - const needlePath = path.resolve(__dirname, "./__mocks__/coverage.png"); - const haystack = await imageLoader.load(haystackPath); - const minConfidence = 0.99; - const searchRegion = new Region(0, 0, 320, 72); - const matchRequest = new MatchRequest(haystack, needlePath, searchRegion, minConfidence); - const expectedRejection = new RegExp(`^No match with required confidence ${minConfidence}. Best match: \\d.\\d* at \\(\\d*, \\d*, \\d*, \\d*\\)$`) - - // WHEN - - // THEN - await expect(SUT.findMatch(matchRequest)) - .rejects - .toThrowError(expectedRejection); - }); - - it("findMatch should throw on invalid image paths", async () => { - // GIVEN - const imageLoader = new ImageReader(); - const SUT = new TemplateMatchingFinder(); - const pathToNeedle = path.resolve(__dirname, "./__mocks__/mouse.png"); - const pathToHaystack = "./__mocks__/foo.png"; - const needle = await imageLoader.load(pathToNeedle); - const minConfidence = 0.99; - const searchRegion = new Region(0, 0, 100, 100); - const haystack = new Image(needle.width, needle.height, needle.data, 3); - const matchRequest = new MatchRequest(haystack, pathToHaystack, searchRegion, minConfidence); - - // WHEN - const result = SUT.findMatch(matchRequest); - - // THEN - await expect(result) - .rejects - .toThrowError(`Failed to load ${pathToHaystack}. Reason: 'Failed to load image from '${pathToHaystack}''.`); - }); - - it("findMatch should reject, if needle was way lager than the haystack", async () => { - // GIVEN - const imageLoader = new ImageReader(); - const SUT = new TemplateMatchingFinder(); - const haystackPath = path.resolve(__dirname, "./__mocks__/mouse.png"); - const needlePath = path.resolve(__dirname, "./__mocks__/fat-needle.png"); - const haystack = await imageLoader.load(haystackPath); - const minConfidence = 0.99; - const searchRegion = new Region(0, 0, haystack.width, haystack.height); - const matchRequest = new MatchRequest(haystack, needlePath, searchRegion, minConfidence); - const expectedRejection = new Error("The provided image sample is larger than the provided search region") - - // WHEN - const findMatchPromise = SUT.findMatch(matchRequest); - - // THEN - await expect(findMatchPromise).rejects.toEqual(expectedRejection) - }); -}); diff --git a/lib/provider/opencv/template-matching-finder.class.ts b/lib/provider/opencv/template-matching-finder.class.ts deleted file mode 100755 index 4ea34976..00000000 --- a/lib/provider/opencv/template-matching-finder.class.ts +++ /dev/null @@ -1,189 +0,0 @@ -import * as cv from "opencv4nodejs-prebuilt"; -import * as path from "path"; -import {Image} from "../../image.class"; -import {MatchRequest} from "../../match-request.class"; -import {MatchResult} from "../../match-result.class"; -import {Region} from "../../region.class"; -import {ScaledMatchResult} from "../../scaled-match-result.class"; -import {DataSource} from "./data-source.interface"; -import {determineScaledSearchRegion} from "./determine-searchregion.function"; -import {FinderInterface} from "./finder.interface"; -import {ImageReader} from "./image-reader.class"; -import {matchImages} from "./match-image.function"; -import {scaleImage} from "./scale-image.function"; -import {scaleLocation} from "./scale-location.function"; -import {fromImageWithAlphaChannel, fromImageWithoutAlphaChannel} from "./image-processor.class"; - -async function loadNeedle(image: Image): Promise { - if (image.hasAlphaChannel) { - return fromImageWithAlphaChannel(image); - } - return fromImageWithoutAlphaChannel(image); -} - -async function loadHaystack(matchRequest: MatchRequest): Promise { - const searchRegion = determineScaledSearchRegion(matchRequest); - if (matchRequest.haystack.hasAlphaChannel) { - return fromImageWithAlphaChannel( - matchRequest.haystack, - searchRegion, - ); - } else { - return fromImageWithoutAlphaChannel( - matchRequest.haystack, - searchRegion, - ); - } -} - -function debugImage(image: cv.Mat, filename: string, suffix?: string) { - const parsedPath = path.parse(filename); - let fullFilename = parsedPath.name; - if (suffix) { - fullFilename = fullFilename + "_" + suffix; - } - fullFilename += parsedPath.ext; - const fullPath = path.join(parsedPath.dir, fullFilename); - cv.imwriteAsync(fullPath, image); -} - -// function debugResult(image: cv.Mat, result: MatchResult, filename: string, suffix?: string) { -// const roiRect = new cv.Rect( -// Math.min(Math.max(result.location.left, 0), image.cols), -// Math.min(Math.max(result.location.top, 0), image.rows), -// Math.min(result.location.width, image.cols - result.location.left), -// Math.min(result.location.height, image.rows - result.location.top)); -// debugImage(image.getRegion(roiRect), filename, suffix); -// } - -function isValidSearch(needle: cv.Mat, haystack: cv.Mat): boolean { - return (needle.cols <= haystack.cols) && (needle.rows <= haystack.rows); -} - -function createResultForInvalidSearch (currentScale: number) { - return new ScaledMatchResult(0, - currentScale, - new Region( - 0, - 0, - 0, - 0 - ), - new Error("The provided image sample is larger than the provided search region") - ) -} - -export default class TemplateMatchingFinder implements FinderInterface { - private initialScale = [1.0]; - private scaleSteps = [0.9, 0.8, 0.7, 0.6, 0.5]; - - constructor( - private source: DataSource = new ImageReader(), - ) { - } - - public async findMatches(matchRequest: MatchRequest, debug: boolean = false): Promise { - let needle: cv.Mat; - try { - const needleInput = await this.source.load(matchRequest.pathToNeedle); - needle = await loadNeedle(needleInput); - } catch (e) { - throw new Error( - `Failed to load ${matchRequest.pathToNeedle}. Reason: '${e}'.`, - ); - } - if (!needle || needle.empty) { - throw new Error( - `Failed to load ${matchRequest.pathToNeedle}, got empty image.`, - ); - } - const haystack = await loadHaystack(matchRequest); - - if (debug) { - debugImage(needle, "input_needle.png"); - debugImage(haystack, "input_haystack.png"); - } - - const matchResults = this.initialScale.map( - async (currentScale) => { - if (!isValidSearch(needle, haystack)) { - return createResultForInvalidSearch(currentScale); - } - const matchResult = await matchImages(haystack, needle); - return new ScaledMatchResult(matchResult.confidence, currentScale, matchResult.location); - } - ); - - if (matchRequest.searchMultipleScales) { - matchResults.push(...this.searchMultipleScales(needle, haystack)) - } - - return Promise.all(matchResults).then(results => { - results.forEach(matchResult => { - matchResult.location.left /= matchRequest.haystack.pixelDensity.scaleX; - matchResult.location.width /= matchRequest.haystack.pixelDensity.scaleX; - matchResult.location.top /= matchRequest.haystack.pixelDensity.scaleY; - matchResult.location.height /= matchRequest.haystack.pixelDensity.scaleY; - }); - return results.sort( - (first, second) => second.confidence - first.confidence, - ); - }); - } - - public async findMatch(matchRequest: MatchRequest, debug: boolean = false): Promise { - - const matches = await this.findMatches(matchRequest, debug); - const potentialMatches = matches - .filter(match => match.confidence >= matchRequest.confidence); - if (potentialMatches.length === 0) { - matches.sort((a, b) => a.confidence - b.confidence); - const bestMatch = matches.pop(); - if (bestMatch) { - if(bestMatch.error) { - throw bestMatch.error - }else { - throw new Error(`No match with required confidence ${matchRequest.confidence}. Best match: ${bestMatch.confidence} at ${bestMatch.location}`) - } - } else { - throw new Error(`Unable to locate ${matchRequest.pathToNeedle}, no match!`); - } - } - return potentialMatches[0]; - } - - private searchMultipleScales(needle: cv.Mat, haystack: cv.Mat) { - const scaledNeedleResult = this.scaleSteps.map( - async (currentScale) => { - const scaledNeedle = await scaleImage(needle, currentScale); - if (!isValidSearch(scaledNeedle, haystack)) { - return createResultForInvalidSearch(currentScale); - } - const matchResult = await matchImages(haystack, scaledNeedle); - return new ScaledMatchResult( - matchResult.confidence, - currentScale, - matchResult.location, - ); - } - ); - const scaledHaystackResult = this.scaleSteps.map( - async (currentScale) => { - const scaledHaystack = await scaleImage(haystack, currentScale); - if (!isValidSearch(needle, scaledHaystack)) { - return createResultForInvalidSearch(currentScale); - } - const matchResult = await matchImages(scaledHaystack, needle); - return new ScaledMatchResult( - matchResult.confidence, - currentScale, - scaleLocation( - matchResult.location, - currentScale - ) - ); - } - ); - return [...scaledHaystackResult, ...scaledNeedleResult]; - } -} diff --git a/lib/provider/provider-registry.class.ts b/lib/provider/provider-registry.class.ts new file mode 100644 index 00000000..17aa1c1f --- /dev/null +++ b/lib/provider/provider-registry.class.ts @@ -0,0 +1,181 @@ +import {ClipboardProviderInterface} from "./clipboard-provider.interface"; +import {ImageFinderInterface} from "./image-finder.interface"; +import {KeyboardProviderInterface} from "./keyboard-provider.interface"; +import {MouseProviderInterface} from "./mouse-provider.interface"; +import {ScreenProviderInterface} from "./screen-provider.interface"; +import {WindowProviderInterface} from "./window-provider.interface"; + +import Clipboard from "./native/clipboardy-clipboard.class"; +import Mouse from "./native/libnut-mouse.class"; +import Keyboard from "./native/libnut-keyboard.class"; +import Screen from "./native/libnut-screen.class"; +import Window from "./native/libnut-window.class"; +import {ImageReader} from "./image-reader.type"; +import {ImageWriter} from "./image-writer.type"; +import {ImageProcessor} from "./image-processor.interface"; + +import ImageReaderImpl from "./io/jimp-image-reader.class"; +import ImageWriterImpl from "./io/jimp-image-writer.class"; +import ImageProcessorImpl from "./image/jimp-image-processor.class"; + +export interface ProviderRegistry { + getClipboard(): ClipboardProviderInterface; + + registerClipboardProvider(value: ClipboardProviderInterface): void; + + getKeyboard(): KeyboardProviderInterface; + + registerKeyboardProvider(value: KeyboardProviderInterface): void; + + getMouse(): MouseProviderInterface; + + registerMouseProvider(value: MouseProviderInterface): void; + + getScreen(): ScreenProviderInterface; + + registerScreenProvider(value: ScreenProviderInterface): void; + + getWindow(): WindowProviderInterface; + + registerWindowProvider(value: WindowProviderInterface): void; + + getImageFinder(): ImageFinderInterface; + + registerImageFinder(value: ImageFinderInterface): void; + + getImageReader(): ImageReader; + + registerImageReader(value: ImageReader): void; + + getImageWriter(): ImageWriter; + + registerImageWriter(value: ImageWriter): void; + + getImageProcessor(): ImageProcessor; + + registerImageProcessor(value: ImageProcessor): void; +} + +class DefaultProviderRegistry implements ProviderRegistry { + private _clipboard?: ClipboardProviderInterface; + private _finder?: ImageFinderInterface; + private _keyboard?: KeyboardProviderInterface; + private _mouse?: MouseProviderInterface; + private _screen?: ScreenProviderInterface; + private _window?: WindowProviderInterface; + private _imageReader?: ImageReader; + private _imageWriter?: ImageWriter; + private _imageProcessor?: ImageProcessor; + + getClipboard(): ClipboardProviderInterface { + if (this._clipboard) { + return this._clipboard; + } + throw new Error(`No ClipboardProvider registered`); + } + + registerClipboardProvider(value: ClipboardProviderInterface) { + this._clipboard = value; + } + + getImageFinder(): ImageFinderInterface { + if (this._finder) { + return this._finder; + } + throw new Error(`No ImageFinder registered`); + } + + registerImageFinder(value: ImageFinderInterface) { + this._finder = value; + } + + getKeyboard(): KeyboardProviderInterface { + if (this._keyboard) { + return this._keyboard; + } + throw new Error(`No KeyboardProvider registered`); + } + + registerKeyboardProvider(value: KeyboardProviderInterface) { + this._keyboard = value; + } + + getMouse(): MouseProviderInterface { + if (this._mouse) { + return this._mouse; + } + throw new Error(`No MouseProvider registered`); + } + + registerMouseProvider(value: MouseProviderInterface) { + this._mouse = value; + } + + getScreen(): ScreenProviderInterface { + if (this._screen) { + return this._screen; + } + throw new Error(`No ScreenProvider registered`); + } + + registerScreenProvider(value: ScreenProviderInterface) { + this._screen = value; + } + + getWindow(): WindowProviderInterface { + if (this._window) { + return this._window; + } + throw new Error(`No WindowProvider registered`); + } + + registerWindowProvider(value: WindowProviderInterface) { + this._window = value; + } + + getImageReader(): ImageReader { + if (this._imageReader) { + return this._imageReader; + } + throw new Error(`No ImageReader registered`); + } + + registerImageReader(value: ImageReader) { + this._imageReader = value; + } + + getImageWriter(): ImageWriter { + if (this._imageWriter) { + return this._imageWriter; + } + throw new Error(`No ImageWriter registered`); + } + + registerImageWriter(value: ImageWriter) { + this._imageWriter = value; + } + + getImageProcessor(): ImageProcessor { + if (this._imageProcessor) { + return this._imageProcessor; + } + throw new Error(`No ImageProcessor registered`); + } + + registerImageProcessor(value: ImageProcessor): void { + this._imageProcessor = value; + } +} + +const providerRegistry = new DefaultProviderRegistry(); + +providerRegistry.registerClipboardProvider(new Clipboard()); +providerRegistry.registerKeyboardProvider(new Keyboard()); +providerRegistry.registerMouseProvider(new Mouse()); +providerRegistry.registerScreenProvider(new Screen()); +providerRegistry.registerWindowProvider(new Window()); +providerRegistry.registerImageWriter(new ImageWriterImpl()); +providerRegistry.registerImageReader(new ImageReaderImpl()); +providerRegistry.registerImageProcessor(new ImageProcessorImpl()); + +export default providerRegistry; \ No newline at end of file diff --git a/lib/provider/native/screen-action-provider.interface.ts b/lib/provider/screen-provider.interface.ts similarity index 89% rename from lib/provider/native/screen-action-provider.interface.ts rename to lib/provider/screen-provider.interface.ts index 2eb390df..367ad65f 100644 --- a/lib/provider/native/screen-action-provider.interface.ts +++ b/lib/provider/screen-provider.interface.ts @@ -1,12 +1,12 @@ -import { Image } from "../../image.class"; -import { Region } from "../../region.class"; +import { Image } from "../image.class"; +import { Region } from "../region.class"; /** * A ScreenActionProvider should provide access to a system's main screen * - * @interface ScreenActionProvider + * @interface ScreenProviderInterface */ -export interface ScreenActionProvider { +export interface ScreenProviderInterface { /** * grabScreen should return an {@link Image} object containing a screenshot data of a systems * main screen as well as its dimensions diff --git a/lib/provider/native/window-action-provider.interface.ts b/lib/provider/window-provider.interface.ts similarity index 90% rename from lib/provider/native/window-action-provider.interface.ts rename to lib/provider/window-provider.interface.ts index 0d5e3e42..f6e4880d 100644 --- a/lib/provider/native/window-action-provider.interface.ts +++ b/lib/provider/window-provider.interface.ts @@ -1,11 +1,11 @@ -import { Region } from "../../region.class"; +import { Region } from "../region.class"; /** * A WindowActionProvider should provide access to a system's window system * - * @interface WindowActionProvider + * @interface WindowProviderInterface */ -export interface WindowActionProvider { +export interface WindowProviderInterface { /** * {@link getWindows} returns a list of window handles for further processing. * These window handles may serve as input to e.g. {@link getWindowTitle} diff --git a/lib/region.class.spec.ts b/lib/region.class.spec.ts index df1c0b64..077f46d1 100644 --- a/lib/region.class.spec.ts +++ b/lib/region.class.spec.ts @@ -1,7 +1,7 @@ import { Region } from "./region.class"; describe("Region", () => { - it("should calcutate the correct area of a region", () => { + it("should calculate the correct area of a region", () => { const region = new Region(0, 0, 100, 100); const expected = 10000; @@ -14,56 +14,4 @@ describe("Region", () => { expect(region.toString()).toEqual(expected); }); - - it("should scale and translate in x", () => { - const scaleFactor = 2.0; - const region = new Region(100, 100, 100, 100); - const result = Region.scaled(region, scaleFactor); - - expect(result.left).toBeCloseTo(region.left * scaleFactor); - expect(result.width).toBeCloseTo(region.width * scaleFactor); - expect(result.top).toBeCloseTo(region.top); - expect(result.height).toBeCloseTo(region.height); - }); - - it("should scale and translate in y", () => { - const scaleFactor = 2.0; - const region = new Region(200, 250, 100, 100); - const result = Region.scaled(region, undefined, scaleFactor); - - expect(result.left).toBeCloseTo(region.left); - expect(result.width).toBeCloseTo(region.width); - expect(result.top).toBeCloseTo(region.top * scaleFactor); - expect(result.height).toBeCloseTo(region.height * scaleFactor); - }); - - it("should scale and translate in both x and y", () => { - const scaleFactorX = 1.75; - const scaleFactorY = 2.5; - const region = new Region(300, 720, 100, 100); - const result = Region.scaled(region, scaleFactorX, scaleFactorY); - - expect(result.left).toBeCloseTo(region.left * scaleFactorX); - expect(result.width).toBeCloseTo(region.width * scaleFactorX); - expect(result.top).toBeCloseTo(region.top * scaleFactorY); - expect(result.height).toBeCloseTo(region.height * scaleFactorY); - }); - - it("should throw an error when scaling to 0 in x", () => { - const scaleFactorX = 0.0; - const scaleFactorY = 2.5; - const region = new Region(300, 720, 100, 100); - expect(() => Region.scaled(region, scaleFactorX, scaleFactorY)).toThrow( - `Scaling to 0. Please check parameters: scaleX: ${scaleFactorX}, scaleY: ${scaleFactorY}`, - ); - }); - - it("should throw an error when scaling to 0 in y", () => { - const scaleFactorX = 2.5; - const scaleFactorY = 0.0; - const region = new Region(300, 720, 100, 100); - expect(() => Region.scaled(region, scaleFactorX, scaleFactorY)).toThrow( - `Scaling to 0. Please check parameters: scaleX: ${scaleFactorX}, scaleY: ${scaleFactorY}`, - ); - }); }); diff --git a/lib/region.class.ts b/lib/region.class.ts index a3e22c71..8dd15f4a 100644 --- a/lib/region.class.ts +++ b/lib/region.class.ts @@ -1,22 +1,4 @@ export class Region { - public static scaled( - region: Region, - scaleX: number = 1.0, - scaleY: number = 1.0, - ): Region { - if (scaleX === 0 || scaleY === 0) { - throw new Error( - `Scaling to 0. Please check parameters: scaleX: ${scaleX}, scaleY: ${scaleY}`, - ); - } - return new Region( - region.left * scaleX, - region.top * scaleY, - region.width * scaleX, - region.height * scaleY, - ); - } - constructor( public left: number, public top: number, @@ -29,7 +11,6 @@ export class Region { } public toString() { - return `(${this.left}, ${this.top}, ${this.left + this.width}, ${this.top + - this.height})`; + return `(${this.left}, ${this.top}, ${this.width}, ${this.height})`; } } diff --git a/lib/rgba.class.ts b/lib/rgba.class.ts new file mode 100644 index 00000000..9e40a245 --- /dev/null +++ b/lib/rgba.class.ts @@ -0,0 +1,13 @@ +export class RGBA { + constructor(public readonly R: number, public readonly G: number, public readonly B: number, public readonly A: number) { + } + + public toString(): string { + return `rgb(${this.R},${this.G},${this.B})`; + } + + public toHex(): string { + return `#${this.R.toString(16).padStart(2, '0')}${this.G.toString(16).padStart(2, '0')}${this.B.toString(16).padStart(2, '0')}${this.A.toString(16).padStart(2, '0')}` + } +} + diff --git a/lib/screen.class.e2e.spec.ts b/lib/screen.class.e2e.spec.ts deleted file mode 100644 index d575c9cc..00000000 --- a/lib/screen.class.e2e.spec.ts +++ /dev/null @@ -1,138 +0,0 @@ -import {existsSync} from "fs"; -import {VisionAdapter} from "./adapter/vision.adapter.class"; -import {FileType} from "./file-type.enum"; -import {Screen} from "./screen.class"; -import {sleep} from "./sleep.function"; -import AbortController from "node-abort-controller"; - -describe("Screen.", () => { - it("should capture the screen", () => { - // GIVEN - const visionAdapter = new VisionAdapter(); - const SUT = new Screen(visionAdapter); - - // WHEN - SUT.capture("asdf", FileType.PNG).then(filename => { - // THEN - expect(filename).not.toBeNull(); - sleep(1000).then(() => { - expect(existsSync(filename)).toBeTruthy(); - }); - }); - }); - - it("should capture the screen and save to JPG", () => { - // GIVEN - const visionAdapter = new VisionAdapter(); - const SUT = new Screen(visionAdapter); - - // WHEN - SUT.capture("asdf", FileType.JPG).then(filename => { - // THEN - expect(filename).not.toBeNull(); - sleep(1000).then(() => { - expect(existsSync(filename)).toBeTruthy(); - }); - }); - }); - - it("should capture the screen and save file with prefix", () => { - // GIVEN - const visionAdapter = new VisionAdapter(); - const SUT = new Screen(visionAdapter); - const prefix = "foo_"; - - // WHEN - SUT.capture("asdf", FileType.JPG, "./", prefix).then(filename => { - // THEN - expect(filename.includes(prefix)).toBeTruthy(); - expect(filename).not.toBeNull(); - sleep(1000).then(() => { - expect(existsSync(filename)).toBeTruthy(); - }); - }); - }); - - it("should capture the screen and save file with postfix", () => { - // GIVEN - const visionAdapter = new VisionAdapter(); - const SUT = new Screen(visionAdapter); - const postfix = "_bar"; - - // WHEN - SUT.capture("asdf", FileType.JPG, "./", "", postfix).then(filename => { - // THEN - expect(filename.includes(postfix)).toBeTruthy(); - expect(filename).not.toBeNull(); - sleep(1000).then(() => { - expect(existsSync(filename)).toBeTruthy(); - }); - }); - }); - - it("should capture the screen and save file with pre- and postfix", () => { - // GIVEN - const visionAdapter = new VisionAdapter(); - const SUT = new Screen(visionAdapter); - const filename = "asdf"; - const prefix = "foo_"; - const postfix = "_bar"; - - // WHEN - SUT.capture("asdf", FileType.JPG, "./", prefix, postfix).then(output => { - // THEN - expect(output.includes(`${prefix}${filename}${postfix}`)).toBeTruthy(); - expect(output).not.toBeNull(); - sleep(1000).then(() => { - expect(existsSync(output)).toBeTruthy(); - }); - }); - }); - - it("should reject after timeout", async () => { - // GIVEN - jest.setTimeout(10000); - const timeout = 5000; - const visionAdapter = new VisionAdapter(); - const SUT = new Screen(visionAdapter); - SUT.config.resourceDirectory = "./e2e/assets"; - - // WHEN - const start = Date.now(); - try { - await SUT.waitFor("calculator.png", timeout); - } catch (e) { - // THEN - expect(e).toBe(`Action timed out after ${timeout} ms`); - } - const end = Date.now(); - - // THEN - expect(end - start).toBeGreaterThanOrEqual(timeout); - }); - - it("should abort via signal", (done) => { - // GIVEN - jest.setTimeout(10000); - const timeout = 5000; - const abortAfterMs = 1000; - const controller = new AbortController(); - const signal = controller.signal; - const visionAdapter = new VisionAdapter(); - const SUT = new Screen(visionAdapter); - SUT.config.resourceDirectory = "./e2e/assets"; - - // WHEN - const start = Date.now(); - SUT.waitFor("calculator.png", timeout, {abort: signal}).catch(e => { - const end = Date.now(); - - // THEN - expect(e).toBe(`Action aborted by signal`); - expect(end - start).toBeGreaterThanOrEqual(abortAfterMs); - expect(end - start).toBeLessThan(timeout); - done(); - }); - setTimeout(() => controller.abort(), abortAfterMs); - }); -}); diff --git a/lib/screen.class.spec.ts b/lib/screen.class.spec.ts index 29e735f4..0c162d94 100644 --- a/lib/screen.class.spec.ts +++ b/lib/screen.class.spec.ts @@ -1,75 +1,79 @@ -import { join } from "path"; -import { cwd } from "process"; -import { VisionAdapter } from "./adapter/vision.adapter.class"; -import { Image } from "./image.class"; -import { LocationParameters } from "./locationparameters.class"; -import { MatchRequest } from "./match-request.class"; -import { MatchResult } from "./match-result.class"; -import { Region } from "./region.class"; -import { Screen } from "./screen.class"; -import { mockPartial } from "sneer"; -import { FileType } from "./file-type.enum"; - -jest.mock("./adapter/native.adapter.class"); -jest.mock("./adapter/vision.adapter.class"); +import {join} from "path"; +import {cwd} from "process"; +import {Image} from "./image.class"; +import {MatchRequest} from "./match-request.class"; +import {MatchResult} from "./match-result.class"; +import {Region} from "./region.class"; +import {ScreenClass} from "./screen.class"; +import {mockPartial} from "sneer"; +import {ProviderRegistry} from "./provider/provider-registry.class"; +import {ImageFinderInterface, ImageWriter, ImageWriterParameters, ScreenProviderInterface} from "./provider"; +import {OptionalSearchParameters} from "./optionalsearchparameters.class"; + +jest.mock('jimp', () => { +}); const searchRegion = new Region(0, 0, 1000, 1000); -beforeAll(() => { - VisionAdapter.prototype.grabScreen = jest.fn(() => { - return Promise.resolve(new Image(searchRegion.width, searchRegion.height, new ArrayBuffer(0), 3)); - }); +const providerRegistryMock = mockPartial({ + getScreen(): ScreenProviderInterface { + return mockPartial({ + grabScreenRegion(): Promise { + return Promise.resolve(new Image(searchRegion.width, searchRegion.height, Buffer.from([]), 3, "needle_image")); + }, + screenSize(): Promise { + return Promise.resolve(searchRegion); + } + }) + } +}); - VisionAdapter.prototype.screenSize = jest.fn(() => { - return Promise.resolve(searchRegion); - }); +beforeEach(() => { + jest.resetAllMocks(); }); describe("Screen.", () => { - describe("find", () => { it("should resolve with sufficient confidence.", async () => { - // GIVEN const matchResult = new MatchResult(0.99, searchRegion); - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.resolve(matchResult); - }); - const visionAdapterMock = new VisionAdapter(); - const SUT = new Screen(visionAdapterMock); - const imagePath = "test/path/to/image.png"; + const SUT = new ScreenClass(providerRegistryMock); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + const needlePromise = Promise.resolve(needle); + const findMatchMock = jest.fn(() => Promise.resolve(matchResult)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); // WHEN - const resultRegion = SUT.find(imagePath); + const resultRegion = SUT.find(needlePromise); // THEN await expect(resultRegion).resolves.toEqual(matchResult.location); const matchRequest = new MatchRequest( expect.any(Image), - join(cwd(), imagePath), - searchRegion, + needle, SUT.config.confidence, true); - expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(matchRequest); + expect(findMatchMock).toHaveBeenCalledWith(matchRequest); }); it("should call registered hook before resolve", async () => { - // GIVEN const matchResult = new MatchResult(0.99, searchRegion); - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.resolve(matchResult); - }); - const visionAdapterMock = new VisionAdapter(); + const findMatchMock = jest.fn(() => Promise.resolve(matchResult)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); - const SUT = new Screen(visionAdapterMock); + const SUT = new ScreenClass(providerRegistryMock); const testCallback = jest.fn(() => Promise.resolve()); - const imagePath = "test/path/to/image.png"; - SUT.on(imagePath, testCallback); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + SUT.on(needle, testCallback); // WHEN - await SUT.find(imagePath); + await SUT.find(needle); // THEN expect(testCallback).toBeCalledTimes(1); @@ -77,23 +81,22 @@ describe("Screen.", () => { }); it("should call multiple registered hooks before resolve", async () => { - // GIVEN const matchResult = new MatchResult(0.99, searchRegion); - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.resolve(matchResult); - }); - const visionAdapterMock = new VisionAdapter(); + const findMatchMock = jest.fn(() => Promise.resolve(matchResult)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); - const SUT = new Screen(visionAdapterMock); + const SUT = new ScreenClass(providerRegistryMock); const testCallback = jest.fn(() => Promise.resolve()); const secondCallback = jest.fn(() => Promise.resolve()); - const imagePath = "test/path/to/image.png"; - SUT.on(imagePath, testCallback); - SUT.on(imagePath, secondCallback); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + SUT.on(needle, testCallback); + SUT.on(needle, secondCallback); // WHEN - await SUT.find(imagePath); + await SUT.find(needle); // THEN for (const callback of [testCallback, secondCallback]) { @@ -105,48 +108,47 @@ describe("Screen.", () => { it("should reject with insufficient confidence.", async () => { // GIVEN - const matchResult = new MatchResult(0.8, searchRegion); - - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.resolve(matchResult); - }); - - const visionAdapterMock = new VisionAdapter(); - - const SUT = new Screen(visionAdapterMock); - const imagePath = "test/path/to/image.png"; + const minConfidence = 0.95; + const failingConfidence = 0.8; + const expectedReason = `No match with required confidence ${minConfidence}. Best match: ${failingConfidence}`; + const findMatchMock = jest.fn(() => Promise.reject(expectedReason)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + const id = "needle_image"; + const needle = new Image(100, 100, Buffer.from([]), 3, id); // WHEN - const resultRegion = SUT.find(imagePath); + const resultRegion = SUT.find(needle, {confidence: minConfidence}); // THEN await expect(resultRegion) .rejects - .toEqual(`No match for ${imagePath}. Required: ${SUT.config.confidence}, given: ${matchResult.confidence}`); + .toEqual(`Searching for ${id} failed. Reason: '${expectedReason}'`); }); it("should reject when search fails.", async () => { // GIVEN const rejectionReason = "Search failed."; - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.reject(rejectionReason); - }); + const findMatchMock = jest.fn(() => Promise.reject(rejectionReason)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); - const visionAdapterMock = new VisionAdapter(); - - const SUT = new Screen(visionAdapterMock); - const imagePath = "test/path/to/image.png"; + const SUT = new ScreenClass(providerRegistryMock); + const id = "needle_image"; + const needle = new Image(100, 100, Buffer.from([]), 3, id); // WHEN - const resultRegion = SUT.find(imagePath); + const resultRegion = SUT.find(needle); // THEN await expect(resultRegion) .rejects - .toEqual(`Searching for ${imagePath} failed. Reason: '${rejectionReason}'`); - - + .toEqual(`Searching for ${id} failed. Reason: '${rejectionReason}'`); }); it("should override default confidence value with parameter.", async () => { @@ -155,78 +157,79 @@ describe("Screen.", () => { const minMatch = 0.8; const matchResult = new MatchResult(minMatch, searchRegion); - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.resolve(matchResult); - }); - - const visionAdapterMock = new VisionAdapter(); + const findMatchMock = jest.fn(() => Promise.resolve(matchResult)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); - const SUT = new Screen(visionAdapterMock); + const SUT = new ScreenClass(providerRegistryMock); - const imagePath = "test/path/to/image.png"; - const parameters = new LocationParameters(undefined, minMatch); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + const parameters = new OptionalSearchParameters(undefined, minMatch); // WHEN - const resultRegion = SUT.find(imagePath, parameters); + const resultRegion = SUT.find(needle, parameters); // THEN await expect(resultRegion).resolves.toEqual(matchResult.location); const matchRequest = new MatchRequest( expect.any(Image), - join(cwd(), imagePath), - searchRegion, + needle, minMatch, true); - expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(matchRequest); + expect(findMatchMock).toHaveBeenCalledWith(matchRequest); }); it("should override default search region with parameter.", async () => { // GIVEN const customSearchRegion = new Region(10, 10, 90, 90); const matchResult = new MatchResult(0.99, searchRegion); - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.resolve(matchResult); - }); - const visionAdapterMock = new VisionAdapter(); - const SUT = new Screen(visionAdapterMock); - const imagePath = "test/path/to/image.png"; - const parameters = new LocationParameters(customSearchRegion); + + const findMatchMock = jest.fn(() => Promise.resolve(matchResult)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + const parameters = new OptionalSearchParameters(customSearchRegion); const expectedMatchRequest = new MatchRequest( expect.any(Image), - join(cwd(), imagePath), - customSearchRegion, + needle, SUT.config.confidence, true); // WHEN - await SUT.find(imagePath, parameters); + await SUT.find(needle, parameters); // THEN - expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(expectedMatchRequest); + expect(findMatchMock).toHaveBeenCalledWith(expectedMatchRequest); }); it("should override searchMultipleScales with parameter.", async () => { // GIVEN const matchResult = new MatchResult(0.99, searchRegion); - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.resolve(matchResult); - }); - const visionAdapterMock = new VisionAdapter(); - const SUT = new Screen(visionAdapterMock); - const imagePath = "test/path/to/image.png"; - const parameters = new LocationParameters(searchRegion, undefined, false); + const findMatchMock = jest.fn(() => Promise.resolve(matchResult)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + + const parameters = new OptionalSearchParameters(searchRegion, undefined, false); const expectedMatchRequest = new MatchRequest( expect.any(Image), - join(cwd(), imagePath), - searchRegion, + needle, SUT.config.confidence, false); // WHEN - await SUT.find(imagePath, parameters); + await SUT.find(needle, parameters); // THEN - expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(expectedMatchRequest); + expect(findMatchMock).toHaveBeenCalledWith(expectedMatchRequest); }); it("should override both confidence and search region with parameter.", async () => { @@ -234,29 +237,28 @@ describe("Screen.", () => { const minMatch = 0.8; const customSearchRegion = new Region(10, 10, 90, 90); const matchResult = new MatchResult(minMatch, searchRegion); - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.resolve(matchResult); - }); - const visionAdapterMock = new VisionAdapter(); - const SUT = new Screen(visionAdapterMock); - const imagePath = "test/path/to/image.png"; - const parameters = new LocationParameters(customSearchRegion, minMatch); + const findMatchMock = jest.fn(() => Promise.resolve(matchResult)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + const parameters = new OptionalSearchParameters(customSearchRegion, minMatch); const expectedMatchRequest = new MatchRequest( expect.any(Image), - join(cwd(), imagePath), - customSearchRegion, + needle, minMatch, true); // WHEN - await SUT.find(imagePath, parameters); + await SUT.find(needle, parameters); // THEN - expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(expectedMatchRequest); + expect(findMatchMock).toHaveBeenCalledWith(expectedMatchRequest); }); it("should add search region offset to result image location", async () => { - // GIVEN const limitedSearchRegion = new Region(100, 200, 300, 400); const resultRegion = new Region(50, 100, 150, 200); @@ -268,17 +270,19 @@ describe("Screen.", () => { resultRegion.width, resultRegion.height); - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.resolve(matchResult); - }); - const SUT = new Screen(new VisionAdapter()); + const findMatchMock = jest.fn(() => Promise.resolve(matchResult)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); + const SUT = new ScreenClass(providerRegistryMock); // WHEN const matchRegion = await SUT.find( - "test/path/to/image.png", + new Image(100, 100, Buffer.from([]), 3, "needle_image"), { searchRegion: limitedSearchRegion - }); + } + ); // THEN expect(matchRegion).toEqual(expectedMatchRegion); @@ -301,39 +305,287 @@ describe("Screen.", () => { ["with NaN y coordinate", new Region(0, "a" as unknown as number, 100, 600)], ["with NaN on width", new Region(0, 0, "a" as unknown as number, 100)], ["with NaN on height", new Region(0, 0, 100, "a" as unknown as number)], - ])("should reject search regions %s", async (_, region) =>{ + ])("should reject search regions %s", async (_, region) => { + // GIVEN + const id = "needle_image"; + const needle = new Image(100, 100, Buffer.from([]), 3, id); + const matchResult = new MatchResult(0.99, region); + const findMatchMock = jest.fn(() => Promise.resolve(matchResult)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatch: findMatchMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + + // WHEN + const findPromise = SUT.find( + needle, + { + searchRegion: region + }); + + // THEN + await expect(findPromise).rejects.toContain(`Searching for ${id} failed. Reason:`); + }) + }); + + describe("findAll", () => { + it("should call registered hook before resolve", async () => { + // GIVEN + const matchResult = new MatchResult(0.99, searchRegion); + const matchResults = [matchResult, matchResult, matchResult]; + const findMatchesMock = jest.fn(() => Promise.resolve(matchResults)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatches: findMatchesMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + const testCallback = jest.fn(() => Promise.resolve()); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + SUT.on(needle, testCallback); + + // WHEN + await SUT.findAll(needle); + + // THEN + expect(testCallback).toBeCalledTimes(matchResults.length); + expect(testCallback).toBeCalledWith(matchResult); + }); + + it("should call multiple registered hooks before resolve", async () => { + // GIVEN + const matchResult = new MatchResult(0.99, searchRegion); + const matchResults = [matchResult, matchResult, matchResult]; + const findMatchesMock = jest.fn(() => Promise.resolve(matchResults)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatches: findMatchesMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + const testCallback = jest.fn(() => Promise.resolve()); + const secondCallback = jest.fn(() => Promise.resolve()); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + SUT.on(needle, testCallback); + SUT.on(needle, secondCallback); + + // WHEN + await SUT.findAll(needle); + + // THEN + for (const callback of [testCallback, secondCallback]) { + expect(callback).toBeCalledTimes(matchResults.length); + expect(callback).toBeCalledWith(matchResult); + } + }); + + it("should reject when search fails.", async () => { + + // GIVEN + const rejectionReason = "Search failed."; + const findMatchesMock = jest.fn(() => Promise.reject(rejectionReason)); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatches: findMatchesMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + const id = "needle_image"; + const needle = new Image(100, 100, Buffer.from([]), 3, id); + + // WHEN + const resultRegion = SUT.findAll(needle); + + // THEN + await expect(resultRegion) + .rejects + .toEqual(`Searching for ${id} failed. Reason: '${rejectionReason}'`); + }); + + it("should override default confidence value with parameter.", async () => { + // GIVEN + const minMatch = 0.8; + const matchResult = new MatchResult(minMatch, searchRegion); + + const findMatchesMock = jest.fn(() => Promise.resolve([matchResult])); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatches: findMatchesMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + const parameters = new OptionalSearchParameters(undefined, minMatch); + + // WHEN + const [resultRegion] = await SUT.findAll(needle, parameters); + + // THEN + expect(resultRegion).toEqual(matchResult.location); + const matchRequest = new MatchRequest( + expect.any(Image), + needle, + minMatch, + true); + expect(findMatchesMock).toHaveBeenCalledWith(matchRequest); + }); + it("should override default search region with parameter.", async () => { // GIVEN - const imagePath = "test/path/to/image.png" - const visionAdapterMock = new VisionAdapter(); + const customSearchRegion = new Region(10, 10, 90, 90); + const matchResult = new MatchResult(0.99, searchRegion); + + const findMatchesMock = jest.fn(() => Promise.resolve([matchResult])); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatches: findMatchesMock + })); - const SUT = new Screen(visionAdapterMock); + const SUT = new ScreenClass(providerRegistryMock); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + const parameters = new OptionalSearchParameters(customSearchRegion); + const expectedMatchRequest = new MatchRequest( + expect.any(Image), + needle, + SUT.config.confidence, + true); + + // WHEN + await SUT.findAll(needle, parameters); + + // THEN + expect(findMatchesMock).toHaveBeenCalledWith(expectedMatchRequest); + }); + + it("should override searchMultipleScales with parameter.", async () => { + // GIVEN + const matchResult = new MatchResult(0.99, searchRegion); + const findMatchesMock = jest.fn(() => Promise.resolve([matchResult])); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatches: findMatchesMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + + const parameters = new OptionalSearchParameters(searchRegion, undefined, false); + const expectedMatchRequest = new MatchRequest( + expect.any(Image), + needle, + SUT.config.confidence, + false); + + // WHEN + await SUT.findAll(needle, parameters); + + // THEN + expect(findMatchesMock).toHaveBeenCalledWith(expectedMatchRequest); + }); + + it("should override both confidence and search region with parameter.", async () => { + // GIVEN + const minMatch = 0.8; + const customSearchRegion = new Region(10, 10, 90, 90); + const matchResult = new MatchResult(minMatch, searchRegion); + const findMatchesMock = jest.fn(() => Promise.resolve([matchResult])); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatches: findMatchesMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image"); + const parameters = new OptionalSearchParameters(customSearchRegion, minMatch); + const expectedMatchRequest = new MatchRequest( + expect.any(Image), + needle, + minMatch, + true); + + // WHEN + await SUT.findAll(needle, parameters); + + // THEN + expect(findMatchesMock).toHaveBeenCalledWith(expectedMatchRequest); + }); + + it("should add search region offset to result image location", async () => { + // GIVEN + const limitedSearchRegion = new Region(100, 200, 300, 400); + const resultRegion = new Region(50, 100, 150, 200); + const matchResult = new MatchResult(0.99, resultRegion); + + const expectedMatchRegion = new Region( + limitedSearchRegion.left + resultRegion.left, + limitedSearchRegion.top + resultRegion.top, + resultRegion.width, + resultRegion.height); + + const findMatchesMock = jest.fn(() => Promise.resolve([matchResult])); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatches: findMatchesMock + })); + + const SUT = new ScreenClass(providerRegistryMock); + // WHEN + const [matchRegion] = await SUT.findAll( + new Image(100, 100, Buffer.from([]), 3, "needle_image"), + { + searchRegion: limitedSearchRegion + } + ); + + // THEN + expect(matchRegion).toEqual(expectedMatchRegion); + }) + + it.each([ + ["with negative x coordinate", new Region(-1, 0, 100, 100)], + ["with negative y coordinate", new Region(0, -1, 100, 100)], + ["with negative width", new Region(0, 0, -100, 100)], + ["with negative height", new Region(0, 0, 100, -100)], + ["with region outside screen on x axis", new Region(1100, 0, 100, 100)], + ["with region outside screen on y axis", new Region(0, 1100, 100, 100)], + ["with region bigger than screen on x axis", new Region(0, 0, 1100, 100)], + ["with region bigger than screen on y axis", new Region(0, 0, 1000, 1100)], + ["with region of 1 px width", new Region(0, 0, 1, 1100)], + ["with region of 1 px height", new Region(0, 0, 100, 1)], + ["with region leaving screen on x axis", new Region(600, 0, 500, 100)], + ["with region leaving screen on y axis", new Region(0, 500, 100, 600)], + ["with NaN x coordinate", new Region("a" as unknown as number, 0, 100, 100)], + ["with NaN y coordinate", new Region(0, "a" as unknown as number, 100, 600)], + ["with NaN on width", new Region(0, 0, "a" as unknown as number, 100)], + ["with NaN on height", new Region(0, 0, 100, "a" as unknown as number)], + ])("should reject search regions %s", async (_, region) => { + // GIVEN + const id = "needle_image"; + const needle = new Image(100, 100, Buffer.from([]), 3, id); const matchResult = new MatchResult(0.99, region); - VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => { - return Promise.resolve(matchResult); - }); + const findMatchesMock = jest.fn(() => Promise.resolve([matchResult])); + providerRegistryMock.getImageFinder = jest.fn(() => mockPartial({ + findMatches: findMatchesMock + })); + + const SUT = new ScreenClass(providerRegistryMock); // WHEN - const findPromise = SUT.find( - imagePath, + const findPromise = SUT.findAll( + needle, { searchRegion: region }); // THEN - await expect(findPromise).rejects.toContain(`Searching for ${imagePath} failed. Reason:`); + await expect(findPromise).rejects.toContain(`Searching for ${id} failed. Reason:`); }) }); - it("should return region to highlight for chaining", async () => { // GIVEN const highlightRegion = new Region(10, 20, 30, 40); - VisionAdapter.prototype.highlightScreenRegion = jest.fn(); - const visionAdapterMock = new VisionAdapter(); - const SUT = new Screen(visionAdapterMock); + const highlightMock = jest.fn((value: any) => Promise.resolve(value)); + providerRegistryMock.getScreen = jest.fn(() => mockPartial({ + highlightScreenRegion: highlightMock + })); + const SUT = new ScreenClass(providerRegistryMock); // WHEN const result = await SUT.highlight(highlightRegion); @@ -345,9 +597,12 @@ describe("Screen.", () => { // GIVEN const highlightRegion = new Region(10, 20, 30, 40); const highlightRegionPromise = new Promise(res => res(highlightRegion)); - VisionAdapter.prototype.highlightScreenRegion = jest.fn(); - const visionAdapterMock = new VisionAdapter(); - const SUT = new Screen(visionAdapterMock); + const highlightMock = jest.fn((value: any) => Promise.resolve(value)); + providerRegistryMock.getScreen = jest.fn(() => mockPartial({ + highlightScreenRegion: highlightMock + })); + + const SUT = new ScreenClass(providerRegistryMock); // WHEN const result = await SUT.highlight(highlightRegionPromise); @@ -356,85 +611,60 @@ describe("Screen.", () => { expect(result).toEqual(highlightRegion); }); - describe("capture",() => { - it("should capture the whole screen and save image", async() => { - + describe("capture", () => { + it("should capture the whole screen and save image", async () => { // GIVEN - const screenshot = mockPartial({data: "pretty pretty image"}); - VisionAdapter.prototype.grabScreen = jest.fn(() => Promise.resolve(screenshot)); - VisionAdapter.prototype.saveImage = jest.fn(); - const visionAdapterMock = new VisionAdapter(); - const SUT = new Screen(visionAdapterMock); + const screenshot = mockPartial({data: Buffer.from([])}); + const grabScreenMock = jest.fn(() => Promise.resolve(screenshot)); + const saveImageMock = jest.fn(); + providerRegistryMock.getScreen = jest.fn(() => mockPartial({ + grabScreen: grabScreenMock + })); + providerRegistryMock.getImageWriter = jest.fn(() => mockPartial({ + store: saveImageMock + })); + + const SUT = new ScreenClass(providerRegistryMock); const imageName = "foobar.png" const expectedImagePath = join(cwd(), imageName) + const expectedData: ImageWriterParameters = {image: screenshot, path: expectedImagePath} // WHEN const imagePath = await SUT.capture(imageName) // THEN expect(imagePath).toBe(expectedImagePath) - expect(VisionAdapter.prototype.grabScreen).toHaveBeenCalled() - expect(VisionAdapter.prototype.saveImage).toHaveBeenCalledWith(screenshot,expectedImagePath) - }) - - it("should consider output configuration", async () => { - - // GIVEN - const visionAdapterMock = new VisionAdapter(); - const SUT = new Screen(visionAdapterMock); - const imageName = "foobar" - const filePath = "/path/to/file" - const prefix = "answer_" - const postfix = "_42" - const expectedImagePath = join(filePath, `${prefix}${imageName}${postfix}${FileType.JPG.toString()}`) - - // WHEN - const imagePath = await SUT.capture(imageName, FileType.JPG, filePath, prefix, postfix) - - // THEN - expect(imagePath).toBe(expectedImagePath) - }) + expect(grabScreenMock).toHaveBeenCalled() + expect(saveImageMock).toHaveBeenCalledWith(expectedData); + }); }) describe("captureRegion", () => { - it("should capture the specified region of the screen and save image", async () => { // GIVEN - const screenshot = mockPartial({data: "pretty partial image"}); - const regionToCapture = mockPartial({top:42, left:9, height: 10, width: 3.14159265359}) - VisionAdapter.prototype.grabScreenRegion = jest.fn(() => Promise.resolve(screenshot)); - VisionAdapter.prototype.saveImage = jest.fn(); - const visionAdapterMock = new VisionAdapter(); - const SUT = new Screen(visionAdapterMock); + const screenshot = mockPartial({data: Buffer.from([])}); + const regionToCapture = mockPartial({top: 42, left: 9, height: 10, width: 3.14159265359}) + const grabScreenMock = jest.fn(() => Promise.resolve(screenshot)); + const saveImageMock = jest.fn(); + providerRegistryMock.getScreen = jest.fn(() => mockPartial({ + grabScreenRegion: grabScreenMock + })); + providerRegistryMock.getImageWriter = jest.fn(() => mockPartial({ + store: saveImageMock + })); + + const SUT = new ScreenClass(providerRegistryMock); const imageName = "foobar.png" const expectedImagePath = join(cwd(), imageName) + const expectedData: ImageWriterParameters = {image: screenshot, path: expectedImagePath} // WHEN const imagePath = await SUT.captureRegion(imageName, regionToCapture) // THEN expect(imagePath).toBe(expectedImagePath) - expect(VisionAdapter.prototype.grabScreenRegion).toHaveBeenCalledWith(regionToCapture) - expect(VisionAdapter.prototype.saveImage).toHaveBeenCalledWith(screenshot,expectedImagePath) - }) - - it("should consider output configuration", async () => { - - // GIVEN - const regionToCapture = mockPartial({top:42, left:9, height: 10, width: 3.14159265359}) - const visionAdapterMock = new VisionAdapter(); - const SUT = new Screen(visionAdapterMock); - const imageName = "foobar" - const filePath = "/path/to/file" - const prefix = "answer_" - const postfix = "_42" - const expectedImagePath = join(filePath, `${prefix}${imageName}${postfix}${FileType.JPG.toString()}`) - - // WHEN - const imagePath = await SUT.captureRegion(imageName, regionToCapture, FileType.JPG, filePath, prefix, postfix) - - // THEN - expect(imagePath).toBe(expectedImagePath) - }) - }) + expect(grabScreenMock).toHaveBeenCalledWith(regionToCapture) + expect(saveImageMock).toHaveBeenCalledWith(expectedData); + }); + }); }); diff --git a/lib/screen.class.ts b/lib/screen.class.ts index 1fe231a1..e095db9a 100644 --- a/lib/screen.class.ts +++ b/lib/screen.class.ts @@ -1,24 +1,40 @@ -import {join, normalize} from "path"; import {cwd} from "process"; -import {VisionAdapter} from "./adapter/vision.adapter.class"; import {FileType} from "./file-type.enum"; import {generateOutputPath} from "./generate-output-path.function"; -import {LocationParameters} from "./locationparameters.class"; import {MatchRequest} from "./match-request.class"; import {MatchResult} from "./match-result.class"; import {Region} from "./region.class"; import {timeout} from "./util/timeout.function"; import {Image} from "./image.class"; +import {ProviderRegistry} from "./provider/provider-registry.class"; +import {FirstArgumentType} from "./typings"; +import {Point} from "./point.class"; +import {OptionalSearchParameters} from "./optionalsearchparameters.class"; export type FindHookCallback = (target: MatchResult) => Promise; +function validateSearchRegion(search: Region, screen: Region) { + if (search.left < 0 || search.top < 0 || search.width < 0 || search.height < 0) { + throw new Error(`Negative values in search region ${search}`) + } + if (isNaN(search.left) || isNaN(search.top) || isNaN(search.width) || isNaN(search.height)) { + throw new Error(`NaN values in search region ${search}`) + } + if (search.width < 2 || search.height < 2) { + throw new Error(`Search region ${search} is not large enough. Must be at least two pixels in both width and height.`) + } + if (search.left + search.width > screen.width || search.top + search.height > screen.height) { + throw new Error(`Search region ${search} extends beyond screen boundaries (${screen.width}x${screen.height})`) + } +} + /** - * {@link Screen} class provides methods to access screen content of a systems main display + * {@link ScreenClass} class provides methods to access screen content of a systems main display */ -export class Screen { +export class ScreenClass { /** - * Config object for {@link Screen} class + * Config object for {@link ScreenClass} class */ public config = { /** @@ -47,13 +63,13 @@ export class Screen { }; /** - * {@link Screen} class constructor - * @param vision {@link VisionAdapter} instance which bundles access to screen and / or computer vision related APIs - * @param findHooks A {@link Map} of {@link FindHookCallback} methods assigned to a template image filename + * {@link ScreenClass} class constructor + * @param providerRegistry A {@link ProviderRegistry} used to access underlying implementations + * @param findHooks A {@link Map} of {@link FindHookCallback} methods assigned to a template image */ constructor( - private vision: VisionAdapter, - private findHooks: Map = new Map()) { + private providerRegistry: ProviderRegistry, + private findHooks: Map = new Map()) { } /** @@ -62,7 +78,7 @@ export class Screen { * Screens with higher pixel density (e.g. retina displays in MacBooks) might have a higher width in in actual pixels */ public width() { - return this.vision.screenWidth(); + return this.providerRegistry.getScreen().screenWidth(); } /** @@ -71,80 +87,113 @@ export class Screen { * Screens with higher pixel density (e.g. retina displays in MacBooks) might have a higher height in in actual pixels */ public height() { - return this.vision.screenHeight(); + return this.providerRegistry.getScreen().screenHeight(); } /** - * {@link find} will search for a template image on a systems main screen - * @param templateImageFilename Filename of the template image, relative to {@link Screen.config.resourceDirectory} + * {@link find} will search for a single occurrence of a template image on a systems main screen + * @param template Template {@link Image} instance * @param params {@link LocationParameters} which are used to fine tune search region and / or match confidence */ public async find( - templateImageFilename: string, - params?: LocationParameters, + template: Image | Promise, + params?: OptionalSearchParameters, ): Promise { const minMatch = (params && params.confidence) || this.config.confidence; - const screenSize = await this.vision.screenSize(); + const screenSize = await this.providerRegistry.getScreen().screenSize(); const searchRegion = (params && params.searchRegion) || screenSize; const searchMultipleScales = (params && params.searchMultipleScales) - const fullPathToNeedle = normalize(join(this.config.resourceDirectory, templateImageFilename)); + const needle = await template; - const screenImage = await this.vision.grabScreen(); + const screenImage = await this.providerRegistry.getScreen().grabScreenRegion(searchRegion); const matchRequest = new MatchRequest( screenImage, - fullPathToNeedle, - searchRegion, + needle, minMatch, searchMultipleScales ); - function validateSearchRegion(search: Region, screen: Region) { - if (search.left < 0 || search.top < 0 || search.width < 0 || search.height < 0) { - throw new Error(`Negative values in search region ${search}`) - } - if (isNaN(search.left) || isNaN(search.top) || isNaN(search.width) || isNaN(search.height)) { - throw new Error(`NaN values in search region ${search}`) - } - if (search.width < 2 || search.height < 2) { - throw new Error(`Search region ${search} is not large enough. Must be at least two pixels in both width and height.`) - } - if (search.left + search.width > screen.width || search.top + search.height > screen.height) { - throw new Error(`Search region ${search} extends beyond screen boundaries (${screen.width}x${screen.height})`) + return new Promise(async (resolve, reject) => { + try { + validateSearchRegion(searchRegion, screenSize); + const matchResult = await this.providerRegistry.getImageFinder().findMatch(matchRequest); + const possibleHooks = this.findHooks.get(needle) || []; + for (const hook of possibleHooks) { + await hook(matchResult); + } + const resultRegion = new Region( + searchRegion.left + matchResult.location.left, + searchRegion.top + matchResult.location.top, + matchResult.location.width, + matchResult.location.height + ) + if (this.config.autoHighlight) { + resolve(this.highlight(resultRegion)); + } else { + resolve(resultRegion); + } + } catch (e) { + reject( + `Searching for ${needle.id} failed. Reason: '${e}'`, + ); } - } + }); + } - return new Promise(async (resolve, reject) => { + /** + * {@link findAll} will search for every occurrences of a template image on a systems main screen + * @param template Template {@link Image} instance + * @param params {@link LocationParameters} which are used to fine tune search region and / or match confidence + */ + public async findAll( + template: FirstArgumentType, + params?: OptionalSearchParameters, + ): Promise { + const minMatch = (params && params.confidence) || this.config.confidence; + const screenSize = await this.providerRegistry.getScreen().screenSize(); + const searchRegion = (params && params.searchRegion) || screenSize; + const searchMultipleScales = (params && params.searchMultipleScales) + + const needle = await template; + + const screenImage = await this.providerRegistry.getScreen().grabScreenRegion(searchRegion); + + const matchRequest = new MatchRequest( + screenImage, + needle, + minMatch, + searchMultipleScales + ); + + return new Promise(async (resolve, reject) => { try { validateSearchRegion(searchRegion, screenSize); - const matchResult = await this.vision.findOnScreenRegion(matchRequest); - if (matchResult.confidence >= minMatch) { - const possibleHooks = this.findHooks.get(templateImageFilename) || []; - for (const hook of possibleHooks) { + const matchResults = await this.providerRegistry.getImageFinder().findMatches(matchRequest); + const possibleHooks = this.findHooks.get(needle) || []; + for (const hook of possibleHooks) { + for (const matchResult of matchResults) { await hook(matchResult); } - const resultRegion = new Region( + } + const resultRegions = matchResults.map(matchResult => { + return new Region( searchRegion.left + matchResult.location.left, searchRegion.top + matchResult.location.top, matchResult.location.width, matchResult.location.height ) - if (this.config.autoHighlight) { - resolve(this.highlight(resultRegion)); - } else { - resolve(resultRegion); - } + }) + if (this.config.autoHighlight) { + resultRegions.forEach(region => this.highlight(region)); + resolve(resultRegions); } else { - reject( - `No match for ${templateImageFilename}. Required: ${minMatch}, given: ${ - matchResult.confidence - }`, - ); + resolve(resultRegions); } } catch (e) { reject( - `Searching for ${templateImageFilename} failed. Reason: '${e}'`, + `Searching for ${needle.id} failed. Reason: '${e}'`, ); } }); @@ -156,32 +205,34 @@ export class Screen { */ public async highlight(regionToHighlight: Region | Promise): Promise { const highlightRegion = await regionToHighlight; - await this.vision.highlightScreenRegion(highlightRegion, this.config.highlightDurationMs, this.config.highlightOpacity); + await this.providerRegistry.getScreen().highlightScreenRegion(highlightRegion, this.config.highlightDurationMs, this.config.highlightOpacity); return highlightRegion; } /** * {@link waitFor} searches for a template image for a specified duration - * @param templateImageFilename Filename of the template image, relative to {@link Screen.config.resourceDirectory} + * @param templateImage Filename of the template image, relative to {@link ScreenClass.config.resourceDirectory}, or an {@link Image} * @param timeoutMs Timeout in milliseconds after which {@link waitFor} fails + * @param updateInterval Update interval in milliseconds to retry search * @param params {@link LocationParameters} which are used to fine tune search region and / or match confidence */ public async waitFor( - templateImageFilename: string, + templateImage: FirstArgumentType, timeoutMs: number = 5000, - params?: LocationParameters, + updateInterval: number = 500, + params?: OptionalSearchParameters, ): Promise { - return timeout(500, timeoutMs, () => this.find(templateImageFilename, params), {signal: params?.abort}); + return timeout(updateInterval, timeoutMs, () => this.find(templateImage, params), {signal: params?.abort}); } /** - * {@link on} registeres a callback which is triggered once a certain template image is found - * @param templateImageFilename Template image to trigger the callback on + * {@link on} registers a callback which is triggered once a certain template image is found + * @param templateImage Template image to trigger the callback on * @param callback The {@link FindHookCallback} function to trigger */ - public on(templateImageFilename: string, callback: FindHookCallback) { - const existingHooks = this.findHooks.get(templateImageFilename) || []; - this.findHooks.set(templateImageFilename, [...existingHooks, callback]); + public on(templateImage: string | Image, callback: FindHookCallback) { + const existingHooks = this.findHooks.get(templateImage) || []; + this.findHooks.set(templateImage, [...existingHooks, callback]); } /** @@ -198,7 +249,7 @@ export class Screen { filePath: string = cwd(), fileNamePrefix: string = "", fileNamePostfix: string = ""): Promise { - const currentScreen = await this.vision.grabScreen(); + const currentScreen = await this.providerRegistry.getScreen().grabScreen(); return this.saveImage( currentScreen, fileName, @@ -208,6 +259,13 @@ export class Screen { fileNamePostfix); } + /** + * {@link grab} grabs screen content of a systems main display + */ + public async grab(): Promise { + return this.providerRegistry.getScreen().grabScreen(); + } + /** * {@link captureRegion} captures a screenshot of a region on the systems main display * @param fileName Basename for the generated screenshot @@ -219,12 +277,12 @@ export class Screen { */ public async captureRegion( fileName: string, - regionToCapture: Region, + regionToCapture: Region | Promise, fileFormat: FileType = FileType.PNG, filePath: string = cwd(), fileNamePrefix: string = "", fileNamePostfix: string = ""): Promise { - const regionImage = await this.vision.grabScreenRegion(regionToCapture); + const regionImage = await this.providerRegistry.getScreen().grabScreenRegion(await regionToCapture); return this.saveImage( regionImage, fileName, @@ -234,6 +292,25 @@ export class Screen { fileNamePostfix); } + /** + * {@link grabRegion} grabs screen content of a region on the systems main display + * @param regionToGrab The screen region to grab + */ + public async grabRegion(regionToGrab: Region | Promise): Promise { + return this.providerRegistry.getScreen().grabScreenRegion(await regionToGrab); + } + + /** + * {@link colorAt} returns RGBA color values for a certain pixel at {@link Point} p + * @param point Location to query color information from + */ + public async colorAt(point: Point | Promise) { + const screenContent = await this.providerRegistry.getScreen().grabScreen(); + const inputPoint = await point; + const scaledPoint = new Point(inputPoint.x * screenContent.pixelDensity.scaleX, inputPoint.y * screenContent.pixelDensity.scaleY); + return this.providerRegistry.getImageProcessor().colorAt(screenContent, scaledPoint); + } + private async saveImage( image: Image, fileName: string, @@ -247,7 +324,7 @@ export class Screen { prefix: fileNamePrefix, type: fileFormat, }); - await this.vision.saveImage(image, outputPath); + await this.providerRegistry.getImageWriter().store({image, path: outputPath}) return outputPath; } } diff --git a/lib/screen.colorAt.spec.ts b/lib/screen.colorAt.spec.ts new file mode 100644 index 00000000..ab515387 --- /dev/null +++ b/lib/screen.colorAt.spec.ts @@ -0,0 +1,67 @@ +import {Image, loadImage, Point, Region, RGBA, ScreenClass, ScreenProviderInterface} from "../index"; +import {mockPartial} from "sneer"; +import providerRegistry, {ProviderRegistry} from "./provider/provider-registry.class"; +import {ImageProcessor} from "./provider/image-processor.interface"; + +const searchRegion = new Region(0, 0, 1000, 1000); +const providerRegistryMock = mockPartial({ + getScreen(): ScreenProviderInterface { + return mockPartial({ + grabScreenRegion(): Promise { + return Promise.resolve(new Image(searchRegion.width, searchRegion.height, Buffer.from([]), 3, "needle_image")); + }, + screenSize(): Promise { + return Promise.resolve(searchRegion); + } + }) + }, + getImageProcessor(): ImageProcessor { + return providerRegistry.getImageProcessor(); + } +}); + +describe("colorAt", () => { + it("should return the correct RGBA value for a given pixel", async () => { + // GIVEN + const screenshot = loadImage(`${__dirname}/../e2e/assets/checkers.png`); + const grabScreenMock = jest.fn(() => Promise.resolve(screenshot)); + providerRegistryMock.getScreen = jest.fn(() => mockPartial({ + grabScreen: grabScreenMock + })); + providerRegistryMock.getImageProcessor() + const SUT = new ScreenClass(providerRegistryMock); + const expectedWhite = new RGBA(255, 255, 255, 255); + const expectedBlack = new RGBA(0, 0, 0, 255); + + // WHEN + const white = await SUT.colorAt(new Point(64, 64)); + const black = await SUT.colorAt(new Point(192, 64)); + + // THEN + expect(white).toStrictEqual(expectedWhite); + expect(black).toStrictEqual(expectedBlack); + }); + + it("should account for pixel density when retrieving pixel color", async () => { + // GIVEN + const screenshot = await loadImage(`${__dirname}/../e2e/assets/checkers.png`); + screenshot.pixelDensity.scaleX = 2.0; + screenshot.pixelDensity.scaleY = 2.0; + const grabScreenMock = jest.fn(() => Promise.resolve(screenshot)); + providerRegistryMock.getScreen = jest.fn(() => mockPartial({ + grabScreen: grabScreenMock + })); + providerRegistryMock.getImageProcessor() + const SUT = new ScreenClass(providerRegistryMock); + const expectedWhite = new RGBA(255, 255, 255, 255); + const expectedBlack = new RGBA(0, 0, 0, 255); + + // WHEN + const white = await SUT.colorAt(new Point(32, 32)); + const black = await SUT.colorAt(new Point(96, 32)); + + // THEN + expect(white).toStrictEqual(expectedWhite); + expect(black).toStrictEqual(expectedBlack); + }); +}); diff --git a/lib/sleep.function.spec.ts b/lib/sleep.function.spec.ts index 9f5e549c..1e00c9c0 100644 --- a/lib/sleep.function.spec.ts +++ b/lib/sleep.function.spec.ts @@ -2,6 +2,8 @@ import {busyWaitForNanoSeconds, sleep} from "./sleep.function"; const maxTimeDeltaInMs = 3; +jest.mock('jimp', () => {}); + describe("sleep", () => { it("should resolve after x ms", async () => { // GIVEN diff --git a/lib/sleep.function.ts b/lib/sleep.function.ts index 9c067ede..74f9407f 100644 --- a/lib/sleep.function.ts +++ b/lib/sleep.function.ts @@ -1,9 +1,9 @@ export const sleep = async (ms: number) => { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise(resolve => setTimeout(resolve, ms)); }; export const busyWaitForNanoSeconds = (duration: number) => { - return new Promise(res => { + return new Promise(res => { const start = process.hrtime.bigint(); let isWaiting = true; while (isWaiting) { diff --git a/lib/typings.ts b/lib/typings.ts new file mode 100644 index 00000000..49f0e4d9 --- /dev/null +++ b/lib/typings.ts @@ -0,0 +1 @@ +export type FirstArgumentType = T extends (first: infer ArgType, ...args: any[]) => any ? ArgType : never; \ No newline at end of file diff --git a/lib/util/timeout.function.spec.ts b/lib/util/timeout.function.spec.ts index bf0de075..9b3d861e 100644 --- a/lib/util/timeout.function.spec.ts +++ b/lib/util/timeout.function.spec.ts @@ -1,5 +1,6 @@ import {timeout} from "./timeout.function"; import AbortController from "node-abort-controller"; +import {sleep} from "../sleep.function"; describe("timeout", () => { it("should timeout after maxDuration if action rejects", async () => { @@ -138,7 +139,7 @@ describe("timeout", () => { expect(action).toBeCalledTimes(1); }); - it("should fail after timeout if no result is returned from long running action", async (done) => { + it("should fail after timeout if no result is returned from long running action", async () => { // GIVEN const updateInterval = 100; const maxDuration = 200; @@ -156,10 +157,8 @@ describe("timeout", () => { // THEN await expect(SUT).rejects.toBe(`Action timed out after ${maxDuration} ms`); expect(action).toBeCalledTimes(1); - setTimeout(() => { - expect(action).toBeCalledTimes(1); - done(); - }, 500); + await sleep(500); + expect(action).toBeCalledTimes(1); }); it("should be externally abortable", async () => { diff --git a/lib/window.class.spec.ts b/lib/window.class.spec.ts index 75d60ebf..b7cbb42d 100644 --- a/lib/window.class.spec.ts +++ b/lib/window.class.spec.ts @@ -1,34 +1,51 @@ import {Window} from "./window.class"; -import {NativeAdapter} from "./adapter/native.adapter.class"; +import {ProviderRegistry} from "./provider/provider-registry.class"; +import {mockPartial} from "sneer"; +import {WindowProviderInterface} from "./provider"; -jest.mock("./adapter/native.adapter.class"); +jest.mock('jimp', () => { +}); describe("Window class", () => { - it("should retrieve the window region via its native adapter", async () => { + it("should retrieve the window region via provider", async () => { // GIVEN - const nativeAdapterMock = new NativeAdapter(); + const windowMock = jest.fn(); + const providerRegistryMock = mockPartial({ + getWindow(): WindowProviderInterface { + return mockPartial({ + getWindowRegion: windowMock + }) + } + }) const mockWindowHandle = 123; - const SUT = new Window(nativeAdapterMock, mockWindowHandle); + const SUT = new Window(providerRegistryMock, mockWindowHandle); // WHEN await SUT.region // THEN - expect(nativeAdapterMock.getWindowRegion).toBeCalledTimes(1); - expect(nativeAdapterMock.getWindowRegion).toBeCalledWith(mockWindowHandle); + expect(windowMock).toBeCalledTimes(1); + expect(windowMock).toBeCalledWith(mockWindowHandle); }); - it("should retrieve the window title via its native adapter", async () => { + it("should retrieve the window title via provider", async () => { // GIVEN - const nativeAdapterMock = new NativeAdapter(); + const windowMock = jest.fn(); + const providerRegistryMock = mockPartial({ + getWindow(): WindowProviderInterface { + return mockPartial({ + getWindowTitle: windowMock + }) + } + }) const mockWindowHandle = 123; - const SUT = new Window(nativeAdapterMock, mockWindowHandle); + const SUT = new Window(providerRegistryMock, mockWindowHandle); // WHEN await SUT.title // THEN - expect(nativeAdapterMock.getWindowTitle).toBeCalledTimes(1); - expect(nativeAdapterMock.getWindowTitle).toBeCalledWith(mockWindowHandle); + expect(windowMock).toBeCalledTimes(1); + expect(windowMock).toBeCalledWith(mockWindowHandle); }); }); \ No newline at end of file diff --git a/lib/window.class.ts b/lib/window.class.ts index f403a73b..834b6583 100644 --- a/lib/window.class.ts +++ b/lib/window.class.ts @@ -1,15 +1,15 @@ -import { NativeAdapter } from "./adapter/native.adapter.class"; -import { Region } from "./region.class"; +import {Region} from "./region.class"; +import {ProviderRegistry} from "./provider/provider-registry.class"; export class Window { - constructor(private nativeActions: NativeAdapter, private windowHandle: number) { - } + constructor(private providerRegistry: ProviderRegistry, private windowHandle: number) { + } - get title(): Promise { - return this.nativeActions.getWindowTitle(this.windowHandle); - } + get title(): Promise { + return this.providerRegistry.getWindow().getWindowTitle(this.windowHandle); + } - get region(): Promise { - return this.nativeActions.getWindowRegion(this.windowHandle); - } + get region(): Promise { + return this.providerRegistry.getWindow().getWindowRegion(this.windowHandle); + } } \ No newline at end of file diff --git a/lib/window.function.spec.ts b/lib/window.function.spec.ts index 15c9ebf4..e4df42f9 100644 --- a/lib/window.function.spec.ts +++ b/lib/window.function.spec.ts @@ -1,12 +1,14 @@ import {createWindowApi} from "./window.function"; -import {NativeAdapter} from "./adapter/native.adapter.class"; import {Window} from "./window.class"; +import providerRegistry from "./provider/provider-registry.class"; + +jest.mock('jimp', () => {}); describe("WindowApi", () => { describe("getWindows", () => { it("should return a list of open Windows", async () => { // GIVEN - const SUT = createWindowApi(new NativeAdapter()); + const SUT = createWindowApi(providerRegistry); // WHEN const windows = await SUT.getWindows() @@ -21,7 +23,7 @@ describe("WindowApi", () => { describe("getActiveWindow", () => { it("should return the a single Window which is currently active", async () => { // GIVEN - const SUT = createWindowApi(new NativeAdapter()); + const SUT = createWindowApi(providerRegistry); // WHEN const window = await SUT.getActiveWindow(); diff --git a/lib/window.function.ts b/lib/window.function.ts index a88cbc78..2aba056a 100644 --- a/lib/window.function.ts +++ b/lib/window.function.ts @@ -1,17 +1,17 @@ import { WindowApi } from "./window-api.interface"; -import { NativeAdapter } from "./adapter/native.adapter.class"; import { Window } from "./window.class"; +import {ProviderRegistry} from "./provider/provider-registry.class"; -export const createWindowApi = (nativeAdapter: NativeAdapter): WindowApi => { +export const createWindowApi = (providerRegistry: ProviderRegistry): WindowApi => { return ({ async getActiveWindow(): Promise { - const windowHandle = await nativeAdapter.getActiveWindow(); - return new Window(nativeAdapter, windowHandle); + const windowHandle = await providerRegistry.getWindow().getActiveWindow(); + return new Window(providerRegistry, windowHandle); }, async getWindows(): Promise { - const windowHandles = await nativeAdapter.getWindows(); + const windowHandles = await providerRegistry.getWindow().getWindows(); return windowHandles.map((handle: number) => { - return new Window(nativeAdapter, handle); + return new Window(providerRegistry, handle); }); }, }); diff --git a/package-lock.json b/package-lock.json index 15d1aa25..c633385b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@nut-tree/nut-js", - "version": "1.7.0", + "version": "2.0.0-RC1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -13,56 +13,123 @@ "@babel/highlight": "^7.8.3" } }, + "@babel/compat-data": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", + "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", + "dev": true + }, "@babel/core": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", - "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.0", - "@babel/helper-module-transforms": "^7.9.0", - "@babel/helpers": "^7.9.0", - "@babel/parser": "^7.9.0", - "@babel/template": "^7.8.6", - "@babel/traverse": "^7.9.0", - "@babel/types": "^7.9.0", + "version": "7.15.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.5.tgz", + "integrity": "sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.4", + "@babel/helper-compilation-targets": "^7.15.4", + "@babel/helper-module-transforms": "^7.15.4", + "@babel/helpers": "^7.15.4", + "@babel/parser": "^7.15.5", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", + "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", + "semver": "^6.3.0", "source-map": "^0.5.0" }, "dependencies": { - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/template": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", + "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4" + } + }, + "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": { - "minimist": "^1.2.5" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "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 + }, "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/generator": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz", - "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.4.tgz", + "integrity": "sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==", "dev": true, "requires": { - "@babel/types": "^7.9.5", + "@babel/types": "^7.15.4", "jsesc": "^2.5.1", - "lodash": "^4.17.13", "source-map": "^0.5.0" }, "dependencies": { @@ -74,120 +141,359 @@ } } }, + "@babel/helper-compilation-targets": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", + "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.15.0", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "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 + } + } + }, "@babel/helper-function-name": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz", - "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", + "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.9.5" + "@babel/helper-get-function-arity": "^7.15.4", + "@babel/template": "^7.15.4", + "@babel/types": "^7.15.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/template": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", + "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4" + } + }, + "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" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "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-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==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", + "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", + "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.15.4" } }, "@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==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", + "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.15.4" } }, "@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==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", + "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.15.4" } }, "@babel/helper-module-transforms": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", - "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.6", - "@babel/helper-simple-access": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/template": "^7.8.6", - "@babel/types": "^7.9.0", - "lodash": "^4.17.13" + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz", + "integrity": "sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.15.4", + "@babel/helper-replace-supers": "^7.15.4", + "@babel/helper-simple-access": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/helper-validator-identifier": "^7.14.9", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/template": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", + "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4" + } + }, + "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" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "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-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==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", + "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.15.4" } }, "@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==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", "dev": true }, "@babel/helper-replace-supers": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", - "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", + "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.8.6", - "@babel/types": "^7.8.6" + "@babel/helper-member-expression-to-functions": "^7.15.4", + "@babel/helper-optimise-call-expression": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@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==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", + "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/types": "^7.15.4" } }, "@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==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", + "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.15.4" } }, "@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", "dev": true }, "@babel/helpers": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", - "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", + "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.9.0", - "@babel/types": "^7.9.0" + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/template": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", + "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4" + } + }, + "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" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "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/highlight": { @@ -254,9 +560,9 @@ } }, "@babel/parser": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", - "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", + "version": "7.15.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.5.tgz", + "integrity": "sha512-2hQstc6I7T6tQsWzlboMh3SgMRPaS4H6H7cPQsJkdzTzEGqQrpLDsE2BGASU5sBPoEQyHzeqU6C8uKbFeEk6sg==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -278,12 +584,21 @@ } }, "@babel/plugin-syntax-class-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.8.3.tgz", - "integrity": "sha512-UcAyQWg2bAN647Q+O811tG9MrJ38Z10jjhQdKNAL8fsyPzE3cCN/uT+f55cFVY4aGO4jqJAvmqsuY3GQDwAoXg==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-json-strings": { @@ -296,12 +611,12 @@ } }, "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.8.3.tgz", - "integrity": "sha512-Zpg2Sgc++37kuFl6ppq2Q7Awc6E6AIW671x5PY8E/f7MCIyPPGK/EoeZXvvY3P42exZ3Q4/t3YOzP/HiN79jDg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-nullish-coalescing-operator": { @@ -314,12 +629,12 @@ } }, "@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==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-object-rest-spread": { @@ -349,6 +664,32 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", + "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/runtime": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.0.tgz", + "integrity": "sha512-Nht8L0O8YCktmsDV6FqFue7vQLRx3Hb0B37lS5y0jDRqRxlBG4wIJHnf9/bgSE2UyipKFA01YtS+npRdTWBUyw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, "@babel/template": { "version": "7.8.6", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", @@ -361,30 +702,86 @@ } }, "@babel/traverse": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz", - "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.5", - "@babel/helper-function-name": "^7.9.5", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.9.0", - "@babel/types": "^7.9.5", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", + "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.4", + "@babel/helper-function-name": "^7.15.4", + "@babel/helper-hoist-variables": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4", "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", - "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.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" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "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/types": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.4.tgz", + "integrity": "sha512-0f1HJFuGmmbrKTCZtbm3cU+b/AqdEYk5toj5iQur58xkVMlS0JWaKxTBSmCXd47uiN7vbcozAupm6Mvs80GNhw==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.9.5", - "lodash": "^4.17.13", + "@babel/helper-validator-identifier": "^7.14.9", "to-fast-properties": "^2.0.0" } }, @@ -394,288 +791,626 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@cnakazawa/watch": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", - "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", - "dev": true, - "requires": { - "exec-sh": "^0.3.2", - "minimist": "^1.2.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==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "requires": { "camelcase": "^5.3.1", "find-up": "^4.1.0", + "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" } }, "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, "@jest/console": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.4.0.tgz", - "integrity": "sha512-CfE0erx4hdJ6t7RzAcE1wLG6ZzsHSmybvIBQDoCkDM1QaSeWL9wJMzID/2BbHHa7ll9SsbbK43HjbERbBaFX2A==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.1.0.tgz", + "integrity": "sha512-+Vl+xmLwAXLNlqT61gmHEixeRbS4L8MUzAjtpBCOPWH+izNI/dR16IeXjkXJdRtIVWVSf9DO1gdp67B1XorZhQ==", "dev": true, "requires": { - "@jest/types": "^25.4.0", - "chalk": "^3.0.0", - "jest-message-util": "^25.4.0", - "jest-util": "^25.4.0", + "@jest/types": "^27.1.0", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.1.0", + "jest-util": "^27.1.0", "slash": "^3.0.0" + } + }, + "@jest/core": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.1.0.tgz", + "integrity": "sha512-3l9qmoknrlCFKfGdrmiQiPne+pUR4ALhKwFTYyOeKw6egfDwJkO21RJ1xf41rN8ZNFLg5W+w6+P4fUqq4EMRWA==", + "dev": true, + "requires": { + "@jest/console": "^27.1.0", + "@jest/reporters": "^27.1.0", + "@jest/test-result": "^27.1.0", + "@jest/transform": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-changed-files": "^27.1.0", + "jest-config": "^27.1.0", + "jest-haste-map": "^27.1.0", + "jest-message-util": "^27.1.0", + "jest-regex-util": "^27.0.6", + "jest-resolve": "^27.1.0", + "jest-resolve-dependencies": "^27.1.0", + "jest-runner": "^27.1.0", + "jest-runtime": "^27.1.0", + "jest-snapshot": "^27.1.0", + "jest-util": "^27.1.0", + "jest-validate": "^27.1.0", + "jest-watcher": "^27.1.0", + "micromatch": "^4.0.4", + "p-each-series": "^2.1.0", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "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": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "ansi-regex": "^5.0.0" } } } }, "@jest/environment": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-25.4.0.tgz", - "integrity": "sha512-KDctiak4mu7b4J6BIoN/+LUL3pscBzoUCP+EtSPd2tK9fqyDY5OF+CmkBywkFWezS9tyH5ACOQNtpjtueEDH6Q==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.1.0.tgz", + "integrity": "sha512-wRp50aAMY2w1U2jP1G32d6FUVBNYqmk8WaGkiIEisU48qyDV0WPtw3IBLnl7orBeggveommAkuijY+RzVnNDOQ==", "dev": true, "requires": { - "@jest/fake-timers": "^25.4.0", - "@jest/types": "^25.4.0", - "jest-mock": "^25.4.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - } + "@jest/fake-timers": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/node": "*", + "jest-mock": "^27.1.0" } }, "@jest/fake-timers": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-25.4.0.tgz", - "integrity": "sha512-lI9z+VOmVX4dPPFzyj0vm+UtaB8dCJJ852lcDnY0uCPRvZAaVGnMwBBc1wxtf+h7Vz6KszoOvKAt4QijDnHDkg==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.1.0.tgz", + "integrity": "sha512-22Zyn8il8DzpS+30jJNVbTlm7vAtnfy1aYvNeOEHloMlGy1PCYLHa4PWlSws0hvNsMM5bON6GISjkLoQUV3oMA==", "dev": true, "requires": { - "@jest/types": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-mock": "^25.4.0", - "jest-util": "^25.4.0", - "lolex": "^5.0.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - } + "@jest/types": "^27.1.0", + "@sinonjs/fake-timers": "^7.0.2", + "@types/node": "*", + "jest-message-util": "^27.1.0", + "jest-mock": "^27.1.0", + "jest-util": "^27.1.0" + } + }, + "@jest/globals": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.1.0.tgz", + "integrity": "sha512-73vLV4aNHAlAgjk0/QcSIzzCZSqVIPbmFROJJv9D3QUR7BI4f517gVdJpSrCHxuRH3VZFhe0yGG/tmttlMll9g==", + "dev": true, + "requires": { + "@jest/environment": "^27.1.0", + "@jest/types": "^27.1.0", + "expect": "^27.1.0" } }, "@jest/reporters": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-25.4.0.tgz", - "integrity": "sha512-bhx/buYbZgLZm4JWLcRJ/q9Gvmd3oUh7k2V7gA4ZYBx6J28pIuykIouclRdiAC6eGVX1uRZT+GK4CQJLd/PwPg==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.1.0.tgz", + "integrity": "sha512-5T/zlPkN2HnK3Sboeg64L5eC8iiaZueLpttdktWTJsvALEtP2YMkC5BQxwjRWQACG9SwDmz+XjjkoxXUDMDgdw==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^25.4.0", - "@jest/test-result": "^25.4.0", - "@jest/transform": "^25.4.0", - "@jest/types": "^25.4.0", - "chalk": "^3.0.0", + "@jest/console": "^27.1.0", + "@jest/test-result": "^27.1.0", + "@jest/transform": "^27.1.0", + "@jest/types": "^27.1.0", + "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.2", + "graceful-fs": "^4.2.4", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-instrument": "^4.0.3", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", - "jest-haste-map": "^25.4.0", - "jest-resolve": "^25.4.0", - "jest-util": "^25.4.0", - "jest-worker": "^25.4.0", - "node-notifier": "^6.0.0", + "jest-haste-map": "^27.1.0", + "jest-resolve": "^27.1.0", + "jest-util": "^27.1.0", + "jest-worker": "^27.1.0", "slash": "^3.0.0", "source-map": "^0.6.0", - "string-length": "^3.1.0", + "string-length": "^4.0.1", "terminal-link": "^2.0.0", - "v8-to-istanbul": "^4.1.3" + "v8-to-istanbul": "^8.0.0" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.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/source-map": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.2.6.tgz", - "integrity": "sha512-VuIRZF8M2zxYFGTEhkNSvQkUKafQro4y+mwUxy5ewRqs5N/ynSFUODYp3fy1zCnbCMy1pz3k+u57uCqx8QRSQQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.6.tgz", + "integrity": "sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g==", "dev": true, "requires": { "callsites": "^3.0.0", - "graceful-fs": "^4.2.3", + "graceful-fs": "^4.2.4", "source-map": "^0.6.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==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true } } }, "@jest/test-result": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.4.0.tgz", - "integrity": "sha512-8BAKPaMCHlL941eyfqhWbmp3MebtzywlxzV+qtngQ3FH+RBqnoSAhNEPj4MG7d2NVUrMOVfrwuzGpVIK+QnMAA==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.1.0.tgz", + "integrity": "sha512-Aoz00gpDL528ODLghat3QSy6UBTD5EmmpjrhZZMK/v1Q2/rRRqTGnFxHuEkrD4z/Py96ZdOHxIWkkCKRpmnE1A==", "dev": true, "requires": { - "@jest/console": "^25.4.0", - "@jest/types": "^25.4.0", + "@jest/console": "^27.1.0", + "@jest/types": "^27.1.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - } } }, "@jest/test-sequencer": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-25.4.0.tgz", - "integrity": "sha512-240cI+nsM3attx2bMp9uGjjHrwrpvxxrZi8Tyqp/cfOzl98oZXVakXBgxODGyBYAy/UGXPKXLvNc2GaqItrsJg==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.1.0.tgz", + "integrity": "sha512-lnCWawDr6Z1DAAK9l25o3AjmKGgcutq1iIbp+hC10s/HxnB8ZkUsYq1FzjOoxxZ5hW+1+AthBtvS4x9yno3V1A==", "dev": true, "requires": { - "@jest/test-result": "^25.4.0", - "jest-haste-map": "^25.4.0", - "jest-runner": "^25.4.0", - "jest-runtime": "^25.4.0" + "@jest/test-result": "^27.1.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.1.0", + "jest-runtime": "^27.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + } } }, "@jest/transform": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.4.0.tgz", - "integrity": "sha512-t1w2S6V1sk++1HHsxboWxPEuSpN8pxEvNrZN+Ud/knkROWtf8LeUmz73A4ezE8476a5AM00IZr9a8FO9x1+j3g==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.1.0.tgz", + "integrity": "sha512-ZRGCA2ZEVJ00ubrhkTG87kyLbN6n55g1Ilq0X9nJb5bX3MhMp3O6M7KG+LvYu+nZRqG5cXsQnJEdZbdpTAV8pQ==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/types": "^25.4.0", + "@jest/types": "^27.1.0", "babel-plugin-istanbul": "^6.0.0", - "chalk": "^3.0.0", + "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.3", - "jest-haste-map": "^25.4.0", - "jest-regex-util": "^25.2.6", - "jest-util": "^25.4.0", - "micromatch": "^4.0.2", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.1.0", + "jest-regex-util": "^27.0.6", + "jest-util": "^27.1.0", + "micromatch": "^4.0.4", "pirates": "^4.0.1", - "realpath-native": "^2.0.0", "slash": "^3.0.0", "source-map": "^0.6.1", "write-file-atomic": "^3.0.0" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, "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==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true } } }, "@jest/types": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.1.0.tgz", - "integrity": "sha512-VpOtt7tCrgvamWZh1reVsGADujKigBUFTi19mlRjqEGsE8qH4r3s+skY33dNdXOwyZIvuftZ5tqdF1IgsMejMA==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.1.0.tgz", + "integrity": "sha512-pRP5cLIzN7I7Vp6mHKRSaZD7YpBTK7hawx5si8trMKqk4+WOdK8NEKOTO2G8PKWD1HbKMVckVB6/XHh/olhf2g==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@jimp/bmp": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.1.tgz", + "integrity": "sha512-iwyNYQeBawrdg/f24x3pQ5rEx+/GwjZcCXd3Kgc+ZUd+Ivia7sIqBsOnDaMZdKCBPlfW364ekexnlOqyVa0NWg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "bmp-js": "^0.1.0" + } + }, + "@jimp/core": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.1.tgz", + "integrity": "sha512-la7kQia31V6kQ4q1kI/uLimu8FXx7imWVajDGtwUG8fzePLWDFJyZl0fdIXVCL1JW2nBcRHidUot6jvlRDi2+g==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^9.0.0", + "load-bmfont": "^1.3.1", + "mkdirp": "^0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" + } + }, + "@jimp/custom": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.1.tgz", + "integrity": "sha512-DNUAHNSiUI/j9hmbatD6WN/EBIyeq4AO0frl5ETtt51VN1SvE4t4v83ZA/V6ikxEf3hxLju4tQ5Pc3zmZkN/3A==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/core": "^0.16.1" + } + }, + "@jimp/gif": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.1.tgz", + "integrity": "sha512-r/1+GzIW1D5zrP4tNrfW+3y4vqD935WBXSc8X/wm23QTY9aJO9Lw6PEdzpYCEY+SOklIFKaJYUAq/Nvgm/9ryw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "gifwrap": "^0.9.2", + "omggif": "^1.0.9" + } + }, + "@jimp/jpeg": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.1.tgz", + "integrity": "sha512-8352zrdlCCLFdZ/J+JjBslDvml+fS3Z8gttdml0We759PnnZGqrnPRhkOEOJbNUlE+dD4ckLeIe6NPxlS/7U+w==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "jpeg-js": "0.4.2" + } + }, + "@jimp/plugin-blit": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.16.1.tgz", + "integrity": "sha512-fKFNARm32RoLSokJ8WZXHHH2CGzz6ire2n1Jh6u+XQLhk9TweT1DcLHIXwQMh8oR12KgjbgsMGvrMVlVknmOAg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-blur": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.16.1.tgz", + "integrity": "sha512-1WhuLGGj9MypFKRcPvmW45ht7nXkOKu+lg3n2VBzIB7r4kKNVchuI59bXaCYQumOLEqVK7JdB4glaDAbCQCLyw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-circle": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.16.1.tgz", + "integrity": "sha512-JK7yi1CIU7/XL8hdahjcbGA3V7c+F+Iw+mhMQhLEi7Q0tCnZ69YJBTamMiNg3fWPVfMuvWJJKOBRVpwNTuaZRg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-color": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.16.1.tgz", + "integrity": "sha512-9yQttBAO5SEFj7S6nJK54f+1BnuBG4c28q+iyzm1JjtnehjqMg6Ljw4gCSDCvoCQ3jBSYHN66pmwTV74SU1B7A==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "tinycolor2": "^1.4.1" + } + }, + "@jimp/plugin-contain": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.16.1.tgz", + "integrity": "sha512-44F3dUIjBDHN+Ym/vEfg+jtjMjAqd2uw9nssN67/n4FdpuZUVs7E7wadKY1RRNuJO+WgcD5aDQcsvurXMETQTg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-cover": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.16.1.tgz", + "integrity": "sha512-YztWCIldBAVo0zxcQXR+a/uk3/TtYnpKU2CanOPJ7baIuDlWPsG+YE4xTsswZZc12H9Kl7CiziEbDtvF9kwA/Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-crop": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.16.1.tgz", + "integrity": "sha512-UQdva9oQzCVadkyo3T5Tv2CUZbf0klm2cD4cWMlASuTOYgaGaFHhT9st+kmfvXjKL8q3STkBu/zUPV6PbuV3ew==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-displace": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.16.1.tgz", + "integrity": "sha512-iVAWuz2+G6Heu8gVZksUz+4hQYpR4R0R/RtBzpWEl8ItBe7O6QjORAkhxzg+WdYLL2A/Yd4ekTpvK0/qW8hTVw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-dither": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.16.1.tgz", + "integrity": "sha512-tADKVd+HDC9EhJRUDwMvzBXPz4GLoU6s5P7xkVq46tskExYSptgj5713J5Thj3NMgH9Rsqu22jNg1H/7tr3V9Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-fisheye": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.16.1.tgz", + "integrity": "sha512-BWHnc5hVobviTyIRHhIy9VxI1ACf4CeSuCfURB6JZm87YuyvgQh5aX5UDKtOz/3haMHXBLP61ZBxlNpMD8CG4A==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-flip": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.16.1.tgz", + "integrity": "sha512-KdxTf0zErfZ8DyHkImDTnQBuHby+a5YFdoKI/G3GpBl3qxLBvC+PWkS2F/iN3H7wszP7/TKxTEvWL927pypT0w==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-gaussian": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.16.1.tgz", + "integrity": "sha512-u9n4wjskh3N1mSqketbL6tVcLU2S5TEaFPR40K6TDv4phPLZALi1Of7reUmYpVm8mBDHt1I6kGhuCJiWvzfGyg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-invert": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.16.1.tgz", + "integrity": "sha512-2DKuyVXANH8WDpW9NG+PYFbehzJfweZszFYyxcaewaPLN0GxvxVLOGOPP1NuUTcHkOdMFbE0nHDuB7f+sYF/2w==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-mask": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.16.1.tgz", + "integrity": "sha512-snfiqHlVuj4bSFS0v96vo2PpqCDMe4JB+O++sMo5jF5mvGcGL6AIeLo8cYqPNpdO6BZpBJ8MY5El0Veckhr39Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-normalize": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.16.1.tgz", + "integrity": "sha512-dOQfIOvGLKDKXPU8xXWzaUeB0nvkosHw6Xg1WhS1Z5Q0PazByhaxOQkSKgUryNN/H+X7UdbDvlyh/yHf3ITRaw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-print": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.16.1.tgz", + "integrity": "sha512-ceWgYN40jbN4cWRxixym+csyVymvrryuKBQ+zoIvN5iE6OyS+2d7Mn4zlNgumSczb9GGyZZESIgVcBDA1ezq0Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "load-bmfont": "^1.4.0" + } + }, + "@jimp/plugin-resize": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.1.tgz", + "integrity": "sha512-u4JBLdRI7dargC04p2Ha24kofQBk3vhaf0q8FwSYgnCRwxfvh2RxvhJZk9H7Q91JZp6wgjz/SjvEAYjGCEgAwQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-rotate": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.16.1.tgz", + "integrity": "sha512-ZUU415gDQ0VjYutmVgAYYxC9Og9ixu2jAGMCU54mSMfuIlmohYfwARQmI7h4QB84M76c9hVLdONWjuo+rip/zg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-scale": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.16.1.tgz", + "integrity": "sha512-jM2QlgThIDIc4rcyughD5O7sOYezxdafg/2Xtd1csfK3z6fba3asxDwthqPZAgitrLgiKBDp6XfzC07Y/CefUw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-shadow": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.16.1.tgz", + "integrity": "sha512-MeD2Is17oKzXLnsphAa1sDstTu6nxscugxAEk3ji0GV1FohCvpHBcec0nAq6/czg4WzqfDts+fcPfC79qWmqrA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-threshold": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.16.1.tgz", + "integrity": "sha512-iGW8U/wiCSR0+6syrPioVGoSzQFt4Z91SsCRbgNKTAk7D+XQv6OI78jvvYg4o0c2FOlwGhqz147HZV5utoSLxA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugins": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.16.1.tgz", + "integrity": "sha512-c+lCqa25b+4q6mJZSetlxhMoYuiltyS+ValLzdwK/47+aYsq+kcJNl+TuxIEKf59yr9+5rkbpsPkZHLF/V7FFA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/plugin-blit": "^0.16.1", + "@jimp/plugin-blur": "^0.16.1", + "@jimp/plugin-circle": "^0.16.1", + "@jimp/plugin-color": "^0.16.1", + "@jimp/plugin-contain": "^0.16.1", + "@jimp/plugin-cover": "^0.16.1", + "@jimp/plugin-crop": "^0.16.1", + "@jimp/plugin-displace": "^0.16.1", + "@jimp/plugin-dither": "^0.16.1", + "@jimp/plugin-fisheye": "^0.16.1", + "@jimp/plugin-flip": "^0.16.1", + "@jimp/plugin-gaussian": "^0.16.1", + "@jimp/plugin-invert": "^0.16.1", + "@jimp/plugin-mask": "^0.16.1", + "@jimp/plugin-normalize": "^0.16.1", + "@jimp/plugin-print": "^0.16.1", + "@jimp/plugin-resize": "^0.16.1", + "@jimp/plugin-rotate": "^0.16.1", + "@jimp/plugin-scale": "^0.16.1", + "@jimp/plugin-shadow": "^0.16.1", + "@jimp/plugin-threshold": "^0.16.1", + "timm": "^1.6.1" + } + }, + "@jimp/png": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.1.tgz", + "integrity": "sha512-iyWoCxEBTW0OUWWn6SveD4LePW89kO7ZOy5sCfYeDM/oTPLpR8iMIGvZpZUz1b8kvzFr27vPst4E5rJhGjwsdw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "pngjs": "^3.3.3" + } + }, + "@jimp/tiff": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.1.tgz", + "integrity": "sha512-3K3+xpJS79RmSkAvFMgqY5dhSB+/sxhwTFA9f4AVHUK0oKW+u6r52Z1L0tMXHnpbAdR9EJ+xaAl2D4x19XShkQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "utif": "^2.0.1" + } + }, + "@jimp/types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.1.tgz", + "integrity": "sha512-g1w/+NfWqiVW4CaXSJyD28JQqZtm2eyKMWPhBBDCJN9nLCN12/Az0WFF3JUAktzdsEC2KRN2AqB1a2oMZBNgSQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/bmp": "^0.16.1", + "@jimp/gif": "^0.16.1", + "@jimp/jpeg": "^0.16.1", + "@jimp/png": "^0.16.1", + "@jimp/tiff": "^0.16.1", + "timm": "^1.6.1" + } + }, + "@jimp/utils": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.1.tgz", + "integrity": "sha512-8fULQjB0x4LzUSiSYG6ZtQl355sZjxbv8r9PPAuYHzS9sGiSHJQavNqK/nKnpDsVkU88/vRGcE7t3nMU0dEnVw==", + "requires": { + "@babel/runtime": "^7.7.2", + "regenerator-runtime": "^0.13.3" } }, "@jsdevtools/ez-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@jsdevtools/ez-spawn/-/ez-spawn-3.0.1.tgz", - "integrity": "sha512-CwxITbpBUTDyJOT1PbOFn2asBVdVknMIVZ6Pxx49+0zCMKRZF12v0ztiDMZob/wc5Cqht7MZj1CiIvimeP3hSg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@jsdevtools/ez-spawn/-/ez-spawn-3.0.4.tgz", + "integrity": "sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==", "dev": true, "requires": { "call-me-maybe": "^1.0.1", - "cross-spawn": "^7.0.1", + "cross-spawn": "^7.0.3", "string-argv": "^0.3.1", "type-detect": "^4.0.8" }, "dependencies": { "cross-spawn": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", - "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -716,45 +1451,45 @@ } }, "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.3", + "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.3", + "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "@nut-tree/libnut": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@nut-tree/libnut/-/libnut-2.1.2.tgz", - "integrity": "sha512-HX8T3v69yY/+3NVNHjpAEl0s0Nv6HRSPiG4wqItj00JDQTqn6EGoQ3Rc7tqCZd2P2olUvYqg4iN10VAODvCWyw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nut-tree/libnut/-/libnut-2.1.3.tgz", + "integrity": "sha512-cOwusjWt5DbCz0h6yrj7wD+OFHyeY2cUgxFXqm4ZHl+JkET3AVzwfxr5OqEnZVjxcn75otf7yGbt2zX6eLUJWg==", "requires": { - "@nut-tree/libnut-darwin": "2.1.1", - "@nut-tree/libnut-linux": "2.1.1", - "@nut-tree/libnut-win32": "2.1.1" + "@nut-tree/libnut-darwin": "2.1.3", + "@nut-tree/libnut-linux": "2.1.3", + "@nut-tree/libnut-win32": "2.1.3" } }, "@nut-tree/libnut-darwin": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@nut-tree/libnut-darwin/-/libnut-darwin-2.1.1.tgz", - "integrity": "sha512-4k5xOiMCVZWvYmVaDrzYcEqxc6COsExpRXZoLFX+5d2gqZ5Mjsay+mfSgc76roCm2JLQ1aooRZ5cXcdAeNdS5g==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nut-tree/libnut-darwin/-/libnut-darwin-2.1.3.tgz", + "integrity": "sha512-w1J/0NZ/gD+qvYUu9iuKHeMY9c7/jdnC/pwS9AOkyKZahoKO/7JKRW5FyQdvoUY5JuJ8majLuyoVXr11jSgspQ==", "requires": { "bindings": "1.5.0", "cmake-js": "6.1.0", @@ -762,9 +1497,9 @@ } }, "@nut-tree/libnut-linux": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@nut-tree/libnut-linux/-/libnut-linux-2.1.1.tgz", - "integrity": "sha512-dabDPJdKituMRdkvTpbW+eQMPLJr68CYS4By1czs9xGO6Luv2cLVYxMD+zdfGyshZjI1lJfsbjkDorwwIE2XDg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nut-tree/libnut-linux/-/libnut-linux-2.1.3.tgz", + "integrity": "sha512-c2XVg5mQKqJWFan9t482a3WiUB70Qd7pmCzUk5f7FwOvIV/TrVl4QzVjET1ESNCSVGSoT9agyD/o5UaACZS9wg==", "requires": { "bindings": "1.5.0", "cmake-js": "6.1.0", @@ -772,9 +1507,9 @@ } }, "@nut-tree/libnut-win32": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@nut-tree/libnut-win32/-/libnut-win32-2.1.1.tgz", - "integrity": "sha512-kZOc1aXXTN0pkQcQNjgROq1LZl9p122MjDLVY+iRYKg7KX3oIS8MlkGy/3eunyLPbnHML+l1kQCwYa3h4cYFpw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nut-tree/libnut-win32/-/libnut-win32-2.1.3.tgz", + "integrity": "sha512-+gDyng4YVw5qUqoRpIhQN/1XOPuD5v1Gb5XySXsQo+ledvOLYqDcl19NpP3bFiuyzZwZtWAo5tOiS/TaLtJcpQ==", "requires": { "bindings": "1.5.0", "cmake-js": "6.1.0", @@ -782,18 +1517,33 @@ } }, "@sinonjs/commons": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.2.tgz", - "integrity": "sha512-+DUO6pnp3udV/v2VfUWgaY5BIE1IfT7lLfeDzPVeMT1XKkaAp9LgSI9x5RtrFQoZ9Oi0PgXQQHPaoKu7dCjVxw==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, "requires": { "type-detect": "4.0.8" } }, + "@sinonjs/fake-timers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, "@types/babel__core": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.7.tgz", - "integrity": "sha512-RL62NqSFPCDK2FM1pSDH0scHpJvsXtZNiYlMB73DgPBaG1E38ZYVL+ei5EkWRbr+KC4YNiAUNBnRj+bgwpgjMw==", + "version": "7.1.15", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.15.tgz", + "integrity": "sha512-bxlMKPDbY8x5h6HBwVzEOk2C8fb6SLfYQ5Jw3uBYuYF1lfWk/kbLd81la82vrIkBb0l+JdmrZaDikPrNxpS/Ew==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -804,18 +1554,18 @@ } }, "@types/babel__generator": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz", - "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz", + "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==", "dev": true, "requires": { "@babel/types": "^7.0.0" } }, "@types/babel__template": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", - "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -823,9 +1573,9 @@ } }, "@types/babel__traverse": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.10.tgz", - "integrity": "sha512-74fNdUGrWsgIB/V9kTO5FGHPWYY6Eqn+3Z7L6Hc4e/BxjYV7puvBqp5HwsVYYfLm6iURYBNCx4Ut37OF9yitCw==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", + "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -840,16 +1590,19 @@ "clipboardy": "*" } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "requires": { + "@types/node": "*" + } }, "@types/istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", "dev": true }, "@types/istanbul-lib-report": { @@ -862,100 +1615,102 @@ } }, "@types/istanbul-reports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "*", "@types/istanbul-lib-report": "*" } }, "@types/jest": { - "version": "25.1.4", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-25.1.4.tgz", - "integrity": "sha512-QDDY2uNAhCV7TMCITrxz+MRk1EizcsevzfeS6LykIlq2V1E5oO4wXG8V2ZEd9w7Snxeeagk46YbMgZ8ESHx3sw==", + "version": "27.0.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.1.tgz", + "integrity": "sha512-HTLpVXHrY69556ozYkcq47TtQJXpcWAWfkoqz+ZGz2JnmZhzlRjprCIyFnetSy8gpDWwTTGBcRVv1J1I1vBrHw==", "dev": true, "requires": { - "jest-diff": "^25.1.0", - "pretty-format": "^25.1.0" + "jest-diff": "^27.0.0", + "pretty-format": "^27.0.0" } }, "@types/node": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.2.tgz", - "integrity": "sha512-jJs9ErFLP403I+hMLGnqDRWT0RYKSvArxuBVh2veudHV7ifEC1WAmjJADacZ7mRbA2nWgHtn8xyECMAot0SkAw==", - "optional": true - }, - "@types/normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "version": "16.7.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.10.tgz", + "integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==", "dev": true }, "@types/prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.3.2.tgz", + "integrity": "sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==", "dev": true }, "@types/stack-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", - "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, "@types/yargs": { - "version": "15.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", - "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", - "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", "dev": true }, "abab": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", - "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", "dev": true }, "acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", + "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", "dev": true }, "acorn-globals": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", - "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", "dev": true, "requires": { - "acorn": "^6.0.1", - "acorn-walk": "^6.0.1" + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" }, "dependencies": { "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true } } }, "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "aggregate-error": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", @@ -967,11 +1722,11 @@ } }, "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha1-kNDVRDnaWHzX6EO/twRfUL0ivfE=", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" @@ -983,12 +1738,12 @@ "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=" }, "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "requires": { - "type-fest": "^0.11.0" + "type-fest": "^0.21.3" } }, "ansi-regex": { @@ -997,19 +1752,40 @@ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "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": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" - } + }, + "dependencies": { + "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==", + "dev": true, + "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==", + "dev": true + } + } + }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -1025,15 +1801,10 @@ "default-require-extensions": "^3.0.0" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, "arch": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.1.tgz", - "integrity": "sha1-j1wnMao1owkpIhuwZA7tZRdeyE4=" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==" }, "archy": { "version": "1.0.0", @@ -1050,6 +1821,11 @@ "readable-stream": "^2.0.0 || ^1.1.13" }, "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -1083,52 +1859,22 @@ "sprintf-js": "~1.0.2" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, "array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "dev": true }, - "array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", - "dev": true - }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "requires": { "safer-buffer": "~2.1.0" } @@ -1138,65 +1884,42 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha1-8OAD2cqef1nHpQiUXXsu+aBKVC8=" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "babel-jest": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-25.4.0.tgz", - "integrity": "sha512-p+epx4K0ypmHuCnd8BapfyOwWwosNCYhedetQey1awddtfmEX0MmdxctGl956uwUmjwXR5VSS5xJcGX9DvdIog==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.1.0.tgz", + "integrity": "sha512-6NrdqzaYemALGCuR97QkC/FkFIEBWP5pw5TMJoUHZTVXyOgocujp6A0JE2V6gE0HtqAAv6VKU/nI+OCR1Z4gHA==", "dev": true, "requires": { - "@jest/transform": "^25.4.0", - "@jest/types": "^25.4.0", - "@types/babel__core": "^7.1.7", + "@jest/transform": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^25.4.0", - "chalk": "^3.0.0", + "babel-preset-jest": "^27.0.6", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", "slash": "^3.0.0" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true } } }, @@ -1214,40 +1937,45 @@ } }, "babel-plugin-jest-hoist": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.4.0.tgz", - "integrity": "sha512-M3a10JCtTyKevb0MjuH6tU+cP/NVQZ82QPADqI1RQYY1OphztsCeIeQmTsHmF/NS6m0E51Zl4QNsI3odXSQF5w==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.0.6.tgz", + "integrity": "sha512-CewFeM9Vv2gM7Yr9n5eyyLVPRSiBnk6lKZRjgwYnGKSl9M14TMn2vkN02wTF04OGuSDLEzlWiMzvjXuW9mB6Gw==", "dev": true, "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", "@types/babel__traverse": "^7.0.6" } }, "babel-preset-current-node-syntax": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.2.tgz", - "integrity": "sha512-u/8cS+dEiK1SFILbOC8/rUI3ml9lboKuuMvZ/4aQnQmhecQAgPw5ew066C1ObnEAUmlx7dv/s2z52psWEtLNiw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, "requires": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.8.3", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" } }, "babel-preset-jest": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-25.4.0.tgz", - "integrity": "sha512-PwFiEWflHdu3JCeTr0Pb9NcHHE34qWFnPQRVPvqQITx4CsDCzs6o05923I10XvLvn9nNsRHuiVgB72wG/90ZHQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.0.6.tgz", + "integrity": "sha512-WObA0/Biw2LrVVwZkF/2GqbOdzhKD6Fkdwhoy9ASIrOWr/zodcSpQh72JOkEn6NWyjmnPDjNSqaGN4KnpKzhXw==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^25.4.0", - "babel-preset-current-node-syntax": "^0.1.2" + "babel-plugin-jest-hoist": "^27.0.6", + "babel-preset-current-node-syntax": "^1.0.0" } }, "balanced-match": { @@ -1255,61 +1983,6 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1324,9 +1997,9 @@ } }, "big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==" + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==" }, "binary": { "version": "0.3.0", @@ -1345,51 +2018,16 @@ "file-uri-to-path": "1.0.0" } }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - } - } - }, "bluebird": { "version": "3.4.7", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=" }, + "bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1414,21 +2052,17 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, - "browser-resolve": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", - "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "browserslist": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.0.tgz", + "integrity": "sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==", "dev": true, "requires": { - "resolve": "1.1.7" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } + "caniuse-lite": "^1.0.30001254", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.830", + "escalade": "^3.1.1", + "node-releases": "^1.1.75" } }, "bs-logger": { @@ -1458,10 +2092,15 @@ "ieee754": "^1.1.13" } }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" + }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, "buffer-indexof-polyfill": { @@ -1479,29 +2118,6 @@ "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, "caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -1532,14 +2148,11 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, - "capture-exit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", - "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", - "dev": true, - "requires": { - "rsvp": "^4.8.4" - } + "caniuse-lite": { + "version": "1.0.30001254", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001254.tgz", + "integrity": "sha512-GxeHOvR0LFMYPmFGA+NiTOt9uwYDxB3h154tW2yBYwfz2EMX3i1IBgr6gmJGfU0K8KQsqPa5XqLD8zVdP5lUzA==", + "dev": true }, "caseless": { "version": "0.12.0", @@ -1555,15 +2168,21 @@ } }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -1576,33 +2195,16 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", + "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", "dev": true }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } + "cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true }, "clean-stack": { "version": "2.2.0", @@ -1620,18 +2222,19 @@ } }, "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true }, "clipboardy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.0.0.tgz", - "integrity": "sha1-P87kIf3spOamLOcrZvPrDEIWWs0=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", "requires": { "arch": "^2.1.1", - "execa": "^1.0.0" + "execa": "^1.0.0", + "is-wsl": "^2.1.1" } }, "cliui": { @@ -1646,9 +2249,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "is-fullwidth-code-point": { @@ -1658,9 +2261,9 @@ "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==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { "emoji-regex": "^8.0.0", @@ -1760,103 +2363,76 @@ "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", "dev": true }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.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==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.3" } }, "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==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colorette": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", + "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", "dev": true }, "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { "delayed-stream": "~1.0.0" } }, "command-line-args": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", - "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.0.tgz", + "integrity": "sha512-4zqtU1hYsSJzcJBOcNZIbW5Fbk9BkjCp1pZVhQKoRaWL5J7N4XphDLwo8aWwdQpTugxwu+jf9u2ZhkXiqp5Z6A==", "dev": true, "requires": { - "array-back": "^3.0.1", + "array-back": "^3.1.0", "find-replace": "^3.0.0", "lodash.camelcase": "^4.3.0", "typical": "^4.0.0" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, "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==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -1872,9 +2448,9 @@ "dev": true }, "cssstyle": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.2.0.tgz", - "integrity": "sha512-sEb3XFPx3jNnCAMtqrXPDeSgQr+jojtCeNf8cvMNMh1cG970+lljssvQDzPq6lmmJu2Vhqood/gtEomBiHOGnA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", "dev": true, "requires": { "cssom": "~0.3.6" @@ -1897,22 +2473,22 @@ } }, "data-urls": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", - "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", "dev": true, "requires": { - "abab": "^2.0.0", - "whatwg-mimetype": "^2.2.0", - "whatwg-url": "^7.0.0" + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "decamelize": { @@ -1920,19 +2496,17 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", "dev": true }, - "decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "requires": { - "mimic-response": "^2.0.0" - } + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true }, "deep-extend": { "version": "0.6.0", @@ -1940,9 +2514,9 @@ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, "deepmerge": { @@ -1960,47 +2534,6 @@ "strip-bom": "^4.0.0" } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2012,32 +2545,21 @@ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "detect-indent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", - "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" - }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, "diff-sequences": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.1.0.tgz", - "integrity": "sha512-nFIfVk5B/NStCsJ+zaPO4vYuLjlzQ6uFvPxzYyHlejNZ/UGa7G/n7peOXVrVNvRuyfstt+mZQYGpjxg9Z6N8Kw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", "dev": true }, "dir-glob": { @@ -2049,13 +2571,26 @@ "path-type": "^4.0.0" } }, + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, "domexception": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", "dev": true, "requires": { - "webidl-conversions": "^4.0.2" + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } } }, "duplexer2": { @@ -2066,6 +2601,11 @@ "readable-stream": "^2.0.2" }, "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -2099,6 +2639,18 @@ "safer-buffer": "^2.1.0" } }, + "electron-to-chromium": { + "version": "1.3.830", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.830.tgz", + "integrity": "sha512-gBN7wNAxV5vl1430dG+XRcQhD4pIeYeak6p6rjdCtlz5wWNwDad8jwvphe5oi1chL5MV6RNRikfffBBiFuj+rQ==", + "dev": true + }, + "emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2128,6 +2680,12 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -2135,13 +2693,13 @@ "dev": true }, "escodegen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", - "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", "dev": true, "requires": { "esprima": "^4.0.1", - "estraverse": "^4.2.0", + "estraverse": "^5.2.0", "esutils": "^2.0.2", "optionator": "^0.8.1", "source-map": "~0.6.1" @@ -2154,9 +2712,9 @@ "dev": true }, "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true }, "esutils": { @@ -2165,16 +2723,10 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "exec-sh": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", - "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==", - "dev": true - }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "requires": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", @@ -2185,97 +2737,35 @@ "strip-eof": "^1.0.0" } }, + "exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" + }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "expect": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.1.0.tgz", + "integrity": "sha512-9kJngV5hOJgkFil4F/uXm3hVBubUK2nERVfvqNNwxxuW8ZOUwSTTSysgfzckYtv/LBzj/LJXbiAF7okHCXgdug==", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "@jest/types": "^27.1.0", + "ansi-styles": "^5.0.0", + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.1.0", + "jest-message-util": "^27.1.0", + "jest-regex-util": "^27.0.6" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" - }, - "expect": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-25.4.0.tgz", - "integrity": "sha512-7BDIX99BTi12/sNGJXA9KMRcby4iAmu1xccBOhyKCyEhjcVKS3hPmHdA/4nSI9QGIOkUropKqr3vv7WMDM5lvQ==", - "dev": true, - "requires": { - "@jest/types": "^25.4.0", - "ansi-styles": "^4.0.0", - "jest-get-type": "^25.2.6", - "jest-matcher-utils": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-regex-util": "^25.2.6" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, - "jest-get-type": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", - "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true } } @@ -2285,27 +2775,6 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -2317,99 +2786,33 @@ "tmp": "^0.0.33" } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz", - "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "micromatch": "^4.0.4" } }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-levenshtein": { "version": "2.0.6", @@ -2418,9 +2821,9 @@ "dev": true }, "fastq": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.1.tgz", - "integrity": "sha512-mpIH5sKYueh3YyeJwqtVo8sORi0CgtmkVbK6kZStpQlZBYQuTzG2CZ7idSiJuA7bY0SFCWUc5WIs+oYumGCQNw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", + "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -2444,6 +2847,11 @@ "escape-string-regexp": "^1.0.5" } }, + "file-type": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", + "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==" + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -2459,9 +2867,9 @@ } }, "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "requires": { "commondir": "^1.0.1", @@ -2488,12 +2896,6 @@ "path-exists": "^4.0.0" } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, "foreach": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", @@ -2568,26 +2970,12 @@ "mime-types": "^2.1.12" } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, "fromentries": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.1.tgz", - "integrity": "sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, "fs-extra": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", @@ -2612,9 +3000,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, @@ -2639,6 +3027,12 @@ } } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, "gauge": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", @@ -2652,9 +3046,9 @@ } }, "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, "get-caller-file": { @@ -2672,28 +3066,11 @@ "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "requires": { "pump": "^3.0.0" - }, - "dependencies": { - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } } }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -2702,15 +3079,19 @@ "assert-plus": "^1.0.0" } }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + "gifwrap": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.2.tgz", + "integrity": "sha512-fcIswrPaiCDAyO8xnWvHSZdWChjKXUanKKpAiWWJ/UTkEi/aYKn5+90e7DE820zbEaVR9CE2y4z9bzhQijZ0BA==", + "requires": { + "image-q": "^1.1.1", + "omggif": "^1.0.10" + } }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2729,6 +3110,15 @@ "is-glob": "^4.0.1" } }, + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "requires": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -2736,9 +3126,9 @@ "dev": true }, "globby": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.0.tgz", - "integrity": "sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", "dev": true, "requires": { "array-union": "^2.1.0", @@ -2750,16 +3140,9 @@ } }, "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha1-/7cD4QZuig7qpMi4C6klPu77+wA=" - }, - "growly": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", - "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", - "dev": true, - "optional": true + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, "handlebars": { "version": "4.7.7", @@ -2780,14 +3163,23 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2799,62 +3191,10 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "hasha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", - "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, "requires": { "is-stream": "^2.0.0", @@ -2862,9 +3202,9 @@ }, "dependencies": { "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, "type-fest": { @@ -2875,12 +3215,6 @@ } } }, - "highlight.js": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.4.1.tgz", - "integrity": "sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg==", - "dev": true - }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -2888,12 +3222,12 @@ "dev": true }, "html-encoding-sniffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", - "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", "dev": true, "requires": { - "whatwg-encoding": "^1.0.1" + "whatwg-encoding": "^1.0.5" } }, "html-escaper": { @@ -2902,6 +3236,17 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -2912,10 +3257,20 @@ "sshpk": "^1.7.0" } }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, "iconv-lite": { @@ -2933,11 +3288,16 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true }, + "image-q": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-1.1.1.tgz", + "integrity": "sha1-/IQJlmRGC5DKhi2TALa/u7+/gFY=" + }, "import-local": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", @@ -2970,9 +3330,9 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "1.3.8", @@ -2980,30 +3340,30 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "inquirer": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", - "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", + "chalk": "^4.1.0", "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", + "cli-width": "^3.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.19", "mute-stream": "0.0.8", "run-async": "^2.4.0", - "rxjs": "^6.5.3", + "rxjs": "^6.6.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6" }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "is-fullwidth-code-point": { @@ -3013,9 +3373,9 @@ "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==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { "emoji-regex": "^8.0.0", @@ -3034,108 +3394,39 @@ } } }, - "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", - "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=" }, - "ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.0.tgz", + "integrity": "sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "ci-info": "^3.1.1" } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "is-core-module": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "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 - } + "has": "^1.0.3" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" }, "is-extglob": { "version": "2.1.1", @@ -3151,6 +3442,11 @@ "number-is-nan": "^1.0.0" } }, + "is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" + }, "is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", @@ -3177,19 +3473,10 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, "is-stream": { @@ -3202,6 +3489,12 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -3215,28 +3508,23 @@ "dev": true }, "is-wsl": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", - "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", - "dev": true, - "optional": true + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } }, "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -3258,15 +3546,12 @@ } }, "istanbul-lib-instrument": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz", - "integrity": "sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "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" @@ -3522,238 +3807,74 @@ } }, "jest": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-25.1.0.tgz", - "integrity": "sha512-FV6jEruneBhokkt9MQk0WUFoNTwnF76CLXtwNMfsc0um0TlB/LG2yxUd0KqaFjEJ9laQmVWQWS0sG/t2GsuI0w==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.1.0.tgz", + "integrity": "sha512-pSQDVwRSwb109Ss13lcMtdfS9r8/w2Zz8+mTUA9VORD66GflCdl8nUFCqM96geOD2EBwWCNURrNAfQsLIDNBdg==", "dev": true, "requires": { - "@jest/core": "^25.1.0", + "@jest/core": "^27.1.0", "import-local": "^3.0.2", - "jest-cli": "^25.1.0" + "jest-cli": "^27.1.0" }, "dependencies": { - "@jest/core": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-25.4.0.tgz", - "integrity": "sha512-h1x9WSVV0+TKVtATGjyQIMJENs8aF6eUjnCoi4jyRemYZmekLr8EJOGQqTWEX8W6SbZ6Skesy9pGXrKeAolUJw==", - "dev": true, - "requires": { - "@jest/console": "^25.4.0", - "@jest/reporters": "^25.4.0", - "@jest/test-result": "^25.4.0", - "@jest/transform": "^25.4.0", - "@jest/types": "^25.4.0", - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.3", - "jest-changed-files": "^25.4.0", - "jest-config": "^25.4.0", - "jest-haste-map": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-regex-util": "^25.2.6", - "jest-resolve": "^25.4.0", - "jest-resolve-dependencies": "^25.4.0", - "jest-runner": "^25.4.0", - "jest-runtime": "^25.4.0", - "jest-snapshot": "^25.4.0", - "jest-util": "^25.4.0", - "jest-validate": "^25.4.0", - "jest-watcher": "^25.4.0", - "micromatch": "^4.0.2", - "p-each-series": "^2.1.0", - "realpath-native": "^2.0.0", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "@jest/test-result": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.4.0.tgz", - "integrity": "sha512-8BAKPaMCHlL941eyfqhWbmp3MebtzywlxzV+qtngQ3FH+RBqnoSAhNEPj4MG7d2NVUrMOVfrwuzGpVIK+QnMAA==", - "dev": true, - "requires": { - "@jest/console": "^25.4.0", - "@jest/types": "^25.4.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, - "jest-config": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-25.4.0.tgz", - "integrity": "sha512-egT9aKYxMyMSQV1aqTgam0SkI5/I2P9qrKexN5r2uuM2+68ypnc+zPGmfUxK7p1UhE7dYH9SLBS7yb+TtmT1AA==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^25.4.0", - "@jest/types": "^25.4.0", - "babel-jest": "^25.4.0", - "chalk": "^3.0.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "jest-environment-jsdom": "^25.4.0", - "jest-environment-node": "^25.4.0", - "jest-get-type": "^25.2.6", - "jest-jasmine2": "^25.4.0", - "jest-regex-util": "^25.2.6", - "jest-resolve": "^25.4.0", - "jest-util": "^25.4.0", - "jest-validate": "^25.4.0", - "micromatch": "^4.0.2", - "pretty-format": "^25.4.0", - "realpath-native": "^2.0.0" - } - }, - "jest-util": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.4.0.tgz", - "integrity": "sha512-WSZD59sBtAUjLv1hMeKbNZXmMcrLRWcYqpO8Dz8b4CeCTZpfNQw2q9uwrYAD+BbJoLJlu4ezVPwtAmM/9/SlZA==", - "dev": true, - "requires": { - "@jest/types": "^25.4.0", - "chalk": "^3.0.0", - "is-ci": "^2.0.0", - "make-dir": "^3.0.0" - } - }, - "jest-validate": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-25.4.0.tgz", - "integrity": "sha512-hvjmes/EFVJSoeP1yOl8qR8mAtMR3ToBkZeXrD/ZS9VxRyWDqQ/E1C5ucMTeSmEOGLipvdlyipiGbHJ+R1MQ0g==", - "dev": true, - "requires": { - "@jest/types": "^25.4.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "jest-get-type": "^25.2.6", - "leven": "^3.1.0", - "pretty-format": "^25.4.0" - } - }, - "realpath-native": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", - "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", - "dev": true - } - } - }, "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "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==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, - "jest-cli": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-25.4.0.tgz", - "integrity": "sha512-usyrj1lzCJZMRN1r3QEdnn8e6E6yCx/QN7+B1sLoA68V7f3WlsxSSQfy0+BAwRiF4Hz2eHauf11GZG3PIfWTXQ==", + "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 + }, + "jest-cli": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.1.0.tgz", + "integrity": "sha512-h6zPUOUu+6oLDrXz0yOWY2YXvBLk8gQinx4HbZ7SF4V3HzasQf+ncoIbKENUMwXyf54/6dBkYXvXJos+gOHYZw==", "dev": true, "requires": { - "@jest/core": "^25.4.0", - "@jest/test-result": "^25.4.0", - "@jest/types": "^25.4.0", - "chalk": "^3.0.0", + "@jest/core": "^27.1.0", + "@jest/test-result": "^27.1.0", + "@jest/types": "^27.1.0", + "chalk": "^4.0.0", "exit": "^0.1.2", + "graceful-fs": "^4.2.4", "import-local": "^3.0.2", - "is-ci": "^2.0.0", - "jest-config": "^25.4.0", - "jest-util": "^25.4.0", - "jest-validate": "^25.4.0", + "jest-config": "^27.1.0", + "jest-util": "^27.1.0", + "jest-validate": "^27.1.0", "prompts": "^2.0.1", - "realpath-native": "^2.0.0", - "yargs": "^15.3.1" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, - "prompts": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.2.tgz", - "integrity": "sha512-Q06uKs2CkNYVID0VqwfAl9mipo99zkBv/n2JtWY89Yxa3ZabWSrs0e2KTudKVa3peLUvYXMefDqIleLPVUBZMA==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.4" - } - } + "yargs": "^16.0.3" } }, - "jest-get-type": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", - "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", - "dev": true - }, - "pretty-format": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.4.0.tgz", - "integrity": "sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ==", - "dev": true, - "requires": { - "@jest/types": "^25.4.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - } - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { - "glob": "^7.1.3" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { @@ -3764,36 +3885,62 @@ "requires": { "ansi-regex": "^5.0.0" } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true } } }, "jest-changed-files": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-25.4.0.tgz", - "integrity": "sha512-VR/rfJsEs4BVMkwOTuStRyS630fidFVekdw/lBaBQjx9KK3VZFOZ2c0fsom2fRp8pMCrCTP6LGna00o/DXGlqA==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.1.0.tgz", + "integrity": "sha512-eRcb13TfQw0xiV2E98EmiEgs9a5uaBIqJChyl0G7jR9fCIvGjXovnDS6Zbku3joij4tXYcSK4SE1AXqOlUxjWg==", "dev": true, "requires": { - "@jest/types": "^25.4.0", - "execa": "^3.2.0", - "throat": "^5.0.0" + "@jest/types": "^27.1.0", + "execa": "^5.0.0", + "throat": "^6.0.1" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, "cross-spawn": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", - "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -3802,36 +3949,32 @@ } }, "execa": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", - "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "p-finally": "^2.0.0", - "signal-exit": "^3.0.2", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true }, "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, "npm-run-path": { @@ -3843,12 +3986,6 @@ "path-key": "^3.0.0" } }, - "p-finally": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", - "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", - "dev": true - }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -3870,6 +4007,12 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3881,857 +4024,800 @@ } } }, + "jest-circus": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.1.0.tgz", + "integrity": "sha512-6FWtHs3nZyZlMBhRf1wvAC5CirnflbGJAY1xssSAnERLiiXQRH+wY2ptBVtXjX4gz4AA2EwRV57b038LmifRbA==", + "dev": true, + "requires": { + "@jest/environment": "^27.1.0", + "@jest/test-result": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.1.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.1.0", + "jest-matcher-utils": "^27.1.0", + "jest-message-util": "^27.1.0", + "jest-runtime": "^27.1.0", + "jest-snapshot": "^27.1.0", + "jest-util": "^27.1.0", + "pretty-format": "^27.1.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + } + }, "jest-config": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-25.4.0.tgz", - "integrity": "sha512-egT9aKYxMyMSQV1aqTgam0SkI5/I2P9qrKexN5r2uuM2+68ypnc+zPGmfUxK7p1UhE7dYH9SLBS7yb+TtmT1AA==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.1.0.tgz", + "integrity": "sha512-GMo7f76vMYUA3b3xOdlcKeKQhKcBIgurjERO2hojo0eLkKPGcw7fyIoanH+m6KOP2bLad+fGnF8aWOJYxzNPeg==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^25.4.0", - "@jest/types": "^25.4.0", - "babel-jest": "^25.4.0", - "chalk": "^3.0.0", + "@jest/test-sequencer": "^27.1.0", + "@jest/types": "^27.1.0", + "babel-jest": "^27.1.0", + "chalk": "^4.0.0", "deepmerge": "^4.2.2", "glob": "^7.1.1", - "jest-environment-jsdom": "^25.4.0", - "jest-environment-node": "^25.4.0", - "jest-get-type": "^25.2.6", - "jest-jasmine2": "^25.4.0", - "jest-regex-util": "^25.2.6", - "jest-resolve": "^25.4.0", - "jest-util": "^25.4.0", - "jest-validate": "^25.4.0", - "micromatch": "^4.0.2", - "pretty-format": "^25.4.0", - "realpath-native": "^2.0.0" + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "jest-circus": "^27.1.0", + "jest-environment-jsdom": "^27.1.0", + "jest-environment-node": "^27.1.0", + "jest-get-type": "^27.0.6", + "jest-jasmine2": "^27.1.0", + "jest-regex-util": "^27.0.6", + "jest-resolve": "^27.1.0", + "jest-runner": "^27.1.0", + "jest-util": "^27.1.0", + "jest-validate": "^27.1.0", + "micromatch": "^4.0.4", + "pretty-format": "^27.1.0" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "jest-get-type": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", - "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true - }, - "pretty-format": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.4.0.tgz", - "integrity": "sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ==", - "dev": true, - "requires": { - "@jest/types": "^25.4.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - } } } }, "jest-diff": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.1.0.tgz", - "integrity": "sha512-nepXgajT+h017APJTreSieh4zCqnSHEJ1iT8HDlewu630lSJ4Kjjr9KNzm+kzGwwcpsDE6Snx1GJGzzsefaEHw==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.1.0.tgz", + "integrity": "sha512-rjfopEYl58g/SZTsQFmspBODvMSytL16I+cirnScWTLkQVXYVZfxm78DFfdIIXc05RCYuGjxJqrdyG4PIFzcJg==", "dev": true, "requires": { - "chalk": "^3.0.0", - "diff-sequences": "^25.1.0", - "jest-get-type": "^25.1.0", - "pretty-format": "^25.1.0" + "chalk": "^4.0.0", + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.1.0" } }, "jest-docblock": { - "version": "25.3.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-25.3.0.tgz", - "integrity": "sha512-aktF0kCar8+zxRHxQZwxMy70stc9R1mOmrLsT5VO3pIT0uzGRSDAXxSlz4NqQWpuLjPpuMhPRl7H+5FRsvIQAg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.0.6.tgz", + "integrity": "sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-25.4.0.tgz", - "integrity": "sha512-lwRIJ8/vQU/6vq3nnSSUw1Y3nz5tkYSFIywGCZpUBd6WcRgpn8NmJoQICojbpZmsJOJNHm0BKdyuJ6Xdx+eDQQ==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.1.0.tgz", + "integrity": "sha512-K/cNvQlmDqQMRHF8CaQ0XPzCfjP5HMJc2bIJglrIqI9fjwpNqITle63IWE+wq4p+3v+iBgh7Wq0IdGpLx5xjDg==", "dev": true, "requires": { - "@jest/types": "^25.4.0", - "chalk": "^3.0.0", - "jest-get-type": "^25.2.6", - "jest-util": "^25.4.0", - "pretty-format": "^25.4.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "jest-get-type": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", - "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", - "dev": true - }, - "pretty-format": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.4.0.tgz", - "integrity": "sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ==", - "dev": true, - "requires": { - "@jest/types": "^25.4.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - } - } + "@jest/types": "^27.1.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.0.6", + "jest-util": "^27.1.0", + "pretty-format": "^27.1.0" } }, "jest-environment-jsdom": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-25.4.0.tgz", - "integrity": "sha512-KTitVGMDrn2+pt7aZ8/yUTuS333w3pWt1Mf88vMntw7ZSBNDkRS6/4XLbFpWXYfWfp1FjcjQTOKzbK20oIehWQ==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.1.0.tgz", + "integrity": "sha512-JbwOcOxh/HOtsj56ljeXQCUJr3ivnaIlM45F5NBezFLVYdT91N5UofB1ux2B1CATsQiudcHdgTaeuqGXJqjJYQ==", "dev": true, "requires": { - "@jest/environment": "^25.4.0", - "@jest/fake-timers": "^25.4.0", - "@jest/types": "^25.4.0", - "jest-mock": "^25.4.0", - "jest-util": "^25.4.0", - "jsdom": "^15.2.1" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - } + "@jest/environment": "^27.1.0", + "@jest/fake-timers": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/node": "*", + "jest-mock": "^27.1.0", + "jest-util": "^27.1.0", + "jsdom": "^16.6.0" } }, "jest-environment-node": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-25.4.0.tgz", - "integrity": "sha512-wryZ18vsxEAKFH7Z74zi/y/SyI1j6UkVZ6QsllBuT/bWlahNfQjLNwFsgh/5u7O957dYFoXj4yfma4n4X6kU9A==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.1.0.tgz", + "integrity": "sha512-JIyJ8H3wVyM4YCXp7njbjs0dIT87yhGlrXCXhDKNIg1OjurXr6X38yocnnbXvvNyqVTqSI4M9l+YfPKueqL1lw==", "dev": true, "requires": { - "@jest/environment": "^25.4.0", - "@jest/fake-timers": "^25.4.0", - "@jest/types": "^25.4.0", - "jest-mock": "^25.4.0", - "jest-util": "^25.4.0", - "semver": "^6.3.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.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 - } + "@jest/environment": "^27.1.0", + "@jest/fake-timers": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/node": "*", + "jest-mock": "^27.1.0", + "jest-util": "^27.1.0" } }, "jest-get-type": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.1.0.tgz", - "integrity": "sha512-yWkBnT+5tMr8ANB6V+OjmrIJufHtCAqI5ic2H40v+tRqxDmE0PGnIiTyvRWFOMtmVHYpwRqyazDbTnhpjsGvLw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.6.tgz", + "integrity": "sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==", "dev": true }, "jest-haste-map": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.4.0.tgz", - "integrity": "sha512-5EoCe1gXfGC7jmXbKzqxESrgRcaO3SzWXGCnvp9BcT0CFMyrB1Q6LIsjl9RmvmJGQgW297TCfrdgiy574Rl9HQ==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.1.0.tgz", + "integrity": "sha512-7mz6LopSe+eA6cTFMf10OfLLqRoIPvmMyz5/OnSXnHO7hB0aDP1iIeLWCXzAcYU5eIJVpHr12Bk9yyq2fTW9vg==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^27.1.0", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", - "fsevents": "^2.1.2", - "graceful-fs": "^4.2.3", - "jest-serializer": "^25.2.6", - "jest-util": "^25.4.0", - "jest-worker": "^25.4.0", - "micromatch": "^4.0.2", - "sane": "^4.0.3", - "walker": "^1.0.7", - "which": "^2.0.2" + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^27.0.6", + "jest-serializer": "^27.0.6", + "jest-util": "^27.1.0", + "jest-worker": "^27.1.0", + "micromatch": "^4.0.4", + "walker": "^1.0.7" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, "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==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true - }, - "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" - } } } }, "jest-jasmine2": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-25.4.0.tgz", - "integrity": "sha512-QccxnozujVKYNEhMQ1vREiz859fPN/XklOzfQjm2j9IGytAkUbSwjFRBtQbHaNZ88cItMpw02JnHGsIdfdpwxQ==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.1.0.tgz", + "integrity": "sha512-Z/NIt0wBDg3przOW2FCWtYjMn3Ip68t0SL60agD/e67jlhTyV3PIF8IzT9ecwqFbeuUSO2OT8WeJgHcalDGFzQ==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^25.4.0", - "@jest/source-map": "^25.2.6", - "@jest/test-result": "^25.4.0", - "@jest/types": "^25.4.0", - "chalk": "^3.0.0", + "@jest/environment": "^27.1.0", + "@jest/source-map": "^27.0.6", + "@jest/test-result": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/node": "*", + "chalk": "^4.0.0", "co": "^4.6.0", - "expect": "^25.4.0", + "expect": "^27.1.0", "is-generator-fn": "^2.0.0", - "jest-each": "^25.4.0", - "jest-matcher-utils": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-runtime": "^25.4.0", - "jest-snapshot": "^25.4.0", - "jest-util": "^25.4.0", - "pretty-format": "^25.4.0", - "throat": "^5.0.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "pretty-format": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.4.0.tgz", - "integrity": "sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ==", - "dev": true, - "requires": { - "@jest/types": "^25.4.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - } - } + "jest-each": "^27.1.0", + "jest-matcher-utils": "^27.1.0", + "jest-message-util": "^27.1.0", + "jest-runtime": "^27.1.0", + "jest-snapshot": "^27.1.0", + "jest-util": "^27.1.0", + "pretty-format": "^27.1.0", + "throat": "^6.0.1" } }, "jest-leak-detector": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-25.4.0.tgz", - "integrity": "sha512-7Y6Bqfv2xWsB+7w44dvZuLs5SQ//fzhETgOGG7Gq3TTGFdYvAgXGwV8z159RFZ6fXiCPm/szQ90CyfVos9JIFQ==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.1.0.tgz", + "integrity": "sha512-oHvSkz1E80VyeTKBvZNnw576qU+cVqRXUD3/wKXh1zpaki47Qty2xeHg2HKie9Hqcd2l4XwircgNOWb/NiGqdA==", + "dev": true, + "requires": { + "jest-get-type": "^27.0.6", + "pretty-format": "^27.1.0" + } + }, + "jest-matcher-utils": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.1.0.tgz", + "integrity": "sha512-VmAudus2P6Yt/JVBRdTPFhUzlIN8DYJd+et5Rd9QDsO/Z82Z4iwGjo43U8Z+PTiz8CBvKvlb6Fh3oKy39hykkQ==", "dev": true, "requires": { - "jest-get-type": "^25.2.6", - "pretty-format": "^25.4.0" + "chalk": "^4.0.0", + "jest-diff": "^27.1.0", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.1.0" + } + }, + "jest-message-util": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.1.0.tgz", + "integrity": "sha512-Eck8NFnJ5Sg36R9XguD65cf2D5+McC+NF5GIdEninoabcuoOfWrID5qJhufq5FB0DRKoiyxB61hS7MKoMD0trQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.1.0", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "pretty-format": "^27.1.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "@babel/highlight": "^7.14.5" } }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "@babel/helper-validator-identifier": { + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", "dev": true }, - "jest-get-type": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", - "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", - "dev": true + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "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==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } }, - "pretty-format": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.4.0.tgz", - "integrity": "sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ==", + "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": { - "@jest/types": "^25.4.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" + "color-convert": "^1.9.0" } - } - } - }, - "jest-matcher-utils": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-25.4.0.tgz", - "integrity": "sha512-yPMdtj7YDgXhnGbc66bowk8AkQ0YwClbbwk3Kzhn5GVDrciiCr27U4NJRbrqXbTdtxjImONITg2LiRIw650k5A==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "jest-diff": "^25.4.0", - "jest-get-type": "^25.2.6", - "pretty-format": "^25.4.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + }, + "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==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "color-name": "1.1.3" } }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "diff-sequences": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", - "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, - "jest-diff": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.4.0.tgz", - "integrity": "sha512-kklLbJVXW0y8UKOWOdYhI6TH5MG6QAxrWiBMgQaPIuhj3dNFGirKCd+/xfplBXICQ7fI+3QcqHm9p9lWu1N6ug==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "diff-sequences": "^25.2.6", - "jest-get-type": "^25.2.6", - "pretty-format": "^25.4.0" - } - }, - "jest-get-type": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", - "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "pretty-format": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.4.0.tgz", - "integrity": "sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ==", - "dev": true, - "requires": { - "@jest/types": "^25.4.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - } - } - } - }, - "jest-message-util": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.4.0.tgz", - "integrity": "sha512-LYY9hRcVGgMeMwmdfh9tTjeux1OjZHMusq/E5f3tJN+dAoVVkJtq5ZUEPIcB7bpxDUt2zjUsrwg0EGgPQ+OhXQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/types": "^25.4.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^3.0.0", - "micromatch": "^4.0.2", - "slash": "^3.0.0", - "stack-utils": "^1.0.1" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + "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": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "has-flag": "^3.0.0" } } } }, "jest-mock": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.4.0.tgz", - "integrity": "sha512-MdazSfcYAUjJjuVTTnusLPzE0pE4VXpOUzWdj8sbM+q6abUjm3bATVPXFqTXrxSieR8ocpvQ9v/QaQCftioQFg==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.1.0.tgz", + "integrity": "sha512-iT3/Yhu7DwAg/0HvvLCqLvrTKTRMyJlrrfJYWzuLSf9RCAxBoIXN3HoymZxMnYsC3eD8ewGbUa9jUknwBenx2w==", "dev": true, "requires": { - "@jest/types": "^25.4.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - } + "@jest/types": "^27.1.0", + "@types/node": "*" } }, "jest-pnp-resolver": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", - "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", "dev": true }, "jest-regex-util": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.2.6.tgz", - "integrity": "sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", + "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", "dev": true }, "jest-resolve": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.4.0.tgz", - "integrity": "sha512-wOsKqVDFWUiv8BtLMCC6uAJ/pHZkfFgoBTgPtmYlsprAjkxrr2U++ZnB3l5ykBMd2O24lXvf30SMAjJIW6k2aA==", - "dev": true, - "requires": { - "@jest/types": "^25.4.0", - "browser-resolve": "^1.11.3", - "chalk": "^3.0.0", - "jest-pnp-resolver": "^1.2.1", - "read-pkg-up": "^7.0.1", - "realpath-native": "^2.0.0", - "resolve": "^1.15.1", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.1.0.tgz", + "integrity": "sha512-TXvzrLyPg0vLOwcWX38ZGYeEztSEmW+cQQKqc4HKDUwun31wsBXwotRlUz4/AYU/Fq4GhbMd/ileIWZEtcdmIA==", + "dev": true, + "requires": { + "@jest/types": "^27.1.0", + "chalk": "^4.0.0", + "escalade": "^3.1.1", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.1.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.1.0", + "jest-validate": "^27.1.0", + "resolve": "^1.20.0", "slash": "^3.0.0" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" } } } }, "jest-resolve-dependencies": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-25.4.0.tgz", - "integrity": "sha512-A0eoZXx6kLiuG1Ui7wITQPl04HwjLErKIJTt8GR3c7UoDAtzW84JtCrgrJ6Tkw6c6MwHEyAaLk7dEPml5pf48A==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.1.0.tgz", + "integrity": "sha512-Kq5XuDAELuBnrERrjFYEzu/A+i2W7l9HnPWqZEeKGEQ7m1R+6ndMbdXCVCx29Se1qwLZLgvoXwinB3SPIaitMQ==", "dev": true, "requires": { - "@jest/types": "^25.4.0", - "jest-regex-util": "^25.2.6", - "jest-snapshot": "^25.4.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - } + "@jest/types": "^27.1.0", + "jest-regex-util": "^27.0.6", + "jest-snapshot": "^27.1.0" } }, "jest-runner": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-25.4.0.tgz", - "integrity": "sha512-wWQSbVgj2e/1chFdMRKZdvlmA6p1IPujhpLT7TKNtCSl1B0PGBGvJjCaiBal/twaU2yfk8VKezHWexM8IliBfA==", - "dev": true, - "requires": { - "@jest/console": "^25.4.0", - "@jest/environment": "^25.4.0", - "@jest/test-result": "^25.4.0", - "@jest/types": "^25.4.0", - "chalk": "^3.0.0", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.1.0.tgz", + "integrity": "sha512-ZWPKr9M5w5gDplz1KsJ6iRmQaDT/yyAFLf18fKbb/+BLWsR1sCNC2wMT0H7pP3gDcBz0qZ6aJraSYUNAGSJGaw==", + "dev": true, + "requires": { + "@jest/console": "^27.1.0", + "@jest/environment": "^27.1.0", + "@jest/test-result": "^27.1.0", + "@jest/transform": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", "exit": "^0.1.2", - "graceful-fs": "^4.2.3", - "jest-config": "^25.4.0", - "jest-docblock": "^25.3.0", - "jest-haste-map": "^25.4.0", - "jest-jasmine2": "^25.4.0", - "jest-leak-detector": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-resolve": "^25.4.0", - "jest-runtime": "^25.4.0", - "jest-util": "^25.4.0", - "jest-worker": "^25.4.0", + "graceful-fs": "^4.2.4", + "jest-docblock": "^27.0.6", + "jest-environment-jsdom": "^27.1.0", + "jest-environment-node": "^27.1.0", + "jest-haste-map": "^27.1.0", + "jest-leak-detector": "^27.1.0", + "jest-message-util": "^27.1.0", + "jest-resolve": "^27.1.0", + "jest-runtime": "^27.1.0", + "jest-util": "^27.1.0", + "jest-worker": "^27.1.0", "source-map-support": "^0.5.6", - "throat": "^5.0.0" + "throat": "^6.0.1" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, "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==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true } } }, "jest-runtime": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-25.4.0.tgz", - "integrity": "sha512-lgNJlCDULtXu9FumnwCyWlOub8iytijwsPNa30BKrSNtgoT6NUMXOPrZvsH06U6v0wgD/Igwz13nKA2wEKU2VA==", - "dev": true, - "requires": { - "@jest/console": "^25.4.0", - "@jest/environment": "^25.4.0", - "@jest/source-map": "^25.2.6", - "@jest/test-result": "^25.4.0", - "@jest/transform": "^25.4.0", - "@jest/types": "^25.4.0", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.1.0.tgz", + "integrity": "sha512-okiR2cpGjY0RkWmUGGado6ETpFOi9oG3yV0CioYdoktkVxy5Hv0WRLWnJFuArSYS8cHMCNcceUUMGiIfgxCO9A==", + "dev": true, + "requires": { + "@jest/console": "^27.1.0", + "@jest/environment": "^27.1.0", + "@jest/fake-timers": "^27.1.0", + "@jest/globals": "^27.1.0", + "@jest/source-map": "^27.0.6", + "@jest/test-result": "^27.1.0", + "@jest/transform": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", "exit": "^0.1.2", "glob": "^7.1.3", - "graceful-fs": "^4.2.3", - "jest-config": "^25.4.0", - "jest-haste-map": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-mock": "^25.4.0", - "jest-regex-util": "^25.2.6", - "jest-resolve": "^25.4.0", - "jest-snapshot": "^25.4.0", - "jest-util": "^25.4.0", - "jest-validate": "^25.4.0", - "realpath-native": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.1.0", + "jest-message-util": "^27.1.0", + "jest-mock": "^27.1.0", + "jest-regex-util": "^27.0.6", + "jest-resolve": "^27.1.0", + "jest-snapshot": "^27.1.0", + "jest-util": "^27.1.0", + "jest-validate": "^27.1.0", "slash": "^3.0.0", "strip-bom": "^4.0.0", - "yargs": "^15.3.1" + "yargs": "^16.0.3" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "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==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true - } - } - }, - "jest-serializer": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.2.6.tgz", - "integrity": "sha512-RMVCfZsezQS2Ww4kB5HJTMaMJ0asmC0BHlnobQC6yEtxiFKIxohFA4QSXSabKwSggaNkqxn6Z2VwdFCjhUWuiQ==", - "dev": true - }, - "jest-snapshot": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.4.0.tgz", - "integrity": "sha512-J4CJ0X2SaGheYRZdLz9CRHn9jUknVmlks4UBeu270hPAvdsauFXOhx9SQP2JtRzhnR3cvro/9N9KP83/uvFfRg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0", - "@jest/types": "^25.4.0", - "@types/prettier": "^1.19.0", - "chalk": "^3.0.0", - "expect": "^25.4.0", - "jest-diff": "^25.4.0", - "jest-get-type": "^25.2.6", - "jest-matcher-utils": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-resolve": "^25.4.0", - "make-dir": "^3.0.0", - "natural-compare": "^1.4.0", - "pretty-format": "^25.4.0", - "semver": "^6.3.0" - }, - "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + }, + "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 + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "path-key": "^3.0.0" } }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "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 }, - "diff-sequences": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", - "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", + "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": { + "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 + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "jest-diff": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.4.0.tgz", - "integrity": "sha512-kklLbJVXW0y8UKOWOdYhI6TH5MG6QAxrWiBMgQaPIuhj3dNFGirKCd+/xfplBXICQ7fI+3QcqHm9p9lWu1N6ug==", + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { - "chalk": "^3.0.0", - "diff-sequences": "^25.2.6", - "jest-get-type": "^25.2.6", - "pretty-format": "^25.4.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, - "jest-get-type": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", - "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", - "dev": true + "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" + } + }, + "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" + } }, - "pretty-format": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.4.0.tgz", - "integrity": "sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ==", + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { - "@jest/types": "^25.4.0", - "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true } } }, - "jest-util": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.4.0.tgz", - "integrity": "sha512-WSZD59sBtAUjLv1hMeKbNZXmMcrLRWcYqpO8Dz8b4CeCTZpfNQw2q9uwrYAD+BbJoLJlu4ezVPwtAmM/9/SlZA==", + "jest-serializer": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.6.tgz", + "integrity": "sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA==", "dev": true, "requires": { - "@jest/types": "^25.4.0", - "chalk": "^3.0.0", - "is-ci": "^2.0.0", - "make-dir": "^3.0.0" + "@types/node": "*", + "graceful-fs": "^4.2.4" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + } + } + }, + "jest-snapshot": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.1.0.tgz", + "integrity": "sha512-eaeUBoEjuuRwmiRI51oTldUsKOohB1F6fPqWKKILuDi/CStxzp2IWekVUXbuHHoz5ik33ioJhshiHpgPFbYgcA==", + "dev": true, + "requires": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/parser": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.1.0", + "graceful-fs": "^4.2.4", + "jest-diff": "^27.1.0", + "jest-get-type": "^27.0.6", + "jest-haste-map": "^27.1.0", + "jest-matcher-utils": "^27.1.0", + "jest-message-util": "^27.1.0", + "jest-resolve": "^27.1.0", + "jest-util": "^27.1.0", + "natural-compare": "^1.4.0", + "pretty-format": "^27.1.0", + "semver": "^7.3.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "lru-cache": "^6.0.0" } } } }, + "jest-util": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.1.0.tgz", + "integrity": "sha512-edSLD2OneYDKC6gZM1yc+wY/877s/fuJNoM1k3sOEpzFyeptSmke3SLnk1dDHk9CgTA+58mnfx3ew3J11Kes/w==", + "dev": true, + "requires": { + "@jest/types": "^27.1.0", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + } + } + }, "jest-validate": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-25.4.0.tgz", - "integrity": "sha512-hvjmes/EFVJSoeP1yOl8qR8mAtMR3ToBkZeXrD/ZS9VxRyWDqQ/E1C5ucMTeSmEOGLipvdlyipiGbHJ+R1MQ0g==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.1.0.tgz", + "integrity": "sha512-QiJ+4XuSuMsfPi9zvdO//IrSRSlG6ybJhOpuqYSsuuaABaNT84h0IoD6vvQhThBOKT+DIKvl5sTM0l6is9+SRA==", "dev": true, "requires": { - "@jest/types": "^25.4.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "jest-get-type": "^25.2.6", + "@jest/types": "^27.1.0", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.0.6", "leven": "^3.1.0", - "pretty-format": "^25.4.0" + "pretty-format": "^27.1.0" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "jest-get-type": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", - "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "dev": true - }, - "pretty-format": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.4.0.tgz", - "integrity": "sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ==", - "dev": true, - "requires": { - "@jest/types": "^25.4.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - } } } }, "jest-watcher": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-25.4.0.tgz", - "integrity": "sha512-36IUfOSRELsKLB7k25j/wutx0aVuHFN6wO94gPNjQtQqFPa2rkOymmx9rM5EzbF3XBZZ2oqD9xbRVoYa2w86gw==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.1.0.tgz", + "integrity": "sha512-ivaWTrA46aHWdgPDgPypSHiNQjyKnLBpUIHeBaGg11U+pDzZpkffGlcB1l1a014phmG0mHgkOHtOgiqJQM6yKQ==", "dev": true, "requires": { - "@jest/test-result": "^25.4.0", - "@jest/types": "^25.4.0", + "@jest/test-result": "^27.1.0", + "@jest/types": "^27.1.0", + "@types/node": "*", "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "jest-util": "^25.4.0", - "string-length": "^3.1.0" + "chalk": "^4.0.0", + "jest-util": "^27.1.0", + "string-length": "^4.0.1" + } + }, + "jest-worker": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.1.0.tgz", + "integrity": "sha512-mO4PHb2QWLn9yRXGp7rkvXLAYuxwhq1ZYUo0LoDhg8wqvv4QizP1ZWEJOeolgbEgAWZLIEU0wsku8J+lGWfBhg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "dependencies": { - "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "has-flag": "^4.0.0" } } } }, - "jest-worker": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.4.0.tgz", - "integrity": "sha512-ghAs/1FtfYpMmYQ0AHqxV62XPvKdUDIBBApMZfly+E9JEmYh2K45G0R5dWxx986RN12pRCxsViwQVtGl+N4whw==", - "dev": true, + "jimp": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.16.1.tgz", + "integrity": "sha512-+EKVxbR36Td7Hfd23wKGIeEyHbxShZDX6L8uJkgVW3ESA9GiTEPK08tG1XI2r/0w5Ch0HyJF5kPqF9K7EmGjaw==", "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" + "@babel/runtime": "^7.7.2", + "@jimp/custom": "^0.16.1", + "@jimp/plugins": "^0.16.1", + "@jimp/types": "^0.16.1", + "regenerator-runtime": "^0.13.3" } }, + "jpeg-js": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.2.tgz", + "integrity": "sha512-+az2gi/hvex7eLTMTlbRLOhH6P6WFdk2ITI8HJsaH2VqYO0I594zXSYEP+tf4FW+8Cy68ScDXoAsQdyQanv3sw==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4739,9 +4825,9 @@ "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -4754,37 +4840,60 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsdom": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.2.1.tgz", - "integrity": "sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "acorn": "^7.1.0", - "acorn-globals": "^4.3.2", - "array-equal": "^1.0.0", - "cssom": "^0.4.1", - "cssstyle": "^2.0.0", - "data-urls": "^1.1.0", - "domexception": "^1.0.1", - "escodegen": "^1.11.1", - "html-encoding-sniffer": "^1.0.2", + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", "nwsapi": "^2.2.0", - "parse5": "5.1.0", - "pn": "^1.1.0", - "request": "^2.88.0", - "request-promise-native": "^1.0.7", - "saxes": "^3.1.9", - "symbol-tree": "^3.2.2", - "tough-cookie": "^3.0.1", - "w3c-hr-time": "^1.0.1", - "w3c-xmlserializer": "^1.1.2", - "webidl-conversions": "^4.0.2", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^7.0.0", - "ws": "^7.0.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } } }, "jsesc": { @@ -4793,16 +4902,10 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, "json-schema-traverse": { "version": "0.4.1", @@ -4815,14 +4918,20 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, "requires": { "minimist": "^1.2.5" } }, + "jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -4832,22 +4941,16 @@ } }, "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", - "json-schema": "0.2.3", + "json-schema": "0.4.0", "verror": "1.10.0" } }, - "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 - }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -4878,17 +4981,26 @@ "type-check": "~0.3.2" } }, - "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 - }, "listenercount": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=" }, + "load-bmfont": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", + "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", + "requires": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^2.9.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -4954,12 +5066,6 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, "lodash.pad": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", @@ -4975,86 +5081,37 @@ "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=" }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "chalk": "^2.4.2" + "yallist": "^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==", - "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" - } - }, - "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==", - "dev": true, - "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=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "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" - } } } }, - "lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, "lunr": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz", - "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==", + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, "make-dir": { @@ -5089,25 +5146,10 @@ "tmpl": "1.0.x" } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, "marked": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-1.0.0.tgz", - "integrity": "sha512-Wo+L1pWTVibfrSr+TTtMuiMfNzmZWiOPeO7rZsQUY5bgsxpHesBEcIWJloWVTFnrMXnf/TL30eTFSGJddmQAng==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/marked/-/marked-3.0.8.tgz", + "integrity": "sha512-0gVrAjo5m0VZSJb4rpL59K1unJAMb/hm8HRXqasD8VeC8m91ytDPMritgFSlKonfdt+rRYYpP/JfLxgIX8yoSw==", "dev": true }, "memory-stream": { @@ -5125,21 +5167,26 @@ "dev": true }, "merge2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", - "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "requires": { "braces": "^3.0.1", - "picomatch": "^2.0.5" + "picomatch": "^2.2.3" } }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, "mime-db": { "version": "1.39.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.39.0.tgz", @@ -5159,10 +5206,13 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, - "mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "^0.1.0" + } }, "minimatch": { "version": "3.0.4", @@ -5194,27 +5244,6 @@ "minipass": "^2.9.0" } }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -5223,11 +5252,6 @@ "minimist": "^1.2.5" } }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -5239,43 +5263,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" - }, - "native-node-utils": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/native-node-utils/-/native-node-utils-0.2.7.tgz", - "integrity": "sha512-61v0G3uVxWlXHppSZGwZi+ZEIgGUKI8QvEkEJLb1GVePI7P8SBe+G747z+QMXSt4TxfgbVZP0DyobbRKYVIjdw==", - "requires": { - "nan": "^2.13.2" - } - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5291,15 +5278,7 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=" - }, - "node-abi": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.0.tgz", - "integrity": "sha512-g6bZh3YCKQRdwuO/tSZZYJAw622SjsRfJ2X0Iy4sSOHZ34/sPPdVBn8fev2tj7njzLwuqPw9uMtGsGkO5kIQvg==", - "requires": { - "semver": "^5.4.1" - } + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, "node-abort-controller": { "version": "2.0.0", @@ -5323,29 +5302,6 @@ "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", "dev": true }, - "node-notifier": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-6.0.0.tgz", - "integrity": "sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw==", - "dev": true, - "optional": true, - "requires": { - "growly": "^1.3.0", - "is-wsl": "^2.1.1", - "semver": "^6.3.0", - "shellwords": "^0.1.1", - "which": "^1.3.1" - }, - "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, - "optional": true - } - } - }, "node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -5355,6 +5311,12 @@ "process-on-spawn": "^1.0.0" } }, + "node-releases": { + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", + "dev": true + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -5458,59 +5420,10 @@ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } + "omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" }, "once": { "version": "1.4.0", @@ -5521,85 +5434,14 @@ } }, "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { "mimic-fn": "^2.1.0" } }, - "opencv4nodejs-prebuilt": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/opencv4nodejs-prebuilt/-/opencv4nodejs-prebuilt-5.3.3.tgz", - "integrity": "sha512-c9n4bLoamHLwafqCR6W4Xh5O/35IJ2A01pWbW/4SVgYJDAhGAW/FrZw0q4VwUPxEe1cXZgr+Wy5HZUQIotkZdg==", - "requires": { - "@types/node": ">6", - "nan": "^2.14.2", - "native-node-utils": "^0.2.7", - "npmlog": "^4.1.2", - "prebuild-install": "^6.1.3" - }, - "dependencies": { - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", @@ -5629,9 +5471,9 @@ "dev": true }, "p-each-series": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", - "integrity": "sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", + "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", "dev": true }, "p-finally": { @@ -5684,28 +5526,39 @@ "release-zalgo": "^1.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, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=" + }, + "parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=" + }, + "parse-bmfont-xml": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", + "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", "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" + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.4.5" } }, - "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", - "dev": true + "parse-headers": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", + "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==" }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true }, "path-exists": { @@ -5725,9 +5578,9 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-type": { @@ -5741,10 +5594,15 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" + }, "picomatch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", - "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, "pify": { @@ -5777,6 +5635,14 @@ "node-modules-regexp": "^1.0.0" } }, + "pixelmatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", + "requires": { + "pngjs": "^3.0.0" + } + }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -5786,96 +5652,10 @@ "find-up": "^4.0.0" } }, - "pn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", - "dev": true - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "prebuild-install": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.3.tgz", - "integrity": "sha512-iqqSR84tNYQUQHRXalSKdIaM8Ov1QxOVuBNWI7+BzZWv6Ih9k75wOnH1rGQ9WWTaaLkTpxWKIciOF0KyfM74+Q==", - "requires": { - "detect-libc": "^1.0.3", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^2.21.0", - "npmlog": "^4.0.1", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^3.0.3", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "dependencies": { - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" }, "prelude-ls": { "version": "1.1.2", @@ -5884,25 +5664,36 @@ "dev": true }, "pretty-format": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.1.0.tgz", - "integrity": "sha512-46zLRSGLd02Rp+Lhad9zzuNZ+swunitn8zIpfD2B4OPCRLXbM87RJT2aBLBWYOznNUML/2l/ReMyWNC80PJBUQ==", + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.1.0.tgz", + "integrity": "sha512-4aGaud3w3rxAO6OXmK3fwBFQ0bctIOG3/if+jYEFGNGIs0EvuidQm3bZ9mlP2/t9epLNC/12czabfy7TZNSwVA==", "dev": true, "requires": { - "@jest/types": "^25.1.0", + "@jest/types": "^27.1.0", "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true } } }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -5923,10 +5714,20 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "prompts": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", + "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "pump": { "version": "3.0.0", @@ -5947,6 +5748,12 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -5959,50 +5766,11 @@ } }, "react-is": { - "version": "16.13.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.0.tgz", - "integrity": "sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", @@ -6012,39 +5780,12 @@ "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - } - } - }, - "realpath-native": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", - "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", - "dev": true - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "release-zalgo": { "version": "1.0.0", @@ -6055,28 +5796,10 @@ "es6-error": "^4.0.1" } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha1-nC/KT301tZLv5Xx/ClXoEFIST+8=", + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -6085,7 +5808,7 @@ "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", - "har-validator": "~5.1.0", + "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -6095,52 +5818,15 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", + "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha1-U/Nto/R3g7CSWvoG/587FlKA94E=", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - } - } - }, - "request-promise-core": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", - "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", - "dev": true, - "requires": { - "lodash": "^4.17.15" - } - }, - "request-promise-native": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", - "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", - "dev": true, - "requires": { - "request-promise-core": "1.1.3", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, "dependencies": { "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, "requires": { "psl": "^1.1.28", "punycode": "^2.1.1" @@ -6184,12 +5870,6 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -6200,12 +5880,6 @@ "signal-exit": "^3.0.2" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -6221,31 +5895,25 @@ "glob": "^7.1.3" } }, - "rsvp": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", - "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true }, - "run-async": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", - "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "requires": { - "is-promise": "^2.1.0" + "queue-microtask": "^1.2.2" } }, - "run-parallel": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true - }, "rxjs": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", - "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -6256,168 +5924,23 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "sane": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", - "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", - "dev": true, - "requires": { - "@cnakazawa/watch": "^1.0.3", - "anymatch": "^2.0.0", - "capture-exit": "^2.0.0", - "exec-sh": "^0.3.2", - "execa": "^1.0.0", - "fb-watchman": "^2.0.0", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } - } + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "saxes": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", - "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", "dev": true, "requires": { - "xmlchars": "^2.1.1" + "xmlchars": "^2.2.0" } }, "semver": { @@ -6428,30 +5951,8 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true }, "setimmediate": { "version": "1.0.5", @@ -6471,184 +5972,34 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, - "shelljs": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", - "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, - "shellwords": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" - }, - "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "requires": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "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 - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "shiki": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.9.15.tgz", + "integrity": "sha512-/Y0z9IzhJ8nD9nbceORCqu6NgT9X6I8Fk8c3SICHI5NbZRLdZYFaB233gwct9sU0vvSypyaL/qaKvzyQGJBZSw==", "dev": true, "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "jsonc-parser": "^3.0.0", + "vscode-oniguruma": "^1.6.1", + "vscode-textmate": "5.2.0" } }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, "sneer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sneer/-/sneer-1.0.1.tgz", @@ -6661,19 +6012,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", @@ -6684,12 +6022,6 @@ "source-map": "^0.6.0" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, "spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", @@ -6747,15 +6079,6 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, "splitargs": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/splitargs/-/splitargs-0.0.7.tgz", @@ -6784,38 +6107,22 @@ } }, "stack-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", - "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "escape-string-regexp": "^2.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } + "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 } } }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true - }, "string-argv": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", @@ -6823,28 +6130,28 @@ "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==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "requires": { - "astral-regex": "^1.0.0", - "strip-ansi": "^5.2.0" + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.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==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "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" } } } @@ -6895,18 +6202,18 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "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": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" } }, "supports-hyperlinks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz", - "integrity": "sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", "dev": true, "requires": { "has-flag": "^4.0.0", @@ -6920,64 +6227,23 @@ "dev": true }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "requires": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" }, "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } } } }, @@ -7019,9 +6285,9 @@ } }, "throat": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", - "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", "dev": true }, "through": { @@ -7030,6 +6296,16 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" + }, + "tinycolor2": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", + "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -7040,9 +6316,9 @@ } }, "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, "to-fast-properties": { @@ -7051,38 +6327,6 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7093,23 +6337,31 @@ } }, "tough-cookie": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", - "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", "dev": true, "requires": { - "ip-regex": "^2.1.0", - "psl": "^1.1.28", - "punycode": "^2.1.1" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "dependencies": { + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + } } }, "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "^2.1.1" } }, "traverse": { @@ -7118,125 +6370,43 @@ "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" }, "ts-jest": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-25.4.0.tgz", - "integrity": "sha512-+0ZrksdaquxGUBwSdTIcdX7VXdwLIlSRsyjivVA9gcO+Cvr6ByqDhu/mi5+HCcb6cMkiQp5xZ8qRO7/eCqLeyw==", + "version": "27.0.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.0.5.tgz", + "integrity": "sha512-lIJApzfTaSSbtlksfFNHkWOzLJuuSm4faFAfo5kvzOiRAuoN4/eKxVJ2zEAho8aecE04qX6K1pAzfH5QHL1/8w==", "dev": true, "requires": { "bs-logger": "0.x", - "buffer-from": "1.x", "fast-json-stable-stringify": "2.x", + "jest-util": "^27.0.0", "json5": "2.x", - "lodash.memoize": "4.x", + "lodash": "4.x", "make-error": "1.x", - "micromatch": "4.x", - "mkdirp": "1.x", - "resolve": "1.x", - "semver": "6.x", - "yargs-parser": "18.x" + "semver": "7.x", + "yargs-parser": "20.x" }, "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "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 - } - } - }, - "tslib": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", - "dev": true - }, - "tslint": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.0.tgz", - "integrity": "sha512-fXjYd/61vU6da04E505OZQGb2VCN2Mq3doeWcOIryuG+eqdmFUXTYVwdhnbEu2k46LNLgUYt9bI5icQze/j0bQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.10.0", - "tsutils": "^2.29.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" - } - }, - "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==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { - "color-name": "1.1.3" + "lru-cache": "^6.0.0" } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "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" - } } } }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "tunnel-agent": { "version": "0.6.0", @@ -7267,9 +6437,9 @@ "dev": true }, "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true }, "typedarray-to-buffer": { @@ -7282,55 +6452,31 @@ } }, "typedoc": { - "version": "0.17.6", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.17.6.tgz", - "integrity": "sha512-pQiYnhG3yJk7939cv2n8uFoTsSgy5Hfiw0dgOQYa9nT9Ya1013dMctQdAXMj8JbNu7KhcauQyq9Zql9D/TziLw==", + "version": "0.21.9", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.21.9.tgz", + "integrity": "sha512-VRo7aII4bnYaBBM1lhw4bQFmUcDQV8m8tqgjtc7oXl87jc1Slbhfw2X5MccfcR2YnEClHDWgsiQGgNB8KJXocA==", "dev": true, "requires": { - "fs-extra": "^8.1.0", - "handlebars": "^4.7.6", - "highlight.js": "^10.0.0", - "lodash": "^4.17.15", - "lunr": "^2.3.8", - "marked": "1.0.0", + "glob": "^7.1.7", + "handlebars": "^4.7.7", + "lunr": "^2.3.9", + "marked": "^3.0.2", "minimatch": "^3.0.0", "progress": "^2.0.3", - "shelljs": "^0.8.4", - "typedoc-default-themes": "^0.10.1" - }, - "dependencies": { - "fs-extra": { - "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.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - } + "shiki": "^0.9.8", + "typedoc-default-themes": "^0.12.10" } }, "typedoc-default-themes": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.10.1.tgz", - "integrity": "sha512-SuqAQI0CkwhqSJ2kaVTgl37cWs733uy9UGUqwtcds8pkFK8oRF4rZmCq+FXTGIb9hIUOu40rf5Kojg0Ha6akeg==", - "dev": true, - "requires": { - "lunr": "^2.3.8" - } + "version": "0.12.10", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.12.10.tgz", + "integrity": "sha512-fIS001cAYHkyQPidWXmHuhs8usjP5XVJjWB8oZGqkTowZaz3v7g3KDZeeqE82FBrmkAnIBOY3jgy7lnPnqATbA==", + "dev": true }, "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", + "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==", "dev": true }, "typical": { @@ -7340,69 +6486,17 @@ "dev": true }, "uglify-js": { - "version": "3.13.7", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.7.tgz", - "integrity": "sha512-1Psi2MmnZJbnEsgJJIlfnd7tFlJfitusmR7zDI8lXlFI0ACD4/Rm/xdrU8bh6zF0i74aiVoBtkRiFulkrmh3AA==", + "version": "3.14.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.5.tgz", + "integrity": "sha512-qZukoSxOG0urUTvjc2ERMTcAy+BiFh3weWAkeurLwjrCba73poHmG3E36XEjd/JGukMzwTL7uCxZiAexj8ppvQ==", "dev": true, "optional": true }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, "unzipper": { "version": "0.8.14", "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.8.14.tgz", @@ -7419,6 +6513,11 @@ "setimmediate": "~1.0.4" }, "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -7441,29 +6540,25 @@ } }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, "url-join": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", "integrity": "sha1-HbSK1CLTQCRpqH99l73r/k+x48g=" }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true + "utif": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", + "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", + "requires": { + "pako": "^1.0.5" + } }, "util-deprecate": { "version": "1.0.2", @@ -7471,14 +6566,14 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE=" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "v8-to-istanbul": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.3.tgz", - "integrity": "sha512-sAjOC+Kki6aJVbUOXJbcR0MnbfjvBzwKZazEJymA2IX49uoOdEdk+4fBq5cXgYgiyKtAyrrJNtBZdOeDIF+Fng==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.0.0.tgz", + "integrity": "sha512-LkmXi8UUNxnCC+JlH7/fsfsKr5AU110l+SYGJimWNkWhxbN5EyeOtm1MJ0hhvqMMOhGwBj1Fp70Yv9i+hX0QAg==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.1", @@ -7512,41 +6607,63 @@ "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + } } }, "version-bump-prompt": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/version-bump-prompt/-/version-bump-prompt-6.0.2.tgz", - "integrity": "sha512-MzPReH0tzqOU+J+vQr9LMb15ORHVgRAwvKKyUuOGD6ePgdwpPAOhpxEH14yx3UYay6Q1u0TNiLBhTqP0RvvyPw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/version-bump-prompt/-/version-bump-prompt-6.1.0.tgz", + "integrity": "sha512-GYC83GP8QOunWueKf2mbtZkdmisXhnBZPhIHWUmN/Yi4XXAQlIi9avM/IGWdI7KkJLfMENzGN1Xee+Zl3VJ5jg==", "dev": true, "requires": { - "@jsdevtools/version-bump-prompt": "6.0.2" + "@jsdevtools/version-bump-prompt": "6.1.0" }, "dependencies": { "@jsdevtools/version-bump-prompt": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@jsdevtools/version-bump-prompt/-/version-bump-prompt-6.0.2.tgz", - "integrity": "sha512-nBXrckBHktLT55dZvlH38hb6v6VgNyi45+7ISQxwilQiuMU0IApTOKT0S9Oy33Asn1TEGMBa4YllNHPilMJJhw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@jsdevtools/version-bump-prompt/-/version-bump-prompt-6.1.0.tgz", + "integrity": "sha512-NJFLJRiD3LLFBgSxAb6B255xhWCGgdtzmh6UjHK2b7SRGX2DDKJH5O4BJ0GTStBu4NnaNgMbkr1TLW3pLOBkOQ==", "dev": true, "requires": { - "@jsdevtools/ez-spawn": "^3.0.0", + "@jsdevtools/ez-spawn": "^3.0.4", "command-line-args": "^5.1.1", "detect-indent": "^6.0.0", "detect-newline": "^3.1.0", - "globby": "^11.0.0", - "inquirer": "^7.0.6", - "log-symbols": "^3.0.0", - "semver": "^7.1.1" + "globby": "^11.0.1", + "inquirer": "^7.3.3", + "log-symbols": "^4.0.0", + "semver": "^7.3.2" } }, "semver": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz", - "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==", - "dev": true + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, + "vscode-oniguruma": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.1.tgz", + "integrity": "sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==", + "dev": true + }, + "vscode-textmate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", + "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", + "dev": true + }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -7557,13 +6674,11 @@ } }, "w3c-xmlserializer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", - "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", "dev": true, "requires": { - "domexception": "^1.0.1", - "webidl-conversions": "^4.0.2", "xml-name-validator": "^3.0.0" } }, @@ -7577,9 +6692,9 @@ } }, "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", "dev": true }, "whatwg-encoding": { @@ -7598,14 +6713,14 @@ "dev": true }, "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", "dev": true, "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" } }, "which": { @@ -7622,14 +6737,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", @@ -7674,23 +6781,58 @@ } }, "ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz", + "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==", "dev": true }, + "xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "requires": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, "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==", "dev": true }, + "xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=" + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, "xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "y18n": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", @@ -7702,9 +6844,9 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { "cliui": "^6.0.0", @@ -7717,7 +6859,7 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" + "yargs-parser": "^18.1.2" }, "dependencies": { "ansi-regex": { @@ -7733,9 +6875,9 @@ "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==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { "emoji-regex": "^8.0.0", @@ -7753,9 +6895,9 @@ } }, "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true } } diff --git a/package.json b/package.json index b9b65235..f0e406ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nut-tree/nut-js", - "version": "1.7.0", + "version": "2.0.0-RC1", "license": "Apache-2.0", "main": "dist/index", "typings": "dist/index", @@ -24,7 +24,7 @@ ], "cpu": [ "x64", - "ia32" + "arm64" ], "keywords": [ "native", @@ -52,7 +52,6 @@ "coverage:clean": "rimraf coverage", "coverage:merge": "istanbul-merge --out coverage/merged/coverage-final.json ./coverage/unit/coverage-final.json ./coverage/e2e/coverage-final.json", "coverage:merge-report": "nyc report --reporter=lcov --reporter=text --temp-dir=./coverage/merged --report-dir=./coverage/merged", - "lint": "tslint -p tsconfig.json", "watch": "tsc -w -p .", "publish-next": "npm publish --tag next", "prepublishOnly": "npm run compile", @@ -60,23 +59,23 @@ "typedoc": "typedoc --options ./typedoc.js --out ./docs lib/" }, "dependencies": { - "@nut-tree/libnut": "2.1.2", - "clipboardy": "2.0.0", - "node-abort-controller": "2.0.0", - "opencv4nodejs-prebuilt": "5.3.3" + "@nut-tree/libnut": "2.1.3", + "clipboardy": "2.3.0", + "jimp": "0.16.1", + "node-abort-controller": "2.0.0" }, "devDependencies": { "@types/clipboardy": "2.0.1", - "@types/jest": "25.1.4", + "@types/jest": "27.0.1", + "@types/node": "16.7.10", "istanbul-merge": "1.1.1", - "jest": "25.1.0", + "jest": "27.1.0", "nyc": "15.1.0", "rimraf": "3.0.2", "sneer": "1.0.1", - "ts-jest": "25.4.0", - "tslint": "6.1.0", - "typedoc": "0.17.6", - "typescript": "3.8.3", - "version-bump-prompt": "6.0.2" + "ts-jest": "27.0.5", + "typedoc": "0.21.9", + "typescript": "4.4.2", + "version-bump-prompt": "6.1.0" } } diff --git a/typedoc.js b/typedoc.js index e49f743d..3cdeb11c 100644 --- a/typedoc.js +++ b/typedoc.js @@ -1,5 +1,4 @@ module.exports = { - "mode": "file", exclude: [ '**/dist/**', '**/node_modules/**', @@ -10,8 +9,6 @@ module.exports = { excludePrivate: true, excludeExternals: true, excludeProtected: true, - excludeNotExported: true, - includeDeclarations: false, hideGenerator: true, theme: 'default', };