diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a20e268..c0f8da11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,31 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org). +## [3.8.0] - 2022-12-03 +### Added +* [#708](https://github.com/shlinkio/shlink-web-client/issues/708) Added support for API v3. +* [#717](https://github.com/shlinkio/shlink-web-client/issues/717) Allowed to select time in 10 minute intervals when configuring "enabled since" and "enabled until" on short URLs. +* [#748](https://github.com/shlinkio/shlink-web-client/issues/748) Improved visits section to add filters to the query string, allowing to navigate to a specific state or bookmarking filters. + +### Changed +* [#713](https://github.com/shlinkio/shlink-web-client/issues/713) Updated dependencies. +* [#620](https://github.com/shlinkio/shlink-web-client/issues/620) Migrated all reducers to redux toolkit. +* [#721](https://github.com/shlinkio/shlink-web-client/issues/721) Migrated from axios to fetch. + +### Deprecated +* *Nothing* + +### Removed +* *Nothing* + +### Fixed +* [#590](https://github.com/shlinkio/shlink-web-client/issues/590) Fixed position of the datepicker triangle. +* [#729](https://github.com/shlinkio/shlink-web-client/issues/729) Fixed wrong stats displayed in tags after renaming. +* [#737](https://github.com/shlinkio/shlink-web-client/issues/737) Fixed incorrect contrast in warning messages when using dark theme. +* [#726](https://github.com/shlinkio/shlink-web-client/issues/726) Fixed delete server and delete short URL modals getting removed from the DOM before finishing close transition. +* [#749](https://github.com/shlinkio/shlink-web-client/issues/749) Fixed broken short URLs table when some short URL has a too long custom slug. + + ## [3.7.3] - 2022-09-13 ### Added * [#703](https://github.com/shlinkio/shlink-web-client/issues/703) Added support to publish docker image in GHCR. diff --git a/README.md b/README.md index 2d431d2a..ffdaf2b1 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ [![Docker pulls](https://img.shields.io/docker/pulls/shlinkio/shlink-web-client.svg?logo=docker&style=flat-square)](https://hub.docker.com/r/shlinkio/shlink-web-client/) [![GitHub license](https://img.shields.io/github/license/shlinkio/shlink-web-client.svg?style=flat-square)](https://github.com/shlinkio/shlink-web-client/blob/main/LICENSE) [![Twitter](https://img.shields.io/twitter/follow/shlinkio?color=blue&label=follow&logo=twitter&style=flat-square)](https://twitter.com/shlinkio) +[![Mastodon](https://img.shields.io/mastodon/follow/109329425426175098?color=%236364ff&domain=https%3A%2F%2Ffosstodon.org&label=follow&logo=mastodon&logoColor=white&style=flat-square)](https://fosstodon.org/@shlinkio) [![Paypal Donate](https://img.shields.io/badge/Donate-paypal-blue.svg?style=flat-square&logo=paypal&colorA=cccccc)](https://slnk.to/donate) A ReactJS-based progressive web application for [Shlink](https://shlink.io). diff --git a/config/jest/setupTests.ts b/config/jest/setupTests.ts index cec71a7a..e8900e09 100644 --- a/config/jest/setupTests.ts +++ b/config/jest/setupTests.ts @@ -1,8 +1,11 @@ import '@testing-library/jest-dom'; import 'jest-canvas-mock'; import ResizeObserver from 'resize-observer-polyfill'; +import { setAutoFreeze } from 'immer'; (global as any).ResizeObserver = ResizeObserver; (global as any).scrollTo = () => {}; (global as any).prompt = () => {}; (global as any).matchMedia = (media: string) => ({ matches: false, media }); + +setAutoFreeze(false); // TODO Bypassing a bug on jest diff --git a/jest.config.js b/jest.config.js index 1e37de5d..cb2b1a57 100644 --- a/jest.config.js +++ b/jest.config.js @@ -17,6 +17,7 @@ module.exports = { }, setupFilesAfterEnv: ['<rootDir>/config/jest/setupTests.ts'], testMatch: ['<rootDir>/test/**/*.test.{ts,tsx}'], + modulePathIgnorePatterns: ['<rootDir>/.stryker-tmp'], testEnvironment: 'jsdom', testEnvironmentOptions: { url: 'http://localhost', diff --git a/package-lock.json b/package-lock.json index 1e4afac2..88a8969c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,89 +7,96 @@ "name": "shlink-web-client", "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-free": "^6.0.0", - "@fortawesome/fontawesome-svg-core": "^1.3.0", - "@fortawesome/free-regular-svg-icons": "^6.0.0", - "@fortawesome/free-solid-svg-icons": "^6.0.0", - "@fortawesome/react-fontawesome": "^0.1.17", - "axios": "^0.26.0", - "bootstrap": "^5.1.3", - "bottlejs": "^2.0.0", + "@fortawesome/fontawesome-free": "^6.2.0", + "@fortawesome/fontawesome-svg-core": "^6.2.0", + "@fortawesome/free-regular-svg-icons": "^6.2.0", + "@fortawesome/free-solid-svg-icons": "^6.2.0", + "@fortawesome/react-fontawesome": "^0.2.0", + "@reduxjs/toolkit": "^1.9.0", + "bootstrap": "^5.2.2", + "bottlejs": "^2.0.1", "bowser": "^2.11.0", - "chart.js": "^3.7.1", + "chart.js": "^3.9.1", "classnames": "^2.3.1", - "compare-versions": "^4.1.3", + "compare-versions": "^5.0.1", "csvtojson": "^2.0.10", - "date-fns": "^2.28.0", - "event-source-polyfill": "^1.0.25", + "date-fns": "^2.29.3", + "event-source-polyfill": "^1.0.31", + "history": "^5.3.0", "json2csv": "^5.0.7", - "leaflet": "^1.7.1", - "qs": "^6.9.6", + "leaflet": "^1.9.2", + "qs": "^6.11.0", "ramda": "^0.27.2", - "react": "^18.1.0", - "react-chartjs-2": "^4.1.0", - "react-colorful": "^5.5.1", + "react": "^18.2.0", + "react-chartjs-2": "^4.3.1", + "react-colorful": "^5.6.1", "react-copy-to-clipboard": "^5.1.0", "react-datepicker": "^4.8.0", - "react-dom": "^18.1.0", + "react-dom": "^18.2.0", "react-external-link": "^2.0.0", - "react-leaflet": "^4.0.0", - "react-redux": "^8.0.0", - "react-router-dom": "^6.3.0", + "react-leaflet": "^4.1.0", + "react-redux": "^8.0.4", + "react-router-dom": "^6.4.1", "react-swipeable": "^7.0.0", "react-tag-autocomplete": "^6.3.0", - "reactstrap": "^9.0.1", + "reactstrap": "^9.1.4", "redux": "^4.2.0", - "redux-localstorage-simple": "^2.4.1", + "redux-localstorage-simple": "^2.5.1", "redux-thunk": "^2.4.1", "stream": "^0.0.2", "uuid": "^8.3.2", - "workbox-core": "^6.5.1", - "workbox-expiration": "^6.5.1", - "workbox-precaching": "^6.5.1", - "workbox-routing": "^6.5.1", - "workbox-strategies": "^6.5.1" + "workbox-core": "^6.5.4", + "workbox-expiration": "^6.5.4", + "workbox-precaching": "^6.5.4", + "workbox-routing": "^6.5.4", + "workbox-strategies": "^6.5.4" }, "devDependencies": { "@shlinkio/eslint-config-js-coding-standard": "~2.0.2", "@shlinkio/stylelint-config-css-coding-standard": "~1.0.1", - "@stryker-mutator/core": "^6.0.2", - "@stryker-mutator/jest-runner": "^6.0.2", - "@stryker-mutator/typescript-checker": "^6.0.2", - "@testing-library/jest-dom": "^5.16.4", - "@testing-library/react": "^13.1.1", - "@testing-library/user-event": "^14.1.1", - "@types/jest": "^27.4.1", + "@stryker-mutator/core": "^6.2.2", + "@stryker-mutator/jest-runner": "^6.2.2", + "@stryker-mutator/typescript-checker": "^6.2.2", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@types/jest": "^29.1.1", "@types/json2csv": "^5.0.3", - "@types/leaflet": "^1.7.9", + "@types/leaflet": "^1.8.0", "@types/qs": "^6.9.7", - "@types/ramda": "0.27.38", - "@types/react": "^18.0.8", + "@types/ramda": "^0.28.15", + "@types/react": "^18.0.21", "@types/react-color": "^3.0.6", - "@types/react-copy-to-clipboard": "^5.0.2", - "@types/react-datepicker": "^4.3.4", - "@types/react-dom": "^18.0.3", - "@types/react-tag-autocomplete": "^6.1.1", + "@types/react-copy-to-clipboard": "^5.0.4", + "@types/react-datepicker": "^4.4.2", + "@types/react-dom": "^18.0.6", + "@types/react-tag-autocomplete": "^6.3.0", "@types/uuid": "^8.3.4", "adm-zip": "^0.5.9", - "babel-jest": "^28.0.3", + "babel-jest": "^29.1.2", "chalk": "^5.0.1", - "eslint": "^8.12.0", + "eslint": "^8.24.0", "identity-obj-proxy": "^3.0.0", - "jest": "^28.0.3", + "jest": "^29.1.2", "jest-canvas-mock": "^2.4.0", - "jest-environment-jsdom": "^28.0.2", + "jest-environment-jsdom": "^29.1.2", "react-scripts": "^5.0.1", "resize-observer-polyfill": "^1.5.1", - "sass": "^1.49.9", - "serve": "^13.0.2", + "sass": "^1.55.0", + "serve": "^14.1.1", "stryker-cli": "^1.0.2", - "stylelint": "^14.8.2", + "stylelint": "^14.13.0", "ts-mockery": "^1.2.0", - "typescript": "^4.6.2", - "webpack": "^5.70.0" + "typescript": "^4.8.4", + "webpack": "^5.74.0" } }, + "node_modules/@adobe/css-tools": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.0.1.tgz", + "integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==", + "dev": true + }, "node_modules/@ampproject/remapping": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", @@ -103,42 +110,42 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "dependencies": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", - "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.3.tgz", + "integrity": "sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.10.tgz", - "integrity": "sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", + "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.10", - "@babel/helper-compilation-targets": "^7.17.10", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.9", - "@babel/parser": "^7.17.10", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.10", - "@babel/types": "^7.17.10", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.3", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.3", + "@babel/types": "^7.19.3", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -222,13 +229,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz", - "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.3.tgz", + "integrity": "sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==", "dev": true, "dependencies": { - "@babel/types": "^7.17.10", - "@jridgewell/gen-mapping": "^0.1.0", + "@babel/types": "^7.19.3", + "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, "engines": { @@ -236,12 +243,12 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", - "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -261,14 +268,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz", - "integrity": "sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", + "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.20.2", + "@babel/compat-data": "^7.19.3", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", "semver": "^6.3.0" }, "engines": { @@ -288,18 +295,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz", - "integrity": "sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-member-expression-to-functions": "^7.17.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -376,13 +383,10 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, "engines": { "node": ">=6.9.0" } @@ -400,89 +404,89 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "dependencies": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", - "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, "dependencies": { - "@babel/types": "^7.17.0" + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", - "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", - "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", "dev": true, "engines": { "node": ">=6.9.0" @@ -503,28 +507,28 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", - "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz", + "integrity": "sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.19.1", + "@babel/types": "^7.19.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, "dependencies": { - "@babel/types": "^7.17.0" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -543,30 +547,39 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true, "engines": { "node": ">=6.9.0" @@ -588,26 +601,26 @@ } }, "node_modules/@babel/helpers": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", - "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", "dev": true, "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0" + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -630,9 +643,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", - "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz", + "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -691,13 +704,13 @@ } }, "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", - "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -724,17 +737,16 @@ } }, "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.9.tgz", - "integrity": "sha512-EfH2LZ/vPa2wuPwJ26j+kYRkaubf89UlwxKXtxqEm57HrgSEYDB8t4swFP+p8LcI9yiP9ZRJJjo/58hS6BnaDA==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.19.3.tgz", + "integrity": "sha512-MbgXtNXqo7RTKYIXVchVJGPvaVufQH3pxvQyfbGvNw1DObIhph+PesYXJTcd8J4DdWibvf6Z2eanOyItX8WnJg==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.17.9", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/plugin-syntax-decorators": "^7.17.0", - "charcodes": "^0.2.0" + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-replace-supers": "^7.19.1", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/plugin-syntax-decorators": "^7.19.0" }, "engines": { "node": ">=6.9.0" @@ -892,13 +904,13 @@ } }, "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.16.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", - "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.10", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -993,12 +1005,12 @@ } }, "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz", - "integrity": "sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.19.0.tgz", + "integrity": "sha512-xaBZUEDntt4faL1yN8oIFlhfXeQAWJW7CLKYsHTUqriCUbj8xOra8bfxxKGi/UwExPFBuPdH4XfHc9rGQhrVkQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.19.0" }, "engines": { "node": ">=6.9.0" @@ -1188,12 +1200,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", - "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1800,14 +1812,14 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", - "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.3.tgz", + "integrity": "sha512-z6fnuK9ve9u/0X0rRvI9MY0xg+DOUaABDYOe+/SQTxtlptaBB/V9JIUxJn6xp3lMBeb9qe8xSFmHU35oZDXD+w==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-typescript": "^7.16.7" + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1981,14 +1993,14 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", - "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-typescript": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -2019,33 +2031,33 @@ } }, "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz", - "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.3.tgz", + "integrity": "sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.10", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.10", - "@babel/types": "^7.17.10", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.3", + "@babel/types": "^7.19.3", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -2078,12 +2090,13 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", - "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.3.tgz", + "integrity": "sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2225,24 +2238,44 @@ "postcss": "^8.3" } }, + "node_modules/@csstools/selector-specificity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", + "dev": true, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2", + "postcss-selector-parser": "^6.0.10" + } + }, "node_modules/@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", + "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", + "espree": "^9.4.0", + "globals": "^13.15.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/eslintrc/node_modules/argparse": { @@ -2269,9 +2302,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -2301,18 +2334,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -2326,75 +2347,75 @@ } }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz", - "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.0.tgz", + "integrity": "sha512-rBevIsj2nclStJ7AxTdfsa3ovHb1H+qApwrxcTVo+NNdeJiB9V75hsKfrkG5AwNcRUNxrPPiScGYCNmLMoh8pg==", "hasInstallScript": true, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.0.0.tgz", - "integrity": "sha512-6LB4PYBST1Rx40klypw1SmSDArjFOcfBf2LeX9Zg5EKJT2eXiyiJq+CyBYKeXyK0sXS2FsCJWSPr/luyhuvh0Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.2.0.tgz", + "integrity": "sha512-CNR7qRIfCwWHNN7FnKUniva94edPdyQzil/zCwk3v6k4R6rR2Fr8i4s3PM7n/lyfPA6Zfko9z5WDzFxG9SW1uQ==", "hasInstallScript": true, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz", - "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.0.tgz", + "integrity": "sha512-Cf2mAAeMWFMzpLC7Y9H1I4o3wEU+XovVJhTiNG8ZNgSQj53yl7OCJaS80K4YjrABWZzbAHVaoHE1dVJ27AAYXw==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "6.2.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.0.0.tgz", - "integrity": "sha512-lYK6oyQL8HwZUAVWGqF7TGuwQBVfphNBVTdvPSD3h4gmQfGazm/xcwg3kmtcRycu3y6QspOC7hPXSoJbVqSYCw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.2.0.tgz", + "integrity": "sha512-M1dG+PAmkYMTL9BSUHFXY5oaHwBYfHCPhbJ8qj8JELsc9XCrUJ6eEHWip4q0tE+h9C0DVyFkwIM9t7QYyCpprQ==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "6.2.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.0.0.tgz", - "integrity": "sha512-o4FZ1XbndcgeWNb8Wh0y+Hgf73CjmyOQowUSaqQCtgIIdS+XliSBSOwCl330wER+I6CGYE96hT27bHBPmzX2Gg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.2.0.tgz", + "integrity": "sha512-UjCILHIQ4I8cN46EiQn0CZL/h8AwCGgR//1c4R96Q5viSRwuKVo0NdQEc4bm+69ZwC0dUvjbDqAHF1RR5FA3XA==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "6.2.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/react-fontawesome": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.17.tgz", - "integrity": "sha512-dX43Z5IvMaW7fwzU8farosYjKNGfRb2HB/DgjVBHeJZ/NSnuuaujPPx0YOdcAq+n3mqn70tyCde2HM1mqbhiuw==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", "dependencies": { "prop-types": "^15.8.1" }, "peerDependencies": { - "@fortawesome/fontawesome-svg-core": "~1 || >=1.3.0-beta1", - "react": ">=16.x" + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", + "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -2428,6 +2449,29 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/@humanwhocodes/gitignore-to-minimatch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", + "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -2524,29 +2568,29 @@ } }, "node_modules/@jest/console": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.0.2.tgz", - "integrity": "sha512-tiRpnMeeyQuuzgL5UNSeiqMwF8UOWPbAE5rzcu/1zyq4oPG2Ox6xm4YCOruwbp10F8odWc+XwVxTyGzMSLMqxA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.1.2.tgz", + "integrity": "sha512-ujEBCcYs82BTmRxqfHMQggSlkUZP63AE5YEaTPj7eFyJOzukkTorstOUC7L6nE3w5SYadGVAnTsQ/ZjTGL0qYQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^28.0.2", - "jest-util": "^28.0.2", + "jest-message-util": "^29.1.2", + "jest-util": "^29.1.2", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/console/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -2554,13 +2598,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/console/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -2619,12 +2663,12 @@ } }, "node_modules/@jest/console/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -2632,7 +2676,7 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/console/node_modules/supports-color": { @@ -2648,43 +2692,42 @@ } }, "node_modules/@jest/core": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.0.3.tgz", - "integrity": "sha512-cCQW06vEZ+5r50SB06pOnSWsOBs7F+lswPYnKKfBz1ncLlj1sMqmvjgam8q40KhlZ8Ut4eNAL2Hvfx4BKIO2FA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.1.2.tgz", + "integrity": "sha512-sCO2Va1gikvQU2ynDN8V4+6wB7iVrD2CvT0zaRst4rglf56yLly0NQ9nuRRAWFeimRf+tCdFsb1Vk1N9LrrMPA==", "dev": true, "dependencies": { - "@jest/console": "^28.0.2", - "@jest/reporters": "^28.0.3", - "@jest/test-result": "^28.0.2", - "@jest/transform": "^28.0.3", - "@jest/types": "^28.0.2", + "@jest/console": "^29.1.2", + "@jest/reporters": "^29.1.2", + "@jest/test-result": "^29.1.2", + "@jest/transform": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^28.0.2", - "jest-config": "^28.0.3", - "jest-haste-map": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.0.3", - "jest-resolve-dependencies": "^28.0.3", - "jest-runner": "^28.0.3", - "jest-runtime": "^28.0.3", - "jest-snapshot": "^28.0.3", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", - "jest-watcher": "^28.0.2", + "jest-changed-files": "^29.0.0", + "jest-config": "^29.1.2", + "jest-haste-map": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-regex-util": "^29.0.0", + "jest-resolve": "^29.1.2", + "jest-resolve-dependencies": "^29.1.2", + "jest-runner": "^29.1.2", + "jest-runtime": "^29.1.2", + "jest-snapshot": "^29.1.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", + "jest-watcher": "^29.1.2", "micromatch": "^4.0.4", - "pretty-format": "^28.0.2", - "rimraf": "^3.0.0", + "pretty-format": "^29.1.2", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -2696,12 +2739,12 @@ } }, "node_modules/@jest/core/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -2709,13 +2752,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -2774,75 +2817,75 @@ } }, "node_modules/@jest/core/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core/node_modules/jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "node_modules/@jest/core/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core/node_modules/jest-resolve": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.0.3.tgz", - "integrity": "sha512-lfgjd9JhEjpjIN3HLUfdysdK+A7ePQoYmd7WL9DUEWqdnngb1rF56eee6iDXJxl/3eSolpP43VD7VrhjL3NsoQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.1.2.tgz", + "integrity": "sha512-7fcOr+k7UYSVRJYhSmJHIid3AnDBcLQX3VmT9OSbPWsWz1MfT7bcoerMhADKGvKCoMpOHUQaDHtQoNp/P9JMGg==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", + "jest-haste-map": "^29.1.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -2850,38 +2893,39 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core/node_modules/jest-validate": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.0.2.tgz", - "integrity": "sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", + "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.0.0", "leven": "^3.1.0", - "pretty-format": "^28.0.2" + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core/node_modules/jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core/node_modules/jest-worker/node_modules/supports-color": { @@ -2900,18 +2944,17 @@ } }, "node_modules/@jest/core/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core/node_modules/pretty-format/node_modules/ansi-styles": { @@ -2927,9 +2970,9 @@ } }, "node_modules/@jest/core/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/@jest/core/node_modules/supports-color": { @@ -2945,27 +2988,27 @@ } }, "node_modules/@jest/environment": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.0.2.tgz", - "integrity": "sha512-IvI7dEfqVEffDYlw9FQfVBt6kXt/OI38V7QUIur0ulOQgzpKYJDVvLzj4B1TVmHWTGW5tcnJdlZ3hqzV6/I9Qg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.1.2.tgz", + "integrity": "sha512-rG7xZ2UeOfvOVzoLIJ0ZmvPl4tBEQ2n73CZJSlzUjPw4or1oSWC0s0Rk0ZX+pIBJ04aVr6hLWFn1DFtrnf8MhQ==", "dev": true, "dependencies": { - "@jest/fake-timers": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/fake-timers": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", - "jest-mock": "^28.0.2" + "jest-mock": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/environment/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -2973,13 +3016,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/environment/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -3050,63 +3093,63 @@ } }, "node_modules/@jest/expect": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.0.3.tgz", - "integrity": "sha512-VEzZr85bqNomgayQkR7hWG5HnbZYWYWagQriZsixhLmOzU6PCpMP61aeVhkCoRrg7ri5f7JDpeTPzDAajIwFHw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.1.2.tgz", + "integrity": "sha512-FXw/UmaZsyfRyvZw3M6POgSNqwmuOXJuzdNiMWW9LCYo0GRoRDhg+R5iq5higmRTHQY7hx32+j7WHwinRmoILQ==", "dev": true, "dependencies": { - "expect": "^28.0.2", - "jest-snapshot": "^28.0.3" + "expect": "^29.1.2", + "jest-snapshot": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.0.2.tgz", - "integrity": "sha512-YryfH2zN5c7M8eLtn9oTBRj1sfD+X4cHNXJnTejqCveOS33wADEZUxJ7de5++lRvByNpRpfAnc8zTK7yrUJqgA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.1.2.tgz", + "integrity": "sha512-4a48bhKfGj/KAH39u0ppzNTABXQ8QPccWAFUFobWBaEMSMp+sB31Z2fK/l47c4a/Mu1po2ffmfAIPxXbVTXdtg==", "dev": true, "dependencies": { - "jest-get-type": "^28.0.2" + "jest-get-type": "^29.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.0.2.tgz", - "integrity": "sha512-R75yUv+WeybPa4ZVhX9C+8XN0TKjUoceUX+/QEaDVQGxZZOK50eD74cs7iMDTtpodh00d8iLlc9197vgF6oZjA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.1.2.tgz", + "integrity": "sha512-GppaEqS+QQYegedxVMpCe2xCXxxeYwQ7RsNx55zc8f+1q1qevkZGKequfTASI7ejmg9WwI+SJCrHe9X11bLL9Q==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", - "@sinonjs/fake-timers": "^9.1.1", + "@jest/types": "^29.1.2", + "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", - "jest-message-util": "^28.0.2", - "jest-mock": "^28.0.2", - "jest-util": "^28.0.2" + "jest-message-util": "^29.1.2", + "jest-mock": "^29.1.2", + "jest-util": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -3114,13 +3157,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -3179,12 +3222,12 @@ } }, "node_modules/@jest/fake-timers/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3192,7 +3235,7 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers/node_modules/supports-color": { @@ -3208,26 +3251,27 @@ } }, "node_modules/@jest/globals": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.0.3.tgz", - "integrity": "sha512-q/zXYI6CKtTSIt1WuTHBYizJhH7K8h+xG5PE3C0oawLlPIvUMDYmpj0JX0XsJwPRLCsz/fYXHZVG46AaEhSPmw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.1.2.tgz", + "integrity": "sha512-uMgfERpJYoQmykAd0ffyMq8wignN4SvLUG6orJQRe9WAlTRc9cdpCaE/29qurXixYJVZWUqIBXhSk8v5xN1V9g==", "dev": true, "dependencies": { - "@jest/environment": "^28.0.2", - "@jest/expect": "^28.0.3", - "@jest/types": "^28.0.2" + "@jest/environment": "^29.1.2", + "@jest/expect": "^29.1.2", + "@jest/types": "^29.1.2", + "jest-mock": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -3235,13 +3279,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -3312,17 +3356,17 @@ } }, "node_modules/@jest/reporters": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.0.3.tgz", - "integrity": "sha512-xrbIc7J/xwo+D7AY3enAR9ZWYCmJ8XIkstTukTGpKDph0gLl/TJje9jl3dssvE4KJzYqMKiSrnE5Nt68I4fTEg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.1.2.tgz", + "integrity": "sha512-X4fiwwyxy9mnfpxL0g9DD0KcTmEIqP0jUdnc2cfa9riHy+I6Gwwp5vOZiwyg0vZxfSDxrOlK9S4+340W4d+DAA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^28.0.2", - "@jest/test-result": "^28.0.2", - "@jest/transform": "^28.0.3", - "@jest/types": "^28.0.2", - "@jridgewell/trace-mapping": "^0.3.7", + "@jest/console": "^29.1.2", + "@jest/test-result": "^29.1.2", + "@jest/transform": "^29.1.2", + "@jest/types": "^29.1.2", + "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -3334,15 +3378,17 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-message-util": "^29.1.2", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "slash": "^3.0.0", "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", "terminal-link": "^2.0.0", - "v8-to-istanbul": "^9.0.0" + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -3354,12 +3400,12 @@ } }, "node_modules/@jest/reporters/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -3367,13 +3413,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -3432,12 +3478,12 @@ } }, "node_modules/@jest/reporters/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3445,21 +3491,22 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters/node_modules/jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters/node_modules/jest-worker/node_modules/supports-color": { @@ -3490,53 +3537,53 @@ } }, "node_modules/@jest/schemas": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.0.2.tgz", - "integrity": "sha512-YVDJZjd4izeTDkij00vHHAymNXQ6WWsdChFRK86qck6Jpr3DCL5W3Is3vslviRlP+bLuMYRLbdp98amMvqudhA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", + "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.23.3" + "@sinclair/typebox": "^0.24.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.0.2.tgz", - "integrity": "sha512-Y9dxC8ZpN3kImkk0LkK5XCEneYMAXlZ8m5bflmSL5vrwyeUpJfentacCUg6fOb8NOpOO7hz2+l37MV77T6BFPw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.0.0.tgz", + "integrity": "sha512-nOr+0EM8GiHf34mq2GcJyz/gYFyLQ2INDhAylrZJ9mMWoW21mLBfZa0BUVPPMxVYrLjeiRe2Z7kWXOGnS0TFhQ==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.15", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.0.2.tgz", - "integrity": "sha512-4EUqgjq9VzyUiVTvZfI9IRJD6t3NYBNP4f+Eq8Zr93+hkJ0RrGU4OBTw8tfNzidKX+bmuYzn8FxqpxOPIGGCMA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.1.2.tgz", + "integrity": "sha512-jjYYjjumCJjH9hHCoMhA8PCl1OxNeGgAoZ7yuGYILRJX9NjgzTN0pCT5qAoYR4jfOP8htIByvAlz9vfNSSBoVg==", "dev": true, "dependencies": { - "@jest/console": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/console": "^29.1.2", + "@jest/types": "^29.1.2", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -3544,13 +3591,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -3621,27 +3668,27 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.0.2.tgz", - "integrity": "sha512-zhnZ8ydkZQTPL7YucB86eOlD79zPy5EGSUKiR2Iv93RVEDU6OEP33kwDBg70ywOcxeJGDRhyo09q7TafNCBiIg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.1.2.tgz", + "integrity": "sha512-fU6dsUqqm8sA+cd85BmeF7Gu9DsXVWFdGn9taxM6xN1cKdcP/ivSgXh5QucFRFz1oZxKv3/9DYYbq0ULly3P/Q==", "dev": true, "dependencies": { - "@jest/test-result": "^28.0.2", + "@jest/test-result": "^29.1.2", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", + "jest-haste-map": "^29.1.2", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -3649,13 +3696,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -3714,46 +3761,46 @@ } }, "node_modules/@jest/test-sequencer/node_modules/jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "node_modules/@jest/test-sequencer/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3761,21 +3808,22 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer/node_modules/jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer/node_modules/jest-worker/node_modules/supports-color": { @@ -3806,38 +3854,38 @@ } }, "node_modules/@jest/transform": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.0.3.tgz", - "integrity": "sha512-+Y0ikI7SwoW/YbK8t9oKwC70h4X2Gd0OVuz5tctRvSV/EDQU00AAkoqevXgPSSFimUmp/sp7Yl8s/1bExDqOIg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.1.2.tgz", + "integrity": "sha512-2uaUuVHTitmkx1tHF+eBjb4p7UuzBG7SXIaA/hNIkaMP6K+gXYGxP38ZcrofzqN0HeZ7A90oqsOa97WU7WZkSw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^28.0.2", - "@jridgewell/trace-mapping": "^0.3.7", + "@jest/types": "^29.1.2", + "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", + "jest-haste-map": "^29.1.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", "write-file-atomic": "^4.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -3845,13 +3893,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -3910,46 +3958,46 @@ } }, "node_modules/@jest/transform/node_modules/jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "node_modules/@jest/transform/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3957,21 +4005,22 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform/node_modules/jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform/node_modules/jest-worker/node_modules/supports-color": { @@ -4002,16 +4051,16 @@ } }, "node_modules/@jest/transform/node_modules/write-file-atomic": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz", - "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/@jest/types": { @@ -4095,13 +4144,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -4135,20 +4185,6 @@ "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.11", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", @@ -4156,9 +4192,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -4201,24 +4237,55 @@ } }, "node_modules/@popperjs/core": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", - "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==", + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" } }, "node_modules/@react-leaflet/core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.0.0.tgz", - "integrity": "sha512-SQQ5DCQIaLzvslN6wCXs5OWqtlvk1Ubv2n5d7zTM8SDl9hM5Rr2wVy7/nOCIY958D75/ovhq6ZoSvT7GLCX6sg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", + "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", "peerDependencies": { - "leaflet": "^1.8.0", + "leaflet": "^1.9.0", "react": "^18.0.0", "react-dom": "^18.0.0" } }, + "node_modules/@reduxjs/toolkit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.0.tgz", + "integrity": "sha512-ak11IrjYcUXRqlhNPwnz6AcvA2ynJTu8PzDbbqQw4a3xR4KZtgiqbNblQD+10CRbfK4+5C79SOyxnT9dhBqFnA==", + "dependencies": { + "immer": "^9.0.16", + "redux": "^4.2.0", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.7" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.0.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@remix-run/router": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.1.tgz", + "integrity": "sha512-eBV5rvW4dRFOU1eajN7FmYxjAIVz/mRHgUE9En9mBn6m3mulK3WTR5C3iQhL9MZ14rWAq+xOlEaCkDiW0/heOg==", + "engines": { + "node": ">=14" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -4341,9 +4408,9 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.23.5", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz", - "integrity": "sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==", + "version": "0.24.44", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.44.tgz", + "integrity": "sha512-ka0W0KN5i6LfrSocduwliMMpqVgohtPFidKdMEOUjoOFCHcOOYkKsPRxfs5f15oPNHTm6ERAm0GV/+/LTKeiWg==", "dev": true }, "node_modules/@sinonjs/commons": { @@ -4365,49 +4432,51 @@ } }, "node_modules/@stryker-mutator/api": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-6.0.2.tgz", - "integrity": "sha512-8LWmArFc7Zb2ntYsD9KY0l+9RbcS1KilkCFWaHs+4KUWp/a9z51Ei606AzfHArwyfRsfFXLmKi+j+Mo0/R5R5w==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-6.2.2.tgz", + "integrity": "sha512-ZMR3ubUh059Xb769ryE1LkwZR7PWbt5TITYYkHZd7pG5yLVzPMDP0d29CQBJW2H7YjlopgImVL8sw8U/RgDcGg==", "dev": true, "dependencies": { "mutation-testing-metrics": "1.7.10", "mutation-testing-report-schema": "1.7.10", - "tslib": "~2.3.0" + "tslib": "~2.4.0" }, "engines": { "node": ">=14.18.0" } }, "node_modules/@stryker-mutator/api/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, "node_modules/@stryker-mutator/core": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-6.0.2.tgz", - "integrity": "sha512-ovRz7vOwjYUGZDCgADDPy5M+eK+l+ZQHseaZfYQv+MxPiXRQQuSxPm3ikeK5Hqds2UDLbzJ1i9XYc51hHqRVOQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-6.2.2.tgz", + "integrity": "sha512-1JS8UIMrwWeHqp508HXwRNmsAkHCtGskCwFWLLJSarVH9lyB8gyhTbhkaRHJGiEuaSTsxV1LZ5VzLK6OLgPtxw==", "dev": true, "dependencies": { - "@stryker-mutator/api": "6.0.2", - "@stryker-mutator/instrumenter": "6.0.2", - "@stryker-mutator/util": "6.0.2", + "@stryker-mutator/api": "6.2.2", + "@stryker-mutator/instrumenter": "6.2.2", + "@stryker-mutator/util": "6.2.2", "ajv": "~8.11.0", "chalk": "~5.0.0", - "commander": "~9.1.0", + "commander": "~9.4.0", + "diff-match-patch": "1.0.5", "execa": "~6.1.0", - "file-url": "~3.0.0", - "get-port": "~6.0.0", - "glob": "~7.2.0", - "inquirer": "~8.2.0", + "file-url": "~4.0.0", + "get-port": "~6.1.0", + "glob": "~8.0.0", + "inquirer": "~9.1.0", "lodash.flatmap": "~4.5.0", "lodash.groupby": "~4.6.0", - "log4js": "~6.4.1", - "minimatch": "~3.0.4", + "log4js": "~6.6.0", + "minimatch": "~5.1.0", "mkdirp": "~1.0.3", - "mutation-testing-elements": "1.7.10", + "mutation-testing-elements": "1.7.12", "mutation-testing-metrics": "1.7.10", + "mutation-testing-report-schema": "1.7.10", "npm-run-path": "~5.1.0", "progress": "~2.0.0", "rimraf": "~3.0.0", @@ -4415,7 +4484,7 @@ "semver": "^7.3.5", "source-map": "~0.7.3", "tree-kill": "~1.2.2", - "tslib": "~2.3.0", + "tslib": "~2.4.0", "typed-inject": "~3.0.0", "typed-rest-client": "~1.8.0" }, @@ -4442,58 +4511,19 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@stryker-mutator/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@stryker-mutator/core/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@stryker-mutator/core/node_modules/cli-width": { - "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, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@stryker-mutator/core/node_modules/color-convert": { + "node_modules/@stryker-mutator/core/node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "balanced-match": "^1.0.0" } }, "node_modules/@stryker-mutator/core/node_modules/commander": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.1.0.tgz", - "integrity": "sha512-i0/MaqBtdbnJ4XQs4Pmyb+oFQl+q0lsAmokVUH92SlSw4fkeAcG3bVon+Qt7hmtF+u3Het6o4VgrcY3qAoEB6w==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", "dev": true, "engines": { "node": "^12.20.0 || >=14" @@ -4563,28 +4593,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@stryker-mutator/core/node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/@stryker-mutator/core/node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.5" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@stryker-mutator/core/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@stryker-mutator/core/node_modules/human-signals": { @@ -4596,56 +4621,6 @@ "node": ">=12.20.0" } }, - "node_modules/@stryker-mutator/core/node_modules/inquirer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", - "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.2.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@stryker-mutator/core/node_modules/inquirer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@stryker-mutator/core/node_modules/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, - "engines": { - "node": ">=8" - } - }, "node_modules/@stryker-mutator/core/node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -4664,13 +4639,16 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/@stryker-mutator/core/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/@stryker-mutator/core/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, "node_modules/@stryker-mutator/core/node_modules/mkdirp": { @@ -4685,12 +4663,6 @@ "node": ">=10" } }, - "node_modules/@stryker-mutator/core/node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, "node_modules/@stryker-mutator/core/node_modules/npm-run-path": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", @@ -4718,21 +4690,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@stryker-mutator/core/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@stryker-mutator/core/node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4742,23 +4699,10 @@ "node": ">=8" } }, - "node_modules/@stryker-mutator/core/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@stryker-mutator/core/node_modules/rxjs": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz", - "integrity": "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", + "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", "dev": true, "dependencies": { "tslib": "^2.1.0" @@ -4809,20 +4753,6 @@ "node": ">= 8" } }, - "node_modules/@stryker-mutator/core/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@stryker-mutator/core/node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", @@ -4835,22 +4765,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@stryker-mutator/core/node_modules/supports-color": { - "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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@stryker-mutator/core/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, "node_modules/@stryker-mutator/core/node_modules/which": { @@ -4869,35 +4787,35 @@ } }, "node_modules/@stryker-mutator/instrumenter": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/instrumenter/-/instrumenter-6.0.2.tgz", - "integrity": "sha512-D2R/RO83ILwGMp7PeYUcmr/cmqZOBrSAwB1RnmqADqLka9NDxS6Pn4NUCacu7xlyIf5Ejt1m9I2+64AH9W96hA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/instrumenter/-/instrumenter-6.2.2.tgz", + "integrity": "sha512-FZIvyL3uiIaLvOSKXe6jnq0FMo6lWy4NoGyYt5K/wmDxN2QuSaChGu/tVe4Z+Ui+4O3/DiGqWY5FWKGv1iHEPA==", "dev": true, "dependencies": { - "@babel/core": "~7.17.9", - "@babel/generator": "~7.17.9", - "@babel/parser": "~7.17.9", - "@babel/plugin-proposal-class-properties": "~7.16.7", - "@babel/plugin-proposal-decorators": "~7.17.9", - "@babel/plugin-proposal-private-methods": "~7.16.11", - "@babel/preset-typescript": "~7.16.7", - "@stryker-mutator/api": "6.0.2", - "@stryker-mutator/util": "6.0.2", + "@babel/core": "~7.19.0", + "@babel/generator": "~7.19.0", + "@babel/parser": "~7.19.0", + "@babel/plugin-proposal-class-properties": "~7.18.0", + "@babel/plugin-proposal-decorators": "~7.19.0", + "@babel/plugin-proposal-private-methods": "~7.18.0", + "@babel/preset-typescript": "~7.18.0", + "@stryker-mutator/api": "6.2.2", + "@stryker-mutator/util": "6.2.2", "angular-html-parser": "~1.8.0", - "weapon-regex": "~0.6.0" + "weapon-regex": "~1.0.2" }, "engines": { "node": ">=14.18.0" } }, "node_modules/@stryker-mutator/jest-runner": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/jest-runner/-/jest-runner-6.0.2.tgz", - "integrity": "sha512-fHa/2izIuqUZDW343/PYa5sXlZUpjZ53kqfUbwXJGxCVKiYrYlWGxAa/LfdBT2mRaPKL9Ji76F2n+53mDuu7rA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/jest-runner/-/jest-runner-6.2.2.tgz", + "integrity": "sha512-xWuzuBUIB2MQVJBCdK5K8/SRV4fu2+wAd9FoZY6AIkKCVv0Od0eYZ6MB78V6jSG9R2/KF9I+zzrQ94PEnp5zaQ==", "dev": true, "dependencies": { - "@stryker-mutator/api": "6.0.2", - "@stryker-mutator/util": "6.0.2", + "@stryker-mutator/api": "6.2.2", + "@stryker-mutator/util": "6.2.2", "semver": "~7.3.7", "tslib": "~2.4.0" }, @@ -4905,7 +4823,7 @@ "node": ">=14.18.0" }, "peerDependencies": { - "@stryker-mutator/core": "~6.0.0" + "@stryker-mutator/core": "~6.2.0" } }, "node_modules/@stryker-mutator/jest-runner/node_modules/semver": { @@ -4930,20 +4848,20 @@ "dev": true }, "node_modules/@stryker-mutator/typescript-checker": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/typescript-checker/-/typescript-checker-6.0.2.tgz", - "integrity": "sha512-UiOnTKvl9K8Jbd3BV+F7nUbDl7JpW+xxOOuWcQxWUCeBDXBqTJ40oX0Yj1OKyA4YMxn+owSxsCca94c4Q+3PNg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/typescript-checker/-/typescript-checker-6.2.2.tgz", + "integrity": "sha512-vYLrPden87i6Fyx6zgBLk2MSrtYDi/ig+ZgNotdavNy34VpiKPTkgpfAWjqkVCxyJhvQvkS6iag17xlWR+uYmg==", "dev": true, "dependencies": { - "@stryker-mutator/api": "6.0.2", - "@stryker-mutator/util": "6.0.2", + "@stryker-mutator/api": "6.2.2", + "@stryker-mutator/util": "6.2.2", "semver": "~7.3.2" }, "engines": { "node": ">=14.18.0" }, "peerDependencies": { - "@stryker-mutator/core": "~6.0.0", + "@stryker-mutator/core": "~6.2.0", "typescript": ">=3.6" } }, @@ -4963,9 +4881,9 @@ } }, "node_modules/@stryker-mutator/util": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-6.0.2.tgz", - "integrity": "sha512-xqeOIOu6yTK4v9kwdfINzdT7qd0nru8tR3mxNnfp6LLgD805pJYiR14EK2yLE0ylrBHaRAjTb/uMclf+7OtAVQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-6.2.2.tgz", + "integrity": "sha512-BjE9wP8V8Vh4VMr/pReNLlMNxSzl25OHJBDK1Y4WN/b+HY9gVy7PiX2HEYiXg7LniHIZ54vX5VLuLzJOfb6pGQ==", "dev": true, "dependencies": { "lodash.flatmap": "~4.5.0" @@ -5214,9 +5132,9 @@ } }, "node_modules/@svgr/webpack/node_modules/loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -5320,16 +5238,16 @@ } }, "node_modules/@testing-library/jest-dom": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.4.tgz", - "integrity": "sha512-Gy+IoFutbMQcky0k+bqqumXZ1cTGswLsFqmNLzNdSKkU9KGV2u9oXhukCbbJ9/LRPKiqwxEE8VpV/+YZlfkPUA==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", + "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", "dev": true, "dependencies": { + "@adobe/css-tools": "^4.0.1", "@babel/runtime": "^7.9.2", "@types/testing-library__jest-dom": "^5.9.1", "aria-query": "^5.0.0", "chalk": "^3.0.0", - "css": "^3.0.0", "css.escape": "^1.5.1", "dom-accessibility-api": "^0.5.6", "lodash": "^4.17.15", @@ -5412,9 +5330,9 @@ } }, "node_modules/@testing-library/react": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.1.1.tgz", - "integrity": "sha512-8mirlAa0OKaUvnqnZF6MdAh2tReYA2KtWVw1PKvaF5EcCZqgK5pl8iF+3uW90JdG5Ua2c2c2E2wtLdaug3dsVg==", + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", + "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", @@ -5430,9 +5348,9 @@ } }, "node_modules/@testing-library/user-event": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.1.1.tgz", - "integrity": "sha512-XrjH/iEUqNl9lF2HX9YhPNV7Amntkcnpw0Bo1KkRzowNDcgSN9i0nm4Q8Oi5wupgdfPaJNMAWa61A+voD6Kmwg==", + "version": "14.4.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", + "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", "dev": true, "engines": { "node": ">=12", @@ -5660,24 +5578,56 @@ } }, "node_modules/@types/jest": { - "version": "27.4.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", - "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.1.1.tgz", + "integrity": "sha512-U9Ey07dGWl6fUFaIaUQUKWG5NoKi/zizeVQCGV8s4nSU0jPgqphVZvS64+8BtWYvrc3ZGw6wo943NSYPxkrp/g==", "dev": true, "dependencies": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, + "node_modules/@types/jest/node_modules/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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@types/jest/node_modules/pretty-format": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.0.0", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, "node_modules/@types/jsdom": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-16.2.14.tgz", - "integrity": "sha512-6BAy1xXEmMuHeAJ4Fv4yXKwBDTGTOseExKE3OaHiNycdHdZw59KfYzrt0DkDluvwmik1HRt6QS7bImxUmpSy+w==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.0.tgz", + "integrity": "sha512-YfAchFs0yM1QPDrLm2VHe+WHGtqms3NXnXAMolrgrVP6fgBHHXy1ozAbo/dFtPNtZC/m66bPiCTWYmqp1F14gA==", "dev": true, "dependencies": { "@types/node": "*", - "@types/parse5": "*", - "@types/tough-cookie": "*" + "@types/tough-cookie": "*", + "parse5": "^7.0.0" } }, "node_modules/@types/json-schema": { @@ -5702,9 +5652,9 @@ "dev": true }, "node_modules/@types/leaflet": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.9.tgz", - "integrity": "sha512-H8vPgD49HKzqM41ArHGZM70g/tfhp8W+JcPxfnF+5H/Xvp+xiP+KQOUNWU8U89fqS1Jj3cpRY/+nbnaHFzwnFA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.8.0.tgz", + "integrity": "sha512-+sXFmiJTFdhaXXIGFlV5re9AdqtAODoXbGAvxx02e5SHXL3ir7ClP5J7pahO8VmzKY3dth4RUS1nf2BTT+DW1A==", "dev": true, "dependencies": { "@types/geojson": "*" @@ -5740,12 +5690,6 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, - "node_modules/@types/parse5": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", - "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==", - "dev": true - }, "node_modules/@types/prettier": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", @@ -5770,9 +5714,9 @@ "dev": true }, "node_modules/@types/ramda": { - "version": "0.27.38", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.27.38.tgz", - "integrity": "sha512-tZoQ0lv1WKkrpBHemL8yCkI9p8kUk/1PSMwhl0eeyqMQjD+2ePUtVLV8PpNS9Kq3OktObwOx9I3k+HumxTviRg==", + "version": "0.28.15", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.28.15.tgz", + "integrity": "sha512-FCaLNVZry65jW8x/FDnKgjgkCNQxgc5AYMQwdNn6yW5M+62R+0nt2Y36U43dTNora9hcquemfrY5gxhE5pcilQ==", "dev": true, "dependencies": { "ts-toolbelt": "^6.15.1" @@ -5785,9 +5729,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.0.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.8.tgz", - "integrity": "sha512-+j2hk9BzCOrrOSJASi5XiOyBbERk9jG5O73Ya4M0env5Ixi6vUNli4qy994AINcEF+1IEHISYFfIT4zwr++LKw==", + "version": "18.0.21", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz", + "integrity": "sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -5805,18 +5749,18 @@ } }, "node_modules/@types/react-copy-to-clipboard": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.2.tgz", - "integrity": "sha512-O29AThfxrkUFRsZXjfSWR2yaWo0ppB1yLEnHA+Oh24oNetjBAwTDu1PmolIqdJKzsZiO4J1jn6R6TmO96uBvGg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.4.tgz", + "integrity": "sha512-otTJsJpofYAeaIeOwV5xBUGpo6exXG2HX7X4nseToCB2VgPEBxGBHCm/FecZ676doNR7HCSTVtmohxfG2b3/yQ==", "dev": true, "dependencies": { "@types/react": "*" } }, "node_modules/@types/react-datepicker": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.3.4.tgz", - "integrity": "sha512-5nTTz37KdTUgMZ1AAxztMWNtEnIMVRo8oCAEhIv0a6uUqDjvSKaMyPRpBV+8chi6f/A8wlTKJIpojpXca2dx3A==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.4.2.tgz", + "integrity": "sha512-g8DhWvYmaIMLzVrIEVLXncylyImyBaoPsEUr3yR13JDaaHoebhDorqnVv4tLkNGa8SjBB8SAOQvxD5jaPNBX8A==", "dev": true, "dependencies": { "@popperjs/core": "^2.9.2", @@ -5854,18 +5798,18 @@ } }, "node_modules/@types/react-dom": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.3.tgz", - "integrity": "sha512-1RRW9kst+67gveJRYPxGmVy8eVJ05O43hg77G2j5m76/RFJtMbcfAs2viQ2UNsvvDg8F7OfQZx8qQcl6ymygaQ==", + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz", + "integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==", "devOptional": true, "dependencies": { "@types/react": "*" } }, "node_modules/@types/react-tag-autocomplete": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/react-tag-autocomplete/-/react-tag-autocomplete-6.1.1.tgz", - "integrity": "sha512-/mVNQUHXtKGihHBP/q0znL/CHbtrZL82t8ch/msQCkywqDkoZeE7QzhyLTG535Y/estsI6EcJi8Jd5HersPHuw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@types/react-tag-autocomplete/-/react-tag-autocomplete-6.3.0.tgz", + "integrity": "sha512-WxAVFlcotjeQKh1UDEjAQwP4dCOtKFrCnSHODhSmBZqDFbjNhhw9QwtZ9wSfKkJ4z2mu5kgC8OD96hNUYtjZ1Q==", "dev": true, "dependencies": { "@types/react": "*" @@ -6677,9 +6621,9 @@ "dev": true }, "node_modules/@zeit/schemas": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", - "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==", + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.21.0.tgz", + "integrity": "sha512-/J4WBTpWtQ4itN1rb3ao8LfClmVcmz2pO6oYb7Qd4h7VSqUhIbJIvrykz9Ew1WMg6eFWsKdsMHc5uPbFxqlCpg==", "dev": true }, "node_modules/abab": { @@ -6784,9 +6728,9 @@ } }, "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -7056,9 +7000,9 @@ ] }, "node_modules/arg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz", - "integrity": "sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", "dev": true }, "node_modules/argparse": { @@ -7196,18 +7140,6 @@ "node": ">= 4.0.0" } }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz", - "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, "node_modules/autoprefixer": { "version": "10.4.4", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.4.tgz", @@ -7250,14 +7182,6 @@ "node": ">=4" } }, - "node_modules/axios": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz", - "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -7265,21 +7189,21 @@ "dev": true }, "node_modules/babel-jest": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.0.3.tgz", - "integrity": "sha512-S0ADyYdcrt5fp9YldRYWCUHdk1BKt9AkvBkLWBoNAEV9NoWZPIj5+MYhPcGgTS65mfv3a+Ymf2UqgWoAVd41cA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.1.2.tgz", + "integrity": "sha512-IuG+F3HTHryJb7gacC7SQ59A9kO56BctUsT67uJHp1mMCHUOMXpDwOHWGifWqdWVknN2WNkCVQELPjXx0aLJ9Q==", "dev": true, "dependencies": { - "@jest/transform": "^28.0.3", + "@jest/transform": "^29.1.2", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^28.0.2", + "babel-preset-jest": "^29.0.2", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.8.0" @@ -7407,9 +7331,9 @@ } }, "node_modules/babel-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -7464,9 +7388,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.0.2.tgz", - "integrity": "sha512-Kizhn/ZL+68ZQHxSnHyuvJv8IchXD62KQxV77TBDV/xoBFBOfgRAk97GNs6hXdTTCiVES9nB2I6+7MXXrk5llQ==", + "version": "29.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.0.2.tgz", + "integrity": "sha512-eBr2ynAEFjcebVvu8Ktx580BD1QKCrBG1XwEUTXJe285p9HA/4hOhfWCFRQhTKSyBV0VzjhG7H91Eifz9s29hg==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -7475,7 +7399,7 @@ "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/babel-plugin-macros": { @@ -7580,16 +7504,16 @@ } }, "node_modules/babel-preset-jest": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.0.2.tgz", - "integrity": "sha512-sYzXIdgIXXroJTFeB3S6sNDWtlJ2dllCdTEsnZ65ACrMojj3hVNFRmnJ1HZtomGi+Be7aqpY/HJ92fr8OhKVkQ==", + "version": "29.0.2", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.0.2.tgz", + "integrity": "sha512-BeVXp7rH5TK96ofyEnHjznjLMQ2nAeDJ+QzxKnHAAMs0RgrQsCywjAN8m4mOm5Di0pxU//3AoEeJJrerMH5UeA==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^28.0.2", + "babel-plugin-jest-hoist": "^29.0.2", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -7685,40 +7609,16 @@ } }, "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz", + "integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==", "dev": true, "dependencies": { - "buffer": "^5.5.0", + "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, - "node_modules/bl/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, "node_modules/bl/node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -7804,21 +7704,27 @@ "dev": true }, "node_modules/bootstrap": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz", - "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - }, + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.2.tgz", + "integrity": "sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], "peerDependencies": { - "@popperjs/core": "^2.10.2" + "@popperjs/core": "^2.11.6" } }, "node_modules/bottlejs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bottlejs/-/bottlejs-2.0.0.tgz", - "integrity": "sha512-Qhz5dd1YPTOHw0gZ1a1WpJ/oEWsq09BMMbxczeAPgubISij+ZFfah7wfOlHFeFQpWLQkS9TGz5C54tV6v0BlFA==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bottlejs/-/bottlejs-2.0.1.tgz", + "integrity": "sha512-50T0bzqeAqZ+//kgjdDxNu7UP8Je04isNPyHPwwOOPoeZmtVESkuF9nwkWEqSEd9Sw1yJ1oaoHBAMxe/wG4Zzg==" }, "node_modules/bowser": { "version": "2.11.0", @@ -7826,126 +7732,130 @@ "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, "node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", + "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", "dev": true, "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" + "ansi-align": "^3.0.1", + "camelcase": "^7.0.0", + "chalk": "^5.0.1", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" }, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/boxen/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/boxen/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/boxen/node_modules/ansi-styles": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.1.tgz", + "integrity": "sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/boxen/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/boxen/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/boxen/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/boxen/node_modules/camelcase": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.0.tgz", + "integrity": "sha512-JToIvOmz6nhGsUhAYScbo2d6Py5wojjNfoxoc2mEVLUdJ70gJK2gnd+ABY1Tc3sVMyK7QDPtN0T/XdlCQWITyQ==", "dev": true, "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/supports-color": { - "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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/boxen/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/boxen/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/wrap-ansi": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", + "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -7975,9 +7885,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.20.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", - "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", "dev": true, "funding": [ { @@ -7990,11 +7900,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001317", - "electron-to-chromium": "^1.4.84", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" }, "bin": { "browserslist": "cli.js" @@ -8012,6 +7921,30 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -8037,7 +7970,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -8131,9 +8063,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001320", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", - "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", + "version": "1.0.30001415", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001415.tgz", + "integrity": "sha512-ER+PfgCJUe8BqunLGWd/1EY4g8AzQcsDAVzdtMGKVtQEmKAwaFfU6vb7EAVIqTMYsqxBorYZi2+22Iouj/y7GQ==", "dev": true, "funding": [ { @@ -8167,6 +8099,85 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/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, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk-template/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk-template/node_modules/supports-color": { + "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, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", @@ -8176,15 +8187,6 @@ "node": ">=10" } }, - "node_modules/charcodes": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/charcodes/-/charcodes-0.2.0.tgz", - "integrity": "sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz", @@ -8192,9 +8194,9 @@ "dev": true }, "node_modules/chart.js": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.7.1.tgz", - "integrity": "sha512-8knRegQLFnPQAheZV8MjxIXc5gQEfDFD897BJgv/klO/vtIyFFmgMXrNfgrXpbTr/XbTturxRgxIXx/Y+ASJBA==" + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", + "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" }, "node_modules/check-types": { "version": "11.1.2", @@ -8268,12 +8270,12 @@ } }, "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", "dev": true, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8292,9 +8294,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", "dev": true, "engines": { "node": ">=6" @@ -8310,59 +8312,20 @@ "dev": true }, "node_modules/clipboardy": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", - "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", + "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", "dev": true, "dependencies": { - "arch": "^2.1.1", - "execa": "^1.0.0", - "is-wsl": "^2.1.1" + "arch": "^2.2.0", + "execa": "^5.1.1", + "is-wsl": "^2.2.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/clipboardy/node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clipboardy/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clipboardy/node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cliui": { @@ -8402,24 +8365,12 @@ "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, "engines": { "node": ">=0.8" } }, - "node_modules/clone-regexp": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz", - "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==", - "dev": true, - "dependencies": { - "is-regexp": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -8486,9 +8437,9 @@ "dev": true }, "node_modules/colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, "node_modules/combined-stream": { @@ -8534,9 +8485,9 @@ "dev": true }, "node_modules/compare-versions": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.3.tgz", - "integrity": "sha512-WQfnbDcrYnGr55UwbxKiQKASnTtNnaAWVi8jZyy8NTpVAXWACSne8lMD1iaIo9AiU6mnuLvSVshCzewVuWxHUg==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.1.tgz", + "integrity": "sha512-v8Au3l0b+Nwkp4G142JcgJFh1/TUhdxut7wzD1Nq1dyp5oa3tXaqb03EXOAB6jS4gMlalkjAUPZBMiAfKUixHQ==" }, "node_modules/compressible": { "version": "2.0.17", @@ -8551,16 +8502,16 @@ } }, "node_modules/compression": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", - "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "dev": true, "dependencies": { "accepts": "~1.3.5", "bytes": "3.0.0", - "compressible": "~2.0.14", + "compressible": "~2.0.16", "debug": "2.6.9", - "on-headers": "~1.0.1", + "on-headers": "~1.0.2", "safe-buffer": "5.1.2", "vary": "~1.1.2" }, @@ -8592,7 +8543,7 @@ "node_modules/content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", "dev": true, "engines": { "node": ">= 0.6" @@ -8695,33 +8646,6 @@ "node": ">=10" } }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/css": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", - "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "source-map": "^0.6.1", - "source-map-resolve": "^0.6.0" - } - }, "node_modules/css-blank-pseudo": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", @@ -8741,9 +8665,9 @@ } }, "node_modules/css-functions-list": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.0.1.tgz", - "integrity": "sha512-PriDuifDt4u4rkDgnqRCLnjfMatufLmWNfQnGCq34xZwpY3oabwhB9SqRBmuvWUgndbemCFlKqg+nO7C2q0SBw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", "dev": true, "engines": { "node": ">=12.22" @@ -8831,23 +8755,6 @@ "integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=", "dev": true }, - "node_modules/css/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/css/node_modules/source-map-resolve": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", - "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0" - } - }, "node_modules/cssdb": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-6.5.0.tgz", @@ -8991,23 +8898,10 @@ "node": ">=12" } }, - "node_modules/data-urls/node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/date-fns": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", - "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", "engines": { "node": ">=0.11" }, @@ -9017,9 +8911,9 @@ } }, "node_modules/date-format": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.4.tgz", - "integrity": "sha512-/jyf4rhB17ge328HJuJjAcmRtCsGd+NDeAtahRBTaK6vSPR6MO5HlrAit3Nn7dVjaa6sowW0WXt8yQtLyZQFRg==", + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", "dev": true, "engines": { "node": ">=4.0" @@ -9066,20 +8960,11 @@ } }, "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz", + "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==", "dev": true }, - "node_modules/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=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -9105,8 +8990,8 @@ }, "node_modules/deep-extend": { "version": "0.6.0", - "resolved": "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "engines": { "node": ">=4.0.0" @@ -9142,7 +9027,7 @@ "node_modules/defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", "dev": true, "dependencies": { "clone": "^1.0.2" @@ -9254,6 +9139,12 @@ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "dev": true }, + "node_modules/diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", + "dev": true + }, "node_modules/diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", @@ -9423,6 +9314,12 @@ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -9445,9 +9342,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.92", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.92.tgz", - "integrity": "sha512-YAVbvQIcDE/IJ/vzDMjD484/hsRbFPW2qXJPaYTfOhtligmfYEYOep+5QojpaEU9kq6bMvNeC2aG7arYvTHYsA==", + "version": "1.4.271", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.271.tgz", + "integrity": "sha512-BCPBtK07xR1/uY2HFDtl3wK2De66AW4MSiPlLrnPNxKC/Qhccxd59W73654S3y6Rb/k3hmuGJOBnhjfoutetXA==", "dev": true }, "node_modules/emitter-component": { @@ -9482,19 +9379,10 @@ "node": ">= 0.8" } }, - "node_modules/end-of-stream": { - "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==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/enhanced-resolve": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", - "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", + "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -9701,13 +9589,15 @@ } }, "node_modules/eslint": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz", - "integrity": "sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz", + "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", + "@eslint/eslintrc": "^1.3.2", + "@humanwhocodes/config-array": "^0.10.5", + "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@humanwhocodes/module-importer": "^1.0.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -9717,30 +9607,32 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", + "find-up": "^5.0.0", "glob-parent": "^6.0.1", - "globals": "^13.6.0", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -10105,18 +9997,6 @@ "node": ">=4.0" } }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.3", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz", @@ -10343,9 +10223,9 @@ } }, "node_modules/eslint/node_modules/globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -10414,18 +10294,6 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -10466,23 +10334,26 @@ } }, "node_modules/espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", "dev": true, "dependencies": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -10580,9 +10451,9 @@ } }, "node_modules/event-source-polyfill": { - "version": "1.0.25", - "resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.25.tgz", - "integrity": "sha512-hQxu6sN1Eq4JjoI7ITdQeGGUN193A2ra83qC0Ltm9I2UJVAten3OFVN6k5RX4YWeCS0BoC8xg/5czOCIHVosQg==" + "version": "1.0.31", + "resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.31.tgz", + "integrity": "sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==" }, "node_modules/eventemitter3": { "version": "4.0.7", @@ -10743,18 +10614,6 @@ "node": ">= 8" } }, - "node_modules/execall": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz", - "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==", - "dev": true, - "dependencies": { - "clone-regexp": "^2.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -10765,28 +10624,28 @@ } }, "node_modules/expect": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-28.0.2.tgz", - "integrity": "sha512-X0qIuI/zKv98k34tM+uGeOgAC73lhs4vROF9MkPk94C1zujtwv4Cla8SxhWn0G1OwvG9gLLL7RjFBkwGVaZ83w==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.1.2.tgz", + "integrity": "sha512-AuAGn1uxva5YBbBlXb+2JPxJRuemZsmlGcapPXWNSBNsQtAULfjioREGBWuI0EOvYUKjDnrCy8PW5Zlr1md5mw==", "dev": true, "dependencies": { - "@jest/expect-utils": "^28.0.2", - "jest-get-type": "^28.0.2", - "jest-matcher-utils": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-util": "^28.0.2" + "@jest/expect-utils": "^29.1.2", + "jest-get-type": "^29.0.0", + "jest-matcher-utils": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-util": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/expect/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -10794,13 +10653,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/expect/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -10850,12 +10709,12 @@ } }, "node_modules/expect/node_modules/diff-sequences": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.0.2.tgz", - "integrity": "sha512-YtEoNynLDFCRznv/XDalsKGSZDoj0U5kLnXvY0JSq3nBboRrZXjD81+eSiwi+nzcZDwedMmcowcxNwwgFW23mQ==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.0.0.tgz", + "integrity": "sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/expect/node_modules/has-flag": { @@ -10868,51 +10727,51 @@ } }, "node_modules/expect/node_modules/jest-diff": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.0.2.tgz", - "integrity": "sha512-33Rnf821Y54OAloav0PGNWHlbtEorXpjwchnToyyWbec10X74FOW7hGfvrXLGz7xOe2dz0uo9JVFAHHj/2B5pg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.1.2.tgz", + "integrity": "sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "diff-sequences": "^29.0.0", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/expect/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/expect/node_modules/jest-matcher-utils": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.0.2.tgz", - "integrity": "sha512-SxtTiI2qLJHFtOz/bySStCnwCvISAuxQ/grS+74dfTy5AuJw3Sgj9TVUvskcnImTfpzLoMCDJseRaeRrVYbAOA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.1.2.tgz", + "integrity": "sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "jest-diff": "^29.1.2", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/expect/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -10920,22 +10779,21 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/expect/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/expect/node_modules/pretty-format/node_modules/ansi-styles": { @@ -10951,9 +10809,9 @@ } }, "node_modules/expect/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/expect/node_modules/supports-color": { @@ -11072,9 +10930,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -11102,7 +10960,7 @@ "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", "dev": true, "dependencies": { "punycode": "^1.3.2" @@ -11111,14 +10969,17 @@ "node_modules/fast-url-parser/node_modules/punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true }, "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } }, "node_modules/fastq": { "version": "1.8.0", @@ -11204,9 +11065,9 @@ } }, "node_modules/file-loader/node_modules/loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -11218,12 +11079,15 @@ } }, "node_modules/file-url": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", - "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/file-url/-/file-url-4.0.0.tgz", + "integrity": "sha512-vRCdScQ6j3Ku6Kd7W1kZk9c++5SqD6Xz5Jotrjr/nkY714M14RFHy/AAVA2WQvpsqVAVgTbDrYyBpU205F0cLw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/filelist": { @@ -11245,9 +11109,9 @@ } }, "node_modules/filelist/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -11334,15 +11198,16 @@ } }, "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, "node_modules/follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "dev": true, "funding": [ { "type": "individual", @@ -11629,8 +11494,7 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/functional-red-black-tree": { "version": "1.0.1", @@ -11660,7 +11524,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -11686,9 +11549,9 @@ } }, "node_modules/get-port": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.0.0.tgz", - "integrity": "sha512-qSVkVF6Eq1GdL/cBNiFuP4nUHMF7OEMTqEjC6alR2N90u8BFOoO0PFhNTX2QtAUoGrz8NnrSWj85TZ8YXZ6LOA==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", + "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==", "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -11697,18 +11560,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -11851,6 +11702,12 @@ "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "node_modules/gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -11891,7 +11748,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -11921,7 +11777,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -12225,7 +12080,8 @@ "node_modules/idb": { "version": "6.1.5", "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" + "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==", + "dev": true }, "node_modules/identity-obj-proxy": { "version": "3.0.0", @@ -12269,10 +12125,9 @@ } }, "node_modules/immer": { - "version": "9.0.12", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz", - "integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==", - "dev": true, + "version": "9.0.16", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz", + "integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -12365,6 +12220,251 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "node_modules/inquirer": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.2.tgz", + "integrity": "sha512-Hj2Ml1WpxKJU2npP2Rj0OURGkHV+GtNW2CwFdHDiXlqUBAUrWTcZHxCkFywX/XHzOS7wrG/kExgJFbUkVgyHzg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^5.0.0", + "chalk": "^5.0.1", + "cli-cursor": "^4.0.0", + "cli-width": "^4.0.0", + "external-editor": "^3.0.3", + "figures": "^5.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^6.1.2", + "run-async": "^2.4.0", + "rxjs": "^7.5.6", + "string-width": "^5.1.2", + "strip-ansi": "^7.0.1", + "through": "^2.3.6", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-escapes": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", + "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.1.tgz", + "integrity": "sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/cli-width": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", + "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/inquirer/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/inquirer/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/figures": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/inquirer/node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/inquirer/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/rxjs": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", + "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/inquirer/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "node_modules/inquirer/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", + "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/internal-slot": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", @@ -12537,12 +12637,15 @@ } }, "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-module": { @@ -12602,6 +12705,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-port-reachable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", + "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/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", @@ -12624,15 +12739,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-regexp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-2.1.0.tgz", - "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/is-root": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", @@ -12651,15 +12757,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -12697,12 +12794,12 @@ "dev": true }, "node_modules/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==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -12725,6 +12822,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz", @@ -12945,20 +13054,21 @@ } }, "node_modules/jest": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.0.3.tgz", - "integrity": "sha512-uS+T5J3w5xyzd1KSJCGKhCo8WTJXbNl86f5SW11wgssbandJOVLRKKUxmhdFfmKxhPeksl1hHZ0HaA8VBzp7xA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.1.2.tgz", + "integrity": "sha512-5wEIPpCezgORnqf+rCaYD1SK+mNN7NsstWzIsuvsnrhR/hSxXWd82oI7DkrbJ+XTD28/eG8SmxdGvukrGGK6Tw==", "dev": true, "dependencies": { - "@jest/core": "^28.0.3", + "@jest/core": "^29.1.2", + "@jest/types": "^29.1.2", "import-local": "^3.0.2", - "jest-cli": "^28.0.3" + "jest-cli": "^29.1.2" }, "bin": { "jest": "bin/jest.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -12980,55 +13090,70 @@ } }, "node_modules/jest-changed-files": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.0.2.tgz", - "integrity": "sha512-QX9u+5I2s54ZnGoMEjiM2WeBvJR2J7w/8ZUmH2um/WLAuGAYFQcsVXY9+1YL6k0H/AGUdH8pXUAv6erDqEsvIA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.0.0.tgz", + "integrity": "sha512-28/iDMDrUpGoCitTURuDqUzWQoWmOmOKOFST1mi2lwh62X4BFf6khgH3uSuo1e49X/UDjuApAj3w0wLOex4VPQ==", "dev": true, "dependencies": { "execa": "^5.0.0", - "throat": "^6.0.1" + "p-limit": "^3.1.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/jest-circus": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.0.3.tgz", - "integrity": "sha512-HJ3rUCm3A3faSy7KVH5MFCncqJLtrjEFkTPn9UIcs4Kq77+TXqHsOaI+/k73aHe6DJQigLUXq9rCYj3MYFlbIw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.1.2.tgz", + "integrity": "sha512-ajQOdxY6mT9GtnfJRZBRYS7toNIJayiiyjDyoZcnvPRUPwJ58JX0ci0PKAKUo2C1RyzlHw0jabjLGKksO42JGA==", "dev": true, "dependencies": { - "@jest/environment": "^28.0.2", - "@jest/expect": "^28.0.3", - "@jest/test-result": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/environment": "^29.1.2", + "@jest/expect": "^29.1.2", + "@jest/test-result": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^28.0.2", - "jest-matcher-utils": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-runtime": "^28.0.3", - "jest-snapshot": "^28.0.3", - "jest-util": "^28.0.2", - "pretty-format": "^28.0.2", + "jest-each": "^29.1.2", + "jest-matcher-utils": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-runtime": "^29.1.2", + "jest-snapshot": "^29.1.2", + "jest-util": "^29.1.2", + "p-limit": "^3.1.0", + "pretty-format": "^29.1.2", "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" + "stack-utils": "^2.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -13036,13 +13161,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -13092,12 +13217,12 @@ } }, "node_modules/jest-circus/node_modules/diff-sequences": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.0.2.tgz", - "integrity": "sha512-YtEoNynLDFCRznv/XDalsKGSZDoj0U5kLnXvY0JSq3nBboRrZXjD81+eSiwi+nzcZDwedMmcowcxNwwgFW23mQ==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.0.0.tgz", + "integrity": "sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus/node_modules/has-flag": { @@ -13110,51 +13235,51 @@ } }, "node_modules/jest-circus/node_modules/jest-diff": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.0.2.tgz", - "integrity": "sha512-33Rnf821Y54OAloav0PGNWHlbtEorXpjwchnToyyWbec10X74FOW7hGfvrXLGz7xOe2dz0uo9JVFAHHj/2B5pg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.1.2.tgz", + "integrity": "sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "diff-sequences": "^29.0.0", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus/node_modules/jest-matcher-utils": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.0.2.tgz", - "integrity": "sha512-SxtTiI2qLJHFtOz/bySStCnwCvISAuxQ/grS+74dfTy5AuJw3Sgj9TVUvskcnImTfpzLoMCDJseRaeRrVYbAOA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.1.2.tgz", + "integrity": "sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "jest-diff": "^29.1.2", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -13162,22 +13287,36 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/jest-circus/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus/node_modules/pretty-format/node_modules/ansi-styles": { @@ -13193,9 +13332,9 @@ } }, "node_modules/jest-circus/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/jest-circus/node_modules/supports-color": { @@ -13211,21 +13350,21 @@ } }, "node_modules/jest-cli": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.0.3.tgz", - "integrity": "sha512-NCPTEONCnhYGo1qzPP4OOcGF04YasM5GZSwQLI1HtEluxa3ct4U65IbZs6DSRt8XN1Rq0jhXwv02m5lHB28Uyg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.1.2.tgz", + "integrity": "sha512-vsvBfQ7oS2o4MJdAH+4u9z76Vw5Q8WBQF5MchDbkylNknZdrPTX1Ix7YRJyTlOWqRaS7ue/cEAn+E4V1MWyMzw==", "dev": true, "dependencies": { - "@jest/core": "^28.0.3", - "@jest/test-result": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/core": "^29.1.2", + "@jest/test-result": "^29.1.2", + "@jest/types": "^29.1.2", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^28.0.3", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-config": "^29.1.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -13233,7 +13372,7 @@ "jest": "bin/jest.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -13245,12 +13384,12 @@ } }, "node_modules/jest-cli/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -13258,13 +13397,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-cli/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -13323,21 +13462,21 @@ } }, "node_modules/jest-cli/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-cli/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -13345,39 +13484,38 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-cli/node_modules/jest-validate": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.0.2.tgz", - "integrity": "sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", + "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.0.0", "leven": "^3.1.0", - "pretty-format": "^28.0.2" + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-cli/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-cli/node_modules/pretty-format/node_modules/ansi-styles": { @@ -13393,9 +13531,9 @@ } }, "node_modules/jest-cli/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/jest-cli/node_modules/supports-color": { @@ -13411,36 +13549,36 @@ } }, "node_modules/jest-config": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.0.3.tgz", - "integrity": "sha512-3gWOEHwGpNhyYOk9vnUMv94x15QcdjACm7A3lERaluwnyD6d1WZWe9RFCShgIXVOHzRfG1hWxsI2U0gKKSGgDQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.1.2.tgz", + "integrity": "sha512-EC3Zi86HJUOz+2YWQcJYQXlf0zuBhJoeyxLM6vb6qJsVmpP7KcCP1JnyF0iaqTaXdBP8Rlwsvs7hnKWQWWLwwA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^28.0.2", - "@jest/types": "^28.0.2", - "babel-jest": "^28.0.3", + "@jest/test-sequencer": "^29.1.2", + "@jest/types": "^29.1.2", + "babel-jest": "^29.1.2", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^28.0.3", - "jest-environment-node": "^28.0.2", - "jest-get-type": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.0.3", - "jest-runner": "^28.0.3", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-circus": "^29.1.2", + "jest-environment-node": "^29.1.2", + "jest-get-type": "^29.0.0", + "jest-regex-util": "^29.0.0", + "jest-resolve": "^29.1.2", + "jest-runner": "^29.1.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^28.0.2", + "pretty-format": "^29.1.2", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@types/node": "*", @@ -13456,12 +13594,12 @@ } }, "node_modules/jest-config/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -13469,13 +13607,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-config/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -13534,75 +13672,75 @@ } }, "node_modules/jest-config/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-config/node_modules/jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "node_modules/jest-config/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-config/node_modules/jest-resolve": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.0.3.tgz", - "integrity": "sha512-lfgjd9JhEjpjIN3HLUfdysdK+A7ePQoYmd7WL9DUEWqdnngb1rF56eee6iDXJxl/3eSolpP43VD7VrhjL3NsoQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.1.2.tgz", + "integrity": "sha512-7fcOr+k7UYSVRJYhSmJHIid3AnDBcLQX3VmT9OSbPWsWz1MfT7bcoerMhADKGvKCoMpOHUQaDHtQoNp/P9JMGg==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", + "jest-haste-map": "^29.1.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-config/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -13610,38 +13748,39 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-config/node_modules/jest-validate": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.0.2.tgz", - "integrity": "sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", + "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.0.0", "leven": "^3.1.0", - "pretty-format": "^28.0.2" + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-config/node_modules/jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-config/node_modules/jest-worker/node_modules/supports-color": { @@ -13660,18 +13799,17 @@ } }, "node_modules/jest-config/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-config/node_modules/pretty-format/node_modules/ansi-styles": { @@ -13687,23 +13825,11 @@ } }, "node_modules/jest-config/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, - "node_modules/jest-config/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/jest-config/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -13796,40 +13922,40 @@ } }, "node_modules/jest-docblock": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.0.2.tgz", - "integrity": "sha512-FH10WWw5NxLoeSdQlJwu+MTiv60aXV/t8KEwIRGEv74WARE1cXIqh1vGdy2CraHuWOOrnzTWj/azQKqW4fO7xg==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.0.0.tgz", + "integrity": "sha512-s5Kpra/kLzbqu9dEjov30kj1n4tfu3e7Pl8v+f8jOkeWNqM6Ds8jRaJfZow3ducoQUrf2Z4rs2N5S3zXnb83gw==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.0.2.tgz", - "integrity": "sha512-/W5Wc0b+ipR36kDaLngdVEJ/5UYPOITK7rW0djTlCCQdMuWpCFJweMW4TzAoJ6GiRrljPL8FwiyOSoSHKrda2w==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.1.2.tgz", + "integrity": "sha512-AmTQp9b2etNeEwMyr4jc0Ql/LIX/dhbgP21gHAizya2X6rUspHn2gysMXaj6iwWuOJ2sYRgP8c1P4cXswgvS1A==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "jest-util": "^28.0.2", - "pretty-format": "^28.0.2" + "jest-get-type": "^29.0.0", + "jest-util": "^29.1.2", + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -13837,13 +13963,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -13902,21 +14028,21 @@ } }, "node_modules/jest-each/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -13924,22 +14050,21 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each/node_modules/pretty-format/node_modules/ansi-styles": { @@ -13955,9 +14080,9 @@ } }, "node_modules/jest-each/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/jest-each/node_modules/supports-color": { @@ -13973,31 +14098,31 @@ } }, "node_modules/jest-environment-jsdom": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-28.0.2.tgz", - "integrity": "sha512-rQhgV9reB6Id7VPa5jEkKx80Ppa/I6C7vKTMnceBS+d/rt+aTfbxbK/P4HRLMLE8KKsETszPpzYtGgsa8xMg7g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.1.2.tgz", + "integrity": "sha512-D+XNIKia5+uDjSMwL/G1l6N9MCb7LymKI8FpcLo7kkISjc/Sa9w+dXXEa7u1Wijo3f8sVLqfxdGqYtRhmca+Xw==", "dev": true, "dependencies": { - "@jest/environment": "^28.0.2", - "@jest/fake-timers": "^28.0.2", - "@jest/types": "^28.0.2", - "@types/jsdom": "^16.2.4", + "@jest/environment": "^29.1.2", + "@jest/fake-timers": "^29.1.2", + "@jest/types": "^29.1.2", + "@types/jsdom": "^20.0.0", "@types/node": "*", - "jest-mock": "^28.0.2", - "jest-util": "^28.0.2", - "jsdom": "^19.0.0" + "jest-mock": "^29.1.2", + "jest-util": "^29.1.2", + "jsdom": "^20.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-jsdom/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -14005,13 +14130,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-jsdom/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -14070,12 +14195,12 @@ } }, "node_modules/jest-environment-jsdom/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -14083,7 +14208,7 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-jsdom/node_modules/supports-color": { @@ -14099,29 +14224,29 @@ } }, "node_modules/jest-environment-node": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.0.2.tgz", - "integrity": "sha512-o9u5UHZ+NCuIoa44KEF0Behhsz/p1wMm0WumsZfWR1k4IVoWSt3aN0BavSC5dd26VxSGQvkrCnJxxOzhhUEG3Q==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.1.2.tgz", + "integrity": "sha512-C59yVbdpY8682u6k/lh8SUMDJPbOyCHOTgLVVi1USWFxtNV+J8fyIwzkg+RJIVI30EKhKiAGNxYaFr3z6eyNhQ==", "dev": true, "dependencies": { - "@jest/environment": "^28.0.2", - "@jest/fake-timers": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/environment": "^29.1.2", + "@jest/fake-timers": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", - "jest-mock": "^28.0.2", - "jest-util": "^28.0.2" + "jest-mock": "^29.1.2", + "jest-util": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -14129,13 +14254,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -14194,12 +14319,12 @@ } }, "node_modules/jest-environment-node/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -14207,7 +14332,7 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node/node_modules/supports-color": { @@ -14669,16 +14794,16 @@ } }, "node_modules/jest-leak-detector": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.0.2.tgz", - "integrity": "sha512-UGaSPYtxKXl/YKacq6juRAKmMp1z2os8NaU8PSC+xvNikmu3wF6QFrXrihMM4hXeMr9HuNotBrQZHmzDY8KIBQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.1.2.tgz", + "integrity": "sha512-TG5gAZJpgmZtjb6oWxBLf2N6CfQ73iwCe6cofu/Uqv9iiAm6g502CAnGtxQaTfpHECBdVEMRBhomSXeLnoKjiQ==", "dev": true, "dependencies": { - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-leak-detector/node_modules/ansi-styles": { @@ -14694,33 +14819,32 @@ } }, "node_modules/jest-leak-detector/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-leak-detector/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/jest-matcher-utils": { @@ -14803,32 +14927,32 @@ } }, "node_modules/jest-message-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.0.2.tgz", - "integrity": "sha512-knK7XyojvwYh1XiF2wmVdskgM/uN11KsjcEWWHfnMZNEdwXCrqB4sCBO94F4cfiAwCS8WFV6CDixDwPlMh/wdA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.1.2.tgz", + "integrity": "sha512-9oJ2Os+Qh6IlxLpmvshVbGUiSkZVc2FK+uGOm6tghafnB2RyjKAxMZhtxThRMxfX1J1SOMhTn9oK3/MutRWQJQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^28.0.2", + "pretty-format": "^29.1.2", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -14836,13 +14960,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -14901,18 +15025,17 @@ } }, "node_modules/jest-message-util/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util/node_modules/pretty-format/node_modules/ansi-styles": { @@ -14928,9 +15051,9 @@ } }, "node_modules/jest-message-util/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/jest-message-util/node_modules/supports-color": { @@ -14946,25 +15069,26 @@ } }, "node_modules/jest-mock": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.0.2.tgz", - "integrity": "sha512-vfnJ4zXRB0i24jOTGtQJyl26JKsgBKtqRlCnsrORZbG06FToSSn33h2x/bmE8XxqxkLWdZBRo+/65l8Vi3nD+g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.1.2.tgz", + "integrity": "sha512-PFDAdjjWbjPUtQPkQufvniXIS3N9Tv7tbibePEjIIprzjgo0qQlyUiVMrT4vL8FaSJo1QXifQUOuPH3HQC/aMA==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", - "@types/node": "*" + "@jest/types": "^29.1.2", + "@types/node": "*", + "jest-util": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-mock/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -14972,13 +15096,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-mock/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -15036,6 +15160,23 @@ "node": ">=8" } }, + "node_modules/jest-mock/node_modules/jest-util": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.1.2", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-mock/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -15096,25 +15237,25 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.0.3.tgz", - "integrity": "sha512-lCgHMm0/5p0qHemrOzm7kI6JDei28xJwIf7XOEcv1HeAVHnsON8B8jO/woqlU+/GcOXb58ymieYqhk3zjGWnvQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.1.2.tgz", + "integrity": "sha512-44yYi+yHqNmH3OoWZvPgmeeiwKxhKV/0CfrzaKLSkZG9gT973PX8i+m8j6pDrTYhhHoiKfF3YUFg/6AeuHw4HQ==", "dev": true, "dependencies": { - "jest-regex-util": "^28.0.2", - "jest-snapshot": "^28.0.3" + "jest-regex-util": "^29.0.0", + "jest-snapshot": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve-dependencies/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve/node_modules/ansi-styles": { @@ -15182,44 +15323,44 @@ } }, "node_modules/jest-runner": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.0.3.tgz", - "integrity": "sha512-4OsHMjBLtYUWCENucAQ4Za0jGfEbOFi/Fusv6dzUuaweqx8apb4+5p2LR2yvgF4StFulmxyC238tGLftfu+zBA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.1.2.tgz", + "integrity": "sha512-yy3LEWw8KuBCmg7sCGDIqKwJlULBuNIQa2eFSVgVASWdXbMYZ9H/X0tnXt70XFoGf92W2sOQDOIFAA6f2BG04Q==", "dev": true, "dependencies": { - "@jest/console": "^28.0.2", - "@jest/environment": "^28.0.2", - "@jest/test-result": "^28.0.2", - "@jest/transform": "^28.0.3", - "@jest/types": "^28.0.2", + "@jest/console": "^29.1.2", + "@jest/environment": "^29.1.2", + "@jest/test-result": "^29.1.2", + "@jest/transform": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.10.2", "graceful-fs": "^4.2.9", - "jest-docblock": "^28.0.2", - "jest-environment-node": "^28.0.2", - "jest-haste-map": "^28.0.2", - "jest-leak-detector": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-resolve": "^28.0.3", - "jest-runtime": "^28.0.3", - "jest-util": "^28.0.2", - "jest-watcher": "^28.0.2", - "jest-worker": "^28.0.2", - "source-map-support": "0.5.13", - "throat": "^6.0.1" + "jest-docblock": "^29.0.0", + "jest-environment-node": "^29.1.2", + "jest-haste-map": "^29.1.2", + "jest-leak-detector": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-resolve": "^29.1.2", + "jest-runtime": "^29.1.2", + "jest-util": "^29.1.2", + "jest-watcher": "^29.1.2", + "jest-worker": "^29.1.2", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -15227,13 +15368,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -15292,75 +15433,75 @@ } }, "node_modules/jest-runner/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "node_modules/jest-runner/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/jest-resolve": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.0.3.tgz", - "integrity": "sha512-lfgjd9JhEjpjIN3HLUfdysdK+A7ePQoYmd7WL9DUEWqdnngb1rF56eee6iDXJxl/3eSolpP43VD7VrhjL3NsoQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.1.2.tgz", + "integrity": "sha512-7fcOr+k7UYSVRJYhSmJHIid3AnDBcLQX3VmT9OSbPWsWz1MfT7bcoerMhADKGvKCoMpOHUQaDHtQoNp/P9JMGg==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", + "jest-haste-map": "^29.1.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -15368,38 +15509,39 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/jest-validate": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.0.2.tgz", - "integrity": "sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", + "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.0.0", "leven": "^3.1.0", - "pretty-format": "^28.0.2" + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/jest-worker/node_modules/supports-color": { @@ -15417,19 +15559,33 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-runner/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "node_modules/jest-runner/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runner/node_modules/pretty-format": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/pretty-format/node_modules/ansi-styles": { @@ -15445,9 +15601,9 @@ } }, "node_modules/jest-runner/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/jest-runner/node_modules/source-map-support": { @@ -15473,45 +15629,45 @@ } }, "node_modules/jest-runtime": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.0.3.tgz", - "integrity": "sha512-7FtPUmvbZEHLOdjsF6dyHg5Pe4E0DU+f3Vvv8BPzVR7mQA6nFR4clQYLAPyJGnsUvN8WRWn+b5a5SVwnj1WaGg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.1.2.tgz", + "integrity": "sha512-jr8VJLIf+cYc+8hbrpt412n5jX3tiXmpPSYTGnwcvNemY+EOuLNiYnHJ3Kp25rkaAcTWOEI4ZdOIQcwYcXIAZw==", "dev": true, "dependencies": { - "@jest/environment": "^28.0.2", - "@jest/fake-timers": "^28.0.2", - "@jest/globals": "^28.0.3", - "@jest/source-map": "^28.0.2", - "@jest/test-result": "^28.0.2", - "@jest/transform": "^28.0.3", - "@jest/types": "^28.0.2", + "@jest/environment": "^29.1.2", + "@jest/fake-timers": "^29.1.2", + "@jest/globals": "^29.1.2", + "@jest/source-map": "^29.0.0", + "@jest/test-result": "^29.1.2", + "@jest/transform": "^29.1.2", + "@jest/types": "^29.1.2", + "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-mock": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.0.3", - "jest-snapshot": "^28.0.3", - "jest-util": "^28.0.2", + "jest-haste-map": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-mock": "^29.1.2", + "jest-regex-util": "^29.0.0", + "jest-resolve": "^29.1.2", + "jest-snapshot": "^29.1.2", + "jest-util": "^29.1.2", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -15519,13 +15675,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -15584,75 +15740,75 @@ } }, "node_modules/jest-runtime/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "node_modules/jest-runtime/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/jest-resolve": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.0.3.tgz", - "integrity": "sha512-lfgjd9JhEjpjIN3HLUfdysdK+A7ePQoYmd7WL9DUEWqdnngb1rF56eee6iDXJxl/3eSolpP43VD7VrhjL3NsoQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.1.2.tgz", + "integrity": "sha512-7fcOr+k7UYSVRJYhSmJHIid3AnDBcLQX3VmT9OSbPWsWz1MfT7bcoerMhADKGvKCoMpOHUQaDHtQoNp/P9JMGg==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", + "jest-haste-map": "^29.1.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -15660,38 +15816,39 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/jest-validate": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.0.2.tgz", - "integrity": "sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", + "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.0.0", "leven": "^3.1.0", - "pretty-format": "^28.0.2" + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/jest-worker/node_modules/supports-color": { @@ -15710,18 +15867,17 @@ } }, "node_modules/jest-runtime/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/pretty-format/node_modules/ansi-styles": { @@ -15737,9 +15893,9 @@ } }, "node_modules/jest-runtime/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/jest-runtime/node_modules/strip-bom": { @@ -15777,46 +15933,47 @@ } }, "node_modules/jest-snapshot": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.0.3.tgz", - "integrity": "sha512-nVzAAIlAbrMuvVUrS1YxmAeo1TfSsDDU+K5wv/Ow56MBp+L+Y71ksAbwRp3kGCgZAz4oOXcAMPAwtT9Yh1hlQQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.1.2.tgz", + "integrity": "sha512-rYFomGpVMdBlfwTYxkUp3sjD6usptvZcONFYNqVlaz4EpHPnDvlWjvmOQ9OCSNKqYZqLM2aS3wq01tWujLg7gg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^28.0.2", - "@jest/transform": "^28.0.3", - "@jest/types": "^28.0.2", + "@jest/expect-utils": "^29.1.2", + "@jest/transform": "^29.1.2", + "@jest/types": "^29.1.2", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^28.0.2", + "expect": "^29.1.2", "graceful-fs": "^4.2.9", - "jest-diff": "^28.0.2", - "jest-get-type": "^28.0.2", - "jest-haste-map": "^28.0.2", - "jest-matcher-utils": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-util": "^28.0.2", + "jest-diff": "^29.1.2", + "jest-get-type": "^29.0.0", + "jest-haste-map": "^29.1.2", + "jest-matcher-utils": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-util": "^29.1.2", "natural-compare": "^1.4.0", - "pretty-format": "^28.0.2", + "pretty-format": "^29.1.2", "semver": "^7.3.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -15824,13 +15981,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -15880,12 +16037,12 @@ } }, "node_modules/jest-snapshot/node_modules/diff-sequences": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.0.2.tgz", - "integrity": "sha512-YtEoNynLDFCRznv/XDalsKGSZDoj0U5kLnXvY0JSq3nBboRrZXjD81+eSiwi+nzcZDwedMmcowcxNwwgFW23mQ==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.0.0.tgz", + "integrity": "sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/has-flag": { @@ -15898,85 +16055,85 @@ } }, "node_modules/jest-snapshot/node_modules/jest-diff": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.0.2.tgz", - "integrity": "sha512-33Rnf821Y54OAloav0PGNWHlbtEorXpjwchnToyyWbec10X74FOW7hGfvrXLGz7xOe2dz0uo9JVFAHHj/2B5pg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.1.2.tgz", + "integrity": "sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "diff-sequences": "^29.0.0", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "node_modules/jest-snapshot/node_modules/jest-matcher-utils": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.0.2.tgz", - "integrity": "sha512-SxtTiI2qLJHFtOz/bySStCnwCvISAuxQ/grS+74dfTy5AuJw3Sgj9TVUvskcnImTfpzLoMCDJseRaeRrVYbAOA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.1.2.tgz", + "integrity": "sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "jest-diff": "^29.1.2", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -15984,21 +16141,22 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-worker/node_modules/supports-color": { @@ -16017,18 +16175,17 @@ } }, "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/pretty-format/node_modules/ansi-styles": { @@ -16044,15 +16201,15 @@ } }, "node_modules/jest-snapshot/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -16238,190 +16395,32 @@ "node": ">=8" } }, - "node_modules/jest-watch-typeahead": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", - "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.1", - "chalk": "^4.0.0", - "jest-regex-util": "^28.0.0", - "jest-watcher": "^28.0.0", - "slash": "^4.0.0", - "string-length": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "jest": "^27.0.0 || ^28.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/char-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", - "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", - "dev": true, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/jest-watch-typeahead/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", - "dev": true, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watch-typeahead/node_modules/string-length": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", - "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", - "dev": true, - "dependencies": { - "char-regex": "^2.0.0", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/supports-color": { - "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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-watcher": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.0.2.tgz", - "integrity": "sha512-uIVJLpQ/5VTGQWBiBatHsi7jrCqHjHl0e0dFHMWzwuIfUbdW/muk0DtSr0fteY2T7QTFylv+7a5Rm8sBKrE12Q==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.1.2.tgz", + "integrity": "sha512-6JUIUKVdAvcxC6bM8/dMgqY2N4lbT+jZVsxh0hCJRbwkIEnbr/aPjMQ28fNDI5lB51Klh00MWZZeVf27KBUj5w==", "dev": true, "dependencies": { - "@jest/test-result": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/test-result": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.10.2", - "jest-util": "^28.0.2", + "jest-util": "^29.1.2", "string-length": "^4.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-watcher/node_modules/@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -16429,13 +16428,13 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-watcher/node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -16494,12 +16493,12 @@ } }, "node_modules/jest-watcher/node_modules/jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "dependencies": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -16507,7 +16506,7 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-watcher/node_modules/supports-color": { @@ -16557,6 +16556,102 @@ "node": ">=8" } }, + "node_modules/jest/node_modules/@jest/types": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.0.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest/node_modules/@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest/node_modules/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, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest/node_modules/supports-color": { + "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, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-sdsl": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", + "dev": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz", @@ -16576,41 +16671,40 @@ } }, "node_modules/jsdom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz", - "integrity": "sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A==", + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", "dev": true, "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.5.0", - "acorn-globals": "^6.0.0", + "abab": "^2.0.6", + "acorn": "^8.8.0", + "acorn-globals": "^7.0.0", "cssom": "^0.5.0", "cssstyle": "^2.3.0", - "data-urls": "^3.0.1", - "decimal.js": "^10.3.1", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.1", "domexception": "^4.0.0", "escodegen": "^2.0.0", "form-data": "^4.0.0", "html-encoding-sniffer": "^3.0.0", "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", + "tough-cookie": "^4.1.2", "w3c-xmlserializer": "^3.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^2.0.0", "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^10.0.0", - "ws": "^8.2.3", + "whatwg-url": "^11.0.0", + "ws": "^8.9.0", "xml-name-validator": "^4.0.0" }, "engines": { - "node": ">=12" + "node": ">=14" }, "peerDependencies": { "canvas": "^2.5.0" @@ -16622,9 +16716,9 @@ } }, "node_modules/jsdom/node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -16633,11 +16727,36 @@ "node": ">=0.4.0" } }, - "node_modules/jsdom/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true + "node_modules/jsdom/node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/jsdom/node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jsdom/node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } }, "node_modules/jsesc": { "version": "2.5.2", @@ -16651,12 +16770,6 @@ "node": ">=4" } }, - "node_modules/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 - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -16718,6 +16831,15 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -16797,9 +16919,9 @@ } }, "node_modules/leaflet": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.8.0.tgz", - "integrity": "sha512-gwhMjFCQiYs3x/Sf+d49f10ERXaEFCPr+nVTryhAW8DWbMGqJqt9G4XuIaHmFW08zYvhgdzqXGr8AlW8v8dQkA==" + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.2.tgz", + "integrity": "sha512-Kc77HQvWO+y9y2oIs3dn5h5sy2kr3j41ewdqCMEUA4N89lgfUUfOBy7wnnHEstDpefiGFObq12FdopGRMx4J7g==" }, "node_modules/leven": { "version": "3.1.0", @@ -16848,9 +16970,9 @@ } }, "node_modules/loader-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", - "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", "dev": true, "engines": { "node": ">= 12.13.0" @@ -16930,105 +17052,41 @@ "dev": true }, "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/log4js": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.2.tgz", - "integrity": "sha512-k80cggS2sZQLBwllpT1p06GtfvzMmSdUCkW96f0Hj83rKGJDAu2vZjt9B9ag2vx8Zz1IXzxoLgqvRJCdMKybGg==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.6.1.tgz", + "integrity": "sha512-J8VYFH2UQq/xucdNu71io4Fo+purYYudyErgBbswWKO0MC6QVOERRomt5su/z6d3RJSmLyTGmXl3Q/XjKCf+/A==", "dev": true, "dependencies": { - "date-format": "^4.0.4", - "debug": "^4.3.3", - "flatted": "^3.2.5", + "date-format": "^4.0.13", + "debug": "^4.3.4", + "flatted": "^3.2.6", "rfdc": "^1.3.0", - "streamroller": "^3.0.4" + "streamroller": "^3.1.2" }, "engines": { "node": ">=8.0" } }, "node_modules/log4js/node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -17330,9 +17388,9 @@ "dev": true }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -17408,9 +17466,9 @@ "dev": true }, "node_modules/mutation-testing-elements": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/mutation-testing-elements/-/mutation-testing-elements-1.7.10.tgz", - "integrity": "sha512-qejt4InSYzFGhN84+mbpj96aKl41g0IRTIEVuOepKgcdMdrmb2dhXBB5Mysncmz7NF/VzXSTGutdQFTz9johfw==", + "version": "1.7.12", + "resolved": "https://registry.npmjs.org/mutation-testing-elements/-/mutation-testing-elements-1.7.12.tgz", + "integrity": "sha512-6L5PiREMKWirDOVoMVpJtq4r1MfHZgme78PFQl9W59YQq/rqmHpYAcwrdUYikPVYASp4r91ZupiKlFHgCPiVBw==", "dev": true }, "node_modules/mutation-testing-metrics": { @@ -17467,12 +17525,6 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=", - "dev": true - }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -17505,9 +17557,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, "node_modules/normalize-package-data": { @@ -17558,24 +17610,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-selector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", - "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", - "dev": true - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", @@ -17586,9 +17620,9 @@ } }, "node_modules/nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", "dev": true }, "node_modules/object-assign": { @@ -17612,7 +17646,6 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -17802,18 +17835,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/open/node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -17832,90 +17853,53 @@ } }, "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz", + "integrity": "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==", "dev": true, "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", + "bl": "^5.0.0", + "chalk": "^5.0.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.6.1", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.1.0", + "log-symbols": "^5.1.0", + "strip-ansi": "^7.0.1", "wcwidth": "^1.0.1" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ora/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/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, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/ora/node_modules/mimic-fn": { @@ -17943,28 +17927,34 @@ } }, "node_modules/ora/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/original": { @@ -17987,15 +17977,6 @@ "node": ">=0.10.0" } }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/p-limit": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", @@ -18106,6 +18087,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse5": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", + "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -18152,24 +18157,21 @@ "node_modules/path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", "dev": true }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/path-parse": { "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 }, + "node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -18350,9 +18352,9 @@ "dev": true }, "node_modules/postcss": { - "version": "8.4.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", - "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", + "version": "8.4.17", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz", + "integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==", "dev": true, "funding": [ { @@ -18365,7 +18367,7 @@ } ], "dependencies": { - "nanoid": "^3.3.3", + "nanoid": "^3.3.4", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -19152,16 +19154,6 @@ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz", @@ -19182,9 +19174,12 @@ } }, "node_modules/qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" }, @@ -19196,9 +19191,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true, - "optional": true, - "peer": true + "dev": true }, "node_modules/quick-lru": { "version": "4.0.1", @@ -19235,7 +19228,7 @@ "node_modules/range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", "dev": true, "engines": { "node": ">= 0.6" @@ -19267,8 +19260,8 @@ }, "node_modules/rc": { "version": "1.2.8", - "resolved": "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz", - "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "dependencies": { "deep-extend": "^0.6.0", @@ -19280,10 +19273,19 @@ "rc": "cli.js" } }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.1.0.tgz", - "integrity": "sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "dependencies": { "loose-envify": "^1.1.0" }, @@ -19320,18 +19322,18 @@ } }, "node_modules/react-chartjs-2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-4.1.0.tgz", - "integrity": "sha512-AsUihxEp8Jm1oBhbEovE+w50m9PVNhz1sfwEIT4hZduRC0m14gHWHd0cUaxkFDb8HNkdMIGzsNlmVqKiOpU74g==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-4.3.1.tgz", + "integrity": "sha512-5i3mjP6tU7QSn0jvb8I4hudTzHJqS8l00ORJnVwI2sYu0ihpj83Lv2YzfxunfxTZkscKvZu2F2w9LkwNBhj6xA==", "peerDependencies": { "chart.js": "^3.5.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/react-colorful": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.5.1.tgz", - "integrity": "sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" @@ -19563,23 +19565,15 @@ } }, "node_modules/react-dom": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.1.0.tgz", - "integrity": "sha512-fU1Txz7Budmvamp7bshe4Zi32d0ll7ect+ccxNu9FlObT605GOEB8BfO4tmRJ39R5Zj831VCpvQ05QPBW5yb+w==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "dependencies": { "loose-envify": "^1.1.0", - "scheduler": "^0.22.0" + "scheduler": "^0.23.0" }, "peerDependencies": { - "react": "^18.1.0" - } - }, - "node_modules/react-dom/node_modules/scheduler": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.22.0.tgz", - "integrity": "sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ==", - "dependencies": { - "loose-envify": "^1.1.0" + "react": "^18.2.0" } }, "node_modules/react-error-overlay": { @@ -19608,22 +19602,22 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-leaflet": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.0.0.tgz", - "integrity": "sha512-qJJvoCNe12XHSWVUwhXYmMObPoSYy8h/hn0aDNvcBuq3O8zmVI5S2RdabhaDg/iWMCJ2jbCWZWtIU5VtztO9sg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.1.0.tgz", + "integrity": "sha512-i+V9pX5lywJ48O2+K3USeeTdYLIhxnLMweH+YLd/UPqVIj3uKzE3Q29bzt83PBtViyZmxDlulzC6uoR3JLiE9A==", "dependencies": { - "@react-leaflet/core": "^2.0.0" + "@react-leaflet/core": "^2.1.0" }, "peerDependencies": { - "leaflet": "^1.8.0", + "leaflet": "^1.9.0", "react": "^18.0.0", "react-dom": "^18.0.0" } }, "node_modules/react-redux": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.1.tgz", - "integrity": "sha512-LMZMsPY4DYdZfLJgd7i79n5Kps5N9XVLCJJeWAaPYTV+Eah2zTuBjTxKtNEbjiyitbq80/eIkm55CYSLqAub3w==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.4.tgz", + "integrity": "sha512-yMfQ7mX6bWuicz2fids6cR1YT59VTuT8MKyyE310wJQlINKENCeT1UcPdEiX6znI5tF8zXyJ/VYvDgeGuaaNwQ==", "dependencies": { "@babel/runtime": "^7.12.1", "@types/hoist-non-react-statics": "^3.3.1", @@ -19673,23 +19667,29 @@ } }, "node_modules/react-router": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", - "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.1.tgz", + "integrity": "sha512-OJASKp5AykDWFewgWUim1vlLr7yfD4vO/h+bSgcP/ix8Md+LMHuAjovA74MQfsfhQJGGN1nHRhwS5qQQbbBt3A==", "dependencies": { - "history": "^5.2.0" + "@remix-run/router": "1.0.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { "react": ">=16.8" } }, "node_modules/react-router-dom": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", - "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.1.tgz", + "integrity": "sha512-MY7NJCrGNVJtGp8ODMOBHu20UaIkmwD2V3YsAOUQoCXFk7Ppdwf55RdcGyrSj+ycSL9Uiwrb3gTLYSnzcRoXww==", "dependencies": { - "history": "^5.2.0", - "react-router": "6.3.0" + "@remix-run/router": "1.0.1", + "react-router": "6.4.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { "react": ">=16.8", @@ -19923,6 +19923,18 @@ } } }, + "node_modules/react-scripts/node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, "node_modules/react-scripts/node_modules/@jest/source-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", @@ -20076,6 +20088,15 @@ "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", "dev": true }, + "node_modules/react-scripts/node_modules/@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, "node_modules/react-scripts/node_modules/acorn": { "version": "8.7.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", @@ -21126,6 +21147,287 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "jest": "^27.0.0 || ^28.0.0" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/@jest/console/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "dev": true, + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/jest-message-util/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "dev": true, + "dependencies": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", + "dev": true, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/react-scripts/node_modules/jest-watch-typeahead/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/react-scripts/node_modules/jest-watcher": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", @@ -21223,9 +21525,9 @@ } }, "node_modules/react-scripts/node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -21780,6 +22082,12 @@ "renderkid": "^3.0.0" } }, + "node_modules/react-scripts/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, "node_modules/react-scripts/node_modules/renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -21890,18 +22198,6 @@ "node": ">=8" } }, - "node_modules/react-scripts/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/react-scripts/node_modules/style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -22190,9 +22486,9 @@ } }, "node_modules/reactstrap": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-9.0.1.tgz", - "integrity": "sha512-89VOv7SRlAlpS7RwXhzOQkSWkuhBR8LBsPGfNHifNL3WhtNP9y1sBdTcTYyH1ee2QtI8zRdwD0T5I/blHiwemg==", + "version": "9.1.4", + "resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-9.1.4.tgz", + "integrity": "sha512-kn+Ex58V4tZatogn472n5fkgvCkXwhQvlqCRGTjpM1MzkD9wv0rp5W0VcM60purpdtzkud2ku6KHvJrqYqnv0w==", "dependencies": { "@babel/runtime": "^7.12.5", "@popperjs/core": "^2.6.0", @@ -22370,15 +22666,15 @@ } }, "node_modules/recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", "dev": true, "dependencies": { - "minimatch": "3.0.4" + "minimatch": "^3.0.5" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, "node_modules/redent": { @@ -22403,17 +22699,17 @@ } }, "node_modules/redux-localstorage-simple": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/redux-localstorage-simple/-/redux-localstorage-simple-2.4.1.tgz", - "integrity": "sha512-Oij3OAPukQVNqHwakfOXWGAcv254HvFtePIyZQY3tfomG8ruz4BV5FL4WytO4Pz8Ja7i3r9cCTEXvnzgv1xCJg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/redux-localstorage-simple/-/redux-localstorage-simple-2.5.1.tgz", + "integrity": "sha512-8HbqBzHoZ4nfL8qyELt4hLd9hNmESCvmXTEBk2mGT23lX8/miJbXz4ZGIF7Eoa1UHikjv+bne3pjC95ub737vA==", "dependencies": { "merge": "2.1.1" } }, "node_modules/redux-thunk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", "peerDependencies": { "redux": "^4" } @@ -22503,8 +22799,8 @@ }, "node_modules/registry-auth-token": { "version": "3.3.2", - "resolved": "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha1-hR/UkDjuy1hpERFa+EUmDuyYPyA=", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", "dev": true, "dependencies": { "rc": "^1.1.6", @@ -22514,7 +22810,7 @@ "node_modules/registry-url": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", "dev": true, "dependencies": { "rc": "^1.0.1" @@ -22583,6 +22879,11 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "node_modules/reselect": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", + "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==" + }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", @@ -22674,9 +22975,9 @@ } }, "node_modules/resolve-url-loader/node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -22857,9 +23158,9 @@ "dev": true }, "node_modules/sass": { - "version": "1.49.9", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.9.tgz", - "integrity": "sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A==", + "version": "1.55.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.55.0.tgz", + "integrity": "sha512-Pk+PMy7OGLs9WaxZGJMn7S96dvlyVBwwtToX895WmCpAOr5YiJYEUJfiJidMuKb613z2xNWcXCHEuOvjZbqC6A==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -22891,6 +23192,14 @@ "node": ">=10" } }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/schema-utils": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", @@ -22985,36 +23294,41 @@ } }, "node_modules/serve": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/serve/-/serve-13.0.2.tgz", - "integrity": "sha512-71R6fKvNgKrqARAag6lYJNnxDzpH7DCNrMuvPY5PLVaC2PDhJsGTj/34o4o4tPWhTuLgEXqvgnAWbATQ9zGZTQ==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/serve/-/serve-14.1.1.tgz", + "integrity": "sha512-7RhRDEirZ7Qyee4QWhBHO9qRtjIGsIPGecDDPzNzlOsjDiZWcq36GS8FioVJAuJPVJBBDTsGp33WWOO4B9A82g==", "dev": true, "dependencies": { - "@zeit/schemas": "2.6.0", - "ajv": "6.12.6", - "arg": "2.0.0", - "boxen": "5.1.2", - "chalk": "2.4.1", - "clipboardy": "2.3.0", - "compression": "1.7.3", - "serve-handler": "6.1.3", - "update-check": "1.5.2" + "@zeit/schemas": "2.21.0", + "ajv": "8.11.0", + "arg": "5.0.2", + "boxen": "7.0.0", + "chalk": "5.0.1", + "chalk-template": "0.4.0", + "clipboardy": "3.0.0", + "compression": "1.7.4", + "is-port-reachable": "4.0.0", + "serve-handler": "6.1.5", + "update-check": "1.5.4" }, "bin": { - "serve": "bin/serve.js" + "serve": "build/main.js" + }, + "engines": { + "node": ">= 14" } }, "node_modules/serve-handler": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", - "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", "dev": true, "dependencies": { "bytes": "3.0.0", "content-disposition": "0.5.2", "fast-url-parser": "1.1.3", "mime-types": "2.1.18", - "minimatch": "3.0.4", + "minimatch": "3.1.2", "path-is-inside": "1.0.2", "path-to-regexp": "2.2.1", "range-parser": "1.2.0" @@ -23041,12 +23355,6 @@ "node": ">= 0.6" } }, - "node_modules/serve-handler/node_modules/path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", - "dev": true - }, "node_modules/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -23101,47 +23409,34 @@ "node": ">= 0.8.0" } }, - "node_modules/serve/node_modules/chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "node_modules/serve/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=4" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/serve/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/shell-quote": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", @@ -23152,7 +23447,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -23459,15 +23753,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/specificity": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", - "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", - "dev": true, - "bin": { - "specificity": "bin/specificity" - } - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -23525,23 +23810,23 @@ } }, "node_modules/streamroller": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.4.tgz", - "integrity": "sha512-GI9NzeD+D88UFuIlJkKNDH/IsuR+qIN7Qh8EsmhoRZr9bQoehTraRgwtLUkZbpcAw+hLPfHOypmppz8YyGK68w==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.3.tgz", + "integrity": "sha512-CphIJyFx2SALGHeINanjFRKQ4l7x2c+rXYJ4BMq0gd+ZK0gi4VT8b+eHe2wi58x4UayBAKx4xtHpXT/ea1cz8w==", "dev": true, "dependencies": { - "date-format": "^4.0.4", - "debug": "^4.3.3", - "fs-extra": "^10.0.1" + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" }, "engines": { "node": ">=8.0" } }, "node_modules/streamroller/node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -23556,29 +23841,17 @@ } }, "node_modules/streamroller/node_modules/fs-extra": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", - "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "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, "dependencies": { "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/streamroller/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "node": ">=6 <7 || >=8" } }, "node_modules/streamroller/node_modules/ms": { @@ -23588,12 +23861,12 @@ "dev": true }, "node_modules/streamroller/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">= 4.0.0" } }, "node_modules/string_decoder": { @@ -23787,15 +24060,6 @@ "node": ">=10" } }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -23818,12 +24082,15 @@ } }, "node_modules/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=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/stryker-cli": { @@ -23918,21 +24185,20 @@ "dev": true }, "node_modules/stylelint": { - "version": "14.8.2", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.8.2.tgz", - "integrity": "sha512-tjDfexCYfoPdl/xcDJ9Fv+Ko9cvzbDnmdiaqEn3ovXHXasi/hbkt5tSjsiReQ+ENqnz0eltaX/AOO+AlzVdcNA==", + "version": "14.13.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.13.0.tgz", + "integrity": "sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==", "dev": true, "dependencies": { + "@csstools/selector-specificity": "^2.0.2", "balanced-match": "^2.0.0", - "colord": "^2.9.2", + "colord": "^2.9.3", "cosmiconfig": "^7.0.1", - "css-functions-list": "^3.0.1", + "css-functions-list": "^3.1.0", "debug": "^4.3.4", - "execall": "^2.0.0", - "fast-glob": "^3.2.11", - "fastest-levenshtein": "^1.0.12", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", "file-entry-cache": "^6.0.1", - "get-stdin": "^8.0.0", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -23946,24 +24212,22 @@ "meow": "^9.0.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", - "normalize-selector": "^0.2.0", "picocolors": "^1.0.0", - "postcss": "^8.4.13", + "postcss": "^8.4.16", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", - "specificity": "^0.4.1", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "style-search": "^0.1.0", - "supports-hyperlinks": "^2.2.0", + "supports-hyperlinks": "^2.3.0", "svg-tags": "^1.0.0", "table": "^6.8.0", "v8-compile-cache": "^2.3.0", - "write-file-atomic": "^4.0.1" + "write-file-atomic": "^4.0.2" }, "bin": { "stylelint": "bin/stylelint.js" @@ -24101,16 +24365,16 @@ } }, "node_modules/stylelint/node_modules/write-file-atomic": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz", - "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/supports-color": { @@ -24126,9 +24390,9 @@ } }, "node_modules/supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, "dependencies": { "has-flag": "^4.0.0", @@ -24347,12 +24611,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/tailwindcss/node_modules/arg": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", - "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", - "dev": true - }, "node_modules/tailwindcss/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -24742,14 +25000,15 @@ } }, "node_modules/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", "dev": true, "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", - "universalify": "^0.1.2" + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, "engines": { "node": ">=6" @@ -24936,9 +25195,9 @@ } }, "node_modules/typescript": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", - "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -25010,9 +25269,9 @@ } }, "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, "engines": { "node": ">= 4.0.0" @@ -25043,10 +25302,36 @@ "yarn": "*" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz", + "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/update-check": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.2.tgz", - "integrity": "sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", + "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", "dev": true, "dependencies": { "registry-auth-token": "3.3.2", @@ -25067,8 +25352,6 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, - "optional": true, - "peer": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -25133,12 +25416,12 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.0.tgz", - "integrity": "sha512-HcvgY/xaRm7isYmyx+lFKA4uQmfUbN0J4M0nNItvzTvH/iQ9kW5j/t4YSR+Ge323/lrgDAWJoF46tzGQHwBHFw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", + "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0" }, @@ -25204,9 +25487,9 @@ } }, "node_modules/watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", @@ -25228,16 +25511,16 @@ "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, "dependencies": { "defaults": "^1.0.3" } }, "node_modules/weapon-regex": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/weapon-regex/-/weapon-regex-0.6.0.tgz", - "integrity": "sha512-k1gh8cffl+uOEakFS3Ze32nBsoqmcXembTI3nNQMPMUKAr83YBShTrjYGyeVC9zNzW5Ac/+dcvk3PLYUtNtSEQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/weapon-regex/-/weapon-regex-1.0.3.tgz", + "integrity": "sha512-V8X6hPIzY1juvrSVREmtRhK9AHn/8c2z8XxaibESU+jyG/RinZ9x9x6aw8qEuFAi7R6Kl/EWGbU2Yq/9u6TTjw==", "dev": true }, "node_modules/webidl-conversions": { @@ -25250,9 +25533,9 @@ } }, "node_modules/webpack": { - "version": "5.70.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", - "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", + "version": "5.74.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", + "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -25260,24 +25543,24 @@ "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", + "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.2", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", + "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "bin": { @@ -25485,24 +25768,6 @@ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", "dev": true }, - "node_modules/webpack-dev-server/node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/webpack-dev-server/node_modules/del": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", @@ -25662,9 +25927,9 @@ "dev": true }, "node_modules/webpack/node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -25763,9 +26028,9 @@ } }, "node_modules/whatwg-url": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-10.0.0.tgz", - "integrity": "sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dev": true, "dependencies": { "tr46": "^3.0.0", @@ -25804,38 +26069,68 @@ } }, "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", "dev": true, "dependencies": { - "string-width": "^4.0.0" + "string-width": "^5.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/widest-line/node_modules/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==", + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, + "node_modules/widest-line/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, "node_modules/widest-line/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/word-wrap": { @@ -25857,6 +26152,12 @@ "workbox-core": "6.5.1" } }, + "node_modules/workbox-background-sync/node_modules/workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, "node_modules/workbox-broadcast-update": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.1.tgz", @@ -25866,6 +26167,12 @@ "workbox-core": "6.5.1" } }, + "node_modules/workbox-broadcast-update/node_modules/workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, "node_modules/workbox-build": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.1.tgz", @@ -26003,6 +26310,51 @@ "webidl-conversions": "^4.0.2" } }, + "node_modules/workbox-build/node_modules/workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, + "node_modules/workbox-build/node_modules/workbox-expiration": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.1.tgz", + "integrity": "sha512-iY/cTADAQATMmPkUBRmQdacqq0TJd2wMHimBQz+tRnPGHSMH+/BoLPABPnu7O7rT/g/s59CUYYRGxe3mEgoJCA==", + "dev": true, + "dependencies": { + "idb": "^6.1.4", + "workbox-core": "6.5.1" + } + }, + "node_modules/workbox-build/node_modules/workbox-precaching": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.1.tgz", + "integrity": "sha512-EzlPBxvmjGfE56YZzsT/vpVkpLG1XJhoplgXa5RPyVWLUL1LbwEAxhkrENElSS/R9tgiTw80IFwysidfUqLihg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.1", + "workbox-routing": "6.5.1", + "workbox-strategies": "6.5.1" + } + }, + "node_modules/workbox-build/node_modules/workbox-routing": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.1.tgz", + "integrity": "sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.1" + } + }, + "node_modules/workbox-build/node_modules/workbox-strategies": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.1.tgz", + "integrity": "sha512-JNaTXPy8wXzKkr+6za7/eJX9opoZk7UgY261I2kPxl80XQD8lMjz0vo9EOcBwvD72v3ZhGJbW84ZaDwFEhFvWA==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.1" + } + }, "node_modules/workbox-cacheable-response": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.1.tgz", @@ -26012,20 +26364,31 @@ "workbox-core": "6.5.1" } }, - "node_modules/workbox-core": { + "node_modules/workbox-cacheable-response/node_modules/workbox-core": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", - "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==" + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, + "node_modules/workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==" }, "node_modules/workbox-expiration": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.1.tgz", - "integrity": "sha512-iY/cTADAQATMmPkUBRmQdacqq0TJd2wMHimBQz+tRnPGHSMH+/BoLPABPnu7O7rT/g/s59CUYYRGxe3mEgoJCA==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", "dependencies": { - "idb": "^6.1.4", - "workbox-core": "6.5.1" + "idb": "^7.0.1", + "workbox-core": "6.5.4" } }, + "node_modules/workbox-expiration/node_modules/idb": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.0.tgz", + "integrity": "sha512-Wsk07aAxDsntgYJY4h0knZJuTxM73eQ4reRAO+Z1liOh8eMCJ/MoDS8fCui1vGT9mnjtl1sOu3I2i/W1swPYZg==" + }, "node_modules/workbox-google-analytics": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.1.tgz", @@ -26038,6 +26401,30 @@ "workbox-strategies": "6.5.1" } }, + "node_modules/workbox-google-analytics/node_modules/workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, + "node_modules/workbox-google-analytics/node_modules/workbox-routing": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.1.tgz", + "integrity": "sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.1" + } + }, + "node_modules/workbox-google-analytics/node_modules/workbox-strategies": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.1.tgz", + "integrity": "sha512-JNaTXPy8wXzKkr+6za7/eJX9opoZk7UgY261I2kPxl80XQD8lMjz0vo9EOcBwvD72v3ZhGJbW84ZaDwFEhFvWA==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.1" + } + }, "node_modules/workbox-navigation-preload": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.1.tgz", @@ -26047,14 +26434,20 @@ "workbox-core": "6.5.1" } }, - "node_modules/workbox-precaching": { + "node_modules/workbox-navigation-preload/node_modules/workbox-core": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.1.tgz", - "integrity": "sha512-EzlPBxvmjGfE56YZzsT/vpVkpLG1XJhoplgXa5RPyVWLUL1LbwEAxhkrENElSS/R9tgiTw80IFwysidfUqLihg==", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, + "node_modules/workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", "dependencies": { - "workbox-core": "6.5.1", - "workbox-routing": "6.5.1", - "workbox-strategies": "6.5.1" + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" } }, "node_modules/workbox-range-requests": { @@ -26066,6 +26459,12 @@ "workbox-core": "6.5.1" } }, + "node_modules/workbox-range-requests/node_modules/workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, "node_modules/workbox-recipes": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.1.tgz", @@ -26080,22 +26479,67 @@ "workbox-strategies": "6.5.1" } }, - "node_modules/workbox-routing": { + "node_modules/workbox-recipes/node_modules/workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, + "node_modules/workbox-recipes/node_modules/workbox-expiration": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.1.tgz", + "integrity": "sha512-iY/cTADAQATMmPkUBRmQdacqq0TJd2wMHimBQz+tRnPGHSMH+/BoLPABPnu7O7rT/g/s59CUYYRGxe3mEgoJCA==", + "dev": true, + "dependencies": { + "idb": "^6.1.4", + "workbox-core": "6.5.1" + } + }, + "node_modules/workbox-recipes/node_modules/workbox-precaching": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.1.tgz", + "integrity": "sha512-EzlPBxvmjGfE56YZzsT/vpVkpLG1XJhoplgXa5RPyVWLUL1LbwEAxhkrENElSS/R9tgiTw80IFwysidfUqLihg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.1", + "workbox-routing": "6.5.1", + "workbox-strategies": "6.5.1" + } + }, + "node_modules/workbox-recipes/node_modules/workbox-routing": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.1.tgz", "integrity": "sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA==", + "dev": true, "dependencies": { "workbox-core": "6.5.1" } }, - "node_modules/workbox-strategies": { + "node_modules/workbox-recipes/node_modules/workbox-strategies": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.1.tgz", "integrity": "sha512-JNaTXPy8wXzKkr+6za7/eJX9opoZk7UgY261I2kPxl80XQD8lMjz0vo9EOcBwvD72v3ZhGJbW84ZaDwFEhFvWA==", + "dev": true, "dependencies": { "workbox-core": "6.5.1" } }, + "node_modules/workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, "node_modules/workbox-streams": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.1.tgz", @@ -26106,6 +26550,21 @@ "workbox-routing": "6.5.1" } }, + "node_modules/workbox-streams/node_modules/workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, + "node_modules/workbox-streams/node_modules/workbox-routing": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.1.tgz", + "integrity": "sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.1" + } + }, "node_modules/workbox-sw": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.1.tgz", @@ -26153,6 +26612,12 @@ "workbox-core": "6.5.1" } }, + "node_modules/workbox-window/node_modules/workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -26239,9 +26704,9 @@ } }, "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", + "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", "dev": true, "engines": { "node": ">=10.0.0" @@ -26308,12 +26773,12 @@ } }, "node_modules/yargs": { - "version": "17.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", - "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", + "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", @@ -26334,6 +26799,20 @@ "node": ">=10" } }, + "node_modules/yargs/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/yargs/node_modules/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", @@ -26358,9 +26837,9 @@ } }, "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "engines": { "node": ">=12" @@ -26380,6 +26859,12 @@ } }, "dependencies": { + "@adobe/css-tools": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.0.1.tgz", + "integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==", + "dev": true + }, "@ampproject/remapping": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", @@ -26390,36 +26875,36 @@ } }, "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "requires": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", - "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.3.tgz", + "integrity": "sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==", "dev": true }, "@babel/core": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.10.tgz", - "integrity": "sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", + "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.10", - "@babel/helper-compilation-targets": "^7.17.10", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.9", - "@babel/parser": "^7.17.10", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.10", - "@babel/types": "^7.17.10", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.3", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.3", + "@babel/types": "^7.19.3", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -26476,23 +26961,23 @@ } }, "@babel/generator": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz", - "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.3.tgz", + "integrity": "sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==", "dev": true, "requires": { - "@babel/types": "^7.17.10", - "@jridgewell/gen-mapping": "^0.1.0", + "@babel/types": "^7.19.3", + "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" } }, "@babel/helper-annotate-as-pure": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", - "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { @@ -26506,14 +26991,14 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz", - "integrity": "sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", + "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", "dev": true, "requires": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.20.2", + "@babel/compat-data": "^7.19.3", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", "semver": "^6.3.0" }, "dependencies": { @@ -26526,18 +27011,18 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz", - "integrity": "sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", + "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-member-expression-to-functions": "^7.17.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" } }, "@babel/helper-create-regexp-features-plugin": { @@ -26590,13 +27075,10 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true }, "@babel/helper-explode-assignable-expression": { "version": "7.16.7", @@ -26608,71 +27090,71 @@ } }, "@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "requires": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" } }, "@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", - "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, "requires": { - "@babel/types": "^7.17.0" + "@babel/types": "^7.18.9" } }, "@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-module-transforms": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", - "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" } }, "@babel/helper-optimise-call-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", - "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", "dev": true }, "@babel/helper-remap-async-to-generator": { @@ -26687,25 +27169,25 @@ } }, "@babel/helper-replace-supers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", - "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz", + "integrity": "sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.19.1", + "@babel/types": "^7.19.0" } }, "@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, "requires": { - "@babel/types": "^7.17.0" + "@babel/types": "^7.18.6" } }, "@babel/helper-skip-transparent-expression-wrappers": { @@ -26718,24 +27200,30 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true + }, "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true }, "@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true }, "@babel/helper-wrap-function": { @@ -26751,23 +27239,23 @@ } }, "@babel/helpers": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", - "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", + "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", "dev": true, "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0" + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" } }, "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -26786,9 +27274,9 @@ } }, "@babel/parser": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", - "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz", + "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==", "dev": true }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { @@ -26823,13 +27311,13 @@ } }, "@babel/plugin-proposal-class-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", - "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-proposal-class-static-block": { @@ -26844,17 +27332,16 @@ } }, "@babel/plugin-proposal-decorators": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.9.tgz", - "integrity": "sha512-EfH2LZ/vPa2wuPwJ26j+kYRkaubf89UlwxKXtxqEm57HrgSEYDB8t4swFP+p8LcI9yiP9ZRJJjo/58hS6BnaDA==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.19.3.tgz", + "integrity": "sha512-MbgXtNXqo7RTKYIXVchVJGPvaVufQH3pxvQyfbGvNw1DObIhph+PesYXJTcd8J4DdWibvf6Z2eanOyItX8WnJg==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.17.9", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/plugin-syntax-decorators": "^7.17.0", - "charcodes": "^0.2.0" + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-replace-supers": "^7.19.1", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/plugin-syntax-decorators": "^7.19.0" } }, "@babel/plugin-proposal-dynamic-import": { @@ -26952,13 +27439,13 @@ } }, "@babel/plugin-proposal-private-methods": { - "version": "7.16.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", - "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.10", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-proposal-private-property-in-object": { @@ -27020,12 +27507,12 @@ } }, "@babel/plugin-syntax-decorators": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz", - "integrity": "sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.19.0.tgz", + "integrity": "sha512-xaBZUEDntt4faL1yN8oIFlhfXeQAWJW7CLKYsHTUqriCUbj8xOra8bfxxKGi/UwExPFBuPdH4XfHc9rGQhrVkQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.19.0" } }, "@babel/plugin-syntax-dynamic-import": { @@ -27155,12 +27642,12 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", - "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-arrow-functions": { @@ -27541,14 +28028,14 @@ } }, "@babel/plugin-transform-typescript": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", - "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.3.tgz", + "integrity": "sha512-z6fnuK9ve9u/0X0rRvI9MY0xg+DOUaABDYOe+/SQTxtlptaBB/V9JIUxJn6xp3lMBeb9qe8xSFmHU35oZDXD+w==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-typescript": "^7.16.7" + "@babel/helper-create-class-features-plugin": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/plugin-syntax-typescript": "^7.18.6" } }, "@babel/plugin-transform-unicode-escapes": { @@ -27688,14 +28175,14 @@ } }, "@babel/preset-typescript": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", - "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-typescript": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" } }, "@babel/runtime": { @@ -27717,30 +28204,30 @@ } }, "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" } }, "@babel/traverse": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz", - "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.3.tgz", + "integrity": "sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.10", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.10", - "@babel/types": "^7.17.10", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.19.3", + "@babel/types": "^7.19.3", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -27763,12 +28250,13 @@ } }, "@babel/types": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", - "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.3.tgz", + "integrity": "sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" } }, @@ -27859,20 +28347,27 @@ "postcss-value-parser": "^4.2.0" } }, + "@csstools/selector-specificity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", + "dev": true, + "requires": {} + }, "@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", + "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", + "espree": "^9.4.0", + "globals": "^13.15.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "dependencies": { @@ -27892,9 +28387,9 @@ } }, "globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -27915,12 +28410,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -27930,51 +28419,51 @@ } }, "@fortawesome/fontawesome-common-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz", - "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.0.tgz", + "integrity": "sha512-rBevIsj2nclStJ7AxTdfsa3ovHb1H+qApwrxcTVo+NNdeJiB9V75hsKfrkG5AwNcRUNxrPPiScGYCNmLMoh8pg==" }, "@fortawesome/fontawesome-free": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.0.0.tgz", - "integrity": "sha512-6LB4PYBST1Rx40klypw1SmSDArjFOcfBf2LeX9Zg5EKJT2eXiyiJq+CyBYKeXyK0sXS2FsCJWSPr/luyhuvh0Q==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.2.0.tgz", + "integrity": "sha512-CNR7qRIfCwWHNN7FnKUniva94edPdyQzil/zCwk3v6k4R6rR2Fr8i4s3PM7n/lyfPA6Zfko9z5WDzFxG9SW1uQ==" }, "@fortawesome/fontawesome-svg-core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz", - "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.0.tgz", + "integrity": "sha512-Cf2mAAeMWFMzpLC7Y9H1I4o3wEU+XovVJhTiNG8ZNgSQj53yl7OCJaS80K4YjrABWZzbAHVaoHE1dVJ27AAYXw==", "requires": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "6.2.0" } }, "@fortawesome/free-regular-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.0.0.tgz", - "integrity": "sha512-lYK6oyQL8HwZUAVWGqF7TGuwQBVfphNBVTdvPSD3h4gmQfGazm/xcwg3kmtcRycu3y6QspOC7hPXSoJbVqSYCw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.2.0.tgz", + "integrity": "sha512-M1dG+PAmkYMTL9BSUHFXY5oaHwBYfHCPhbJ8qj8JELsc9XCrUJ6eEHWip4q0tE+h9C0DVyFkwIM9t7QYyCpprQ==", "requires": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "6.2.0" } }, "@fortawesome/free-solid-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.0.0.tgz", - "integrity": "sha512-o4FZ1XbndcgeWNb8Wh0y+Hgf73CjmyOQowUSaqQCtgIIdS+XliSBSOwCl330wER+I6CGYE96hT27bHBPmzX2Gg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.2.0.tgz", + "integrity": "sha512-UjCILHIQ4I8cN46EiQn0CZL/h8AwCGgR//1c4R96Q5viSRwuKVo0NdQEc4bm+69ZwC0dUvjbDqAHF1RR5FA3XA==", "requires": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "6.2.0" } }, "@fortawesome/react-fontawesome": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.17.tgz", - "integrity": "sha512-dX43Z5IvMaW7fwzU8farosYjKNGfRb2HB/DgjVBHeJZ/NSnuuaujPPx0YOdcAq+n3mqn70tyCde2HM1mqbhiuw==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", "requires": { "prop-types": "^15.8.1" } }, "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", + "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -27999,6 +28488,18 @@ } } }, + "@humanwhocodes/gitignore-to-minimatch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", + "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", + "dev": true + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, "@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -28073,26 +28574,26 @@ "dev": true }, "@jest/console": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.0.2.tgz", - "integrity": "sha512-tiRpnMeeyQuuzgL5UNSeiqMwF8UOWPbAE5rzcu/1zyq4oPG2Ox6xm4YCOruwbp10F8odWc+XwVxTyGzMSLMqxA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.1.2.tgz", + "integrity": "sha512-ujEBCcYs82BTmRxqfHMQggSlkUZP63AE5YEaTPj7eFyJOzukkTorstOUC7L6nE3w5SYadGVAnTsQ/ZjTGL0qYQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^28.0.2", - "jest-util": "^28.0.2", + "jest-message-util": "^29.1.2", + "jest-util": "^29.1.2", "slash": "^3.0.0" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -28101,9 +28602,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -28144,12 +28645,12 @@ "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -28169,49 +28670,48 @@ } }, "@jest/core": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.0.3.tgz", - "integrity": "sha512-cCQW06vEZ+5r50SB06pOnSWsOBs7F+lswPYnKKfBz1ncLlj1sMqmvjgam8q40KhlZ8Ut4eNAL2Hvfx4BKIO2FA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.1.2.tgz", + "integrity": "sha512-sCO2Va1gikvQU2ynDN8V4+6wB7iVrD2CvT0zaRst4rglf56yLly0NQ9nuRRAWFeimRf+tCdFsb1Vk1N9LrrMPA==", "dev": true, "requires": { - "@jest/console": "^28.0.2", - "@jest/reporters": "^28.0.3", - "@jest/test-result": "^28.0.2", - "@jest/transform": "^28.0.3", - "@jest/types": "^28.0.2", + "@jest/console": "^29.1.2", + "@jest/reporters": "^29.1.2", + "@jest/test-result": "^29.1.2", + "@jest/transform": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^28.0.2", - "jest-config": "^28.0.3", - "jest-haste-map": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.0.3", - "jest-resolve-dependencies": "^28.0.3", - "jest-runner": "^28.0.3", - "jest-runtime": "^28.0.3", - "jest-snapshot": "^28.0.3", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", - "jest-watcher": "^28.0.2", + "jest-changed-files": "^29.0.0", + "jest-config": "^29.1.2", + "jest-haste-map": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-regex-util": "^29.0.0", + "jest-resolve": "^29.1.2", + "jest-resolve-dependencies": "^29.1.2", + "jest-runner": "^29.1.2", + "jest-runtime": "^29.1.2", + "jest-snapshot": "^29.1.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", + "jest-watcher": "^29.1.2", "micromatch": "^4.0.4", - "pretty-format": "^28.0.2", - "rimraf": "^3.0.0", + "pretty-format": "^29.1.2", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -28220,9 +28720,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -28263,61 +28763,61 @@ "dev": true }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true }, "jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" } }, "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true }, "jest-resolve": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.0.3.tgz", - "integrity": "sha512-lfgjd9JhEjpjIN3HLUfdysdK+A7ePQoYmd7WL9DUEWqdnngb1rF56eee6iDXJxl/3eSolpP43VD7VrhjL3NsoQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.1.2.tgz", + "integrity": "sha512-7fcOr+k7UYSVRJYhSmJHIid3AnDBcLQX3VmT9OSbPWsWz1MfT7bcoerMhADKGvKCoMpOHUQaDHtQoNp/P9JMGg==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", + "jest-haste-map": "^29.1.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" } }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -28326,26 +28826,27 @@ } }, "jest-validate": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.0.2.tgz", - "integrity": "sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", + "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.0.0", "leven": "^3.1.0", - "pretty-format": "^28.0.2" + "pretty-format": "^29.1.2" } }, "jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "requires": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -28362,13 +28863,12 @@ } }, "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -28382,9 +28882,9 @@ } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "supports-color": { @@ -28399,24 +28899,24 @@ } }, "@jest/environment": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.0.2.tgz", - "integrity": "sha512-IvI7dEfqVEffDYlw9FQfVBt6kXt/OI38V7QUIur0ulOQgzpKYJDVvLzj4B1TVmHWTGW5tcnJdlZ3hqzV6/I9Qg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.1.2.tgz", + "integrity": "sha512-rG7xZ2UeOfvOVzoLIJ0ZmvPl4tBEQ2n73CZJSlzUjPw4or1oSWC0s0Rk0ZX+pIBJ04aVr6hLWFn1DFtrnf8MhQ==", "dev": true, "requires": { - "@jest/fake-timers": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/fake-timers": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", - "jest-mock": "^28.0.2" + "jest-mock": "^29.1.2" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -28425,9 +28925,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -28479,53 +28979,53 @@ } }, "@jest/expect": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.0.3.tgz", - "integrity": "sha512-VEzZr85bqNomgayQkR7hWG5HnbZYWYWagQriZsixhLmOzU6PCpMP61aeVhkCoRrg7ri5f7JDpeTPzDAajIwFHw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.1.2.tgz", + "integrity": "sha512-FXw/UmaZsyfRyvZw3M6POgSNqwmuOXJuzdNiMWW9LCYo0GRoRDhg+R5iq5higmRTHQY7hx32+j7WHwinRmoILQ==", "dev": true, "requires": { - "expect": "^28.0.2", - "jest-snapshot": "^28.0.3" + "expect": "^29.1.2", + "jest-snapshot": "^29.1.2" } }, "@jest/expect-utils": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.0.2.tgz", - "integrity": "sha512-YryfH2zN5c7M8eLtn9oTBRj1sfD+X4cHNXJnTejqCveOS33wADEZUxJ7de5++lRvByNpRpfAnc8zTK7yrUJqgA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.1.2.tgz", + "integrity": "sha512-4a48bhKfGj/KAH39u0ppzNTABXQ8QPccWAFUFobWBaEMSMp+sB31Z2fK/l47c4a/Mu1po2ffmfAIPxXbVTXdtg==", "dev": true, "requires": { - "jest-get-type": "^28.0.2" + "jest-get-type": "^29.0.0" }, "dependencies": { "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true } } }, "@jest/fake-timers": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.0.2.tgz", - "integrity": "sha512-R75yUv+WeybPa4ZVhX9C+8XN0TKjUoceUX+/QEaDVQGxZZOK50eD74cs7iMDTtpodh00d8iLlc9197vgF6oZjA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.1.2.tgz", + "integrity": "sha512-GppaEqS+QQYegedxVMpCe2xCXxxeYwQ7RsNx55zc8f+1q1qevkZGKequfTASI7ejmg9WwI+SJCrHe9X11bLL9Q==", "dev": true, "requires": { - "@jest/types": "^28.0.2", - "@sinonjs/fake-timers": "^9.1.1", + "@jest/types": "^29.1.2", + "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", - "jest-message-util": "^28.0.2", - "jest-mock": "^28.0.2", - "jest-util": "^28.0.2" + "jest-message-util": "^29.1.2", + "jest-mock": "^29.1.2", + "jest-util": "^29.1.2" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -28534,9 +29034,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -28577,12 +29077,12 @@ "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -28602,23 +29102,24 @@ } }, "@jest/globals": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.0.3.tgz", - "integrity": "sha512-q/zXYI6CKtTSIt1WuTHBYizJhH7K8h+xG5PE3C0oawLlPIvUMDYmpj0JX0XsJwPRLCsz/fYXHZVG46AaEhSPmw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.1.2.tgz", + "integrity": "sha512-uMgfERpJYoQmykAd0ffyMq8wignN4SvLUG6orJQRe9WAlTRc9cdpCaE/29qurXixYJVZWUqIBXhSk8v5xN1V9g==", "dev": true, "requires": { - "@jest/environment": "^28.0.2", - "@jest/expect": "^28.0.3", - "@jest/types": "^28.0.2" + "@jest/environment": "^29.1.2", + "@jest/expect": "^29.1.2", + "@jest/types": "^29.1.2", + "jest-mock": "^29.1.2" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -28627,9 +29128,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -28681,17 +29182,17 @@ } }, "@jest/reporters": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.0.3.tgz", - "integrity": "sha512-xrbIc7J/xwo+D7AY3enAR9ZWYCmJ8XIkstTukTGpKDph0gLl/TJje9jl3dssvE4KJzYqMKiSrnE5Nt68I4fTEg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.1.2.tgz", + "integrity": "sha512-X4fiwwyxy9mnfpxL0g9DD0KcTmEIqP0jUdnc2cfa9riHy+I6Gwwp5vOZiwyg0vZxfSDxrOlK9S4+340W4d+DAA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^28.0.2", - "@jest/test-result": "^28.0.2", - "@jest/transform": "^28.0.3", - "@jest/types": "^28.0.2", - "@jridgewell/trace-mapping": "^0.3.7", + "@jest/console": "^29.1.2", + "@jest/test-result": "^29.1.2", + "@jest/transform": "^29.1.2", + "@jest/types": "^29.1.2", + "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -28703,21 +29204,23 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-message-util": "^29.1.2", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "slash": "^3.0.0", "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", "terminal-link": "^2.0.0", - "v8-to-istanbul": "^9.0.0" + "v8-to-istanbul": "^9.0.1" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -28726,9 +29229,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -28769,12 +29272,12 @@ "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -28783,12 +29286,13 @@ } }, "jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "requires": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -28816,44 +29320,44 @@ } }, "@jest/schemas": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.0.2.tgz", - "integrity": "sha512-YVDJZjd4izeTDkij00vHHAymNXQ6WWsdChFRK86qck6Jpr3DCL5W3Is3vslviRlP+bLuMYRLbdp98amMvqudhA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", + "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", "dev": true, "requires": { - "@sinclair/typebox": "^0.23.3" + "@sinclair/typebox": "^0.24.1" } }, "@jest/source-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.0.2.tgz", - "integrity": "sha512-Y9dxC8ZpN3kImkk0LkK5XCEneYMAXlZ8m5bflmSL5vrwyeUpJfentacCUg6fOb8NOpOO7hz2+l37MV77T6BFPw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.0.0.tgz", + "integrity": "sha512-nOr+0EM8GiHf34mq2GcJyz/gYFyLQ2INDhAylrZJ9mMWoW21mLBfZa0BUVPPMxVYrLjeiRe2Z7kWXOGnS0TFhQ==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.15", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" } }, "@jest/test-result": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.0.2.tgz", - "integrity": "sha512-4EUqgjq9VzyUiVTvZfI9IRJD6t3NYBNP4f+Eq8Zr93+hkJ0RrGU4OBTw8tfNzidKX+bmuYzn8FxqpxOPIGGCMA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.1.2.tgz", + "integrity": "sha512-jjYYjjumCJjH9hHCoMhA8PCl1OxNeGgAoZ7yuGYILRJX9NjgzTN0pCT5qAoYR4jfOP8htIByvAlz9vfNSSBoVg==", "dev": true, "requires": { - "@jest/console": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/console": "^29.1.2", + "@jest/types": "^29.1.2", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -28862,9 +29366,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -28916,24 +29420,24 @@ } }, "@jest/test-sequencer": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.0.2.tgz", - "integrity": "sha512-zhnZ8ydkZQTPL7YucB86eOlD79zPy5EGSUKiR2Iv93RVEDU6OEP33kwDBg70ywOcxeJGDRhyo09q7TafNCBiIg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.1.2.tgz", + "integrity": "sha512-fU6dsUqqm8sA+cd85BmeF7Gu9DsXVWFdGn9taxM6xN1cKdcP/ivSgXh5QucFRFz1oZxKv3/9DYYbq0ULly3P/Q==", "dev": true, "requires": { - "@jest/test-result": "^28.0.2", + "@jest/test-result": "^29.1.2", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", + "jest-haste-map": "^29.1.2", "slash": "^3.0.0" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -28942,9 +29446,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -28985,38 +29489,38 @@ "dev": true }, "jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" } }, "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -29025,12 +29529,13 @@ } }, "jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "requires": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -29058,22 +29563,22 @@ } }, "@jest/transform": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.0.3.tgz", - "integrity": "sha512-+Y0ikI7SwoW/YbK8t9oKwC70h4X2Gd0OVuz5tctRvSV/EDQU00AAkoqevXgPSSFimUmp/sp7Yl8s/1bExDqOIg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.1.2.tgz", + "integrity": "sha512-2uaUuVHTitmkx1tHF+eBjb4p7UuzBG7SXIaA/hNIkaMP6K+gXYGxP38ZcrofzqN0HeZ7A90oqsOa97WU7WZkSw==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^28.0.2", - "@jridgewell/trace-mapping": "^0.3.7", + "@jest/types": "^29.1.2", + "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", + "jest-haste-map": "^29.1.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -29081,12 +29586,12 @@ }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -29095,9 +29600,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -29138,38 +29643,38 @@ "dev": true }, "jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" } }, "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -29178,12 +29683,13 @@ } }, "jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "requires": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -29209,9 +29715,9 @@ } }, "write-file-atomic": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz", - "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "requires": { "imurmurhash": "^0.1.4", @@ -29279,13 +29785,14 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" } }, "@jridgewell/resolve-uri": { @@ -29308,19 +29815,6 @@ "requires": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } } }, "@jridgewell/sourcemap-codec": { @@ -29330,9 +29824,9 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", @@ -29366,16 +29860,32 @@ } }, "@popperjs/core": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", - "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==" + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" }, "@react-leaflet/core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.0.0.tgz", - "integrity": "sha512-SQQ5DCQIaLzvslN6wCXs5OWqtlvk1Ubv2n5d7zTM8SDl9hM5Rr2wVy7/nOCIY958D75/ovhq6ZoSvT7GLCX6sg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", + "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", "requires": {} }, + "@reduxjs/toolkit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.0.tgz", + "integrity": "sha512-ak11IrjYcUXRqlhNPwnz6AcvA2ynJTu8PzDbbqQw4a3xR4KZtgiqbNblQD+10CRbfK4+5C79SOyxnT9dhBqFnA==", + "requires": { + "immer": "^9.0.16", + "redux": "^4.2.0", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.7" + } + }, + "@remix-run/router": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.1.tgz", + "integrity": "sha512-eBV5rvW4dRFOU1eajN7FmYxjAIVz/mRHgUE9En9mBn6m3mulK3WTR5C3iQhL9MZ14rWAq+xOlEaCkDiW0/heOg==" + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -29460,9 +29970,9 @@ } }, "@sinclair/typebox": { - "version": "0.23.5", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz", - "integrity": "sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==", + "version": "0.24.44", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.44.tgz", + "integrity": "sha512-ka0W0KN5i6LfrSocduwliMMpqVgohtPFidKdMEOUjoOFCHcOOYkKsPRxfs5f15oPNHTm6ERAm0GV/+/LTKeiWg==", "dev": true }, "@sinonjs/commons": { @@ -29484,48 +29994,50 @@ } }, "@stryker-mutator/api": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-6.0.2.tgz", - "integrity": "sha512-8LWmArFc7Zb2ntYsD9KY0l+9RbcS1KilkCFWaHs+4KUWp/a9z51Ei606AzfHArwyfRsfFXLmKi+j+Mo0/R5R5w==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-6.2.2.tgz", + "integrity": "sha512-ZMR3ubUh059Xb769ryE1LkwZR7PWbt5TITYYkHZd7pG5yLVzPMDP0d29CQBJW2H7YjlopgImVL8sw8U/RgDcGg==", "dev": true, "requires": { "mutation-testing-metrics": "1.7.10", "mutation-testing-report-schema": "1.7.10", - "tslib": "~2.3.0" + "tslib": "~2.4.0" }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true } } }, "@stryker-mutator/core": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-6.0.2.tgz", - "integrity": "sha512-ovRz7vOwjYUGZDCgADDPy5M+eK+l+ZQHseaZfYQv+MxPiXRQQuSxPm3ikeK5Hqds2UDLbzJ1i9XYc51hHqRVOQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-6.2.2.tgz", + "integrity": "sha512-1JS8UIMrwWeHqp508HXwRNmsAkHCtGskCwFWLLJSarVH9lyB8gyhTbhkaRHJGiEuaSTsxV1LZ5VzLK6OLgPtxw==", "dev": true, "requires": { - "@stryker-mutator/api": "6.0.2", - "@stryker-mutator/instrumenter": "6.0.2", - "@stryker-mutator/util": "6.0.2", + "@stryker-mutator/api": "6.2.2", + "@stryker-mutator/instrumenter": "6.2.2", + "@stryker-mutator/util": "6.2.2", "ajv": "~8.11.0", "chalk": "~5.0.0", - "commander": "~9.1.0", + "commander": "~9.4.0", + "diff-match-patch": "1.0.5", "execa": "~6.1.0", - "file-url": "~3.0.0", - "get-port": "~6.0.0", - "glob": "~7.2.0", - "inquirer": "~8.2.0", + "file-url": "~4.0.0", + "get-port": "~6.1.0", + "glob": "~8.0.0", + "inquirer": "~9.1.0", "lodash.flatmap": "~4.5.0", "lodash.groupby": "~4.6.0", - "log4js": "~6.4.1", - "minimatch": "~3.0.4", + "log4js": "~6.6.0", + "minimatch": "~5.1.0", "mkdirp": "~1.0.3", - "mutation-testing-elements": "1.7.10", + "mutation-testing-elements": "1.7.12", "mutation-testing-metrics": "1.7.10", + "mutation-testing-report-schema": "1.7.10", "npm-run-path": "~5.1.0", "progress": "~2.0.0", "rimraf": "~3.0.0", @@ -29533,7 +30045,7 @@ "semver": "^7.3.5", "source-map": "~0.7.3", "tree-kill": "~1.2.2", - "tslib": "~2.3.0", + "tslib": "~2.4.0", "typed-inject": "~3.0.0", "typed-rest-client": "~1.8.0" }, @@ -29550,43 +30062,19 @@ "uri-js": "^4.2.2" } }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-width": { - "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 - }, - "color-convert": { + "brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "requires": { - "color-name": "~1.1.4" + "balanced-match": "^1.0.0" } }, "commander": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.1.0.tgz", - "integrity": "sha512-i0/MaqBtdbnJ4XQs4Pmyb+oFQl+q0lsAmokVUH92SlSw4fkeAcG3bVon+Qt7hmtF+u3Het6o4VgrcY3qAoEB6w==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", "dev": true }, "cross-spawn": { @@ -29634,67 +30122,25 @@ } } }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "human-signals": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", "dev": true }, - "inquirer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", - "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.2.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "chalk": { - "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" - } - } - } - }, - "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": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -29707,11 +30153,14 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } }, "mkdirp": { "version": "1.0.4", @@ -29719,12 +30168,6 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, "npm-run-path": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", @@ -29742,35 +30185,16 @@ } } }, - "onetime": { - "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" - } - }, "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 }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, "rxjs": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz", - "integrity": "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", + "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", "dev": true, "requires": { "tslib": "^2.1.0" @@ -29806,36 +30230,16 @@ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", "dev": true }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, "strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true }, - "supports-color": { - "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" - } - }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, "which": { @@ -29850,32 +30254,32 @@ } }, "@stryker-mutator/instrumenter": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/instrumenter/-/instrumenter-6.0.2.tgz", - "integrity": "sha512-D2R/RO83ILwGMp7PeYUcmr/cmqZOBrSAwB1RnmqADqLka9NDxS6Pn4NUCacu7xlyIf5Ejt1m9I2+64AH9W96hA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/instrumenter/-/instrumenter-6.2.2.tgz", + "integrity": "sha512-FZIvyL3uiIaLvOSKXe6jnq0FMo6lWy4NoGyYt5K/wmDxN2QuSaChGu/tVe4Z+Ui+4O3/DiGqWY5FWKGv1iHEPA==", "dev": true, "requires": { - "@babel/core": "~7.17.9", - "@babel/generator": "~7.17.9", - "@babel/parser": "~7.17.9", - "@babel/plugin-proposal-class-properties": "~7.16.7", - "@babel/plugin-proposal-decorators": "~7.17.9", - "@babel/plugin-proposal-private-methods": "~7.16.11", - "@babel/preset-typescript": "~7.16.7", - "@stryker-mutator/api": "6.0.2", - "@stryker-mutator/util": "6.0.2", + "@babel/core": "~7.19.0", + "@babel/generator": "~7.19.0", + "@babel/parser": "~7.19.0", + "@babel/plugin-proposal-class-properties": "~7.18.0", + "@babel/plugin-proposal-decorators": "~7.19.0", + "@babel/plugin-proposal-private-methods": "~7.18.0", + "@babel/preset-typescript": "~7.18.0", + "@stryker-mutator/api": "6.2.2", + "@stryker-mutator/util": "6.2.2", "angular-html-parser": "~1.8.0", - "weapon-regex": "~0.6.0" + "weapon-regex": "~1.0.2" } }, "@stryker-mutator/jest-runner": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/jest-runner/-/jest-runner-6.0.2.tgz", - "integrity": "sha512-fHa/2izIuqUZDW343/PYa5sXlZUpjZ53kqfUbwXJGxCVKiYrYlWGxAa/LfdBT2mRaPKL9Ji76F2n+53mDuu7rA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/jest-runner/-/jest-runner-6.2.2.tgz", + "integrity": "sha512-xWuzuBUIB2MQVJBCdK5K8/SRV4fu2+wAd9FoZY6AIkKCVv0Od0eYZ6MB78V6jSG9R2/KF9I+zzrQ94PEnp5zaQ==", "dev": true, "requires": { - "@stryker-mutator/api": "6.0.2", - "@stryker-mutator/util": "6.0.2", + "@stryker-mutator/api": "6.2.2", + "@stryker-mutator/util": "6.2.2", "semver": "~7.3.7", "tslib": "~2.4.0" }, @@ -29898,13 +30302,13 @@ } }, "@stryker-mutator/typescript-checker": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/typescript-checker/-/typescript-checker-6.0.2.tgz", - "integrity": "sha512-UiOnTKvl9K8Jbd3BV+F7nUbDl7JpW+xxOOuWcQxWUCeBDXBqTJ40oX0Yj1OKyA4YMxn+owSxsCca94c4Q+3PNg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/typescript-checker/-/typescript-checker-6.2.2.tgz", + "integrity": "sha512-vYLrPden87i6Fyx6zgBLk2MSrtYDi/ig+ZgNotdavNy34VpiKPTkgpfAWjqkVCxyJhvQvkS6iag17xlWR+uYmg==", "dev": true, "requires": { - "@stryker-mutator/api": "6.0.2", - "@stryker-mutator/util": "6.0.2", + "@stryker-mutator/api": "6.2.2", + "@stryker-mutator/util": "6.2.2", "semver": "~7.3.2" }, "dependencies": { @@ -29920,9 +30324,9 @@ } }, "@stryker-mutator/util": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-6.0.2.tgz", - "integrity": "sha512-xqeOIOu6yTK4v9kwdfINzdT7qd0nru8tR3mxNnfp6LLgD805pJYiR14EK2yLE0ylrBHaRAjTb/uMclf+7OtAVQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-6.2.2.tgz", + "integrity": "sha512-BjE9wP8V8Vh4VMr/pReNLlMNxSzl25OHJBDK1Y4WN/b+HY9gVy7PiX2HEYiXg7LniHIZ54vX5VLuLzJOfb6pGQ==", "dev": true, "requires": { "lodash.flatmap": "~4.5.0" @@ -30070,9 +30474,9 @@ "dev": true }, "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "requires": { "big.js": "^5.2.2", @@ -30150,16 +30554,16 @@ } }, "@testing-library/jest-dom": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.4.tgz", - "integrity": "sha512-Gy+IoFutbMQcky0k+bqqumXZ1cTGswLsFqmNLzNdSKkU9KGV2u9oXhukCbbJ9/LRPKiqwxEE8VpV/+YZlfkPUA==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", + "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", "dev": true, "requires": { + "@adobe/css-tools": "^4.0.1", "@babel/runtime": "^7.9.2", "@types/testing-library__jest-dom": "^5.9.1", "aria-query": "^5.0.0", "chalk": "^3.0.0", - "css": "^3.0.0", "css.escape": "^1.5.1", "dom-accessibility-api": "^0.5.6", "lodash": "^4.17.15", @@ -30218,9 +30622,9 @@ } }, "@testing-library/react": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.1.1.tgz", - "integrity": "sha512-8mirlAa0OKaUvnqnZF6MdAh2tReYA2KtWVw1PKvaF5EcCZqgK5pl8iF+3uW90JdG5Ua2c2c2E2wtLdaug3dsVg==", + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", + "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", "dev": true, "requires": { "@babel/runtime": "^7.12.5", @@ -30229,9 +30633,9 @@ } }, "@testing-library/user-event": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.1.1.tgz", - "integrity": "sha512-XrjH/iEUqNl9lF2HX9YhPNV7Amntkcnpw0Bo1KkRzowNDcgSN9i0nm4Q8Oi5wupgdfPaJNMAWa61A+voD6Kmwg==", + "version": "14.4.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", + "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", "dev": true, "requires": {} }, @@ -30447,24 +30851,49 @@ } }, "@types/jest": { - "version": "27.4.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", - "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.1.1.tgz", + "integrity": "sha512-U9Ey07dGWl6fUFaIaUQUKWG5NoKi/zizeVQCGV8s4nSU0jPgqphVZvS64+8BtWYvrc3ZGw6wo943NSYPxkrp/g==", "dev": true, "requires": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + }, + "dependencies": { + "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 + }, + "pretty-format": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "dev": true, + "requires": { + "@jest/schemas": "^29.0.0", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + } } }, "@types/jsdom": { - "version": "16.2.14", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-16.2.14.tgz", - "integrity": "sha512-6BAy1xXEmMuHeAJ4Fv4yXKwBDTGTOseExKE3OaHiNycdHdZw59KfYzrt0DkDluvwmik1HRt6QS7bImxUmpSy+w==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.0.tgz", + "integrity": "sha512-YfAchFs0yM1QPDrLm2VHe+WHGtqms3NXnXAMolrgrVP6fgBHHXy1ozAbo/dFtPNtZC/m66bPiCTWYmqp1F14gA==", "dev": true, "requires": { "@types/node": "*", - "@types/parse5": "*", - "@types/tough-cookie": "*" + "@types/tough-cookie": "*", + "parse5": "^7.0.0" } }, "@types/json-schema": { @@ -30489,9 +30918,9 @@ "dev": true }, "@types/leaflet": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.9.tgz", - "integrity": "sha512-H8vPgD49HKzqM41ArHGZM70g/tfhp8W+JcPxfnF+5H/Xvp+xiP+KQOUNWU8U89fqS1Jj3cpRY/+nbnaHFzwnFA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.8.0.tgz", + "integrity": "sha512-+sXFmiJTFdhaXXIGFlV5re9AdqtAODoXbGAvxx02e5SHXL3ir7ClP5J7pahO8VmzKY3dth4RUS1nf2BTT+DW1A==", "dev": true, "requires": { "@types/geojson": "*" @@ -30527,12 +30956,6 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, - "@types/parse5": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", - "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==", - "dev": true - }, "@types/prettier": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", @@ -30557,9 +30980,9 @@ "dev": true }, "@types/ramda": { - "version": "0.27.38", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.27.38.tgz", - "integrity": "sha512-tZoQ0lv1WKkrpBHemL8yCkI9p8kUk/1PSMwhl0eeyqMQjD+2ePUtVLV8PpNS9Kq3OktObwOx9I3k+HumxTviRg==", + "version": "0.28.15", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.28.15.tgz", + "integrity": "sha512-FCaLNVZry65jW8x/FDnKgjgkCNQxgc5AYMQwdNn6yW5M+62R+0nt2Y36U43dTNora9hcquemfrY5gxhE5pcilQ==", "dev": true, "requires": { "ts-toolbelt": "^6.15.1" @@ -30572,9 +30995,9 @@ "dev": true }, "@types/react": { - "version": "18.0.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.8.tgz", - "integrity": "sha512-+j2hk9BzCOrrOSJASi5XiOyBbERk9jG5O73Ya4M0env5Ixi6vUNli4qy994AINcEF+1IEHISYFfIT4zwr++LKw==", + "version": "18.0.21", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz", + "integrity": "sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -30592,18 +31015,18 @@ } }, "@types/react-copy-to-clipboard": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.2.tgz", - "integrity": "sha512-O29AThfxrkUFRsZXjfSWR2yaWo0ppB1yLEnHA+Oh24oNetjBAwTDu1PmolIqdJKzsZiO4J1jn6R6TmO96uBvGg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.4.tgz", + "integrity": "sha512-otTJsJpofYAeaIeOwV5xBUGpo6exXG2HX7X4nseToCB2VgPEBxGBHCm/FecZ676doNR7HCSTVtmohxfG2b3/yQ==", "dev": true, "requires": { "@types/react": "*" } }, "@types/react-datepicker": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.3.4.tgz", - "integrity": "sha512-5nTTz37KdTUgMZ1AAxztMWNtEnIMVRo8oCAEhIv0a6uUqDjvSKaMyPRpBV+8chi6f/A8wlTKJIpojpXca2dx3A==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.4.2.tgz", + "integrity": "sha512-g8DhWvYmaIMLzVrIEVLXncylyImyBaoPsEUr3yR13JDaaHoebhDorqnVv4tLkNGa8SjBB8SAOQvxD5jaPNBX8A==", "dev": true, "requires": { "@popperjs/core": "^2.9.2", @@ -30636,18 +31059,18 @@ } }, "@types/react-dom": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.3.tgz", - "integrity": "sha512-1RRW9kst+67gveJRYPxGmVy8eVJ05O43hg77G2j5m76/RFJtMbcfAs2viQ2UNsvvDg8F7OfQZx8qQcl6ymygaQ==", + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz", + "integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==", "devOptional": true, "requires": { "@types/react": "*" } }, "@types/react-tag-autocomplete": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/react-tag-autocomplete/-/react-tag-autocomplete-6.1.1.tgz", - "integrity": "sha512-/mVNQUHXtKGihHBP/q0znL/CHbtrZL82t8ch/msQCkywqDkoZeE7QzhyLTG535Y/estsI6EcJi8Jd5HersPHuw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@types/react-tag-autocomplete/-/react-tag-autocomplete-6.3.0.tgz", + "integrity": "sha512-WxAVFlcotjeQKh1UDEjAQwP4dCOtKFrCnSHODhSmBZqDFbjNhhw9QwtZ9wSfKkJ4z2mu5kgC8OD96hNUYtjZ1Q==", "dev": true, "requires": { "@types/react": "*" @@ -31268,9 +31691,9 @@ "dev": true }, "@zeit/schemas": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", - "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==", + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.21.0.tgz", + "integrity": "sha512-/J4WBTpWtQ4itN1rb3ao8LfClmVcmz2pO6oYb7Qd4h7VSqUhIbJIvrykz9Ew1WMg6eFWsKdsMHc5uPbFxqlCpg==", "dev": true }, "abab": { @@ -31352,9 +31775,9 @@ "dev": true }, "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "requires": { "big.js": "^5.2.2", @@ -31546,9 +31969,9 @@ "dev": true }, "arg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz", - "integrity": "sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", "dev": true }, "argparse": { @@ -31656,12 +32079,6 @@ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz", - "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", - "dev": true - }, "autoprefixer": { "version": "10.4.4", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.4.tgz", @@ -31682,14 +32099,6 @@ "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", "dev": true }, - "axios": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz", - "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==", - "requires": { - "follow-redirects": "^1.14.8" - } - }, "axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -31697,15 +32106,15 @@ "dev": true }, "babel-jest": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.0.3.tgz", - "integrity": "sha512-S0ADyYdcrt5fp9YldRYWCUHdk1BKt9AkvBkLWBoNAEV9NoWZPIj5+MYhPcGgTS65mfv3a+Ymf2UqgWoAVd41cA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.1.2.tgz", + "integrity": "sha512-IuG+F3HTHryJb7gacC7SQ59A9kO56BctUsT67uJHp1mMCHUOMXpDwOHWGifWqdWVknN2WNkCVQELPjXx0aLJ9Q==", "dev": true, "requires": { - "@jest/transform": "^28.0.3", + "@jest/transform": "^29.1.2", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^28.0.2", + "babel-preset-jest": "^29.0.2", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -31795,9 +32204,9 @@ } }, "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", "dev": true, "requires": { "big.js": "^5.2.2", @@ -31841,9 +32250,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.0.2.tgz", - "integrity": "sha512-Kizhn/ZL+68ZQHxSnHyuvJv8IchXD62KQxV77TBDV/xoBFBOfgRAk97GNs6hXdTTCiVES9nB2I6+7MXXrk5llQ==", + "version": "29.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.0.2.tgz", + "integrity": "sha512-eBr2ynAEFjcebVvu8Ktx580BD1QKCrBG1XwEUTXJe285p9HA/4hOhfWCFRQhTKSyBV0VzjhG7H91Eifz9s29hg==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -31935,12 +32344,12 @@ } }, "babel-preset-jest": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.0.2.tgz", - "integrity": "sha512-sYzXIdgIXXroJTFeB3S6sNDWtlJ2dllCdTEsnZ65ACrMojj3hVNFRmnJ1HZtomGi+Be7aqpY/HJ92fr8OhKVkQ==", + "version": "29.0.2", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.0.2.tgz", + "integrity": "sha512-BeVXp7rH5TK96ofyEnHjznjLMQ2nAeDJ+QzxKnHAAMs0RgrQsCywjAN8m4mOm5Di0pxU//3AoEeJJrerMH5UeA==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^28.0.2", + "babel-plugin-jest-hoist": "^29.0.2", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -32011,26 +32420,16 @@ "dev": true }, "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz", + "integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==", "dev": true, "requires": { - "buffer": "^5.5.0", + "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^3.4.0" }, "dependencies": { - "buffer": { - "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" - } - }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -32108,15 +32507,15 @@ "dev": true }, "bootstrap": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz", - "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.2.tgz", + "integrity": "sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==", "requires": {} }, "bottlejs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bottlejs/-/bottlejs-2.0.0.tgz", - "integrity": "sha512-Qhz5dd1YPTOHw0gZ1a1WpJ/oEWsq09BMMbxczeAPgubISij+ZFfah7wfOlHFeFQpWLQkS9TGz5C54tV6v0BlFA==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bottlejs/-/bottlejs-2.0.1.tgz", + "integrity": "sha512-50T0bzqeAqZ+//kgjdDxNu7UP8Je04isNPyHPwwOOPoeZmtVESkuF9nwkWEqSEd9Sw1yJ1oaoHBAMxe/wG4Zzg==" }, "bowser": { "version": "2.11.0", @@ -32124,86 +32523,81 @@ "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, "boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", + "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", "dev": true, "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" + "ansi-align": "^3.0.1", + "camelcase": "^7.0.0", + "chalk": "^5.0.1", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "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" - } - }, - "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" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "ansi-styles": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.1.tgz", + "integrity": "sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==", + "dev": true + }, + "camelcase": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.0.tgz", + "integrity": "sha512-JToIvOmz6nhGsUhAYScbo2d6Py5wojjNfoxoc2mEVLUdJ70gJK2gnd+ABY1Tc3sVMyK7QDPtN0T/XdlCQWITyQ==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "ansi-regex": "^6.0.1" } }, "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true + }, + "wrap-ansi": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", + "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } } } }, @@ -32233,16 +32627,15 @@ "dev": true }, "browserslist": { - "version": "4.20.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", - "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001317", - "electron-to-chromium": "^1.4.84", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" } }, "bser": { @@ -32254,6 +32647,16 @@ "node-int64": "^0.4.0" } }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -32276,7 +32679,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -32350,9 +32752,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001320", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", - "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", + "version": "1.0.30001415", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001415.tgz", + "integrity": "sha512-ER+PfgCJUe8BqunLGWd/1EY4g8AzQcsDAVzdtMGKVtQEmKAwaFfU6vb7EAVIqTMYsqxBorYZi2+22Iouj/y7GQ==", "dev": true }, "case-sensitive-paths-webpack-plugin": { @@ -32367,18 +32769,66 @@ "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", "dev": true }, + "chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "dev": true, + "requires": { + "chalk": "^4.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "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" + } + }, + "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" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "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" + } + } + } + }, "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 }, - "charcodes": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/charcodes/-/charcodes-0.2.0.tgz", - "integrity": "sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ==", - "dev": true - }, "chardet": { "version": "0.7.0", "resolved": "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz", @@ -32386,9 +32836,9 @@ "dev": true }, "chart.js": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.7.1.tgz", - "integrity": "sha512-8knRegQLFnPQAheZV8MjxIXc5gQEfDFD897BJgv/klO/vtIyFFmgMXrNfgrXpbTr/XbTturxRgxIXx/Y+ASJBA==" + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", + "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" }, "check-types": { "version": "11.1.2", @@ -32445,9 +32895,9 @@ "dev": true }, "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", "dev": true }, "cli-cursor": { @@ -32460,9 +32910,9 @@ } }, "cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", "dev": true }, "cli-width": { @@ -32472,49 +32922,14 @@ "dev": true }, "clipboardy": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", - "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", + "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", "dev": true, "requires": { - "arch": "^2.1.1", - "execa": "^1.0.0", - "is-wsl": "^2.1.1" - }, - "dependencies": { - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - } + "arch": "^2.2.0", + "execa": "^5.1.1", + "is-wsl": "^2.2.0" } }, "cliui": { @@ -32550,18 +32965,9 @@ "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true }, - "clone-regexp": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz", - "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==", - "dev": true, - "requires": { - "is-regexp": "^2.0.0" - } - }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -32622,9 +33028,9 @@ "dev": true }, "colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, "combined-stream": { @@ -32661,9 +33067,9 @@ "dev": true }, "compare-versions": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.3.tgz", - "integrity": "sha512-WQfnbDcrYnGr55UwbxKiQKASnTtNnaAWVi8jZyy8NTpVAXWACSne8lMD1iaIo9AiU6mnuLvSVshCzewVuWxHUg==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.1.tgz", + "integrity": "sha512-v8Au3l0b+Nwkp4G142JcgJFh1/TUhdxut7wzD1Nq1dyp5oa3tXaqb03EXOAB6jS4gMlalkjAUPZBMiAfKUixHQ==" }, "compressible": { "version": "2.0.17", @@ -32675,16 +33081,16 @@ } }, "compression": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", - "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "dev": true, "requires": { "accepts": "~1.3.5", "bytes": "3.0.0", - "compressible": "~2.0.14", + "compressible": "~2.0.16", "debug": "2.6.9", - "on-headers": "~1.0.1", + "on-headers": "~1.0.2", "safe-buffer": "5.1.2", "vary": "~1.1.2" } @@ -32710,7 +33116,7 @@ "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", "dev": true }, "content-type": { @@ -32791,48 +33197,6 @@ "yaml": "^1.10.0" } }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "css": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", - "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "source-map": "^0.6.1", - "source-map-resolve": "^0.6.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "source-map-resolve": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", - "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0" - } - } - } - }, "css-blank-pseudo": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", @@ -32843,9 +33207,9 @@ } }, "css-functions-list": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.0.1.tgz", - "integrity": "sha512-PriDuifDt4u4rkDgnqRCLnjfMatufLmWNfQnGCq34xZwpY3oabwhB9SqRBmuvWUgndbemCFlKqg+nO7C2q0SBw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", "dev": true }, "css-has-pseudo": { @@ -33021,29 +33385,17 @@ "abab": "^2.0.6", "whatwg-mimetype": "^3.0.0", "whatwg-url": "^11.0.0" - }, - "dependencies": { - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - } } }, "date-fns": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", - "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==" + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" }, "date-format": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.4.tgz", - "integrity": "sha512-/jyf4rhB17ge328HJuJjAcmRtCsGd+NDeAtahRBTaK6vSPR6MO5HlrAit3Nn7dVjaa6sowW0WXt8yQtLyZQFRg==", + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", "dev": true }, "debug": { @@ -33080,15 +33432,9 @@ } }, "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 - }, - "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=", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz", + "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==", "dev": true }, "dedent": { @@ -33113,8 +33459,8 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true }, "deep-is": { @@ -33141,7 +33487,7 @@ "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", "dev": true, "requires": { "clone": "^1.0.2" @@ -33225,6 +33571,12 @@ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "dev": true }, + "diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", + "dev": true + }, "diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", @@ -33383,6 +33735,12 @@ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -33399,9 +33757,9 @@ } }, "electron-to-chromium": { - "version": "1.4.92", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.92.tgz", - "integrity": "sha512-YAVbvQIcDE/IJ/vzDMjD484/hsRbFPW2qXJPaYTfOhtligmfYEYOep+5QojpaEU9kq6bMvNeC2aG7arYvTHYsA==", + "version": "1.4.271", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.271.tgz", + "integrity": "sha512-BCPBtK07xR1/uY2HFDtl3wK2De66AW4MSiPlLrnPNxKC/Qhccxd59W73654S3y6Rb/k3hmuGJOBnhjfoutetXA==", "dev": true }, "emitter-component": { @@ -33427,19 +33785,10 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, - "end-of-stream": { - "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==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, "enhanced-resolve": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", - "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", + "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", "dev": true, "requires": { "graceful-fs": "^4.2.4", @@ -33602,13 +33951,15 @@ } }, "eslint": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz", - "integrity": "sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz", + "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", + "@eslint/eslintrc": "^1.3.2", + "@humanwhocodes/config-array": "^0.10.5", + "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@humanwhocodes/module-importer": "^1.0.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -33618,30 +33969,32 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", + "find-up": "^5.0.0", "glob-parent": "^6.0.1", - "globals": "^13.6.0", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "dependencies": { "ansi-styles": { @@ -33739,9 +34092,9 @@ } }, "globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -33789,12 +34142,6 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -34076,15 +34423,6 @@ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, "resolve": { "version": "2.0.0-next.3", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz", @@ -34153,20 +34491,20 @@ "dev": true }, "espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", "dev": true, "requires": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.3.0" }, "dependencies": { "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", "dev": true } } @@ -34236,9 +34574,9 @@ "dev": true }, "event-source-polyfill": { - "version": "1.0.25", - "resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.25.tgz", - "integrity": "sha512-hQxu6sN1Eq4JjoI7ITdQeGGUN193A2ra83qC0Ltm9I2UJVAten3OFVN6k5RX4YWeCS0BoC8xg/5czOCIHVosQg==" + "version": "1.0.31", + "resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.31.tgz", + "integrity": "sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==" }, "eventemitter3": { "version": "4.0.7", @@ -34353,15 +34691,6 @@ } } }, - "execall": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz", - "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==", - "dev": true, - "requires": { - "clone-regexp": "^2.1.0" - } - }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -34369,25 +34698,25 @@ "dev": true }, "expect": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-28.0.2.tgz", - "integrity": "sha512-X0qIuI/zKv98k34tM+uGeOgAC73lhs4vROF9MkPk94C1zujtwv4Cla8SxhWn0G1OwvG9gLLL7RjFBkwGVaZ83w==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.1.2.tgz", + "integrity": "sha512-AuAGn1uxva5YBbBlXb+2JPxJRuemZsmlGcapPXWNSBNsQtAULfjioREGBWuI0EOvYUKjDnrCy8PW5Zlr1md5mw==", "dev": true, "requires": { - "@jest/expect-utils": "^28.0.2", - "jest-get-type": "^28.0.2", - "jest-matcher-utils": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-util": "^28.0.2" + "@jest/expect-utils": "^29.1.2", + "jest-get-type": "^29.0.0", + "jest-matcher-utils": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-util": "^29.1.2" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -34396,9 +34725,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -34433,9 +34762,9 @@ } }, "diff-sequences": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.0.2.tgz", - "integrity": "sha512-YtEoNynLDFCRznv/XDalsKGSZDoj0U5kLnXvY0JSq3nBboRrZXjD81+eSiwi+nzcZDwedMmcowcxNwwgFW23mQ==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.0.0.tgz", + "integrity": "sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==", "dev": true }, "has-flag": { @@ -34445,42 +34774,42 @@ "dev": true }, "jest-diff": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.0.2.tgz", - "integrity": "sha512-33Rnf821Y54OAloav0PGNWHlbtEorXpjwchnToyyWbec10X74FOW7hGfvrXLGz7xOe2dz0uo9JVFAHHj/2B5pg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.1.2.tgz", + "integrity": "sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "diff-sequences": "^29.0.0", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" } }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true }, "jest-matcher-utils": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.0.2.tgz", - "integrity": "sha512-SxtTiI2qLJHFtOz/bySStCnwCvISAuxQ/grS+74dfTy5AuJw3Sgj9TVUvskcnImTfpzLoMCDJseRaeRrVYbAOA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.1.2.tgz", + "integrity": "sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "jest-diff": "^29.1.2", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" } }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -34489,13 +34818,12 @@ } }, "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -34509,9 +34837,9 @@ } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "supports-color": { @@ -34616,9 +34944,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -34643,7 +34971,7 @@ "fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", "dev": true, "requires": { "punycode": "^1.3.2" @@ -34652,15 +34980,15 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true } } }, "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true }, "fastq": { @@ -34725,9 +35053,9 @@ "dev": true }, "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "requires": { "big.js": "^5.2.2", @@ -34738,9 +35066,9 @@ } }, "file-url": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", - "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/file-url/-/file-url-4.0.0.tgz", + "integrity": "sha512-vRCdScQ6j3Ku6Kd7W1kZk9c++5SqD6Xz5Jotrjr/nkY714M14RFHy/AAVA2WQvpsqVAVgTbDrYyBpU205F0cLw==", "dev": true }, "filelist": { @@ -34762,9 +35090,9 @@ } }, "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -34831,15 +35159,16 @@ } }, "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, "follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "dev": true }, "fork-ts-checker-webpack-plugin": { "version": "6.5.2", @@ -35029,8 +35358,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -35054,7 +35382,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -35074,15 +35401,9 @@ "dev": true }, "get-port": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.0.0.tgz", - "integrity": "sha512-qSVkVF6Eq1GdL/cBNiFuP4nUHMF7OEMTqEjC6alR2N90u8BFOoO0PFhNTX2QtAUoGrz8NnrSWj85TZ8YXZ6LOA==", - "dev": true - }, - "get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", + "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==", "dev": true }, "get-stream": { @@ -35190,6 +35511,12 @@ "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -35221,7 +35548,6 @@ "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" } @@ -35241,8 +35567,7 @@ "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "has-tostringtag": { "version": "1.0.0", @@ -35466,7 +35791,8 @@ "idb": { "version": "6.1.5", "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" + "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==", + "dev": true }, "identity-obj-proxy": { "version": "3.0.0", @@ -35490,10 +35816,9 @@ "dev": true }, "immer": { - "version": "9.0.12", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz", - "integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==", - "dev": true + "version": "9.0.16", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz", + "integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==" }, "immutable": { "version": "4.0.0", @@ -35561,6 +35886,172 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "inquirer": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.2.tgz", + "integrity": "sha512-Hj2Ml1WpxKJU2npP2Rj0OURGkHV+GtNW2CwFdHDiXlqUBAUrWTcZHxCkFywX/XHzOS7wrG/kExgJFbUkVgyHzg==", + "dev": true, + "requires": { + "ansi-escapes": "^5.0.0", + "chalk": "^5.0.1", + "cli-cursor": "^4.0.0", + "cli-width": "^4.0.0", + "external-editor": "^3.0.3", + "figures": "^5.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^6.1.2", + "run-async": "^2.4.0", + "rxjs": "^7.5.6", + "string-width": "^5.1.2", + "strip-ansi": "^7.0.1", + "through": "^2.3.6", + "wrap-ansi": "^8.0.1" + }, + "dependencies": { + "ansi-escapes": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", + "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "dev": true, + "requires": { + "type-fest": "^1.0.2" + } + }, + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.1.tgz", + "integrity": "sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==", + "dev": true + }, + "cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "requires": { + "restore-cursor": "^4.0.0" + } + }, + "cli-width": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", + "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true + }, + "figures": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", + "dev": true, + "requires": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "onetime": { + "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" + } + }, + "restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "rxjs": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", + "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + }, + "wrap-ansi": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", + "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, "internal-slot": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", @@ -35679,9 +36170,9 @@ } }, "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", "dev": true }, "is-module": { @@ -35720,6 +36211,12 @@ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true }, + "is-port-reachable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", + "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", + "dev": true + }, "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", @@ -35736,12 +36233,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-regexp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-2.1.0.tgz", - "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==", - "dev": true - }, "is-root": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", @@ -35754,12 +36245,6 @@ "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", "dev": true }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, "is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -35785,9 +36270,9 @@ "dev": true }, "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==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true }, "is-utf8": { @@ -35804,6 +36289,15 @@ "call-bind": "^1.0.2" } }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz", @@ -35973,14 +36467,83 @@ } }, "jest": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.0.3.tgz", - "integrity": "sha512-uS+T5J3w5xyzd1KSJCGKhCo8WTJXbNl86f5SW11wgssbandJOVLRKKUxmhdFfmKxhPeksl1hHZ0HaA8VBzp7xA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.1.2.tgz", + "integrity": "sha512-5wEIPpCezgORnqf+rCaYD1SK+mNN7NsstWzIsuvsnrhR/hSxXWd82oI7DkrbJ+XTD28/eG8SmxdGvukrGGK6Tw==", "dev": true, "requires": { - "@jest/core": "^28.0.3", + "@jest/core": "^29.1.2", + "@jest/types": "^29.1.2", "import-local": "^3.0.2", - "jest-cli": "^28.0.3" + "jest-cli": "^29.1.2" + }, + "dependencies": { + "@jest/types": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", + "dev": true, + "requires": { + "@jest/schemas": "^29.0.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "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" + } + }, + "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" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "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" + } + } } }, "jest-canvas-mock": { @@ -35994,49 +36557,60 @@ } }, "jest-changed-files": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.0.2.tgz", - "integrity": "sha512-QX9u+5I2s54ZnGoMEjiM2WeBvJR2J7w/8ZUmH2um/WLAuGAYFQcsVXY9+1YL6k0H/AGUdH8pXUAv6erDqEsvIA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.0.0.tgz", + "integrity": "sha512-28/iDMDrUpGoCitTURuDqUzWQoWmOmOKOFST1mi2lwh62X4BFf6khgH3uSuo1e49X/UDjuApAj3w0wLOex4VPQ==", "dev": true, "requires": { "execa": "^5.0.0", - "throat": "^6.0.1" + "p-limit": "^3.1.0" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + } } }, "jest-circus": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.0.3.tgz", - "integrity": "sha512-HJ3rUCm3A3faSy7KVH5MFCncqJLtrjEFkTPn9UIcs4Kq77+TXqHsOaI+/k73aHe6DJQigLUXq9rCYj3MYFlbIw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.1.2.tgz", + "integrity": "sha512-ajQOdxY6mT9GtnfJRZBRYS7toNIJayiiyjDyoZcnvPRUPwJ58JX0ci0PKAKUo2C1RyzlHw0jabjLGKksO42JGA==", "dev": true, "requires": { - "@jest/environment": "^28.0.2", - "@jest/expect": "^28.0.3", - "@jest/test-result": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/environment": "^29.1.2", + "@jest/expect": "^29.1.2", + "@jest/test-result": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^28.0.2", - "jest-matcher-utils": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-runtime": "^28.0.3", - "jest-snapshot": "^28.0.3", - "jest-util": "^28.0.2", - "pretty-format": "^28.0.2", + "jest-each": "^29.1.2", + "jest-matcher-utils": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-runtime": "^29.1.2", + "jest-snapshot": "^29.1.2", + "jest-util": "^29.1.2", + "p-limit": "^3.1.0", + "pretty-format": "^29.1.2", "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" + "stack-utils": "^2.0.3" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -36045,9 +36619,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -36082,9 +36656,9 @@ } }, "diff-sequences": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.0.2.tgz", - "integrity": "sha512-YtEoNynLDFCRznv/XDalsKGSZDoj0U5kLnXvY0JSq3nBboRrZXjD81+eSiwi+nzcZDwedMmcowcxNwwgFW23mQ==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.0.0.tgz", + "integrity": "sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==", "dev": true }, "has-flag": { @@ -36094,42 +36668,42 @@ "dev": true }, "jest-diff": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.0.2.tgz", - "integrity": "sha512-33Rnf821Y54OAloav0PGNWHlbtEorXpjwchnToyyWbec10X74FOW7hGfvrXLGz7xOe2dz0uo9JVFAHHj/2B5pg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.1.2.tgz", + "integrity": "sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "diff-sequences": "^29.0.0", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" } }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true }, "jest-matcher-utils": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.0.2.tgz", - "integrity": "sha512-SxtTiI2qLJHFtOz/bySStCnwCvISAuxQ/grS+74dfTy5AuJw3Sgj9TVUvskcnImTfpzLoMCDJseRaeRrVYbAOA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.1.2.tgz", + "integrity": "sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "jest-diff": "^29.1.2", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" } }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -36137,14 +36711,22 @@ "picomatch": "^2.2.3" } }, - "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "yocto-queue": "^0.1.0" + } + }, + "pretty-format": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "dev": true, + "requires": { + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -36158,9 +36740,9 @@ } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "supports-color": { @@ -36175,32 +36757,32 @@ } }, "jest-cli": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.0.3.tgz", - "integrity": "sha512-NCPTEONCnhYGo1qzPP4OOcGF04YasM5GZSwQLI1HtEluxa3ct4U65IbZs6DSRt8XN1Rq0jhXwv02m5lHB28Uyg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.1.2.tgz", + "integrity": "sha512-vsvBfQ7oS2o4MJdAH+4u9z76Vw5Q8WBQF5MchDbkylNknZdrPTX1Ix7YRJyTlOWqRaS7ue/cEAn+E4V1MWyMzw==", "dev": true, "requires": { - "@jest/core": "^28.0.3", - "@jest/test-result": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/core": "^29.1.2", + "@jest/test-result": "^29.1.2", + "@jest/types": "^29.1.2", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^28.0.3", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-config": "^29.1.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "prompts": "^2.0.1", "yargs": "^17.3.1" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -36209,9 +36791,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -36252,18 +36834,18 @@ "dev": true }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -36272,27 +36854,26 @@ } }, "jest-validate": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.0.2.tgz", - "integrity": "sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", + "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.0.0", "leven": "^3.1.0", - "pretty-format": "^28.0.2" + "pretty-format": "^29.1.2" } }, "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -36306,9 +36887,9 @@ } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "supports-color": { @@ -36323,42 +36904,42 @@ } }, "jest-config": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.0.3.tgz", - "integrity": "sha512-3gWOEHwGpNhyYOk9vnUMv94x15QcdjACm7A3lERaluwnyD6d1WZWe9RFCShgIXVOHzRfG1hWxsI2U0gKKSGgDQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.1.2.tgz", + "integrity": "sha512-EC3Zi86HJUOz+2YWQcJYQXlf0zuBhJoeyxLM6vb6qJsVmpP7KcCP1JnyF0iaqTaXdBP8Rlwsvs7hnKWQWWLwwA==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^28.0.2", - "@jest/types": "^28.0.2", - "babel-jest": "^28.0.3", + "@jest/test-sequencer": "^29.1.2", + "@jest/types": "^29.1.2", + "babel-jest": "^29.1.2", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^28.0.3", - "jest-environment-node": "^28.0.2", - "jest-get-type": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.0.3", - "jest-runner": "^28.0.3", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-circus": "^29.1.2", + "jest-environment-node": "^29.1.2", + "jest-get-type": "^29.0.0", + "jest-regex-util": "^29.0.0", + "jest-resolve": "^29.1.2", + "jest-runner": "^29.1.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^28.0.2", + "pretty-format": "^29.1.2", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -36367,9 +36948,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -36410,61 +36991,61 @@ "dev": true }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true }, "jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" } }, "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true }, "jest-resolve": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.0.3.tgz", - "integrity": "sha512-lfgjd9JhEjpjIN3HLUfdysdK+A7ePQoYmd7WL9DUEWqdnngb1rF56eee6iDXJxl/3eSolpP43VD7VrhjL3NsoQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.1.2.tgz", + "integrity": "sha512-7fcOr+k7UYSVRJYhSmJHIid3AnDBcLQX3VmT9OSbPWsWz1MfT7bcoerMhADKGvKCoMpOHUQaDHtQoNp/P9JMGg==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", + "jest-haste-map": "^29.1.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" } }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -36473,26 +37054,27 @@ } }, "jest-validate": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.0.2.tgz", - "integrity": "sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", + "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.0.0", "leven": "^3.1.0", - "pretty-format": "^28.0.2" + "pretty-format": "^29.1.2" } }, "jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "requires": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -36509,13 +37091,12 @@ } }, "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -36529,15 +37110,9 @@ } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "supports-color": { @@ -36609,34 +37184,34 @@ } }, "jest-docblock": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.0.2.tgz", - "integrity": "sha512-FH10WWw5NxLoeSdQlJwu+MTiv60aXV/t8KEwIRGEv74WARE1cXIqh1vGdy2CraHuWOOrnzTWj/azQKqW4fO7xg==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.0.0.tgz", + "integrity": "sha512-s5Kpra/kLzbqu9dEjov30kj1n4tfu3e7Pl8v+f8jOkeWNqM6Ds8jRaJfZow3ducoQUrf2Z4rs2N5S3zXnb83gw==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.0.2.tgz", - "integrity": "sha512-/W5Wc0b+ipR36kDaLngdVEJ/5UYPOITK7rW0djTlCCQdMuWpCFJweMW4TzAoJ6GiRrljPL8FwiyOSoSHKrda2w==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.1.2.tgz", + "integrity": "sha512-AmTQp9b2etNeEwMyr4jc0Ql/LIX/dhbgP21gHAizya2X6rUspHn2gysMXaj6iwWuOJ2sYRgP8c1P4cXswgvS1A==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "jest-util": "^28.0.2", - "pretty-format": "^28.0.2" + "jest-get-type": "^29.0.0", + "jest-util": "^29.1.2", + "pretty-format": "^29.1.2" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -36645,9 +37220,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -36688,18 +37263,18 @@ "dev": true }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -36708,13 +37283,12 @@ } }, "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -36728,9 +37302,9 @@ } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "supports-color": { @@ -36745,28 +37319,28 @@ } }, "jest-environment-jsdom": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-28.0.2.tgz", - "integrity": "sha512-rQhgV9reB6Id7VPa5jEkKx80Ppa/I6C7vKTMnceBS+d/rt+aTfbxbK/P4HRLMLE8KKsETszPpzYtGgsa8xMg7g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.1.2.tgz", + "integrity": "sha512-D+XNIKia5+uDjSMwL/G1l6N9MCb7LymKI8FpcLo7kkISjc/Sa9w+dXXEa7u1Wijo3f8sVLqfxdGqYtRhmca+Xw==", "dev": true, "requires": { - "@jest/environment": "^28.0.2", - "@jest/fake-timers": "^28.0.2", - "@jest/types": "^28.0.2", - "@types/jsdom": "^16.2.4", + "@jest/environment": "^29.1.2", + "@jest/fake-timers": "^29.1.2", + "@jest/types": "^29.1.2", + "@types/jsdom": "^20.0.0", "@types/node": "*", - "jest-mock": "^28.0.2", - "jest-util": "^28.0.2", - "jsdom": "^19.0.0" + "jest-mock": "^29.1.2", + "jest-util": "^29.1.2", + "jsdom": "^20.0.0" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -36775,9 +37349,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -36818,12 +37392,12 @@ "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -36843,26 +37417,26 @@ } }, "jest-environment-node": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.0.2.tgz", - "integrity": "sha512-o9u5UHZ+NCuIoa44KEF0Behhsz/p1wMm0WumsZfWR1k4IVoWSt3aN0BavSC5dd26VxSGQvkrCnJxxOzhhUEG3Q==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.1.2.tgz", + "integrity": "sha512-C59yVbdpY8682u6k/lh8SUMDJPbOyCHOTgLVVi1USWFxtNV+J8fyIwzkg+RJIVI30EKhKiAGNxYaFr3z6eyNhQ==", "dev": true, "requires": { - "@jest/environment": "^28.0.2", - "@jest/fake-timers": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/environment": "^29.1.2", + "@jest/fake-timers": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", - "jest-mock": "^28.0.2", - "jest-util": "^28.0.2" + "jest-mock": "^29.1.2", + "jest-util": "^29.1.2" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -36871,9 +37445,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -36914,12 +37488,12 @@ "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -37297,13 +37871,13 @@ } }, "jest-leak-detector": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.0.2.tgz", - "integrity": "sha512-UGaSPYtxKXl/YKacq6juRAKmMp1z2os8NaU8PSC+xvNikmu3wF6QFrXrihMM4hXeMr9HuNotBrQZHmzDY8KIBQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.1.2.tgz", + "integrity": "sha512-TG5gAZJpgmZtjb6oWxBLf2N6CfQ73iwCe6cofu/Uqv9iiAm6g502CAnGtxQaTfpHECBdVEMRBhomSXeLnoKjiQ==", "dev": true, "requires": { - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" }, "dependencies": { "ansi-styles": { @@ -37313,27 +37887,26 @@ "dev": true }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true }, "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true } } @@ -37396,29 +37969,29 @@ } }, "jest-message-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.0.2.tgz", - "integrity": "sha512-knK7XyojvwYh1XiF2wmVdskgM/uN11KsjcEWWHfnMZNEdwXCrqB4sCBO94F4cfiAwCS8WFV6CDixDwPlMh/wdA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.1.2.tgz", + "integrity": "sha512-9oJ2Os+Qh6IlxLpmvshVbGUiSkZVc2FK+uGOm6tghafnB2RyjKAxMZhtxThRMxfX1J1SOMhTn9oK3/MutRWQJQ==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^28.0.2", + "pretty-format": "^29.1.2", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -37427,9 +38000,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -37470,13 +38043,12 @@ "dev": true }, "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -37490,9 +38062,9 @@ } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "supports-color": { @@ -37507,22 +38079,23 @@ } }, "jest-mock": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.0.2.tgz", - "integrity": "sha512-vfnJ4zXRB0i24jOTGtQJyl26JKsgBKtqRlCnsrORZbG06FToSSn33h2x/bmE8XxqxkLWdZBRo+/65l8Vi3nD+g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.1.2.tgz", + "integrity": "sha512-PFDAdjjWbjPUtQPkQufvniXIS3N9Tv7tbibePEjIIprzjgo0qQlyUiVMrT4vL8FaSJo1QXifQUOuPH3HQC/aMA==", "dev": true, "requires": { - "@jest/types": "^28.0.2", - "@types/node": "*" + "@jest/types": "^29.1.2", + "@types/node": "*", + "jest-util": "^29.1.2" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -37531,9 +38104,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -37573,6 +38146,20 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "jest-util": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", + "dev": true, + "requires": { + "@jest/types": "^29.1.2", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -37661,59 +38248,59 @@ } }, "jest-resolve-dependencies": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.0.3.tgz", - "integrity": "sha512-lCgHMm0/5p0qHemrOzm7kI6JDei28xJwIf7XOEcv1HeAVHnsON8B8jO/woqlU+/GcOXb58ymieYqhk3zjGWnvQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.1.2.tgz", + "integrity": "sha512-44yYi+yHqNmH3OoWZvPgmeeiwKxhKV/0CfrzaKLSkZG9gT973PX8i+m8j6pDrTYhhHoiKfF3YUFg/6AeuHw4HQ==", "dev": true, "requires": { - "jest-regex-util": "^28.0.2", - "jest-snapshot": "^28.0.3" + "jest-regex-util": "^29.0.0", + "jest-snapshot": "^29.1.2" }, "dependencies": { "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true } } }, "jest-runner": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.0.3.tgz", - "integrity": "sha512-4OsHMjBLtYUWCENucAQ4Za0jGfEbOFi/Fusv6dzUuaweqx8apb4+5p2LR2yvgF4StFulmxyC238tGLftfu+zBA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.1.2.tgz", + "integrity": "sha512-yy3LEWw8KuBCmg7sCGDIqKwJlULBuNIQa2eFSVgVASWdXbMYZ9H/X0tnXt70XFoGf92W2sOQDOIFAA6f2BG04Q==", "dev": true, "requires": { - "@jest/console": "^28.0.2", - "@jest/environment": "^28.0.2", - "@jest/test-result": "^28.0.2", - "@jest/transform": "^28.0.3", - "@jest/types": "^28.0.2", + "@jest/console": "^29.1.2", + "@jest/environment": "^29.1.2", + "@jest/test-result": "^29.1.2", + "@jest/transform": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.10.2", "graceful-fs": "^4.2.9", - "jest-docblock": "^28.0.2", - "jest-environment-node": "^28.0.2", - "jest-haste-map": "^28.0.2", - "jest-leak-detector": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-resolve": "^28.0.3", - "jest-runtime": "^28.0.3", - "jest-util": "^28.0.2", - "jest-watcher": "^28.0.2", - "jest-worker": "^28.0.2", - "source-map-support": "0.5.13", - "throat": "^6.0.1" + "jest-docblock": "^29.0.0", + "jest-environment-node": "^29.1.2", + "jest-haste-map": "^29.1.2", + "jest-leak-detector": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-resolve": "^29.1.2", + "jest-runtime": "^29.1.2", + "jest-util": "^29.1.2", + "jest-watcher": "^29.1.2", + "jest-worker": "^29.1.2", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -37722,9 +38309,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -37765,61 +38352,61 @@ "dev": true }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true }, "jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" } }, "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true }, "jest-resolve": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.0.3.tgz", - "integrity": "sha512-lfgjd9JhEjpjIN3HLUfdysdK+A7ePQoYmd7WL9DUEWqdnngb1rF56eee6iDXJxl/3eSolpP43VD7VrhjL3NsoQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.1.2.tgz", + "integrity": "sha512-7fcOr+k7UYSVRJYhSmJHIid3AnDBcLQX3VmT9OSbPWsWz1MfT7bcoerMhADKGvKCoMpOHUQaDHtQoNp/P9JMGg==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", + "jest-haste-map": "^29.1.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" } }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -37828,26 +38415,27 @@ } }, "jest-validate": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.0.2.tgz", - "integrity": "sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", + "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.0.0", "leven": "^3.1.0", - "pretty-format": "^28.0.2" + "pretty-format": "^29.1.2" } }, "jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "requires": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -37863,14 +38451,22 @@ } } }, - "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "yocto-queue": "^0.1.0" + } + }, + "pretty-format": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "dev": true, + "requires": { + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -37884,9 +38480,9 @@ } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "source-map-support": { @@ -37911,42 +38507,42 @@ } }, "jest-runtime": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.0.3.tgz", - "integrity": "sha512-7FtPUmvbZEHLOdjsF6dyHg5Pe4E0DU+f3Vvv8BPzVR7mQA6nFR4clQYLAPyJGnsUvN8WRWn+b5a5SVwnj1WaGg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.1.2.tgz", + "integrity": "sha512-jr8VJLIf+cYc+8hbrpt412n5jX3tiXmpPSYTGnwcvNemY+EOuLNiYnHJ3Kp25rkaAcTWOEI4ZdOIQcwYcXIAZw==", "dev": true, "requires": { - "@jest/environment": "^28.0.2", - "@jest/fake-timers": "^28.0.2", - "@jest/globals": "^28.0.3", - "@jest/source-map": "^28.0.2", - "@jest/test-result": "^28.0.2", - "@jest/transform": "^28.0.3", - "@jest/types": "^28.0.2", + "@jest/environment": "^29.1.2", + "@jest/fake-timers": "^29.1.2", + "@jest/globals": "^29.1.2", + "@jest/source-map": "^29.0.0", + "@jest/test-result": "^29.1.2", + "@jest/transform": "^29.1.2", + "@jest/types": "^29.1.2", + "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-mock": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.0.3", - "jest-snapshot": "^28.0.3", - "jest-util": "^28.0.2", + "jest-haste-map": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-mock": "^29.1.2", + "jest-regex-util": "^29.0.0", + "jest-resolve": "^29.1.2", + "jest-snapshot": "^29.1.2", + "jest-util": "^29.1.2", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -37955,9 +38551,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -37998,61 +38594,61 @@ "dev": true }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true }, "jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" } }, "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true }, "jest-resolve": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.0.3.tgz", - "integrity": "sha512-lfgjd9JhEjpjIN3HLUfdysdK+A7ePQoYmd7WL9DUEWqdnngb1rF56eee6iDXJxl/3eSolpP43VD7VrhjL3NsoQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.1.2.tgz", + "integrity": "sha512-7fcOr+k7UYSVRJYhSmJHIid3AnDBcLQX3VmT9OSbPWsWz1MfT7bcoerMhADKGvKCoMpOHUQaDHtQoNp/P9JMGg==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.0.2", + "jest-haste-map": "^29.1.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.0.2", - "jest-validate": "^28.0.2", + "jest-util": "^29.1.2", + "jest-validate": "^29.1.2", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" } }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -38061,26 +38657,27 @@ } }, "jest-validate": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.0.2.tgz", - "integrity": "sha512-nr0UOvCTtxP0YPdsk01Gk7e7c0xIiEe2nncAe3pj0wBfUvAykTVrMrdeASlAJnlEQCBuwN/GF4hKoCzbkGNCNw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", + "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.0.0", "leven": "^3.1.0", - "pretty-format": "^28.0.2" + "pretty-format": "^29.1.2" } }, "jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "requires": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -38097,13 +38694,12 @@ } }, "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -38117,9 +38713,9 @@ } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "strip-bom": { @@ -38150,43 +38746,44 @@ } }, "jest-snapshot": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.0.3.tgz", - "integrity": "sha512-nVzAAIlAbrMuvVUrS1YxmAeo1TfSsDDU+K5wv/Ow56MBp+L+Y71ksAbwRp3kGCgZAz4oOXcAMPAwtT9Yh1hlQQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.1.2.tgz", + "integrity": "sha512-rYFomGpVMdBlfwTYxkUp3sjD6usptvZcONFYNqVlaz4EpHPnDvlWjvmOQ9OCSNKqYZqLM2aS3wq01tWujLg7gg==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^28.0.2", - "@jest/transform": "^28.0.3", - "@jest/types": "^28.0.2", + "@jest/expect-utils": "^29.1.2", + "@jest/transform": "^29.1.2", + "@jest/types": "^29.1.2", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^28.0.2", + "expect": "^29.1.2", "graceful-fs": "^4.2.9", - "jest-diff": "^28.0.2", - "jest-get-type": "^28.0.2", - "jest-haste-map": "^28.0.2", - "jest-matcher-utils": "^28.0.2", - "jest-message-util": "^28.0.2", - "jest-util": "^28.0.2", + "jest-diff": "^29.1.2", + "jest-get-type": "^29.0.0", + "jest-haste-map": "^29.1.2", + "jest-matcher-utils": "^29.1.2", + "jest-message-util": "^29.1.2", + "jest-util": "^29.1.2", "natural-compare": "^1.4.0", - "pretty-format": "^28.0.2", + "pretty-format": "^29.1.2", "semver": "^7.3.5" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -38195,9 +38792,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -38232,9 +38829,9 @@ } }, "diff-sequences": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.0.2.tgz", - "integrity": "sha512-YtEoNynLDFCRznv/XDalsKGSZDoj0U5kLnXvY0JSq3nBboRrZXjD81+eSiwi+nzcZDwedMmcowcxNwwgFW23mQ==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.0.0.tgz", + "integrity": "sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==", "dev": true }, "has-flag": { @@ -38244,68 +38841,68 @@ "dev": true }, "jest-diff": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.0.2.tgz", - "integrity": "sha512-33Rnf821Y54OAloav0PGNWHlbtEorXpjwchnToyyWbec10X74FOW7hGfvrXLGz7xOe2dz0uo9JVFAHHj/2B5pg==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.1.2.tgz", + "integrity": "sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "diff-sequences": "^29.0.0", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" } }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", + "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", "dev": true }, "jest-haste-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.0.2.tgz", - "integrity": "sha512-EokdL7l5uk4TqWGawwrIt8w3tZNcbeiRxmKGEURf42pl+/rWJy3sCJlon5HBhJXZTW978jk6600BLQOI7i25Ig==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", + "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.0.2", - "jest-worker": "^28.0.2", + "jest-regex-util": "^29.0.0", + "jest-util": "^29.1.2", + "jest-worker": "^29.1.2", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" } }, "jest-matcher-utils": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.0.2.tgz", - "integrity": "sha512-SxtTiI2qLJHFtOz/bySStCnwCvISAuxQ/grS+74dfTy5AuJw3Sgj9TVUvskcnImTfpzLoMCDJseRaeRrVYbAOA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.1.2.tgz", + "integrity": "sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^28.0.2", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.0.2" + "jest-diff": "^29.1.2", + "jest-get-type": "^29.0.0", + "pretty-format": "^29.1.2" } }, "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", + "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -38314,12 +38911,13 @@ } }, "jest-worker": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.0.2.tgz", - "integrity": "sha512-pijNxfjxT0tGAx+8+OzZ+eayVPCwy/rsZFhebmC0F4YnXu1EHPEPxg7utL3m5uX3EaFH1/jwDxGa1EbjJCST2g==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", + "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", "dev": true, "requires": { "@types/node": "*", + "jest-util": "^29.1.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -38336,13 +38934,12 @@ } }, "pretty-format": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.0.2.tgz", - "integrity": "sha512-UmGZ1IERwS3yY35LDMTaBUYI1w4udZDdJGGT/DqQeKG9ZLDn7/K2Jf/JtYSRiHCCKMHvUA+zsEGSmHdpaVp1yw==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", + "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -38356,15 +38953,15 @@ } }, "react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -38499,132 +39096,29 @@ } } }, - "jest-watch-typeahead": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", - "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.1", - "chalk": "^4.0.0", - "jest-regex-util": "^28.0.0", - "jest-watcher": "^28.0.0", - "slash": "^4.0.0", - "string-length": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "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": "2.0.1", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", - "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", - "dev": true - }, - "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" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", - "dev": true - }, - "slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true - }, - "string-length": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", - "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", - "dev": true, - "requires": { - "char-regex": "^2.0.0", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "supports-color": { - "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" - } - } - } - }, "jest-watcher": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.0.2.tgz", - "integrity": "sha512-uIVJLpQ/5VTGQWBiBatHsi7jrCqHjHl0e0dFHMWzwuIfUbdW/muk0DtSr0fteY2T7QTFylv+7a5Rm8sBKrE12Q==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.1.2.tgz", + "integrity": "sha512-6JUIUKVdAvcxC6bM8/dMgqY2N4lbT+jZVsxh0hCJRbwkIEnbr/aPjMQ28fNDI5lB51Klh00MWZZeVf27KBUj5w==", "dev": true, "requires": { - "@jest/test-result": "^28.0.2", - "@jest/types": "^28.0.2", + "@jest/test-result": "^29.1.2", + "@jest/types": "^29.1.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.10.2", - "jest-util": "^28.0.2", + "jest-util": "^29.1.2", "string-length": "^4.0.1" }, "dependencies": { "@jest/types": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.0.2.tgz", - "integrity": "sha512-hi3jUdm9iht7I2yrV5C4s3ucCJHUP8Eh3W6rQ1s4n/Qw9rQgsda4eqCt+r3BKRi7klVmZfQlMx1nGlzNMP2d8A==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", + "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -38633,9 +39127,9 @@ } }, "@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -38676,12 +39170,12 @@ "dev": true }, "jest-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.0.2.tgz", - "integrity": "sha512-EVdpIRCC8lzqhp9A0u0aAKlsFIzufK6xKxNK7awsnebTdOP4hpyQW5o6Ox2qPl8gbeUKYF+POLyItaND53kpGA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", + "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", "dev": true, "requires": { - "@jest/types": "^28.0.2", + "@jest/types": "^29.1.2", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -38728,6 +39222,12 @@ } } }, + "js-sdsl": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz", @@ -38744,51 +39244,69 @@ } }, "jsdom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz", - "integrity": "sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A==", + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", "dev": true, "requires": { - "abab": "^2.0.5", - "acorn": "^8.5.0", - "acorn-globals": "^6.0.0", + "abab": "^2.0.6", + "acorn": "^8.8.0", + "acorn-globals": "^7.0.0", "cssom": "^0.5.0", "cssstyle": "^2.3.0", - "data-urls": "^3.0.1", - "decimal.js": "^10.3.1", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.1", "domexception": "^4.0.0", "escodegen": "^2.0.0", "form-data": "^4.0.0", "html-encoding-sniffer": "^3.0.0", "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", + "tough-cookie": "^4.1.2", "w3c-xmlserializer": "^3.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^2.0.0", "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^10.0.0", - "ws": "^8.2.3", + "whatwg-url": "^11.0.0", + "ws": "^8.9.0", "xml-name-validator": "^4.0.0" }, "dependencies": { "acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", "dev": true }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "requires": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true + }, + "saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } } } }, @@ -38798,12 +39316,6 @@ "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-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -38851,6 +39363,15 @@ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -38912,9 +39433,9 @@ } }, "leaflet": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.8.0.tgz", - "integrity": "sha512-gwhMjFCQiYs3x/Sf+d49f10ERXaEFCPr+nVTryhAW8DWbMGqJqt9G4XuIaHmFW08zYvhgdzqXGr8AlW8v8dQkA==" + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.2.tgz", + "integrity": "sha512-Kc77HQvWO+y9y2oIs3dn5h5sy2kr3j41ewdqCMEUA4N89lgfUUfOBy7wnnHEstDpefiGFObq12FdopGRMx4J7g==" }, "leven": { "version": "3.1.0", @@ -38951,9 +39472,9 @@ "dev": true }, "loader-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", - "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", "dev": true }, "locate-path": { @@ -39024,77 +39545,32 @@ "dev": true }, "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", "dev": true, "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "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" - } - }, - "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" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "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" - } - } + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" } }, "log4js": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.2.tgz", - "integrity": "sha512-k80cggS2sZQLBwllpT1p06GtfvzMmSdUCkW96f0Hj83rKGJDAu2vZjt9B9ag2vx8Zz1IXzxoLgqvRJCdMKybGg==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.6.1.tgz", + "integrity": "sha512-J8VYFH2UQq/xucdNu71io4Fo+purYYudyErgBbswWKO0MC6QVOERRomt5su/z6d3RJSmLyTGmXl3Q/XjKCf+/A==", "dev": true, "requires": { - "date-format": "^4.0.4", - "debug": "^4.3.3", - "flatted": "^3.2.5", + "date-format": "^4.0.13", + "debug": "^4.3.4", + "flatted": "^3.2.6", "rfdc": "^1.3.0", - "streamroller": "^3.0.4" + "streamroller": "^3.1.2" }, "dependencies": { "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -39323,9 +39799,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -39389,9 +39865,9 @@ "dev": true }, "mutation-testing-elements": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/mutation-testing-elements/-/mutation-testing-elements-1.7.10.tgz", - "integrity": "sha512-qejt4InSYzFGhN84+mbpj96aKl41g0IRTIEVuOepKgcdMdrmb2dhXBB5Mysncmz7NF/VzXSTGutdQFTz9johfw==", + "version": "1.7.12", + "resolved": "https://registry.npmjs.org/mutation-testing-elements/-/mutation-testing-elements-1.7.12.tgz", + "integrity": "sha512-6L5PiREMKWirDOVoMVpJtq4r1MfHZgme78PFQl9W59YQq/rqmHpYAcwrdUYikPVYASp4r91ZupiKlFHgCPiVBw==", "dev": true }, "mutation-testing-metrics": { @@ -39439,12 +39915,6 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=", - "dev": true - }, "no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -39476,9 +39946,9 @@ "dev": true }, "node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, "normalize-package-data": { @@ -39516,21 +39986,6 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, - "normalize-selector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", - "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", - "dev": true - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, "nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", @@ -39541,9 +39996,9 @@ } }, "nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", "dev": true }, "object-assign": { @@ -39560,8 +40015,7 @@ "object-inspect": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "dev": true + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" }, "object-is": { "version": "1.1.3", @@ -39692,17 +40146,6 @@ "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" - }, - "dependencies": { - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - } } }, "optionator": { @@ -39720,64 +40163,36 @@ } }, "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz", + "integrity": "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==", "dev": true, "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", + "bl": "^5.0.0", + "chalk": "^5.0.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.6.1", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.1.0", + "log-symbols": "^5.1.0", + "strip-ansi": "^7.0.1", "wcwidth": "^1.0.1" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "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" - } + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true }, "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "requires": { + "restore-cursor": "^4.0.0" + } }, "mimic-fn": { "version": "2.1.0", @@ -39795,22 +40210,22 @@ } }, "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, "requires": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "ansi-regex": "^6.0.1" } } } @@ -39832,12 +40247,6 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, "p-limit": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", @@ -39922,6 +40331,23 @@ "lines-and-columns": "^1.1.6" } }, + "parse5": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", + "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", + "dev": true, + "requires": { + "entities": "^4.4.0" + }, + "dependencies": { + "entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "dev": true + } + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -39961,13 +40387,7 @@ "path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", "dev": true }, "path-parse": { @@ -39976,6 +40396,12 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -40119,12 +40545,12 @@ } }, "postcss": { - "version": "8.4.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", - "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", + "version": "8.4.17", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz", + "integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==", "dev": true, "requires": { - "nanoid": "^3.3.3", + "nanoid": "^3.3.4", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -40651,16 +41077,6 @@ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz", @@ -40674,17 +41090,18 @@ "dev": true }, "qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } }, "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true, - "optional": true, - "peer": true + "dev": true }, "quick-lru": { "version": "4.0.1", @@ -40718,7 +41135,7 @@ "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", "dev": true }, "raw-body": { @@ -40743,20 +41160,28 @@ }, "rc": { "version": "1.2.8", - "resolved": "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz", - "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", + "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", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true + } } }, "react": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.1.0.tgz", - "integrity": "sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "requires": { "loose-envify": "^1.1.0" } @@ -40784,15 +41209,15 @@ } }, "react-chartjs-2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-4.1.0.tgz", - "integrity": "sha512-AsUihxEp8Jm1oBhbEovE+w50m9PVNhz1sfwEIT4hZduRC0m14gHWHd0cUaxkFDb8HNkdMIGzsNlmVqKiOpU74g==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-4.3.1.tgz", + "integrity": "sha512-5i3mjP6tU7QSn0jvb8I4hudTzHJqS8l00ORJnVwI2sYu0ihpj83Lv2YzfxunfxTZkscKvZu2F2w9LkwNBhj6xA==", "requires": {} }, "react-colorful": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.5.1.tgz", - "integrity": "sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", "requires": {} }, "react-copy-to-clipboard": { @@ -40959,22 +41384,12 @@ } }, "react-dom": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.1.0.tgz", - "integrity": "sha512-fU1Txz7Budmvamp7bshe4Zi32d0ll7ect+ccxNu9FlObT605GOEB8BfO4tmRJ39R5Zj831VCpvQ05QPBW5yb+w==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "requires": { "loose-envify": "^1.1.0", - "scheduler": "^0.22.0" - }, - "dependencies": { - "scheduler": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.22.0.tgz", - "integrity": "sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ==", - "requires": { - "loose-envify": "^1.1.0" - } - } + "scheduler": "^0.23.0" } }, "react-error-overlay": { @@ -41000,17 +41415,17 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "react-leaflet": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.0.0.tgz", - "integrity": "sha512-qJJvoCNe12XHSWVUwhXYmMObPoSYy8h/hn0aDNvcBuq3O8zmVI5S2RdabhaDg/iWMCJ2jbCWZWtIU5VtztO9sg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.1.0.tgz", + "integrity": "sha512-i+V9pX5lywJ48O2+K3USeeTdYLIhxnLMweH+YLd/UPqVIj3uKzE3Q29bzt83PBtViyZmxDlulzC6uoR3JLiE9A==", "requires": { - "@react-leaflet/core": "^2.0.0" + "@react-leaflet/core": "^2.1.0" } }, "react-redux": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.1.tgz", - "integrity": "sha512-LMZMsPY4DYdZfLJgd7i79n5Kps5N9XVLCJJeWAaPYTV+Eah2zTuBjTxKtNEbjiyitbq80/eIkm55CYSLqAub3w==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.4.tgz", + "integrity": "sha512-yMfQ7mX6bWuicz2fids6cR1YT59VTuT8MKyyE310wJQlINKENCeT1UcPdEiX6znI5tF8zXyJ/VYvDgeGuaaNwQ==", "requires": { "@babel/runtime": "^7.12.1", "@types/hoist-non-react-statics": "^3.3.1", @@ -41034,20 +41449,20 @@ "dev": true }, "react-router": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", - "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.1.tgz", + "integrity": "sha512-OJASKp5AykDWFewgWUim1vlLr7yfD4vO/h+bSgcP/ix8Md+LMHuAjovA74MQfsfhQJGGN1nHRhwS5qQQbbBt3A==", "requires": { - "history": "^5.2.0" + "@remix-run/router": "1.0.1" } }, "react-router-dom": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", - "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.1.tgz", + "integrity": "sha512-MY7NJCrGNVJtGp8ODMOBHu20UaIkmwD2V3YsAOUQoCXFk7Ppdwf55RdcGyrSj+ycSL9Uiwrb3gTLYSnzcRoXww==", "requires": { - "history": "^5.2.0", - "react-router": "6.3.0" + "@remix-run/router": "1.0.1", + "react-router": "6.4.1" } }, "react-scripts": { @@ -41226,6 +41641,15 @@ "v8-to-istanbul": "^8.1.0" } }, + "@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.24.1" + } + }, "@jest/source-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", @@ -41330,6 +41754,15 @@ "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", "dev": true }, + "@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, "acorn": { "version": "8.7.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", @@ -42082,6 +42515,218 @@ "semver": "^7.3.2" } }, + "jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "dev": true, + "requires": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "dependencies": { + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, + "@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "dev": true, + "requires": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "requires": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "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 + }, + "emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "dev": true + }, + "jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, + "jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "dev": true + }, + "jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dev": true, + "requires": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "dev": true, + "requires": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "dependencies": { + "string-length": { + "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": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "requires": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true + }, + "string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "dev": true, + "requires": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + } + } + } + } + }, "jest-watcher": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", @@ -42160,9 +42805,9 @@ } }, "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "requires": { "big.js": "^5.2.2", @@ -42518,6 +43163,12 @@ "renderkid": "^3.0.0" } }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, "renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -42578,12 +43229,6 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, "style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -42787,9 +43432,9 @@ } }, "reactstrap": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-9.0.1.tgz", - "integrity": "sha512-89VOv7SRlAlpS7RwXhzOQkSWkuhBR8LBsPGfNHifNL3WhtNP9y1sBdTcTYyH1ee2QtI8zRdwD0T5I/blHiwemg==", + "version": "9.1.4", + "resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-9.1.4.tgz", + "integrity": "sha512-kn+Ex58V4tZatogn472n5fkgvCkXwhQvlqCRGTjpM1MzkD9wv0rp5W0VcM60purpdtzkud2ku6KHvJrqYqnv0w==", "requires": { "@babel/runtime": "^7.12.5", "@popperjs/core": "^2.6.0", @@ -42937,12 +43582,12 @@ } }, "recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", "dev": true, "requires": { - "minimatch": "3.0.4" + "minimatch": "^3.0.5" } }, "redent": { @@ -42964,17 +43609,17 @@ } }, "redux-localstorage-simple": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/redux-localstorage-simple/-/redux-localstorage-simple-2.4.1.tgz", - "integrity": "sha512-Oij3OAPukQVNqHwakfOXWGAcv254HvFtePIyZQY3tfomG8ruz4BV5FL4WytO4Pz8Ja7i3r9cCTEXvnzgv1xCJg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/redux-localstorage-simple/-/redux-localstorage-simple-2.5.1.tgz", + "integrity": "sha512-8HbqBzHoZ4nfL8qyELt4hLd9hNmESCvmXTEBk2mGT23lX8/miJbXz4ZGIF7Eoa1UHikjv+bne3pjC95ub737vA==", "requires": { "merge": "2.1.1" } }, "redux-thunk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", "requires": {} }, "regenerate": { @@ -43044,8 +43689,8 @@ }, "registry-auth-token": { "version": "3.3.2", - "resolved": "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha1-hR/UkDjuy1hpERFa+EUmDuyYPyA=", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", "dev": true, "requires": { "rc": "^1.1.6", @@ -43055,7 +43700,7 @@ "registry-url": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", "dev": true, "requires": { "rc": "^1.0.1" @@ -43108,6 +43753,11 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "reselect": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", + "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==" + }, "resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", @@ -43168,9 +43818,9 @@ "dev": true }, "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "requires": { "big.js": "^5.2.2", @@ -43311,9 +43961,9 @@ "dev": true }, "sass": { - "version": "1.49.9", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.9.tgz", - "integrity": "sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A==", + "version": "1.55.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.55.0.tgz", + "integrity": "sha512-Pk+PMy7OGLs9WaxZGJMn7S96dvlyVBwwtToX895WmCpAOr5YiJYEUJfiJidMuKb613z2xNWcXCHEuOvjZbqC6A==", "dev": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", @@ -43336,6 +43986,14 @@ "xmlchars": "^2.2.0" } }, + "scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "requires": { + "loose-envify": "^1.1.0" + } + }, "schema-utils": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", @@ -43413,46 +44071,55 @@ } }, "serve": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/serve/-/serve-13.0.2.tgz", - "integrity": "sha512-71R6fKvNgKrqARAag6lYJNnxDzpH7DCNrMuvPY5PLVaC2PDhJsGTj/34o4o4tPWhTuLgEXqvgnAWbATQ9zGZTQ==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/serve/-/serve-14.1.1.tgz", + "integrity": "sha512-7RhRDEirZ7Qyee4QWhBHO9qRtjIGsIPGecDDPzNzlOsjDiZWcq36GS8FioVJAuJPVJBBDTsGp33WWOO4B9A82g==", "dev": true, "requires": { - "@zeit/schemas": "2.6.0", - "ajv": "6.12.6", - "arg": "2.0.0", - "boxen": "5.1.2", - "chalk": "2.4.1", - "clipboardy": "2.3.0", - "compression": "1.7.3", - "serve-handler": "6.1.3", - "update-check": "1.5.2" + "@zeit/schemas": "2.21.0", + "ajv": "8.11.0", + "arg": "5.0.2", + "boxen": "7.0.0", + "chalk": "5.0.1", + "chalk-template": "0.4.0", + "clipboardy": "3.0.0", + "compression": "1.7.4", + "is-port-reachable": "4.0.0", + "serve-handler": "6.1.5", + "update-check": "1.5.4" }, "dependencies": { - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true } } }, "serve-handler": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", - "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", "dev": true, "requires": { "bytes": "3.0.0", "content-disposition": "0.5.2", "fast-url-parser": "1.1.3", "mime-types": "2.1.18", - "minimatch": "3.0.4", + "minimatch": "3.1.2", "path-is-inside": "1.0.2", "path-to-regexp": "2.2.1", "range-parser": "1.2.0" @@ -43472,12 +44139,6 @@ "requires": { "mime-db": "~1.33.0" } - }, - "path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", - "dev": true } } }, @@ -43534,21 +44195,6 @@ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, "shell-quote": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", @@ -43559,7 +44205,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "requires": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -43814,12 +44459,6 @@ } } }, - "specificity": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", - "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", - "dev": true - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -43870,44 +44509,34 @@ } }, "streamroller": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.4.tgz", - "integrity": "sha512-GI9NzeD+D88UFuIlJkKNDH/IsuR+qIN7Qh8EsmhoRZr9bQoehTraRgwtLUkZbpcAw+hLPfHOypmppz8YyGK68w==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.3.tgz", + "integrity": "sha512-CphIJyFx2SALGHeINanjFRKQ4l7x2c+rXYJ4BMq0gd+ZK0gi4VT8b+eHe2wi58x4UayBAKx4xtHpXT/ea1cz8w==", "dev": true, "requires": { - "date-format": "^4.0.4", - "debug": "^4.3.3", - "fs-extra": "^10.0.1" + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" }, "dependencies": { "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" } }, "fs-extra": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", - "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "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": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, "ms": { @@ -43917,9 +44546,9 @@ "dev": true }, "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true } } @@ -44078,12 +44707,6 @@ "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", "dev": true }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -44100,9 +44723,9 @@ } }, "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=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "stryker-cli": { @@ -44178,21 +44801,20 @@ "dev": true }, "stylelint": { - "version": "14.8.2", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.8.2.tgz", - "integrity": "sha512-tjDfexCYfoPdl/xcDJ9Fv+Ko9cvzbDnmdiaqEn3ovXHXasi/hbkt5tSjsiReQ+ENqnz0eltaX/AOO+AlzVdcNA==", + "version": "14.13.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.13.0.tgz", + "integrity": "sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==", "dev": true, "requires": { + "@csstools/selector-specificity": "^2.0.2", "balanced-match": "^2.0.0", - "colord": "^2.9.2", + "colord": "^2.9.3", "cosmiconfig": "^7.0.1", - "css-functions-list": "^3.0.1", + "css-functions-list": "^3.1.0", "debug": "^4.3.4", - "execall": "^2.0.0", - "fast-glob": "^3.2.11", - "fastest-levenshtein": "^1.0.12", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", "file-entry-cache": "^6.0.1", - "get-stdin": "^8.0.0", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -44206,24 +44828,22 @@ "meow": "^9.0.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", - "normalize-selector": "^0.2.0", "picocolors": "^1.0.0", - "postcss": "^8.4.13", + "postcss": "^8.4.16", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", - "specificity": "^0.4.1", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "style-search": "^0.1.0", - "supports-hyperlinks": "^2.2.0", + "supports-hyperlinks": "^2.3.0", "svg-tags": "^1.0.0", "table": "^6.8.0", "v8-compile-cache": "^2.3.0", - "write-file-atomic": "^4.0.1" + "write-file-atomic": "^4.0.2" }, "dependencies": { "balanced-match": { @@ -44271,9 +44891,9 @@ } }, "write-file-atomic": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz", - "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "requires": { "imurmurhash": "^0.1.4", @@ -44344,9 +44964,9 @@ } }, "supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, "requires": { "has-flag": "^4.0.0", @@ -44516,12 +45136,6 @@ "color-convert": "^2.0.1" } }, - "arg": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", - "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", - "dev": true - }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -44790,14 +45404,15 @@ "dev": true }, "tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", "dev": true, "requires": { "psl": "^1.1.33", "punycode": "^2.1.1", - "universalify": "^0.1.2" + "universalify": "^0.2.0", + "url-parse": "^1.5.3" } }, "tr46": { @@ -44942,9 +45557,9 @@ } }, "typescript": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", - "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true }, "unbox-primitive": { @@ -44994,9 +45609,9 @@ "dev": true }, "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true }, "unpipe": { @@ -45017,10 +45632,20 @@ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, + "update-browserslist-db": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz", + "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "update-check": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.2.tgz", - "integrity": "sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", + "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", "dev": true, "requires": { "registry-auth-token": "3.3.2", @@ -45041,8 +45666,6 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, - "optional": true, - "peer": true, "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -45096,12 +45719,12 @@ "dev": true }, "v8-to-istanbul": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.0.tgz", - "integrity": "sha512-HcvgY/xaRm7isYmyx+lFKA4uQmfUbN0J4M0nNItvzTvH/iQ9kW5j/t4YSR+Ge323/lrgDAWJoF46tzGQHwBHFw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", + "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0" } @@ -45158,9 +45781,9 @@ } }, "watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -45179,16 +45802,16 @@ "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, "requires": { "defaults": "^1.0.3" } }, "weapon-regex": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/weapon-regex/-/weapon-regex-0.6.0.tgz", - "integrity": "sha512-k1gh8cffl+uOEakFS3Ze32nBsoqmcXembTI3nNQMPMUKAr83YBShTrjYGyeVC9zNzW5Ac/+dcvk3PLYUtNtSEQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/weapon-regex/-/weapon-regex-1.0.3.tgz", + "integrity": "sha512-V8X6hPIzY1juvrSVREmtRhK9AHn/8c2z8XxaibESU+jyG/RinZ9x9x6aw8qEuFAi7R6Kl/EWGbU2Yq/9u6TTjw==", "dev": true }, "webidl-conversions": { @@ -45198,9 +45821,9 @@ "dev": true }, "webpack": { - "version": "5.70.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", - "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", + "version": "5.74.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", + "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", @@ -45208,24 +45831,24 @@ "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", + "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.2", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", + "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "dependencies": { @@ -45236,9 +45859,9 @@ "dev": true }, "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", "dev": true }, "acorn-import-assertions": { @@ -45399,21 +46022,6 @@ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", "dev": true }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - } - }, "del": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", @@ -45574,9 +46182,9 @@ "dev": true }, "whatwg-url": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-10.0.0.tgz", - "integrity": "sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dev": true, "requires": { "tr46": "^3.0.0", @@ -45606,29 +46214,44 @@ } }, "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", "dev": true, "requires": { - "string-width": "^4.0.0" + "string-width": "^5.0.1" }, "dependencies": { - "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==", + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" } } } @@ -45647,6 +46270,14 @@ "requires": { "idb": "^6.1.4", "workbox-core": "6.5.1" + }, + "dependencies": { + "workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + } } }, "workbox-broadcast-update": { @@ -45656,6 +46287,14 @@ "dev": true, "requires": { "workbox-core": "6.5.1" + }, + "dependencies": { + "workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + } } }, "workbox-build": { @@ -45772,6 +46411,51 @@ "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } + }, + "workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, + "workbox-expiration": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.1.tgz", + "integrity": "sha512-iY/cTADAQATMmPkUBRmQdacqq0TJd2wMHimBQz+tRnPGHSMH+/BoLPABPnu7O7rT/g/s59CUYYRGxe3mEgoJCA==", + "dev": true, + "requires": { + "idb": "^6.1.4", + "workbox-core": "6.5.1" + } + }, + "workbox-precaching": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.1.tgz", + "integrity": "sha512-EzlPBxvmjGfE56YZzsT/vpVkpLG1XJhoplgXa5RPyVWLUL1LbwEAxhkrENElSS/R9tgiTw80IFwysidfUqLihg==", + "dev": true, + "requires": { + "workbox-core": "6.5.1", + "workbox-routing": "6.5.1", + "workbox-strategies": "6.5.1" + } + }, + "workbox-routing": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.1.tgz", + "integrity": "sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA==", + "dev": true, + "requires": { + "workbox-core": "6.5.1" + } + }, + "workbox-strategies": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.1.tgz", + "integrity": "sha512-JNaTXPy8wXzKkr+6za7/eJX9opoZk7UgY261I2kPxl80XQD8lMjz0vo9EOcBwvD72v3ZhGJbW84ZaDwFEhFvWA==", + "dev": true, + "requires": { + "workbox-core": "6.5.1" + } } } }, @@ -45782,20 +46466,35 @@ "dev": true, "requires": { "workbox-core": "6.5.1" + }, + "dependencies": { + "workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + } } }, "workbox-core": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", - "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==" + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==" }, "workbox-expiration": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.1.tgz", - "integrity": "sha512-iY/cTADAQATMmPkUBRmQdacqq0TJd2wMHimBQz+tRnPGHSMH+/BoLPABPnu7O7rT/g/s59CUYYRGxe3mEgoJCA==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", "requires": { - "idb": "^6.1.4", - "workbox-core": "6.5.1" + "idb": "^7.0.1", + "workbox-core": "6.5.4" + }, + "dependencies": { + "idb": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.0.tgz", + "integrity": "sha512-Wsk07aAxDsntgYJY4h0knZJuTxM73eQ4reRAO+Z1liOh8eMCJ/MoDS8fCui1vGT9mnjtl1sOu3I2i/W1swPYZg==" + } } }, "workbox-google-analytics": { @@ -45808,6 +46507,32 @@ "workbox-core": "6.5.1", "workbox-routing": "6.5.1", "workbox-strategies": "6.5.1" + }, + "dependencies": { + "workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, + "workbox-routing": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.1.tgz", + "integrity": "sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA==", + "dev": true, + "requires": { + "workbox-core": "6.5.1" + } + }, + "workbox-strategies": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.1.tgz", + "integrity": "sha512-JNaTXPy8wXzKkr+6za7/eJX9opoZk7UgY261I2kPxl80XQD8lMjz0vo9EOcBwvD72v3ZhGJbW84ZaDwFEhFvWA==", + "dev": true, + "requires": { + "workbox-core": "6.5.1" + } + } } }, "workbox-navigation-preload": { @@ -45817,16 +46542,24 @@ "dev": true, "requires": { "workbox-core": "6.5.1" + }, + "dependencies": { + "workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + } } }, "workbox-precaching": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.1.tgz", - "integrity": "sha512-EzlPBxvmjGfE56YZzsT/vpVkpLG1XJhoplgXa5RPyVWLUL1LbwEAxhkrENElSS/R9tgiTw80IFwysidfUqLihg==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", "requires": { - "workbox-core": "6.5.1", - "workbox-routing": "6.5.1", - "workbox-strategies": "6.5.1" + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" } }, "workbox-range-requests": { @@ -45836,6 +46569,14 @@ "dev": true, "requires": { "workbox-core": "6.5.1" + }, + "dependencies": { + "workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + } } }, "workbox-recipes": { @@ -45850,22 +46591,69 @@ "workbox-precaching": "6.5.1", "workbox-routing": "6.5.1", "workbox-strategies": "6.5.1" + }, + "dependencies": { + "workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, + "workbox-expiration": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.1.tgz", + "integrity": "sha512-iY/cTADAQATMmPkUBRmQdacqq0TJd2wMHimBQz+tRnPGHSMH+/BoLPABPnu7O7rT/g/s59CUYYRGxe3mEgoJCA==", + "dev": true, + "requires": { + "idb": "^6.1.4", + "workbox-core": "6.5.1" + } + }, + "workbox-precaching": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.1.tgz", + "integrity": "sha512-EzlPBxvmjGfE56YZzsT/vpVkpLG1XJhoplgXa5RPyVWLUL1LbwEAxhkrENElSS/R9tgiTw80IFwysidfUqLihg==", + "dev": true, + "requires": { + "workbox-core": "6.5.1", + "workbox-routing": "6.5.1", + "workbox-strategies": "6.5.1" + } + }, + "workbox-routing": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.1.tgz", + "integrity": "sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA==", + "dev": true, + "requires": { + "workbox-core": "6.5.1" + } + }, + "workbox-strategies": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.1.tgz", + "integrity": "sha512-JNaTXPy8wXzKkr+6za7/eJX9opoZk7UgY261I2kPxl80XQD8lMjz0vo9EOcBwvD72v3ZhGJbW84ZaDwFEhFvWA==", + "dev": true, + "requires": { + "workbox-core": "6.5.1" + } + } } }, "workbox-routing": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.1.tgz", - "integrity": "sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", "requires": { - "workbox-core": "6.5.1" + "workbox-core": "6.5.4" } }, "workbox-strategies": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.1.tgz", - "integrity": "sha512-JNaTXPy8wXzKkr+6za7/eJX9opoZk7UgY261I2kPxl80XQD8lMjz0vo9EOcBwvD72v3ZhGJbW84ZaDwFEhFvWA==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", "requires": { - "workbox-core": "6.5.1" + "workbox-core": "6.5.4" } }, "workbox-streams": { @@ -45876,6 +46664,23 @@ "requires": { "workbox-core": "6.5.1", "workbox-routing": "6.5.1" + }, + "dependencies": { + "workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + }, + "workbox-routing": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.1.tgz", + "integrity": "sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA==", + "dev": true, + "requires": { + "workbox-core": "6.5.1" + } + } } }, "workbox-sw": { @@ -45913,6 +46718,14 @@ "requires": { "@types/trusted-types": "^2.0.2", "workbox-core": "6.5.1" + }, + "dependencies": { + "workbox-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.1.tgz", + "integrity": "sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw==", + "dev": true + } } }, "wrap-ansi": { @@ -45982,9 +46795,9 @@ } }, "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", + "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", "dev": true, "requires": {} }, @@ -46025,12 +46838,12 @@ "dev": true }, "yargs": { - "version": "17.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", - "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", + "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", "dev": true, "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", @@ -46039,6 +46852,17 @@ "yargs-parser": "^21.0.0" }, "dependencies": { + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "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", @@ -46057,9 +46881,9 @@ } }, "yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true } } diff --git a/package.json b/package.json index c151625e..6fa80e31 100644 --- a/package.json +++ b/package.json @@ -24,87 +24,88 @@ "mutate": "./node_modules/.bin/stryker run --concurrency 4 --ignoreStatic" }, "dependencies": { - "@fortawesome/fontawesome-free": "^6.0.0", - "@fortawesome/fontawesome-svg-core": "^1.3.0", - "@fortawesome/free-regular-svg-icons": "^6.0.0", - "@fortawesome/free-solid-svg-icons": "^6.0.0", - "@fortawesome/react-fontawesome": "^0.1.17", - "axios": "^0.26.0", - "bootstrap": "^5.1.3", - "bottlejs": "^2.0.0", + "@fortawesome/fontawesome-free": "^6.2.0", + "@fortawesome/fontawesome-svg-core": "^6.2.0", + "@fortawesome/free-regular-svg-icons": "^6.2.0", + "@fortawesome/free-solid-svg-icons": "^6.2.0", + "@fortawesome/react-fontawesome": "^0.2.0", + "@reduxjs/toolkit": "^1.9.0", + "bootstrap": "^5.2.2", + "bottlejs": "^2.0.1", "bowser": "^2.11.0", - "chart.js": "^3.7.1", + "chart.js": "^3.9.1", "classnames": "^2.3.1", - "compare-versions": "^4.1.3", + "compare-versions": "^5.0.1", "csvtojson": "^2.0.10", - "date-fns": "^2.28.0", - "event-source-polyfill": "^1.0.25", + "date-fns": "^2.29.3", + "event-source-polyfill": "^1.0.31", + "history": "^5.3.0", "json2csv": "^5.0.7", - "leaflet": "^1.7.1", - "qs": "^6.9.6", + "leaflet": "^1.9.2", + "qs": "^6.11.0", "ramda": "^0.27.2", - "react": "^18.1.0", - "react-chartjs-2": "^4.1.0", - "react-colorful": "^5.5.1", + "react": "^18.2.0", + "react-chartjs-2": "^4.3.1", + "react-colorful": "^5.6.1", "react-copy-to-clipboard": "^5.1.0", "react-datepicker": "^4.8.0", - "react-dom": "^18.1.0", + "react-dom": "^18.2.0", "react-external-link": "^2.0.0", - "react-leaflet": "^4.0.0", - "react-redux": "^8.0.0", - "react-router-dom": "^6.3.0", + "react-leaflet": "^4.1.0", + "react-redux": "^8.0.4", + "react-router-dom": "^6.4.1", "react-swipeable": "^7.0.0", "react-tag-autocomplete": "^6.3.0", - "reactstrap": "^9.0.1", + "reactstrap": "^9.1.4", "redux": "^4.2.0", - "redux-localstorage-simple": "^2.4.1", + "redux-localstorage-simple": "^2.5.1", "redux-thunk": "^2.4.1", "stream": "^0.0.2", "uuid": "^8.3.2", - "workbox-core": "^6.5.1", - "workbox-expiration": "^6.5.1", - "workbox-precaching": "^6.5.1", - "workbox-routing": "^6.5.1", - "workbox-strategies": "^6.5.1" + "workbox-core": "^6.5.4", + "workbox-expiration": "^6.5.4", + "workbox-precaching": "^6.5.4", + "workbox-routing": "^6.5.4", + "workbox-strategies": "^6.5.4" }, "devDependencies": { "@shlinkio/eslint-config-js-coding-standard": "~2.0.2", "@shlinkio/stylelint-config-css-coding-standard": "~1.0.1", - "@stryker-mutator/core": "^6.0.2", - "@stryker-mutator/jest-runner": "^6.0.2", - "@stryker-mutator/typescript-checker": "^6.0.2", - "@testing-library/jest-dom": "^5.16.4", - "@testing-library/react": "^13.1.1", - "@testing-library/user-event": "^14.1.1", - "@types/jest": "^27.4.1", + "@stryker-mutator/core": "^6.2.2", + "@stryker-mutator/jest-runner": "^6.2.2", + "@stryker-mutator/typescript-checker": "^6.2.2", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@types/jest": "^29.1.1", "@types/json2csv": "^5.0.3", - "@types/leaflet": "^1.7.9", + "@types/leaflet": "^1.8.0", "@types/qs": "^6.9.7", - "@types/ramda": "0.27.38", - "@types/react": "^18.0.8", + "@types/ramda": "^0.28.15", + "@types/react": "^18.0.21", "@types/react-color": "^3.0.6", - "@types/react-copy-to-clipboard": "^5.0.2", - "@types/react-datepicker": "^4.3.4", - "@types/react-dom": "^18.0.3", - "@types/react-tag-autocomplete": "^6.1.1", + "@types/react-copy-to-clipboard": "^5.0.4", + "@types/react-datepicker": "^4.4.2", + "@types/react-dom": "^18.0.6", + "@types/react-tag-autocomplete": "^6.3.0", "@types/uuid": "^8.3.4", "adm-zip": "^0.5.9", - "babel-jest": "^28.0.3", + "babel-jest": "^29.1.2", "chalk": "^5.0.1", - "eslint": "^8.12.0", + "eslint": "^8.24.0", "identity-obj-proxy": "^3.0.0", - "jest": "^28.0.3", + "jest": "^29.1.2", "jest-canvas-mock": "^2.4.0", - "jest-environment-jsdom": "^28.0.2", + "jest-environment-jsdom": "^29.1.2", "react-scripts": "^5.0.1", "resize-observer-polyfill": "^1.5.1", - "sass": "^1.49.9", - "serve": "^13.0.2", + "sass": "^1.55.0", + "serve": "^14.1.1", "stryker-cli": "^1.0.2", - "stylelint": "^14.8.2", + "stylelint": "^14.13.0", "ts-mockery": "^1.2.0", - "typescript": "^4.6.2", - "webpack": "^5.70.0" + "typescript": "^4.8.4", + "webpack": "^5.74.0" }, "browserslist": [ ">0.2%", diff --git a/src/api/ShlinkApiError.tsx b/src/api/ShlinkApiError.tsx index ed3c5708..6b78da38 100644 --- a/src/api/ShlinkApiError.tsx +++ b/src/api/ShlinkApiError.tsx @@ -1,5 +1,5 @@ -import { ProblemDetailsError } from './types'; import { isInvalidArgumentError } from './utils'; +import { ProblemDetailsError } from './types/errors'; export interface ShlinkApiErrorProps { errorData?: ProblemDetailsError; diff --git a/src/api/services/ShlinkApiClient.ts b/src/api/services/ShlinkApiClient.ts index 3e4c1b51..8617a30a 100644 --- a/src/api/services/ShlinkApiClient.ts +++ b/src/api/services/ShlinkApiClient.ts @@ -1,5 +1,4 @@ import { isEmpty, isNil, reject } from 'ramda'; -import { AxiosInstance, AxiosResponse, Method } from 'axios'; import { ShortUrl, ShortUrlData } from '../../short-urls/data'; import { OptionalString } from '../../utils/utils'; import { @@ -18,111 +17,122 @@ import { ShlinkShortUrlsListParams, ShlinkShortUrlsListNormalizedParams, } from '../types'; -import { stringifyQuery } from '../../utils/helpers/query'; import { orderToString } from '../../utils/helpers/ordering'; +import { isRegularNotFound, parseApiError } from '../utils'; +import { stringifyQuery } from '../../utils/helpers/query'; +import { HttpClient } from '../../common/services/HttpClient'; -const buildShlinkBaseUrl = (url: string) => (url ? `${url}/rest/v2` : ''); +const buildShlinkBaseUrl = (url: string, version: 2 | 3) => `${url}/rest/v${version}`; const rejectNilProps = reject(isNil); -const normalizeOrderByInParams = (params: ShlinkShortUrlsListParams): ShlinkShortUrlsListNormalizedParams => { - const { orderBy = {}, ...rest } = params; - - return { ...rest, orderBy: orderToString(orderBy) }; -}; +const normalizeOrderByInParams = ( + { orderBy = {}, ...rest }: ShlinkShortUrlsListParams, +): ShlinkShortUrlsListNormalizedParams => ({ ...rest, orderBy: orderToString(orderBy) }); export class ShlinkApiClient { + private apiVersion: 2 | 3; + public constructor( - private readonly axios: AxiosInstance, + private readonly httpClient: HttpClient, private readonly baseUrl: string, private readonly apiKey: string, ) { + this.apiVersion = 3; } public readonly listShortUrls = async (params: ShlinkShortUrlsListParams = {}): Promise<ShlinkShortUrlsResponse> => this.performRequest<{ shortUrls: ShlinkShortUrlsResponse }>('/short-urls', 'GET', normalizeOrderByInParams(params)) - .then(({ data }) => data.shortUrls); + .then(({ shortUrls }) => shortUrls); public readonly createShortUrl = async (options: ShortUrlData): Promise<ShortUrl> => { const filteredOptions = reject((value) => isEmpty(value) || isNil(value), options as any); - - return this.performRequest<ShortUrl>('/short-urls', 'POST', {}, filteredOptions) - .then((resp) => resp.data); + return this.performRequest<ShortUrl>('/short-urls', 'POST', {}, filteredOptions); }; public readonly getShortUrlVisits = async (shortCode: string, query?: ShlinkVisitsParams): Promise<ShlinkVisits> => this.performRequest<{ visits: ShlinkVisits }>(`/short-urls/${shortCode}/visits`, 'GET', query) - .then(({ data }) => data.visits); + .then(({ visits }) => visits); public readonly getTagVisits = async (tag: string, query?: Omit<ShlinkVisitsParams, 'domain'>): Promise<ShlinkVisits> => - this.performRequest<{ visits: ShlinkVisits }>(`/tags/${tag}/visits`, 'GET', query) - .then(({ data }) => data.visits); + this.performRequest<{ visits: ShlinkVisits }>(`/tags/${tag}/visits`, 'GET', query).then(({ visits }) => visits); public readonly getDomainVisits = async (domain: string, query?: Omit<ShlinkVisitsParams, 'domain'>): Promise<ShlinkVisits> => - this.performRequest<{ visits: ShlinkVisits }>(`/domains/${domain}/visits`, 'GET', query) - .then(({ data }) => data.visits); + this.performRequest<{ visits: ShlinkVisits }>(`/domains/${domain}/visits`, 'GET', query).then(({ visits }) => visits); public readonly getOrphanVisits = async (query?: Omit<ShlinkVisitsParams, 'domain'>): Promise<ShlinkVisits> => - this.performRequest<{ visits: ShlinkVisits }>('/visits/orphan', 'GET', query) - .then(({ data }) => data.visits); + this.performRequest<{ visits: ShlinkVisits }>('/visits/orphan', 'GET', query).then(({ visits }) => visits); public readonly getNonOrphanVisits = async (query?: Omit<ShlinkVisitsParams, 'domain'>): Promise<ShlinkVisits> => - this.performRequest<{ visits: ShlinkVisits }>('/visits/non-orphan', 'GET', query) - .then(({ data }) => data.visits); + this.performRequest<{ visits: ShlinkVisits }>('/visits/non-orphan', 'GET', query).then(({ visits }) => visits); public readonly getVisitsOverview = async (): Promise<ShlinkVisitsOverview> => - this.performRequest<{ visits: ShlinkVisitsOverview }>('/visits', 'GET') - .then(({ data }) => data.visits); + this.performRequest<{ visits: ShlinkVisitsOverview }>('/visits').then(({ visits }) => visits); public readonly getShortUrl = async (shortCode: string, domain?: OptionalString): Promise<ShortUrl> => - this.performRequest<ShortUrl>(`/short-urls/${shortCode}`, 'GET', { domain }) - .then(({ data }) => data); + this.performRequest<ShortUrl>(`/short-urls/${shortCode}`, 'GET', { domain }); public readonly deleteShortUrl = async (shortCode: string, domain?: OptionalString): Promise<void> => - this.performRequest(`/short-urls/${shortCode}`, 'DELETE', { domain }) - .then(() => {}); + this.performEmptyRequest(`/short-urls/${shortCode}`, 'DELETE', { domain }); public readonly updateShortUrl = async ( shortCode: string, domain: OptionalString, edit: ShlinkShortUrlData, ): Promise<ShortUrl> => - this.performRequest<ShortUrl>(`/short-urls/${shortCode}`, 'PATCH', { domain }, edit).then(({ data }) => data); + this.performRequest<ShortUrl>(`/short-urls/${shortCode}`, 'PATCH', { domain }, edit); public readonly listTags = async (): Promise<ShlinkTags> => this.performRequest<{ tags: ShlinkTagsResponse }>('/tags', 'GET', { withStats: 'true' }) - .then((resp) => resp.data.tags) + .then(({ tags }) => tags) .then(({ data, stats }) => ({ tags: data, stats })); public readonly deleteTags = async (tags: string[]): Promise<{ tags: string[] }> => - this.performRequest('/tags', 'DELETE', { tags }) - .then(() => ({ tags })); + this.performEmptyRequest('/tags', 'DELETE', { tags }).then(() => ({ tags })); public readonly editTag = async (oldName: string, newName: string): Promise<{ oldName: string; newName: string }> => - this.performRequest('/tags', 'PUT', {}, { oldName, newName }) - .then(() => ({ oldName, newName })); + this.performEmptyRequest('/tags', 'PUT', {}, { oldName, newName }).then(() => ({ oldName, newName })); - public readonly health = async (): Promise<ShlinkHealth> => - this.performRequest<ShlinkHealth>('/health', 'GET') - .then((resp) => resp.data); + public readonly health = async (): Promise<ShlinkHealth> => this.performRequest<ShlinkHealth>('/health', 'GET'); public readonly mercureInfo = async (): Promise<ShlinkMercureInfo> => - this.performRequest<ShlinkMercureInfo>('/mercure-info', 'GET') - .then((resp) => resp.data); + this.performRequest<ShlinkMercureInfo>('/mercure-info', 'GET'); public readonly listDomains = async (): Promise<ShlinkDomainsResponse> => - this.performRequest<{ domains: ShlinkDomainsResponse }>('/domains', 'GET').then(({ data }) => data.domains); + this.performRequest<{ domains: ShlinkDomainsResponse }>('/domains').then(({ domains }) => domains); public readonly editDomainRedirects = async ( domainRedirects: ShlinkEditDomainRedirects, ): Promise<ShlinkDomainRedirects> => - this.performRequest<ShlinkDomainRedirects>('/domains/redirects', 'PATCH', {}, domainRedirects).then(({ data }) => data); + this.performRequest<ShlinkDomainRedirects>('/domains/redirects', 'PATCH', {}, domainRedirects); - private readonly performRequest = async <T>(url: string, method: Method = 'GET', query = {}, body = {}): Promise<AxiosResponse<T>> => - this.axios({ + private readonly performRequest = async <T>(url: string, method = 'GET', query = {}, body?: object): Promise<T> => + this.httpClient.fetchJson<T>(...this.toFetchParams(url, method, query, body)).catch( + this.handleFetchError(() => this.httpClient.fetchJson<T>(...this.toFetchParams(url, method, query, body))), + ); + + private readonly performEmptyRequest = async (url: string, method = 'GET', query = {}, body?: object): Promise<void> => + this.httpClient.fetchEmpty(...this.toFetchParams(url, method, query, body)).catch( + this.handleFetchError(() => this.httpClient.fetchEmpty(...this.toFetchParams(url, method, query, body))), + ); + + private readonly toFetchParams = (url: string, method: string, query = {}, body?: object): [string, RequestInit] => { + const normalizedQuery = stringifyQuery(rejectNilProps(query)); + const stringifiedQuery = isEmpty(normalizedQuery) ? '' : `?${normalizedQuery}`; + + return [`${buildShlinkBaseUrl(this.baseUrl, this.apiVersion)}${url}${stringifiedQuery}`, { method, - url: `${buildShlinkBaseUrl(this.baseUrl)}${url}`, + body: body && JSON.stringify(body), headers: { 'X-Api-Key': this.apiKey }, - params: rejectNilProps(query), - data: body, - paramsSerializer: stringifyQuery, - }); + }]; + }; + + private readonly handleFetchError = (retryFetch: Function) => (e: unknown) => { + if (!isRegularNotFound(parseApiError(e))) { + throw e; + } + + // If we capture a not found error, let's assume this Shlink version does not support API v3, so we decrease to + // v2 and retry + this.apiVersion = 2; + return retryFetch(); + }; } diff --git a/src/api/services/ShlinkApiClientBuilder.ts b/src/api/services/ShlinkApiClientBuilder.ts index 0d7efc0f..ef74356a 100644 --- a/src/api/services/ShlinkApiClientBuilder.ts +++ b/src/api/services/ShlinkApiClientBuilder.ts @@ -1,34 +1,32 @@ -import { AxiosInstance } from 'axios'; -import { prop } from 'ramda'; -import { hasServerData, SelectedServer, ServerWithId } from '../../servers/data'; +import { hasServerData, ServerWithId } from '../../servers/data'; import { GetState } from '../../container/types'; import { ShlinkApiClient } from './ShlinkApiClient'; +import { HttpClient } from '../../common/services/HttpClient'; const apiClients: Record<string, ShlinkApiClient> = {}; const isGetState = (getStateOrSelectedServer: GetState | ServerWithId): getStateOrSelectedServer is GetState => typeof getStateOrSelectedServer === 'function'; -const getSelectedServerFromState = (getState: GetState): SelectedServer => prop('selectedServer', getState()); - -export type ShlinkApiClientBuilder = (getStateOrSelectedServer: GetState | ServerWithId) => ShlinkApiClient; - -export const buildShlinkApiClient = (axios: AxiosInstance): ShlinkApiClientBuilder => ( - getStateOrSelectedServer: GetState | ServerWithId, -) => { - const server = isGetState(getStateOrSelectedServer) - ? getSelectedServerFromState(getStateOrSelectedServer) - : getStateOrSelectedServer; - - if (!hasServerData(server)) { +const getSelectedServerFromState = (getState: GetState): ServerWithId => { + const { selectedServer } = getState(); + if (!hasServerData(selectedServer)) { throw new Error('There\'s no selected server or it is not found'); } - const { url, apiKey } = server; + return selectedServer; +}; + +export const buildShlinkApiClient = (httpClient: HttpClient) => (getStateOrSelectedServer: GetState | ServerWithId) => { + const { url, apiKey } = isGetState(getStateOrSelectedServer) + ? getSelectedServerFromState(getStateOrSelectedServer) + : getStateOrSelectedServer; const clientKey = `${url}_${apiKey}`; if (!apiClients[clientKey]) { - apiClients[clientKey] = new ShlinkApiClient(axios, url, apiKey); + apiClients[clientKey] = new ShlinkApiClient(httpClient, url, apiKey); } return apiClients[clientKey]; }; + +export type ShlinkApiClientBuilder = ReturnType<typeof buildShlinkApiClient>; diff --git a/src/api/services/provideServices.ts b/src/api/services/provideServices.ts index 3ddb60e7..c8bcd854 100644 --- a/src/api/services/provideServices.ts +++ b/src/api/services/provideServices.ts @@ -2,7 +2,7 @@ import Bottle from 'bottlejs'; import { buildShlinkApiClient } from './ShlinkApiClientBuilder'; const provideServices = (bottle: Bottle) => { - bottle.serviceFactory('buildShlinkApiClient', buildShlinkApiClient, 'axios'); + bottle.serviceFactory('buildShlinkApiClient', buildShlinkApiClient, 'HttpClient'); }; export default provideServices; diff --git a/src/api/types/actions.ts b/src/api/types/actions.ts deleted file mode 100644 index 5359b6b3..00000000 --- a/src/api/types/actions.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Action } from 'redux'; -import { ProblemDetailsError } from './index'; - -export interface ApiErrorAction extends Action<string> { - errorData?: ProblemDetailsError; -} diff --git a/src/api/types/errors.ts b/src/api/types/errors.ts new file mode 100644 index 00000000..97b04cec --- /dev/null +++ b/src/api/types/errors.ts @@ -0,0 +1,54 @@ +export enum ErrorTypeV2 { + INVALID_ARGUMENT = 'INVALID_ARGUMENT', + INVALID_SHORT_URL_DELETION = 'INVALID_SHORT_URL_DELETION', + DOMAIN_NOT_FOUND = 'DOMAIN_NOT_FOUND', + FORBIDDEN_OPERATION = 'FORBIDDEN_OPERATION', + INVALID_URL = 'INVALID_URL', + INVALID_SLUG = 'INVALID_SLUG', + INVALID_SHORTCODE = 'INVALID_SHORTCODE', + TAG_CONFLICT = 'TAG_CONFLICT', + TAG_NOT_FOUND = 'TAG_NOT_FOUND', + MERCURE_NOT_CONFIGURED = 'MERCURE_NOT_CONFIGURED', + INVALID_AUTHORIZATION = 'INVALID_AUTHORIZATION', + INVALID_API_KEY = 'INVALID_API_KEY', + NOT_FOUND = 'NOT_FOUND', +} + +export enum ErrorTypeV3 { + INVALID_ARGUMENT = 'https://shlink.io/api/error/invalid-data', + INVALID_SHORT_URL_DELETION = 'https://shlink.io/api/error/invalid-short-url-deletion', + DOMAIN_NOT_FOUND = 'https://shlink.io/api/error/domain-not-found', + FORBIDDEN_OPERATION = 'https://shlink.io/api/error/forbidden-tag-operation', + INVALID_URL = 'https://shlink.io/api/error/invalid-url', + INVALID_SLUG = 'https://shlink.io/api/error/non-unique-slug', + INVALID_SHORTCODE = 'https://shlink.io/api/error/short-url-not-found', + TAG_CONFLICT = 'https://shlink.io/api/error/tag-conflict', + TAG_NOT_FOUND = 'https://shlink.io/api/error/tag-not-found', + MERCURE_NOT_CONFIGURED = 'https://shlink.io/api/error/mercure-not-configured', + INVALID_AUTHORIZATION = 'https://shlink.io/api/error/missing-authentication', + INVALID_API_KEY = 'https://shlink.io/api/error/invalid-api-key', + NOT_FOUND = 'https://shlink.io/api/error/not-found', +} + +export interface ProblemDetailsError { + type: string; + detail: string; + title: string; + status: number; + [extraProps: string]: any; +} + +export interface InvalidArgumentError extends ProblemDetailsError { + type: ErrorTypeV2.INVALID_ARGUMENT | ErrorTypeV3.INVALID_ARGUMENT; + invalidElements: string[]; +} + +export interface InvalidShortUrlDeletion extends ProblemDetailsError { + type: 'INVALID_SHORTCODE_DELETION' | ErrorTypeV2.INVALID_SHORT_URL_DELETION | ErrorTypeV3.INVALID_SHORT_URL_DELETION; + threshold: number; +} + +export interface RegularNotFound extends ProblemDetailsError { + type: ErrorTypeV2.NOT_FOUND | ErrorTypeV3.NOT_FOUND; + status: 404; +} diff --git a/src/api/types/index.ts b/src/api/types/index.ts index 126750bd..fc3fe6de 100644 --- a/src/api/types/index.ts +++ b/src/api/types/index.ts @@ -102,21 +102,3 @@ export interface ShlinkShortUrlsListParams { export interface ShlinkShortUrlsListNormalizedParams extends Omit<ShlinkShortUrlsListParams, 'orderBy'> { orderBy?: string; } - -export interface ProblemDetailsError { - type: string; - detail: string; - title: string; - status: number; - [extraProps: string]: any; -} - -export interface InvalidArgumentError extends ProblemDetailsError { - type: 'INVALID_ARGUMENT'; - invalidElements: string[]; -} - -export interface InvalidShortUrlDeletion extends ProblemDetailsError { - type: 'INVALID_SHORTCODE_DELETION' | 'INVALID_SHORT_URL_DELETION'; - threshold: number; -} diff --git a/src/api/utils/index.ts b/src/api/utils/index.ts index af2517e0..4d60a21e 100644 --- a/src/api/utils/index.ts +++ b/src/api/utils/index.ts @@ -1,10 +1,24 @@ -import { AxiosError } from 'axios'; -import { InvalidArgumentError, InvalidShortUrlDeletion, ProblemDetailsError } from '../types'; +import { + ErrorTypeV2, + ErrorTypeV3, + InvalidArgumentError, + InvalidShortUrlDeletion, + ProblemDetailsError, + RegularNotFound, +} from '../types/errors'; -export const parseApiError = (e: AxiosError<ProblemDetailsError>) => e.response?.data; +const isProblemDetails = (e: unknown): e is ProblemDetailsError => + !!e && typeof e === 'object' && ['type', 'detail', 'title', 'status'].every((prop) => prop in e); + +export const parseApiError = (e: unknown): ProblemDetailsError | undefined => (isProblemDetails(e) ? e : undefined); export const isInvalidArgumentError = (error?: ProblemDetailsError): error is InvalidArgumentError => - error?.type === 'INVALID_ARGUMENT'; + error?.type === ErrorTypeV2.INVALID_ARGUMENT || error?.type === ErrorTypeV3.INVALID_ARGUMENT; export const isInvalidDeletionError = (error?: ProblemDetailsError): error is InvalidShortUrlDeletion => - error?.type === 'INVALID_SHORTCODE_DELETION' || error?.type === 'INVALID_SHORT_URL_DELETION'; + error?.type === 'INVALID_SHORTCODE_DELETION' + || error?.type === ErrorTypeV2.INVALID_SHORT_URL_DELETION + || error?.type === ErrorTypeV3.INVALID_SHORT_URL_DELETION; + +export const isRegularNotFound = (error?: ProblemDetailsError): error is RegularNotFound => + (error?.type === ErrorTypeV2.NOT_FOUND || error?.type === ErrorTypeV3.NOT_FOUND) && error?.status === 404; diff --git a/src/app/reducers/appUpdates.ts b/src/app/reducers/appUpdates.ts index 36db12ec..675b3959 100644 --- a/src/app/reducers/appUpdates.ts +++ b/src/app/reducers/appUpdates.ts @@ -1,16 +1,14 @@ -import { Action } from 'redux'; -import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; +import { createSlice } from '@reduxjs/toolkit'; -export const APP_UPDATE_AVAILABLE = 'shlink/appUpdates/APP_UPDATE_AVAILABLE'; -export const RESET_APP_UPDATE = 'shlink/appUpdates/RESET_APP_UPDATE'; +const { actions, reducer } = createSlice({ + name: 'shlink/appUpdates', + initialState: false, + reducers: { + appUpdateAvailable: () => true, + resetAppUpdate: () => false, + }, +}); -const initialState = false; +export const { appUpdateAvailable, resetAppUpdate } = actions; -export default buildReducer<boolean, Action<string>>({ - [APP_UPDATE_AVAILABLE]: () => true, - [RESET_APP_UPDATE]: () => false, -}, initialState); - -export const appUpdateAvailable = buildActionCreator(APP_UPDATE_AVAILABLE); - -export const resetAppUpdate = buildActionCreator(RESET_APP_UPDATE); +export const appUpdatesReducer = reducer; diff --git a/src/common/reducers/sidebar.ts b/src/common/reducers/sidebar.ts index d90b0d5a..2203ee43 100644 --- a/src/common/reducers/sidebar.ts +++ b/src/common/reducers/sidebar.ts @@ -1,25 +1,22 @@ -import { Action } from 'redux'; -import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; - -export const SIDEBAR_PRESENT = 'shlink/common/SIDEBAR_PRESENT'; -export const SIDEBAR_NOT_PRESENT = 'shlink/common/SIDEBAR_NOT_PRESENT'; +import { createSlice } from '@reduxjs/toolkit'; export interface Sidebar { sidebarPresent: boolean; } -type SidebarRenderedAction = Action<string>; -type SidebarNotRenderedAction = Action<string>; - const initialState: Sidebar = { sidebarPresent: false, }; -export default buildReducer<Sidebar, SidebarRenderedAction & SidebarNotRenderedAction>({ - [SIDEBAR_PRESENT]: () => ({ sidebarPresent: true }), - [SIDEBAR_NOT_PRESENT]: () => ({ sidebarPresent: false }), -}, initialState); +const { actions, reducer } = createSlice({ + name: 'shlink/sidebar', + initialState, + reducers: { + sidebarPresent: () => ({ sidebarPresent: true }), + sidebarNotPresent: () => ({ sidebarPresent: false }), + }, +}); -export const sidebarPresent = buildActionCreator(SIDEBAR_PRESENT); +export const { sidebarPresent, sidebarNotPresent } = actions; -export const sidebarNotPresent = buildActionCreator(SIDEBAR_NOT_PRESENT); +export const sidebarReducer = reducer; diff --git a/src/common/services/HttpClient.ts b/src/common/services/HttpClient.ts new file mode 100644 index 00000000..af8aedf3 --- /dev/null +++ b/src/common/services/HttpClient.ts @@ -0,0 +1,25 @@ +import { Fetch } from '../../utils/types'; + +export class HttpClient { + constructor(private readonly fetch: Fetch) {} + + public readonly fetchJson = <T>(url: string, options?: RequestInit): Promise<T> => + this.fetch(url, options).then(async (resp) => { + const json = await resp.json(); + + if (!resp.ok) { + throw json; + } + + return json as T; + }); + + public readonly fetchEmpty = (url: string, options?: RequestInit): Promise<void> => + this.fetch(url, options).then(async (resp) => { + if (!resp.ok) { + throw await resp.json(); + } + }); + + public readonly fetchBlob = (url: string): Promise<Blob> => this.fetch(url).then((resp) => resp.blob()); +} diff --git a/src/common/services/ImageDownloader.ts b/src/common/services/ImageDownloader.ts index 2e131d7a..39314d7e 100644 --- a/src/common/services/ImageDownloader.ts +++ b/src/common/services/ImageDownloader.ts @@ -1,11 +1,11 @@ -import { AxiosInstance } from 'axios'; import { saveUrl } from '../../utils/helpers/files'; +import { HttpClient } from './HttpClient'; export class ImageDownloader { - public constructor(private readonly axios: AxiosInstance, private readonly window: Window) {} + public constructor(private readonly httpClient: HttpClient, private readonly window: Window) {} public async saveImage(imgUrl: string, filename: string): Promise<void> { - const { data } = await this.axios.get(imgUrl, { responseType: 'blob' }); + const data = await this.httpClient.fetchBlob(imgUrl); const url = URL.createObjectURL(data); saveUrl(this.window, url, filename); diff --git a/src/common/services/provideServices.ts b/src/common/services/provideServices.ts index 3a613bd2..c6b2d3ef 100644 --- a/src/common/services/provideServices.ts +++ b/src/common/services/provideServices.ts @@ -1,4 +1,3 @@ -import axios from 'axios'; import Bottle from 'bottlejs'; import { ScrollToTop } from '../ScrollToTop'; import { MainHeader } from '../MainHeader'; @@ -12,14 +11,16 @@ import { withoutSelectedServer } from '../../servers/helpers/withoutSelectedServ import { sidebarNotPresent, sidebarPresent } from '../reducers/sidebar'; import { ImageDownloader } from './ImageDownloader'; import { ReportExporter } from './ReportExporter'; +import { HttpClient } from './HttpClient'; const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { // Services bottle.constant('window', (global as any).window); bottle.constant('console', global.console); - bottle.constant('axios', axios); + bottle.constant('fetch', (global as any).fetch.bind(global)); - bottle.service('ImageDownloader', ImageDownloader, 'axios', 'window'); + bottle.service('HttpClient', HttpClient, 'fetch'); + bottle.service('ImageDownloader', ImageDownloader, 'HttpClient', 'window'); bottle.service('ReportExporter', ReportExporter, 'window', 'jsonToCsv'); // Components diff --git a/src/container/store.ts b/src/container/store.ts index f4c80820..590c8382 100644 --- a/src/container/store.ts +++ b/src/container/store.ts @@ -1,14 +1,11 @@ -import ReduxThunk from 'redux-thunk'; -import { applyMiddleware, compose, createStore } from 'redux'; +import { IContainer } from 'bottlejs'; import { save, load, RLSOptions } from 'redux-localstorage-simple'; -import reducers from '../reducers'; +import { configureStore } from '@reduxjs/toolkit'; +import reducer from '../reducers'; import { migrateDeprecatedSettings } from '../settings/helpers'; import { ShlinkState } from './types'; const isProduction = process.env.NODE_ENV === 'production'; -// eslint-disable-next-line no-mixed-operators -const composeEnhancers: Function = !isProduction && (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; - const localStorageConfig: RLSOptions = { states: ['settings', 'servers'], namespace: 'shlink', @@ -17,6 +14,12 @@ const localStorageConfig: RLSOptions = { }; const preloadedState = migrateDeprecatedSettings(load(localStorageConfig) as ShlinkState); -export const store = createStore(reducers, preloadedState, composeEnhancers( - applyMiddleware(save(localStorageConfig), ReduxThunk), -)); +export const setUpStore = (container: IContainer) => configureStore({ + devTools: !isProduction, + reducer: reducer(container), + preloadedState, + middleware: (defaultMiddlewaresIncludingReduxThunk) => + defaultMiddlewaresIncludingReduxThunk({ immutableCheck: false, serializableCheck: false }) // State is too big for these + .prepend(container.selectServerListener.middleware) + .concat(save(localStorageConfig)), +}); diff --git a/src/container/types.ts b/src/container/types.ts index 84cb2df1..3be8ee4c 100644 --- a/src/container/types.ts +++ b/src/container/types.ts @@ -13,15 +13,15 @@ import { ShortUrlVisits } from '../visits/reducers/shortUrlVisits'; import { TagVisits } from '../visits/reducers/tagVisits'; import { DomainsList } from '../domains/reducers/domainsList'; import { VisitsOverview } from '../visits/reducers/visitsOverview'; -import { VisitsInfo } from '../visits/types'; import { Sidebar } from '../common/reducers/sidebar'; import { DomainVisits } from '../visits/reducers/domainVisits'; +import { VisitsInfo } from '../visits/reducers/types'; export interface ShlinkState { servers: ServersMap; selectedServer: SelectedServer; shortUrlsList: ShortUrlsList; - shortUrlCreationResult: ShortUrlCreation; + shortUrlCreation: ShortUrlCreation; shortUrlDeletion: ShortUrlDeletion; shortUrlEdition: ShortUrlEdition; shortUrlVisits: ShortUrlVisits; diff --git a/src/domains/DomainRow.tsx b/src/domains/DomainRow.tsx index f3ca7426..e57b0f36 100644 --- a/src/domains/DomainRow.tsx +++ b/src/domains/DomainRow.tsx @@ -8,11 +8,12 @@ import { SelectedServer } from '../servers/data'; import { Domain } from './data'; import { DomainStatusIcon } from './helpers/DomainStatusIcon'; import { DomainDropdown } from './helpers/DomainDropdown'; +import { EditDomainRedirects } from './reducers/domainRedirects'; interface DomainRowProps { domain: Domain; defaultRedirects?: ShlinkDomainRedirects; - editDomainRedirects: (domain: string, redirects: Partial<ShlinkDomainRedirects>) => Promise<void>; + editDomainRedirects: (redirects: EditDomainRedirects) => Promise<void>; checkDomainHealth: (domain: string) => void; selectedServer: SelectedServer; } diff --git a/src/domains/ManageDomains.tsx b/src/domains/ManageDomains.tsx index a6170595..f7c52992 100644 --- a/src/domains/ManageDomains.tsx +++ b/src/domains/ManageDomains.tsx @@ -4,7 +4,7 @@ import { Result } from '../utils/Result'; import { ShlinkApiError } from '../api/ShlinkApiError'; import { SimpleCard } from '../utils/SimpleCard'; import { SearchField } from '../utils/SearchField'; -import { ShlinkDomainRedirects } from '../api/types'; +import { EditDomainRedirects } from './reducers/domainRedirects'; import { SelectedServer } from '../servers/data'; import { DomainsList } from './reducers/domainsList'; import { DomainRow } from './DomainRow'; @@ -12,7 +12,7 @@ import { DomainRow } from './DomainRow'; interface ManageDomainsProps { listDomains: Function; filterDomains: (searchTerm: string) => void; - editDomainRedirects: (domain: string, redirects: Partial<ShlinkDomainRedirects>) => Promise<void>; + editDomainRedirects: (redirects: EditDomainRedirects) => Promise<void>; checkDomainHealth: (domain: string) => void; domainsList: DomainsList; selectedServer: SelectedServer; diff --git a/src/domains/helpers/DomainDropdown.tsx b/src/domains/helpers/DomainDropdown.tsx index 423c4db5..a91b40a8 100644 --- a/src/domains/helpers/DomainDropdown.tsx +++ b/src/domains/helpers/DomainDropdown.tsx @@ -7,14 +7,14 @@ import { useToggle } from '../../utils/helpers/hooks'; import { DropdownBtnMenu } from '../../utils/DropdownBtnMenu'; import { EditDomainRedirectsModal } from './EditDomainRedirectsModal'; import { Domain } from '../data'; -import { ShlinkDomainRedirects } from '../../api/types'; +import { EditDomainRedirects } from '../reducers/domainRedirects'; import { supportsDefaultDomainRedirectsEdition, supportsDomainVisits } from '../../utils/helpers/features'; import { getServerId, SelectedServer } from '../../servers/data'; import { DEFAULT_DOMAIN } from '../../visits/reducers/domainVisits'; interface DomainDropdownProps { domain: Domain; - editDomainRedirects: (domain: string, redirects: Partial<ShlinkDomainRedirects>) => Promise<void>; + editDomainRedirects: (redirects: EditDomainRedirects) => Promise<void>; selectedServer: SelectedServer; } diff --git a/src/domains/helpers/EditDomainRedirectsModal.tsx b/src/domains/helpers/EditDomainRedirectsModal.tsx index 0bc86bf8..26d11be5 100644 --- a/src/domains/helpers/EditDomainRedirectsModal.tsx +++ b/src/domains/helpers/EditDomainRedirectsModal.tsx @@ -1,15 +1,16 @@ import { FC, useState } from 'react'; import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; -import { ShlinkDomain, ShlinkDomainRedirects } from '../../api/types'; +import { ShlinkDomain } from '../../api/types'; import { InputFormGroup, InputFormGroupProps } from '../../utils/forms/InputFormGroup'; import { handleEventPreventingDefault, nonEmptyValueOrNull } from '../../utils/utils'; import { InfoTooltip } from '../../utils/InfoTooltip'; +import { EditDomainRedirects } from '../reducers/domainRedirects'; interface EditDomainRedirectsModalProps { domain: ShlinkDomain; isOpen: boolean; toggle: () => void; - editDomainRedirects: (domain: string, redirects: Partial<ShlinkDomainRedirects>) => Promise<void>; + editDomainRedirects: (redirects: EditDomainRedirects) => Promise<void>; } const FormGroup: FC<InputFormGroupProps & { isLast?: boolean }> = ({ isLast, ...rest }) => ( @@ -30,10 +31,13 @@ export const EditDomainRedirectsModal: FC<EditDomainRedirectsModalProps> = ( const [invalidShortUrlRedirect, setInvalidShortUrlRedirect] = useState( domain.redirects?.invalidShortUrlRedirect ?? '', ); - const handleSubmit = handleEventPreventingDefault(async () => editDomainRedirects(domain.domain, { - baseUrlRedirect: nonEmptyValueOrNull(baseUrlRedirect), - regular404Redirect: nonEmptyValueOrNull(regular404Redirect), - invalidShortUrlRedirect: nonEmptyValueOrNull(invalidShortUrlRedirect), + const handleSubmit = handleEventPreventingDefault(async () => editDomainRedirects({ + domain: domain.domain, + redirects: { + baseUrlRedirect: nonEmptyValueOrNull(baseUrlRedirect), + regular404Redirect: nonEmptyValueOrNull(regular404Redirect), + invalidShortUrlRedirect: nonEmptyValueOrNull(invalidShortUrlRedirect), + }, }).then(toggle)); return ( diff --git a/src/domains/reducers/domainRedirects.ts b/src/domains/reducers/domainRedirects.ts index 8cb65d93..7aea1b15 100644 --- a/src/domains/reducers/domainRedirects.ts +++ b/src/domains/reducers/domainRedirects.ts @@ -1,31 +1,22 @@ -import { Action, Dispatch } from 'redux'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; import { ShlinkDomainRedirects } from '../../api/types'; -import { GetState } from '../../container/types'; -import { ApiErrorAction } from '../../api/types/actions'; -import { parseApiError } from '../../api/utils'; -export const EDIT_DOMAIN_REDIRECTS_START = 'shlink/domainRedirects/EDIT_DOMAIN_REDIRECTS_START'; -export const EDIT_DOMAIN_REDIRECTS_ERROR = 'shlink/domainRedirects/EDIT_DOMAIN_REDIRECTS_ERROR'; -export const EDIT_DOMAIN_REDIRECTS = 'shlink/domainRedirects/EDIT_DOMAIN_REDIRECTS'; +const EDIT_DOMAIN_REDIRECTS = 'shlink/domainRedirects/EDIT_DOMAIN_REDIRECTS'; -export interface EditDomainRedirectsAction extends Action<string> { +export interface EditDomainRedirects { domain: string; redirects: ShlinkDomainRedirects; } -export const editDomainRedirects = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - domain: string, - domainRedirects: Partial<ShlinkDomainRedirects>, -) => async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: EDIT_DOMAIN_REDIRECTS_START }); - const { editDomainRedirects: shlinkEditDomainRedirects } = buildShlinkApiClient(getState); +export const editDomainRedirects = ( + buildShlinkApiClient: ShlinkApiClientBuilder, +) => createAsyncThunk( + EDIT_DOMAIN_REDIRECTS, + async ({ domain, redirects: providedRedirects }: EditDomainRedirects, { getState }): Promise<EditDomainRedirects> => { + const { editDomainRedirects: shlinkEditDomainRedirects } = buildShlinkApiClient(getState); + const redirects = await shlinkEditDomainRedirects({ domain, ...providedRedirects }); - try { - const redirects = await shlinkEditDomainRedirects({ domain, ...domainRedirects }); - - dispatch<EditDomainRedirectsAction>({ type: EDIT_DOMAIN_REDIRECTS, domain, redirects }); - } catch (e: any) { - dispatch<ApiErrorAction>({ type: EDIT_DOMAIN_REDIRECTS_ERROR, errorData: parseApiError(e) }); - } -}; + return { domain, redirects }; + }, +); diff --git a/src/domains/reducers/domainsList.ts b/src/domains/reducers/domainsList.ts index b2349810..f1e622e0 100644 --- a/src/domains/reducers/domainsList.ts +++ b/src/domains/reducers/domainsList.ts @@ -1,20 +1,15 @@ -import { Action, Dispatch } from 'redux'; -import { ProblemDetailsError, ShlinkDomainRedirects } from '../../api/types'; -import { buildReducer } from '../../utils/helpers/redux'; +import { createSlice, createAction, SliceCaseReducers, AsyncThunk } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '../../utils/helpers/redux'; +import { ShlinkDomainRedirects } from '../../api/types'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { GetState } from '../../container/types'; -import { parseApiError } from '../../api/utils'; -import { ApiErrorAction } from '../../api/types/actions'; import { Domain, DomainStatus } from '../data'; import { hasServerData } from '../../servers/data'; import { replaceAuthorityFromUri } from '../../utils/helpers/uri'; -import { EDIT_DOMAIN_REDIRECTS, EditDomainRedirectsAction } from './domainRedirects'; +import { ProblemDetailsError } from '../../api/types/errors'; +import { parseApiError } from '../../api/utils'; +import { EditDomainRedirects } from './domainRedirects'; -export const LIST_DOMAINS_START = 'shlink/domainsList/LIST_DOMAINS_START'; -export const LIST_DOMAINS_ERROR = 'shlink/domainsList/LIST_DOMAINS_ERROR'; -export const LIST_DOMAINS = 'shlink/domainsList/LIST_DOMAINS'; -export const FILTER_DOMAINS = 'shlink/domainsList/FILTER_DOMAINS'; -export const VALIDATE_DOMAIN = 'shlink/domainsList/VALIDATE_DOMAIN'; +const REDUCER_PREFIX = 'shlink/domainsList'; export interface DomainsList { domains: Domain[]; @@ -25,16 +20,12 @@ export interface DomainsList { errorData?: ProblemDetailsError; } -export interface ListDomainsAction extends Action<string> { +interface ListDomains { domains: Domain[]; defaultRedirects?: ShlinkDomainRedirects; } -interface FilterDomainsAction extends Action<string> { - searchTerm: string; -} - -interface ValidateDomain extends Action<string> { +interface ValidateDomain { domain: string; status: DomainStatus; } @@ -46,83 +37,89 @@ const initialState: DomainsList = { error: false, }; -export type DomainsCombinedAction = ListDomainsAction -& ApiErrorAction -& FilterDomainsAction -& EditDomainRedirectsAction -& ValidateDomain; - -export const replaceRedirectsOnDomain = (domain: string, redirects: ShlinkDomainRedirects) => +export const replaceRedirectsOnDomain = ({ domain, redirects }: EditDomainRedirects) => (d: Domain): Domain => (d.domain !== domain ? d : { ...d, redirects }); export const replaceStatusOnDomain = (domain: string, status: DomainStatus) => (d: Domain): Domain => (d.domain !== domain ? d : { ...d, status }); -export default buildReducer<DomainsList, DomainsCombinedAction>({ - [LIST_DOMAINS_START]: () => ({ ...initialState, loading: true }), - [LIST_DOMAINS_ERROR]: ({ errorData }) => ({ ...initialState, error: true, errorData }), - [LIST_DOMAINS]: (_, { domains, defaultRedirects }) => - ({ ...initialState, domains, filteredDomains: domains, defaultRedirects }), - [FILTER_DOMAINS]: (state, { searchTerm }) => ({ - ...state, - filteredDomains: state.domains.filter(({ domain }) => domain.toLowerCase().match(searchTerm.toLowerCase())), - }), - [EDIT_DOMAIN_REDIRECTS]: (state, { domain, redirects }) => ({ - ...state, - domains: state.domains.map(replaceRedirectsOnDomain(domain, redirects)), - filteredDomains: state.filteredDomains.map(replaceRedirectsOnDomain(domain, redirects)), - }), - [VALIDATE_DOMAIN]: (state, { domain, status }) => ({ - ...state, - domains: state.domains.map(replaceStatusOnDomain(domain, status)), - filteredDomains: state.filteredDomains.map(replaceStatusOnDomain(domain, status)), - }), -}, initialState); - -export const listDomains = (buildShlinkApiClient: ShlinkApiClientBuilder) => () => async ( - dispatch: Dispatch, - getState: GetState, +export const domainsListReducerCreator = ( + buildShlinkApiClient: ShlinkApiClientBuilder, + editDomainRedirects: AsyncThunk<EditDomainRedirects, any, any>, ) => { - dispatch({ type: LIST_DOMAINS_START }); - const { listDomains: shlinkListDomains } = buildShlinkApiClient(getState); + const listDomains = createAsyncThunk(`${REDUCER_PREFIX}/listDomains`, async (_: void, { getState }): Promise<ListDomains> => { + const { listDomains: shlinkListDomains } = buildShlinkApiClient(getState); + const { data, defaultRedirects } = await shlinkListDomains(); - try { - const resp = await shlinkListDomains().then(({ data, defaultRedirects }) => ({ + return { domains: data.map((domain): Domain => ({ ...domain, status: 'validating' })), defaultRedirects, - })); + }; + }); - dispatch<ListDomainsAction>({ type: LIST_DOMAINS, ...resp }); - } catch (e: any) { - dispatch<ApiErrorAction>({ type: LIST_DOMAINS_ERROR, errorData: parseApiError(e) }); - } -}; - -export const filterDomains = (searchTerm: string): FilterDomainsAction => ({ type: FILTER_DOMAINS, searchTerm }); - -export const checkDomainHealth = (buildShlinkApiClient: ShlinkApiClientBuilder) => (domain: string) => async ( - dispatch: Dispatch, - getState: GetState, -) => { - const { selectedServer } = getState(); - - if (!hasServerData(selectedServer)) { - dispatch<ValidateDomain>({ type: VALIDATE_DOMAIN, domain, status: 'invalid' }); - - return; - } - - try { - const { url, ...rest } = selectedServer; - const { health } = buildShlinkApiClient({ - ...rest, - url: replaceAuthorityFromUri(url, domain), - }); - - const { status } = await health(); - - dispatch<ValidateDomain>({ type: VALIDATE_DOMAIN, domain, status: status === 'pass' ? 'valid' : 'invalid' }); - } catch (e) { - dispatch<ValidateDomain>({ type: VALIDATE_DOMAIN, domain, status: 'invalid' }); - } + const checkDomainHealth = createAsyncThunk( + `${REDUCER_PREFIX}/checkDomainHealth`, + async (domain: string, { getState }): Promise<ValidateDomain> => { + const { selectedServer } = getState(); + + if (!hasServerData(selectedServer)) { + return { domain, status: 'invalid' }; + } + + try { + const { url, ...rest } = selectedServer; + const { health } = buildShlinkApiClient({ + ...rest, + url: replaceAuthorityFromUri(url, domain), + }); + + const { status } = await health(); + + return { domain, status: status === 'pass' ? 'valid' : 'invalid' }; + } catch (e) { + return { domain, status: 'invalid' }; + } + }, + ); + + const filterDomains = createAction<string>(`${REDUCER_PREFIX}/filterDomains`); + + const { reducer } = createSlice<DomainsList, SliceCaseReducers<DomainsList>>({ + name: REDUCER_PREFIX, + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(listDomains.pending, () => ({ ...initialState, loading: true })); + builder.addCase(listDomains.rejected, (_, { error }) => ( + { ...initialState, error: true, errorData: parseApiError(error) } + )); + builder.addCase(listDomains.fulfilled, (_, { payload }) => ( + { ...initialState, ...payload, filteredDomains: payload.domains } + )); + + builder.addCase(checkDomainHealth.fulfilled, ({ domains, filteredDomains, ...rest }, { payload }) => ({ + ...rest, + domains: domains.map(replaceStatusOnDomain(payload.domain, payload.status)), + filteredDomains: filteredDomains.map(replaceStatusOnDomain(payload.domain, payload.status)), + })); + + builder.addCase(filterDomains, (state, { payload }) => ({ + ...state, + filteredDomains: state.domains.filter(({ domain }) => domain.toLowerCase().match(payload.toLowerCase())), + })); + + builder.addCase(editDomainRedirects.fulfilled, (state, { payload }) => ({ + ...state, + domains: state.domains.map(replaceRedirectsOnDomain(payload)), + filteredDomains: state.filteredDomains.map(replaceRedirectsOnDomain(payload)), + })); + }, + }); + + return { + reducer, + listDomains, + checkDomainHealth, + filterDomains, + }; }; diff --git a/src/domains/services/provideServices.ts b/src/domains/services/provideServices.ts index 9a4ba7fe..827302a3 100644 --- a/src/domains/services/provideServices.ts +++ b/src/domains/services/provideServices.ts @@ -1,6 +1,7 @@ +import { prop } from 'ramda'; import Bottle from 'bottlejs'; import { ConnectDecorator } from '../../container/types'; -import { checkDomainHealth, filterDomains, listDomains } from '../reducers/domainsList'; +import { domainsListReducerCreator } from '../reducers/domainsList'; import { DomainSelector } from '../DomainSelector'; import { ManageDomains } from '../ManageDomains'; import { editDomainRedirects } from '../reducers/domainRedirects'; @@ -16,11 +17,20 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { ['listDomains', 'filterDomains', 'editDomainRedirects', 'checkDomainHealth'], )); + // Reducer + bottle.serviceFactory( + 'domainsListReducerCreator', + domainsListReducerCreator, + 'buildShlinkApiClient', + 'editDomainRedirects', + ); + bottle.serviceFactory('domainsListReducer', prop('reducer'), 'domainsListReducerCreator'); + // Actions - bottle.serviceFactory('listDomains', listDomains, 'buildShlinkApiClient'); - bottle.serviceFactory('filterDomains', () => filterDomains); + bottle.serviceFactory('listDomains', prop('listDomains'), 'domainsListReducerCreator'); + bottle.serviceFactory('filterDomains', prop('filterDomains'), 'domainsListReducerCreator'); bottle.serviceFactory('editDomainRedirects', editDomainRedirects, 'buildShlinkApiClient'); - bottle.serviceFactory('checkDomainHealth', checkDomainHealth, 'buildShlinkApiClient'); + bottle.serviceFactory('checkDomainHealth', prop('checkDomainHealth'), 'domainsListReducerCreator'); }; export default provideServices; diff --git a/src/index.scss b/src/index.scss index f9cb0643..6092dc3f 100644 --- a/src/index.scss +++ b/src/index.scss @@ -3,7 +3,8 @@ @import './utils/base'; @import 'node_modules/bootstrap/scss/bootstrap.scss'; @import './common/react-tag-autocomplete.scss'; -@import './theme/theme'; +@import './utils/theme/theme'; +@import './utils/mixins/text-ellipsis'; @import './utils/table/ResponsiveTable'; @import './utils/StickyCardPaginator'; @@ -39,6 +40,10 @@ a:not(.nav-link):not(.navbar-brand):not(.page-link):not(.highlight-card):not(.bt background-color: $mainColor !important; } +.bg-warning { + color: $lightTextColor; +} + .card-body, .card-header, .list-group-item { @@ -218,9 +223,7 @@ hr { } .text-ellipsis { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; + @include text-ellipsis(); } .progress-bar { diff --git a/src/index.tsx b/src/index.tsx index dc13305e..e8d471c2 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,7 +3,7 @@ import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import pack from '../package.json'; import { container } from './container'; -import { store } from './container/store'; +import { setUpStore } from './container/store'; import { fixLeafletIcons } from './utils/helpers/leaflet'; import { register as registerServiceWorker } from './serviceWorkerRegistration'; import 'chart.js/auto'; // TODO Import specific ones to reduce bundle size https://react-chartjs-2.js.org/docs/migration-to-v4/#tree-shaking @@ -14,6 +14,7 @@ import './index.scss'; // This overwrites icons used for leaflet maps, fixing some issues caused by webpack while processing the CSS fixLeafletIcons(); +const store = setUpStore(container); const { App, ScrollToTop, ErrorHandler, appUpdateAvailable } = container; createRoot(document.getElementById('root')!).render( // eslint-disable-line @typescript-eslint/no-non-null-assertion diff --git a/src/mercure/reducers/mercureInfo.ts b/src/mercure/reducers/mercureInfo.ts index ca882138..d9ec7974 100644 --- a/src/mercure/reducers/mercureInfo.ts +++ b/src/mercure/reducers/mercureInfo.ts @@ -1,52 +1,44 @@ -import { Action, Dispatch } from 'redux'; +import { createSlice } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkMercureInfo } from '../../api/types'; -import { GetState } from '../../container/types'; -import { buildReducer } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -export const GET_MERCURE_INFO_START = 'shlink/mercure/GET_MERCURE_INFO_START'; -export const GET_MERCURE_INFO_ERROR = 'shlink/mercure/GET_MERCURE_INFO_ERROR'; -export const GET_MERCURE_INFO = 'shlink/mercure/GET_MERCURE_INFO'; +const REDUCER_PREFIX = 'shlink/mercure'; -export interface MercureInfo { - token?: string; - mercureHubUrl?: string; +export interface MercureInfo extends Partial<ShlinkMercureInfo> { interval?: number; loading: boolean; error: boolean; } -export type GetMercureInfoAction = Action<string> & ShlinkMercureInfo & { interval?: number }; - const initialState: MercureInfo = { loading: true, error: false, }; -export default buildReducer<MercureInfo, GetMercureInfoAction>({ - [GET_MERCURE_INFO_START]: (state) => ({ ...state, loading: true, error: false }), - [GET_MERCURE_INFO_ERROR]: (state) => ({ ...state, loading: false, error: true }), - [GET_MERCURE_INFO]: (_, action) => ({ ...action, loading: false, error: false }), -}, initialState); +export const mercureInfoReducerCreator = (buildShlinkApiClient: ShlinkApiClientBuilder) => { + const loadMercureInfo = createAsyncThunk( + `${REDUCER_PREFIX}/loadMercureInfo`, + (_: void, { getState }): Promise<ShlinkMercureInfo> => { + const { settings } = getState(); + if (!settings.realTimeUpdates.enabled) { + throw new Error('Real time updates not enabled'); + } -export const loadMercureInfo = (buildShlinkApiClient: ShlinkApiClientBuilder) => - () => async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: GET_MERCURE_INFO_START }); + return buildShlinkApiClient(getState).mercureInfo(); + }, + ); - const { settings } = getState(); - const { mercureInfo } = buildShlinkApiClient(getState); + const { reducer } = createSlice({ + name: REDUCER_PREFIX, + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(loadMercureInfo.pending, (state) => ({ ...state, loading: true, error: false })); + builder.addCase(loadMercureInfo.rejected, (state) => ({ ...state, loading: false, error: true })); + builder.addCase(loadMercureInfo.fulfilled, (_, { payload }) => ({ ...payload, loading: false, error: false })); + }, + }); - if (!settings.realTimeUpdates.enabled) { - dispatch({ type: GET_MERCURE_INFO_ERROR }); - - return; - } - - try { - const info = await mercureInfo(); - - dispatch<GetMercureInfoAction>({ type: GET_MERCURE_INFO, interval: settings.realTimeUpdates.interval, ...info }); - } catch (e) { - dispatch({ type: GET_MERCURE_INFO_ERROR }); - } - }; + return { loadMercureInfo, reducer }; +}; diff --git a/src/mercure/services/provideServices.ts b/src/mercure/services/provideServices.ts index bf29b207..06c341c7 100644 --- a/src/mercure/services/provideServices.ts +++ b/src/mercure/services/provideServices.ts @@ -1,9 +1,14 @@ +import { prop } from 'ramda'; import Bottle from 'bottlejs'; -import { loadMercureInfo } from '../reducers/mercureInfo'; +import { mercureInfoReducerCreator } from '../reducers/mercureInfo'; const provideServices = (bottle: Bottle) => { + // Reducer + bottle.serviceFactory('mercureInfoReducerCreator', mercureInfoReducerCreator, 'buildShlinkApiClient'); + bottle.serviceFactory('mercureInfoReducer', prop('reducer'), 'mercureInfoReducerCreator'); + // Actions - bottle.serviceFactory('loadMercureInfo', loadMercureInfo, 'buildShlinkApiClient'); + bottle.serviceFactory('loadMercureInfo', prop('loadMercureInfo'), 'mercureInfoReducerCreator'); }; export default provideServices; diff --git a/src/reducers/index.ts b/src/reducers/index.ts index da523b81..56734ac7 100644 --- a/src/reducers/index.ts +++ b/src/reducers/index.ts @@ -1,47 +1,31 @@ -import { combineReducers } from 'redux'; -import serversReducer from '../servers/reducers/servers'; -import selectedServerReducer from '../servers/reducers/selectedServer'; -import shortUrlsListReducer from '../short-urls/reducers/shortUrlsList'; -import shortUrlCreationReducer from '../short-urls/reducers/shortUrlCreation'; -import shortUrlDeletionReducer from '../short-urls/reducers/shortUrlDeletion'; -import shortUrlEditionReducer from '../short-urls/reducers/shortUrlEdition'; -import shortUrlVisitsReducer from '../visits/reducers/shortUrlVisits'; -import tagVisitsReducer from '../visits/reducers/tagVisits'; -import domainVisitsReducer from '../visits/reducers/domainVisits'; -import orphanVisitsReducer from '../visits/reducers/orphanVisits'; -import nonOrphanVisitsReducer from '../visits/reducers/nonOrphanVisits'; -import shortUrlDetailReducer from '../short-urls/reducers/shortUrlDetail'; -import tagsListReducer from '../tags/reducers/tagsList'; -import tagDeleteReducer from '../tags/reducers/tagDelete'; -import tagEditReducer from '../tags/reducers/tagEdit'; -import mercureInfoReducer from '../mercure/reducers/mercureInfo'; -import settingsReducer from '../settings/reducers/settings'; -import domainsListReducer from '../domains/reducers/domainsList'; -import visitsOverviewReducer from '../visits/reducers/visitsOverview'; -import appUpdatesReducer from '../app/reducers/appUpdates'; -import sidebarReducer from '../common/reducers/sidebar'; +import { IContainer } from 'bottlejs'; +import { combineReducers } from '@reduxjs/toolkit'; +import { serversReducer } from '../servers/reducers/servers'; +import { settingsReducer } from '../settings/reducers/settings'; +import { appUpdatesReducer } from '../app/reducers/appUpdates'; +import { sidebarReducer } from '../common/reducers/sidebar'; import { ShlinkState } from '../container/types'; -export default combineReducers<ShlinkState>({ +export default (container: IContainer) => combineReducers<ShlinkState>({ servers: serversReducer, - selectedServer: selectedServerReducer, - shortUrlsList: shortUrlsListReducer, - shortUrlCreationResult: shortUrlCreationReducer, - shortUrlDeletion: shortUrlDeletionReducer, - shortUrlEdition: shortUrlEditionReducer, - shortUrlVisits: shortUrlVisitsReducer, - tagVisits: tagVisitsReducer, - domainVisits: domainVisitsReducer, - orphanVisits: orphanVisitsReducer, - nonOrphanVisits: nonOrphanVisitsReducer, - shortUrlDetail: shortUrlDetailReducer, - tagsList: tagsListReducer, - tagDelete: tagDeleteReducer, - tagEdit: tagEditReducer, - mercureInfo: mercureInfoReducer, + selectedServer: container.selectedServerReducer, + shortUrlsList: container.shortUrlsListReducer, + shortUrlCreation: container.shortUrlCreationReducer, + shortUrlDeletion: container.shortUrlDeletionReducer, + shortUrlEdition: container.shortUrlEditionReducer, + shortUrlDetail: container.shortUrlDetailReducer, + shortUrlVisits: container.shortUrlVisitsReducer, + tagVisits: container.tagVisitsReducer, + domainVisits: container.domainVisitsReducer, + orphanVisits: container.orphanVisitsReducer, + nonOrphanVisits: container.nonOrphanVisitsReducer, + tagsList: container.tagsListReducer, + tagDelete: container.tagDeleteReducer, + tagEdit: container.tagEditReducer, + mercureInfo: container.mercureInfoReducer, settings: settingsReducer, - domainsList: domainsListReducer, - visitsOverview: visitsOverviewReducer, + domainsList: container.domainsListReducer, + visitsOverview: container.visitsOverviewReducer, appUpdated: appUpdatesReducer, sidebar: sidebarReducer, }); diff --git a/src/servers/CreateServer.tsx b/src/servers/CreateServer.tsx index df96e838..4ffd93ea 100644 --- a/src/servers/CreateServer.tsx +++ b/src/servers/CreateServer.tsx @@ -13,7 +13,7 @@ import { DuplicatedServersModal } from './helpers/DuplicatedServersModal'; const SHOW_IMPORT_MSG_TIME = 4000; interface CreateServerProps { - createServer: (server: ServerWithId) => void; + createServers: (servers: ServerWithId[]) => void; servers: ServersMap; } @@ -27,7 +27,7 @@ const ImportResult = ({ type }: { type: 'error' | 'success' }) => ( ); export const CreateServer = (ImportServersBtn: FC<ImportServersBtnProps>, useTimeoutToggle: TimeoutToggle) => ( - { servers, createServer }: CreateServerProps, + { servers, createServers }: CreateServerProps, ) => { const navigate = useNavigate(); const goBack = useGoBack(); @@ -43,7 +43,7 @@ export const CreateServer = (ImportServersBtn: FC<ImportServersBtnProps>, useTim const id = uuid(); - createServer({ ...serverData, id }); + createServers([{ ...serverData, id }]); navigate(`/server/${id}`); }; diff --git a/src/servers/DeleteServerModal.tsx b/src/servers/DeleteServerModal.tsx index 8fba141c..d22c93c4 100644 --- a/src/servers/DeleteServerModal.tsx +++ b/src/servers/DeleteServerModal.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react'; +import { FC, useRef } from 'react'; import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import { useNavigate } from 'react-router-dom'; import { ServerWithId } from './data'; @@ -18,14 +18,22 @@ export const DeleteServerModal: FC<DeleteServerModalConnectProps> = ( { server, toggle, isOpen, deleteServer, redirectHome = true }, ) => { const navigate = useNavigate(); - const closeModal = () => { - deleteServer(server); + const doDelete = useRef<boolean>(false); + const toggleAndDelete = () => { + doDelete.current = true; toggle(); + }; + const onClosed = () => { + if (!doDelete.current) { + return; + } + + deleteServer(server); redirectHome && navigate('/'); }; return ( - <Modal isOpen={isOpen} toggle={toggle} centered> + <Modal isOpen={isOpen} toggle={toggle} centered onClosed={onClosed}> <ModalHeader toggle={toggle} className="text-danger">Remove server</ModalHeader> <ModalBody> <p>Are you sure you want to remove <b>{server ? server.name : ''}</b>?</p> @@ -38,7 +46,7 @@ export const DeleteServerModal: FC<DeleteServerModalConnectProps> = ( </ModalBody> <ModalFooter> <Button color="link" onClick={toggle}>Cancel</Button> - <Button color="danger" onClick={() => closeModal()}>Delete</Button> + <Button color="danger" onClick={toggleAndDelete}>Delete</Button> </ModalFooter> </Modal> ); diff --git a/src/servers/reducers/remoteServers.ts b/src/servers/reducers/remoteServers.ts index 52e1bc9f..8776441d 100644 --- a/src/servers/reducers/remoteServers.ts +++ b/src/servers/reducers/remoteServers.ts @@ -1,18 +1,17 @@ -import { pipe, prop } from 'ramda'; -import { AxiosInstance } from 'axios'; -import { Dispatch } from 'redux'; import pack from '../../../package.json'; import { hasServerData, ServerData } from '../data'; import { createServers } from './servers'; +import { createAsyncThunk } from '../../utils/helpers/redux'; +import { HttpClient } from '../../common/services/HttpClient'; -const responseToServersList = pipe( - prop<any, any>('data'), - (data: any): ServerData[] => (Array.isArray(data) ? data.filter(hasServerData) : []), +const responseToServersList = (data: any): ServerData[] => (Array.isArray(data) ? data.filter(hasServerData) : []); + +export const fetchServers = (httpClient: HttpClient) => createAsyncThunk( + 'shlink/remoteServers/fetchServers', + async (_: void, { dispatch }): Promise<void> => { + const resp = await httpClient.fetchJson<any>(`${pack.homepage}/servers.json`); + const result = responseToServersList(resp); + + dispatch(createServers(result)); + }, ); - -export const fetchServers = ({ get }: AxiosInstance) => () => async (dispatch: Dispatch) => { - const resp = await get(`${pack.homepage}/servers.json`); - const remoteList = responseToServersList(resp); - - dispatch(createServers(remoteList)); -}; diff --git a/src/servers/reducers/selectedServer.ts b/src/servers/reducers/selectedServer.ts index b33f344d..3415a15c 100644 --- a/src/servers/reducers/selectedServer.ts +++ b/src/servers/reducers/selectedServer.ts @@ -1,23 +1,17 @@ +import { createAction, createListenerMiddleware, createSlice, PayloadAction } from '@reduxjs/toolkit'; import { identity, memoizeWith, pipe } from 'ramda'; -import { Action, Dispatch } from 'redux'; import { versionToPrintable, versionToSemVer as toSemVer } from '../../utils/helpers/version'; -import { SelectedServer } from '../data'; -import { GetState } from '../../container/types'; +import { isReachableServer, SelectedServer } from '../data'; import { ShlinkHealth } from '../../api/types'; -import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -export const SELECT_SERVER = 'shlink/selectedServer/SELECT_SERVER'; -export const RESET_SELECTED_SERVER = 'shlink/selectedServer/RESET_SELECTED_SERVER'; +const REDUCER_PREFIX = 'shlink/selectedServer'; export const MIN_FALLBACK_VERSION = '1.0.0'; export const MAX_FALLBACK_VERSION = '999.999.999'; export const LATEST_VERSION_CONSTRAINT = 'latest'; -export interface SelectServerAction extends Action<string> { - selectedServer: SelectedServer; -} - const versionToSemVer = pipe( (version: string) => (version === LATEST_VERSION_CONSTRAINT ? MAX_FALLBACK_VERSION : version), toSemVer(MIN_FALLBACK_VERSION), @@ -33,53 +27,59 @@ const getServerVersion = memoizeWith( const initialState: SelectedServer = null; -export default buildReducer<SelectedServer, SelectServerAction>({ - [RESET_SELECTED_SERVER]: () => initialState, - [SELECT_SERVER]: (_, { selectedServer }) => selectedServer, -}, initialState); +export const resetSelectedServer = createAction<void>(`${REDUCER_PREFIX}/resetSelectedServer`); -export const resetSelectedServer = buildActionCreator(RESET_SELECTED_SERVER); +export const selectServer = (buildShlinkApiClient: ShlinkApiClientBuilder) => createAsyncThunk( + `${REDUCER_PREFIX}/selectServer`, + async (serverId: string, { dispatch, getState }): Promise<SelectedServer> => { + dispatch(resetSelectedServer()); -export const selectServer = ( - buildShlinkApiClient: ShlinkApiClientBuilder, - loadMercureInfo: () => Action, -) => ( - serverId: string, -) => async ( - dispatch: Dispatch, - getState: GetState, -) => { - dispatch(resetSelectedServer()); + const { servers } = getState(); + const selectedServer = servers[serverId]; - const { servers } = getState(); - const selectedServer = servers[serverId]; + if (!selectedServer) { + return { serverNotFound: true }; + } - if (!selectedServer) { - dispatch<SelectServerAction>({ - type: SELECT_SERVER, - selectedServer: { serverNotFound: true }, - }); + try { + const { health } = buildShlinkApiClient(selectedServer); + const { version, printableVersion } = await getServerVersion(serverId, health); - return; - } - - try { - const { health } = buildShlinkApiClient(selectedServer); - const { version, printableVersion } = await getServerVersion(serverId, health); - - dispatch<SelectServerAction>({ - type: SELECT_SERVER, - selectedServer: { + return { ...selectedServer, version, printableVersion, - }, - }); - dispatch(loadMercureInfo()); - } catch (e) { - dispatch<SelectServerAction>({ - type: SELECT_SERVER, - selectedServer: { ...selectedServer, serverNotReachable: true }, - }); - } + }; + } catch (e) { + return { ...selectedServer, serverNotReachable: true }; + } + }, +); + +type SelectServerThunk = ReturnType<typeof selectServer>; + +export const selectServerListener = ( + selectServerThunk: SelectServerThunk, + loadMercureInfo: () => PayloadAction<any>, // TODO Consider setting actual type, if relevant +) => { + const listener = createListenerMiddleware(); + + listener.startListening({ + actionCreator: selectServerThunk.fulfilled, + effect: ({ payload }, { dispatch }) => { + isReachableServer(payload) && dispatch(loadMercureInfo()); + }, + }); + + return listener; }; + +export const selectedServerReducerCreator = (selectServerThunk: SelectServerThunk) => createSlice({ + name: REDUCER_PREFIX, + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(resetSelectedServer, () => initialState); + builder.addCase(selectServerThunk.fulfilled, (_, { payload }) => payload as any); + }, +}); diff --git a/src/servers/reducers/servers.ts b/src/servers/reducers/servers.ts index 31cd4d13..faa2c9c6 100644 --- a/src/servers/reducers/servers.ts +++ b/src/servers/reducers/servers.ts @@ -1,23 +1,14 @@ +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { assoc, dissoc, fromPairs, map, pipe, reduce, toPairs } from 'ramda'; import { v4 as uuid } from 'uuid'; -import { Action } from 'redux'; import { ServerData, ServersMap, ServerWithId } from '../data'; -import { buildReducer } from '../../utils/helpers/redux'; -export const EDIT_SERVER = 'shlink/servers/EDIT_SERVER'; -export const DELETE_SERVER = 'shlink/servers/DELETE_SERVER'; -export const CREATE_SERVERS = 'shlink/servers/CREATE_SERVERS'; -export const SET_AUTO_CONNECT = 'shlink/servers/SET_AUTO_CONNECT'; - -export interface CreateServersAction extends Action<string> { - newServers: ServersMap; -} - -interface DeleteServerAction extends Action<string> { +interface EditServer { serverId: string; + serverData: Partial<ServerData>; } -interface SetAutoConnectAction extends Action<string> { +interface SetAutoConnect { serverId: string; autoConnect: boolean; } @@ -32,50 +23,57 @@ const serverWithId = (server: ServerWithId | ServerData): ServerWithId => { return assoc('id', uuid(), server); }; -export default buildReducer<ServersMap, CreateServersAction & DeleteServerAction & SetAutoConnectAction>({ - [CREATE_SERVERS]: (state, { newServers }) => ({ ...state, ...newServers }), - [DELETE_SERVER]: (state, { serverId }) => dissoc(serverId, state), - [EDIT_SERVER]: (state, { serverId, serverData }: any) => ( - !state[serverId] ? state : assoc(serverId, { ...state[serverId], ...serverData }, state) - ), - [SET_AUTO_CONNECT]: (state, { serverId, autoConnect }) => { - if (!state[serverId]) { - return state; - } - - if (!autoConnect) { - return assoc(serverId, { ...state[serverId], autoConnect }, state); - } - - return fromPairs( - toPairs(state).map(([evaluatedServerId, server]) => [ - evaluatedServerId, - { ...server, autoConnect: evaluatedServerId === serverId }, - ]), - ); - }, -}, initialState); - const serversListToMap = reduce<ServerWithId, ServersMap>((acc, server) => assoc(server.id, server, acc), {}); -export const createServers = pipe( - map(serverWithId), - serversListToMap, - (newServers: ServersMap) => ({ type: CREATE_SERVERS, newServers }), -); +export const { actions, reducer } = createSlice({ + name: 'shlink/servers', + initialState, + reducers: { + editServer: { + prepare: (serverId: string, serverData: Partial<ServerData>) => ({ + payload: { serverId, serverData }, + }), + reducer: (state, { payload }: PayloadAction<EditServer>) => { + const { serverId, serverData } = payload; + return ( + !state[serverId] ? state : assoc(serverId, { ...state[serverId], ...serverData }, state) + ); + }, + }, + deleteServer: (state, { payload }) => dissoc(payload.id, state), + setAutoConnect: { + prepare: ({ id: serverId }: ServerWithId, autoConnect: boolean) => ({ + payload: { serverId, autoConnect }, + }), + reducer: (state, { payload }: PayloadAction<SetAutoConnect>) => { + const { serverId, autoConnect } = payload; + if (!state[serverId]) { + return state; + } -export const createServer = (server: ServerWithId) => createServers([server]); + if (!autoConnect) { + return assoc(serverId, { ...state[serverId], autoConnect }, state); + } -export const editServer = (serverId: string, serverData: Partial<ServerData>) => ({ - type: EDIT_SERVER, - serverId, - serverData, + return fromPairs( + toPairs(state).map(([evaluatedServerId, server]) => [ + evaluatedServerId, + { ...server, autoConnect: evaluatedServerId === serverId }, + ]), + ); + }, + }, + createServers: { + prepare: pipe( + map(serverWithId), + serversListToMap, + (payload: ServersMap) => ({ payload }), + ), + reducer: (state, { payload: newServers }: PayloadAction<ServersMap>) => ({ ...state, ...newServers }), + }, + }, }); -export const deleteServer = ({ id }: ServerWithId): DeleteServerAction => ({ type: DELETE_SERVER, serverId: id }); +export const { editServer, deleteServer, setAutoConnect, createServers } = actions; -export const setAutoConnect = ({ id }: ServerWithId, autoConnect: boolean): SetAutoConnectAction => ({ - type: SET_AUTO_CONNECT, - serverId: id, - autoConnect, -}); +export const serversReducer = reducer; diff --git a/src/servers/services/provideServices.ts b/src/servers/services/provideServices.ts index 6f56cc84..92aaca58 100644 --- a/src/servers/services/provideServices.ts +++ b/src/servers/services/provideServices.ts @@ -1,3 +1,4 @@ +import { prop } from 'ramda'; import Bottle from 'bottlejs'; import { CreateServer } from '../CreateServer'; import { ServersDropdown } from '../ServersDropdown'; @@ -5,8 +6,13 @@ import { DeleteServerModal } from '../DeleteServerModal'; import { DeleteServerButton } from '../DeleteServerButton'; import { EditServer } from '../EditServer'; import { ImportServersBtn } from '../helpers/ImportServersBtn'; -import { resetSelectedServer, selectServer } from '../reducers/selectedServer'; -import { createServer, createServers, deleteServer, editServer, setAutoConnect } from '../reducers/servers'; +import { + resetSelectedServer, + selectedServerReducerCreator, + selectServer, + selectServerListener, +} from '../reducers/selectedServer'; +import { createServers, deleteServer, editServer, setAutoConnect } from '../reducers/servers'; import { fetchServers } from '../reducers/remoteServers'; import { ServerError } from '../helpers/ServerError'; import { ConnectDecorator } from '../../container/types'; @@ -38,7 +44,7 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { bottle.serviceFactory('CreateServer', CreateServer, 'ImportServersBtn', 'useTimeoutToggle'); bottle.decorator('CreateServer', withoutSelectedServer); - bottle.decorator('CreateServer', connect(['selectedServer', 'servers'], ['createServer', 'resetSelectedServer'])); + bottle.decorator('CreateServer', connect(['selectedServer', 'servers'], ['createServers', 'resetSelectedServer'])); bottle.serviceFactory('EditServer', EditServer, 'ServerError'); bottle.decorator('EditServer', connect(['selectedServer'], ['editServer', 'selectServer', 'resetSelectedServer'])); @@ -70,14 +76,18 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { // Actions bottle.serviceFactory('selectServer', selectServer, 'buildShlinkApiClient', 'loadMercureInfo'); - bottle.serviceFactory('createServer', () => createServer); bottle.serviceFactory('createServers', () => createServers); bottle.serviceFactory('deleteServer', () => deleteServer); bottle.serviceFactory('editServer', () => editServer); bottle.serviceFactory('setAutoConnect', () => setAutoConnect); - bottle.serviceFactory('fetchServers', fetchServers, 'axios'); + bottle.serviceFactory('fetchServers', fetchServers, 'HttpClient'); bottle.serviceFactory('resetSelectedServer', () => resetSelectedServer); + + // Reducers + bottle.serviceFactory('selectServerListener', selectServerListener, 'selectServer', 'loadMercureInfo'); + bottle.serviceFactory('selectedServerReducerCreator', selectedServerReducerCreator, 'selectServer'); + bottle.serviceFactory('selectedServerReducer', prop('reducer'), 'selectedServerReducerCreator'); }; export default provideServices; diff --git a/src/settings/reducers/settings.ts b/src/settings/reducers/settings.ts index 8a106682..b707160c 100644 --- a/src/settings/reducers/settings.ts +++ b/src/settings/reducers/settings.ts @@ -1,14 +1,10 @@ -import { Action } from 'redux'; -import { dissoc, mergeDeepRight } from 'ramda'; -import { buildReducer } from '../../utils/helpers/redux'; -import { RecursivePartial } from '../../utils/utils'; +import { createSlice, PayloadAction, PrepareAction } from '@reduxjs/toolkit'; +import { mergeDeepRight } from 'ramda'; import { Theme } from '../../utils/theme'; -import { DateInterval } from '../../utils/dates/types'; +import { DateInterval } from '../../utils/helpers/dateIntervals'; import { TagsOrder } from '../../tags/data/TagsListChildrenProps'; import { ShortUrlsOrder } from '../../short-urls/data'; -export const SET_SETTINGS = 'shlink/realTimeUpdates/SET_SETTINGS'; - export const DEFAULT_SHORT_URLS_ORDERING: ShortUrlsOrder = { field: 'dateCreated', dir: 'DESC', @@ -78,45 +74,37 @@ const initialState: Settings = { }, }; -type SettingsAction = Action & Settings; +type SettingsAction = PayloadAction<Settings>; +type SettingsPrepareAction = PrepareAction<Settings>; -type PartialSettingsAction = Action & RecursivePartial<Settings>; +const commonReducer = (state: Settings, { payload }: SettingsAction) => mergeDeepRight(state, payload); +const toReducer = (prepare: SettingsPrepareAction) => ({ reducer: commonReducer, prepare }); +const toPreparedAction: SettingsPrepareAction = (payload: Settings) => ({ payload }); -export default buildReducer<Settings, SettingsAction>({ - [SET_SETTINGS]: (state, action) => mergeDeepRight(state, dissoc('type', action)), -}, initialState); - -export const toggleRealTimeUpdates = (enabled: boolean): PartialSettingsAction => ({ - type: SET_SETTINGS, - realTimeUpdates: { enabled }, +const { reducer, actions } = createSlice({ + name: 'shlink/settings', + initialState, + reducers: { + toggleRealTimeUpdates: toReducer((enabled: boolean) => toPreparedAction({ realTimeUpdates: { enabled } })), + setRealTimeUpdatesInterval: toReducer((interval: number) => toPreparedAction({ realTimeUpdates: { interval } })), + setShortUrlCreationSettings: toReducer( + (shortUrlCreation: ShortUrlCreationSettings) => toPreparedAction({ shortUrlCreation }), + ), + setShortUrlsListSettings: toReducer((shortUrlsList: ShortUrlsListSettings) => toPreparedAction({ shortUrlsList })), + setUiSettings: toReducer((ui: UiSettings) => toPreparedAction({ ui })), + setVisitsSettings: toReducer((visits: VisitsSettings) => toPreparedAction({ visits })), + setTagsSettings: toReducer((tags: TagsSettings) => toPreparedAction({ tags })), + }, }); -export const setRealTimeUpdatesInterval = (interval: number): PartialSettingsAction => ({ - type: SET_SETTINGS, - realTimeUpdates: { interval }, -}); +export const { + toggleRealTimeUpdates, + setRealTimeUpdatesInterval, + setShortUrlCreationSettings, + setShortUrlsListSettings, + setUiSettings, + setVisitsSettings, + setTagsSettings, +} = actions; -export const setShortUrlCreationSettings = (settings: ShortUrlCreationSettings): PartialSettingsAction => ({ - type: SET_SETTINGS, - shortUrlCreation: settings, -}); - -export const setShortUrlsListSettings = (settings: ShortUrlsListSettings): PartialSettingsAction => ({ - type: SET_SETTINGS, - shortUrlsList: settings, -}); - -export const setUiSettings = (settings: UiSettings): PartialSettingsAction => ({ - type: SET_SETTINGS, - ui: settings, -}); - -export const setVisitsSettings = (settings: VisitsSettings): PartialSettingsAction => ({ - type: SET_SETTINGS, - visits: settings, -}); - -export const setTagsSettings = (settings: TagsSettings): PartialSettingsAction => ({ - type: SET_SETTINGS, - tags: settings, -}); +export const settingsReducer = reducer; diff --git a/src/short-urls/CreateShortUrl.tsx b/src/short-urls/CreateShortUrl.tsx index 8da5a480..2f045023 100644 --- a/src/short-urls/CreateShortUrl.tsx +++ b/src/short-urls/CreateShortUrl.tsx @@ -12,7 +12,7 @@ export interface CreateShortUrlProps { interface CreateShortUrlConnectProps extends CreateShortUrlProps { settings: Settings; - shortUrlCreationResult: ShortUrlCreation; + shortUrlCreation: ShortUrlCreation; selectedServer: SelectedServer; createShortUrl: (data: ShortUrlData) => Promise<void>; resetCreateShortUrl: () => void; @@ -38,7 +38,7 @@ export const CreateShortUrl = ( CreateShortUrlResult: FC<CreateShortUrlResultProps>, ) => ({ createShortUrl, - shortUrlCreationResult, + shortUrlCreation, resetCreateShortUrl, selectedServer, basicMode = false, @@ -50,7 +50,7 @@ export const CreateShortUrl = ( <> <ShortUrlForm initialState={initialState} - saving={shortUrlCreationResult.saving} + saving={shortUrlCreation.saving} selectedServer={selectedServer} mode={basicMode ? 'create-basic' : 'create'} onSave={async (data: ShortUrlData) => { @@ -59,7 +59,7 @@ export const CreateShortUrl = ( }} /> <CreateShortUrlResult - {...shortUrlCreationResult} + creation={shortUrlCreation} resetCreateShortUrl={resetCreateShortUrl} canBeClosed={basicMode} /> diff --git a/src/short-urls/EditShortUrl.tsx b/src/short-urls/EditShortUrl.tsx index 3c243a25..db8c4d43 100644 --- a/src/short-urls/EditShortUrl.tsx +++ b/src/short-urls/EditShortUrl.tsx @@ -6,16 +6,15 @@ import { ExternalLink } from 'react-external-link'; import { useLocation, useParams } from 'react-router-dom'; import { SelectedServer } from '../servers/data'; import { Settings } from '../settings/reducers/settings'; -import { OptionalString } from '../utils/utils'; +import { ShortUrlIdentifier } from './data'; import { parseQuery } from '../utils/helpers/query'; import { Message } from '../utils/Message'; import { Result } from '../utils/Result'; import { ShlinkApiError } from '../api/ShlinkApiError'; -import { useGoBack, useToggle } from '../utils/helpers/hooks'; +import { useGoBack } from '../utils/helpers/hooks'; import { ShortUrlFormProps } from './ShortUrlForm'; import { ShortUrlDetail } from './reducers/shortUrlDetail'; -import { EditShortUrlData } from './data'; -import { ShortUrlEdition } from './reducers/shortUrlEdition'; +import { EditShortUrl as EditShortUrlInfo, ShortUrlEdition } from './reducers/shortUrlEdition'; import { shortUrlDataFromShortUrl, urlDecodeShortCode } from './helpers'; interface EditShortUrlConnectProps { @@ -23,8 +22,8 @@ interface EditShortUrlConnectProps { selectedServer: SelectedServer; shortUrlDetail: ShortUrlDetail; shortUrlEdition: ShortUrlEdition; - getShortUrlDetail: (shortCode: string, domain: OptionalString) => void; - editShortUrl: (shortUrl: string, domain: OptionalString, data: EditShortUrlData) => Promise<void>; + getShortUrlDetail: (shortUrl: ShortUrlIdentifier) => void; + editShortUrl: (editShortUrl: EditShortUrlInfo) => void; } export const EditShortUrl = (ShortUrlForm: FC<ShortUrlFormProps>) => ({ @@ -39,16 +38,15 @@ export const EditShortUrl = (ShortUrlForm: FC<ShortUrlFormProps>) => ({ const params = useParams<{ shortCode: string }>(); const goBack = useGoBack(); const { loading, error, errorData, shortUrl } = shortUrlDetail; - const { saving, error: savingError, errorData: savingErrorData } = shortUrlEdition; + const { saving, saved, error: savingError, errorData: savingErrorData } = shortUrlEdition; const { domain } = parseQuery<{ domain?: string }>(search); const initialState = useMemo( () => shortUrlDataFromShortUrl(shortUrl, shortUrlCreationSettings), [shortUrl, shortUrlCreationSettings], ); - const [savingSucceeded,, isSuccessful, isNotSuccessful] = useToggle(); useEffect(() => { - params.shortCode && getShortUrlDetail(urlDecodeShortCode(params.shortCode), domain); + params.shortCode && getShortUrlDetail({ shortCode: urlDecodeShortCode(params.shortCode), domain }); }, []); if (loading) { @@ -88,18 +86,15 @@ export const EditShortUrl = (ShortUrlForm: FC<ShortUrlFormProps>) => ({ return; } - isNotSuccessful(); - editShortUrl(shortUrl.shortCode, shortUrl.domain, shortUrlData) - .then(isSuccessful) - .catch(isNotSuccessful); + editShortUrl({ ...shortUrl, data: shortUrlData }); }} /> - {savingError && ( + {saved && savingError && ( <Result type="error" className="mt-3"> <ShlinkApiError errorData={savingErrorData} fallbackMessage="An error occurred while updating short URL :(" /> </Result> )} - {savingSucceeded && <Result type="success" className="mt-3">Short URL properly edited.</Result>} + {saved && !savingError && <Result type="success" className="mt-3">Short URL properly edited.</Result>} </> ); }; diff --git a/src/short-urls/ShortUrlForm.tsx b/src/short-urls/ShortUrlForm.tsx index 5385d784..8c3f6635 100644 --- a/src/short-urls/ShortUrlForm.tsx +++ b/src/short-urls/ShortUrlForm.tsx @@ -3,7 +3,7 @@ import { InputType } from 'reactstrap/types/lib/Input'; import { Button, FormGroup, Input, Row } from 'reactstrap'; import { cond, isEmpty, pipe, replace, trim, T } from 'ramda'; import { parseISO } from 'date-fns'; -import { DateInput, DateInputProps } from '../utils/DateInput'; +import { DateTimeInput, DateTimeInputProps } from '../utils/dates/DateTimeInput'; import { supportsCrawlableVisits, supportsForwardQuery } from '../utils/helpers/features'; import { SimpleCard } from '../utils/SimpleCard'; import { handleEventPreventingDefault, hasValue, OptionalString } from '../utils/utils'; @@ -83,8 +83,8 @@ export const ShortUrlForm = ( /> </FormGroup> ); - const renderDateInput = (id: DateFields, placeholder: string, props: Partial<DateInputProps> = {}) => ( - <DateInput + const renderDateInput = (id: DateFields, placeholder: string, props: Partial<DateTimeInputProps> = {}) => ( + <DateTimeInput selected={shortUrlData[id] ? toDate(shortUrlData[id] as string | Date) : null} placeholderText={placeholder} isClearable diff --git a/src/short-urls/ShortUrlsFilteringBar.tsx b/src/short-urls/ShortUrlsFilteringBar.tsx index 205c62ef..1a5ec29d 100644 --- a/src/short-urls/ShortUrlsFilteringBar.tsx +++ b/src/short-urls/ShortUrlsFilteringBar.tsx @@ -1,6 +1,5 @@ import { FC } from 'react'; import { isEmpty, pipe } from 'ramda'; -import { parseISO } from 'date-fns'; import { Button, InputGroup, Row, UncontrolledTooltip } from 'reactstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTag, faTags } from '@fortawesome/free-solid-svg-icons'; @@ -8,7 +7,7 @@ import classNames from 'classnames'; import { SearchField } from '../utils/SearchField'; import { DateRangeSelector } from '../utils/dates/DateRangeSelector'; import { formatIsoDate } from '../utils/helpers/date'; -import { DateRange } from '../utils/dates/types'; +import { DateRange, datesToDateRange } from '../utils/helpers/dateIntervals'; import { supportsAllTagsFiltering } from '../utils/helpers/features'; import { SelectedServer } from '../servers/data'; import { OrderDir } from '../utils/helpers/ordering'; @@ -27,8 +26,6 @@ export interface ShortUrlsFilteringProps { shortUrlsAmount?: number; } -const dateOrNull = (date?: string) => (date ? parseISO(date) : null); - export const ShortUrlsFilteringBar = ( ExportShortUrlsBtn: FC<ExportShortUrlsBtnProps>, TagsSelector: FC<TagsSelectorProps>, @@ -74,10 +71,7 @@ export const ShortUrlsFilteringBar = ( <div className="col-lg-8 col-xl-6 mt-3"> <DateRangeSelector defaultText="All short URLs" - initialDateRange={{ - startDate: dateOrNull(startDate), - endDate: dateOrNull(endDate), - }} + initialDateRange={datesToDateRange(startDate, endDate)} onDatesChange={setDates} /> </div> diff --git a/src/short-urls/data/index.ts b/src/short-urls/data/index.ts index 3c17a812..88f5b22b 100644 --- a/src/short-urls/data/index.ts +++ b/src/short-urls/data/index.ts @@ -21,6 +21,11 @@ export interface ShortUrlData extends EditShortUrlData { findIfExists?: boolean; } +export interface ShortUrlIdentifier { + shortCode: string; + domain?: OptionalString; +} + export interface ShortUrl { shortCode: string; shortUrl: string; @@ -47,11 +52,6 @@ export interface ShortUrlModalProps { toggle: () => void; } -export interface ShortUrlIdentifier { - shortCode: string; - domain: OptionalString; -} - export const SHORT_URLS_ORDERABLE_FIELDS = { dateCreated: 'Created at', shortCode: 'Short URL', diff --git a/src/short-urls/helpers/CreateShortUrlResult.tsx b/src/short-urls/helpers/CreateShortUrlResult.tsx index 218755b3..220eb42f 100644 --- a/src/short-urls/helpers/CreateShortUrlResult.tsx +++ b/src/short-urls/helpers/CreateShortUrlResult.tsx @@ -1,7 +1,6 @@ import { faCopy as copyIcon } from '@fortawesome/free-regular-svg-icons'; import { faTimes as closeIcon } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { isNil } from 'ramda'; import { useEffect } from 'react'; import CopyToClipboard from 'react-copy-to-clipboard'; import { Tooltip } from 'reactstrap'; @@ -11,15 +10,17 @@ import { Result } from '../../utils/Result'; import './CreateShortUrlResult.scss'; import { ShlinkApiError } from '../../api/ShlinkApiError'; -export interface CreateShortUrlResultProps extends ShortUrlCreation { +export interface CreateShortUrlResultProps { + creation: ShortUrlCreation; resetCreateShortUrl: () => void; canBeClosed?: boolean; } export const CreateShortUrlResult = (useTimeoutToggle: TimeoutToggle) => ( - { error, errorData, result, resetCreateShortUrl, canBeClosed = false }: CreateShortUrlResultProps, + { creation, resetCreateShortUrl, canBeClosed = false }: CreateShortUrlResultProps, ) => { const [showCopyTooltip, setShowCopyTooltip] = useTimeoutToggle(); + const { error, saved } = creation; useEffect(() => { resetCreateShortUrl(); @@ -29,16 +30,16 @@ export const CreateShortUrlResult = (useTimeoutToggle: TimeoutToggle) => ( return ( <Result type="error" className="mt-3"> {canBeClosed && <FontAwesomeIcon icon={closeIcon} className="float-end pointer" onClick={resetCreateShortUrl} />} - <ShlinkApiError errorData={errorData} fallbackMessage="An error occurred while creating the URL :(" /> + <ShlinkApiError errorData={creation.errorData} fallbackMessage="An error occurred while creating the URL :(" /> </Result> ); } - if (isNil(result)) { + if (!saved) { return null; } - const { shortUrl } = result; + const { shortUrl } = creation.result; return ( <Result type="success" className="mt-3"> diff --git a/src/short-urls/helpers/DeleteShortUrlModal.tsx b/src/short-urls/helpers/DeleteShortUrlModal.tsx index 1bf7579f..e62a946e 100644 --- a/src/short-urls/helpers/DeleteShortUrlModal.tsx +++ b/src/short-urls/helpers/DeleteShortUrlModal.tsx @@ -1,38 +1,41 @@ import { useEffect, useState } from 'react'; import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; -import { identity, pipe } from 'ramda'; +import { pipe } from 'ramda'; import { ShortUrlDeletion } from '../reducers/shortUrlDeletion'; -import { ShortUrlModalProps } from '../data'; -import { handleEventPreventingDefault, OptionalString } from '../../utils/utils'; +import { ShortUrlIdentifier, ShortUrlModalProps } from '../data'; +import { handleEventPreventingDefault } from '../../utils/utils'; import { Result } from '../../utils/Result'; import { isInvalidDeletionError } from '../../api/utils'; import { ShlinkApiError } from '../../api/ShlinkApiError'; interface DeleteShortUrlModalConnectProps extends ShortUrlModalProps { shortUrlDeletion: ShortUrlDeletion; - deleteShortUrl: (shortCode: string, domain: OptionalString) => Promise<void>; + deleteShortUrl: (shortUrl: ShortUrlIdentifier) => Promise<void>; + shortUrlDeleted: (shortUrl: ShortUrlIdentifier) => void; resetDeleteShortUrl: () => void; } -export const DeleteShortUrlModal = ( - { shortUrl, toggle, isOpen, shortUrlDeletion, resetDeleteShortUrl, deleteShortUrl }: DeleteShortUrlModalConnectProps, -) => { +const DELETION_PATTERN = 'delete'; + +export const DeleteShortUrlModal = ({ + shortUrl, + toggle, + isOpen, + shortUrlDeletion, + resetDeleteShortUrl, + deleteShortUrl, + shortUrlDeleted, +}: DeleteShortUrlModalConnectProps) => { const [inputValue, setInputValue] = useState(''); useEffect(() => resetDeleteShortUrl, []); - const { error, errorData } = shortUrlDeletion; + const { loading, error, deleted, errorData } = shortUrlDeletion; const close = pipe(resetDeleteShortUrl, toggle); - const handleDeleteUrl = handleEventPreventingDefault(() => { - const { shortCode, domain } = shortUrl; - - deleteShortUrl(shortCode, domain) - .then(toggle) - .catch(identity); - }); + const handleDeleteUrl = handleEventPreventingDefault(() => deleteShortUrl(shortUrl).then(toggle)); return ( - <Modal isOpen={isOpen} toggle={close} centered> + <Modal isOpen={isOpen} toggle={close} centered onClosed={() => deleted && shortUrlDeleted(shortUrl)}> <form onSubmit={handleDeleteUrl}> <ModalHeader toggle={close}> <span className="text-danger">Delete short URL</span> @@ -40,12 +43,12 @@ export const DeleteShortUrlModal = ( <ModalBody> <p><b className="text-danger">Caution!</b> You are about to delete a short URL.</p> <p>This action cannot be undone. Once you have deleted it, all the visits stats will be lost.</p> - <p>Write <b>{shortUrl.shortCode}</b> to confirm deletion.</p> + <p>Write <b>{DELETION_PATTERN}</b> to confirm deletion.</p> <input type="text" className="form-control" - placeholder={`Insert the short code (${shortUrl.shortCode})`} + placeholder={`Insert ${DELETION_PATTERN}`} value={inputValue} onChange={(e) => setInputValue(e.target.value)} /> @@ -61,9 +64,9 @@ export const DeleteShortUrlModal = ( <button type="submit" className="btn btn-danger" - disabled={inputValue !== shortUrl.shortCode || shortUrlDeletion.loading} + disabled={inputValue !== DELETION_PATTERN || loading} > - {shortUrlDeletion.loading ? 'Deleting...' : 'Delete'} + {loading ? 'Deleting...' : 'Delete'} </button> </ModalFooter> </form> diff --git a/src/short-urls/helpers/ShortUrlsRow.scss b/src/short-urls/helpers/ShortUrlsRow.scss index 92410c15..4666be1a 100644 --- a/src/short-urls/helpers/ShortUrlsRow.scss +++ b/src/short-urls/helpers/ShortUrlsRow.scss @@ -1,4 +1,5 @@ @import '../../utils/base'; +@import '../../utils/mixins/text-ellipsis'; @import '../../utils/mixins/vertical-align'; .short-urls-row__cell.short-urls-row__cell { @@ -13,6 +14,26 @@ position: relative; } +.short-urls-row__cell--indivisible { + @media (min-width: $lgMin) { + white-space: nowrap; + } +} + +.short-urls-row__short-url-wrapper { + @media (max-width: $mdMax) { + word-break: break-all; + } + + @media (min-width: $lgMin) { + @include text-ellipsis(); + + vertical-align: bottom; + display: inline-block; + max-width: 18rem; + } +} + .short-urls-row__copy-hint { @include vertical-align(translateX(10px)); diff --git a/src/short-urls/helpers/ShortUrlsRow.tsx b/src/short-urls/helpers/ShortUrlsRow.tsx index eed961af..1b7fafb1 100644 --- a/src/short-urls/helpers/ShortUrlsRow.tsx +++ b/src/short-urls/helpers/ShortUrlsRow.tsx @@ -7,7 +7,7 @@ import { Tag } from '../../tags/helpers/Tag'; import { SelectedServer } from '../../servers/data'; import { CopyToClipboardIcon } from '../../utils/CopyToClipboardIcon'; import { ShortUrl } from '../data'; -import { Time } from '../../utils/Time'; +import { Time } from '../../utils/dates/Time'; import { ShortUrlVisitsCount } from './ShortUrlVisitsCount'; import { ShortUrlsRowMenuProps } from './ShortUrlsRowMenu'; import './ShortUrlsRow.scss'; @@ -43,11 +43,8 @@ export const ShortUrlsRow = ( }; useEffect(() => { - if (isFirstRun.current) { - isFirstRun.current = false; - } else { - setActive(); - } + !isFirstRun.current && setActive(); + isFirstRun.current = false; }, [shortUrl.visitsCount]); return ( @@ -56,15 +53,20 @@ export const ShortUrlsRow = ( <Time date={shortUrl.dateCreated} /> </td> <td className="responsive-table__cell short-urls-row__cell" data-th="Short URL"> - <span className="indivisible short-urls-row__cell--relative"> - <ExternalLink href={shortUrl.shortUrl} /> + <span className="short-urls-row__cell--relative short-urls-row__cell--indivisible"> + <span className="short-urls-row__short-url-wrapper"> + <ExternalLink href={shortUrl.shortUrl} /> + </span> <CopyToClipboardIcon text={shortUrl.shortUrl} onCopy={setCopiedToClipboard} /> <span className="badge bg-warning text-black short-urls-row__copy-hint" hidden={!copiedToClipboard}> Copied short URL! </span> </span> </td> - <td className="responsive-table__cell short-urls-row__cell short-urls-row__cell--break" data-th={`${shortUrl.title ? 'Title' : 'Long URL'}`}> + <td + className="responsive-table__cell short-urls-row__cell short-urls-row__cell--break" + data-th={`${shortUrl.title ? 'Title' : 'Long URL'}`} + > <ExternalLink href={shortUrl.longUrl}>{shortUrl.title ?? shortUrl.longUrl}</ExternalLink> </td> {shortUrl.title && ( diff --git a/src/short-urls/helpers/ShortUrlsRowMenu.tsx b/src/short-urls/helpers/ShortUrlsRowMenu.tsx index 877233f3..a4563a52 100644 --- a/src/short-urls/helpers/ShortUrlsRowMenu.tsx +++ b/src/short-urls/helpers/ShortUrlsRowMenu.tsx @@ -24,8 +24,8 @@ export const ShortUrlsRowMenu = ( QrCodeModal: ShortUrlModal, ) => ({ shortUrl, selectedServer }: ShortUrlsRowMenuProps) => { const [isOpen, toggle] = useToggle(); - const [isQrModalOpen, toggleQrCode] = useToggle(); - const [isDeleteModalOpen, toggleDelete] = useToggle(); + const [isQrModalOpen,, openQrCodeModal, closeQrCodeModal] = useToggle(); + const [isDeleteModalOpen,, openDeleteModal, closeDeleteModal] = useToggle(); return ( <DropdownBtnMenu toggle={toggle} isOpen={isOpen}> @@ -37,17 +37,17 @@ export const ShortUrlsRowMenu = ( <FontAwesomeIcon icon={editIcon} fixedWidth /> Edit short URL </DropdownItem> - <DropdownItem onClick={toggleQrCode}> + <DropdownItem onClick={openQrCodeModal}> <FontAwesomeIcon icon={qrIcon} fixedWidth /> QR code </DropdownItem> - <QrCodeModal shortUrl={shortUrl} isOpen={isQrModalOpen} toggle={toggleQrCode} /> + <QrCodeModal shortUrl={shortUrl} isOpen={isQrModalOpen} toggle={closeQrCodeModal} /> <DropdownItem divider /> - <DropdownItem className="dropdown-item--danger" onClick={toggleDelete}> + <DropdownItem className="dropdown-item--danger" onClick={openDeleteModal}> <FontAwesomeIcon icon={deleteIcon} fixedWidth /> Delete short URL </DropdownItem> - <DeleteShortUrlModal shortUrl={shortUrl} isOpen={isDeleteModalOpen} toggle={toggleDelete} /> + <DeleteShortUrlModal shortUrl={shortUrl} isOpen={isDeleteModalOpen} toggle={closeDeleteModal} /> </DropdownBtnMenu> ); }; diff --git a/src/short-urls/helpers/hooks.ts b/src/short-urls/helpers/hooks.ts index 3f1c165c..29fe8516 100644 --- a/src/short-urls/helpers/hooks.ts +++ b/src/short-urls/helpers/hooks.ts @@ -6,8 +6,6 @@ import { ShortUrlsOrder, ShortUrlsOrderableFields } from '../data'; import { orderToString, stringToOrder } from '../../utils/helpers/ordering'; import { TagsFilteringMode } from '../../api/types'; -type ToFirstPage = (extra: Partial<ShortUrlsFiltering>) => void; - interface ShortUrlsQueryCommon { search?: string; startDate?: string; @@ -25,35 +23,36 @@ interface ShortUrlsFiltering extends ShortUrlsQueryCommon { tags: string[]; } +type ToFirstPage = (extra: Partial<ShortUrlsFiltering>) => void; + export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => { const navigate = useNavigate(); - const location = useLocation(); - const params = useParams<{ serverId: string }>(); + const { search } = useLocation(); + const { serverId = '' } = useParams<{ serverId: string }>(); - const query = useMemo( + const filtering = useMemo( pipe( - () => parseQuery<ShortUrlsQuery>(location.search), + () => parseQuery<ShortUrlsQuery>(search), ({ orderBy, tags, ...rest }: ShortUrlsQuery): ShortUrlsFiltering => { const parsedOrderBy = orderBy ? stringToOrder<ShortUrlsOrderableFields>(orderBy) : undefined; const parsedTags = tags?.split(',') ?? []; - return { ...rest, orderBy: parsedOrderBy, tags: parsedTags }; }, ), - [location.search], + [search], ); const toFirstPageWithExtra = (extra: Partial<ShortUrlsFiltering>) => { - const { orderBy, tags, ...mergedQuery } = { ...query, ...extra }; - const normalizedQuery: ShortUrlsQuery = { - ...mergedQuery, + const { orderBy, tags, ...mergedFiltering } = { ...filtering, ...extra }; + const query: ShortUrlsQuery = { + ...mergedFiltering, orderBy: orderBy && orderToString(orderBy), tags: tags.length > 0 ? tags.join(',') : undefined, }; - const evolvedQuery = stringifyQuery(normalizedQuery); - const queryString = isEmpty(evolvedQuery) ? '' : `?${evolvedQuery}`; + const stringifiedQuery = stringifyQuery(query); + const queryString = isEmpty(stringifiedQuery) ? '' : `?${stringifiedQuery}`; - navigate(`/server/${params.serverId ?? ''}/list-short-urls/1${queryString}`); + navigate(`/server/${serverId}/list-short-urls/1${queryString}`); }; - return [query, toFirstPageWithExtra]; + return [filtering, toFirstPageWithExtra]; }; diff --git a/src/short-urls/reducers/shortUrlCreation.ts b/src/short-urls/reducers/shortUrlCreation.ts index 2be9ff7e..1a48b63e 100644 --- a/src/short-urls/reducers/shortUrlCreation.ts +++ b/src/short-urls/reducers/shortUrlCreation.ts @@ -1,57 +1,72 @@ -import { Action, Dispatch } from 'redux'; -import { GetState } from '../../container/types'; +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { ShortUrl, ShortUrlData } from '../data'; -import { buildReducer, buildActionCreator } from '../../utils/helpers/redux'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { ProblemDetailsError } from '../../api/types'; import { parseApiError } from '../../api/utils'; -import { ApiErrorAction } from '../../api/types/actions'; +import { ProblemDetailsError } from '../../api/types/errors'; -export const CREATE_SHORT_URL_START = 'shlink/createShortUrl/CREATE_SHORT_URL_START'; -export const CREATE_SHORT_URL_ERROR = 'shlink/createShortUrl/CREATE_SHORT_URL_ERROR'; -export const CREATE_SHORT_URL = 'shlink/createShortUrl/CREATE_SHORT_URL'; -export const RESET_CREATE_SHORT_URL = 'shlink/createShortUrl/RESET_CREATE_SHORT_URL'; +const REDUCER_PREFIX = 'shlink/shortUrlCreation'; -export interface ShortUrlCreation { - result: ShortUrl | null; - saving: boolean; - error: boolean; +export type ShortUrlCreation = { + saving: false; + saved: false; + error: false; +} | { + saving: true; + saved: false; + error: false; +} | { + saving: false; + saved: false; + error: true; errorData?: ProblemDetailsError; -} - -export interface CreateShortUrlAction extends Action<string> { +} | { result: ShortUrl; -} + saving: false; + saved: true; + error: false; +}; + +export type CreateShortUrlAction = PayloadAction<ShortUrl>; const initialState: ShortUrlCreation = { - result: null, saving: false, + saved: false, error: false, }; -export default buildReducer<ShortUrlCreation, CreateShortUrlAction & ApiErrorAction>({ - [CREATE_SHORT_URL_START]: (state) => ({ ...state, saving: true, error: false }), - [CREATE_SHORT_URL_ERROR]: (state, { errorData }) => ({ ...state, saving: false, error: true, errorData }), - [CREATE_SHORT_URL]: (_, { result }) => ({ result, saving: false, error: false }), - [RESET_CREATE_SHORT_URL]: () => initialState, -}, initialState); +export const createShortUrl = (buildShlinkApiClient: ShlinkApiClientBuilder) => createAsyncThunk( + `${REDUCER_PREFIX}/createShortUrl`, + (data: ShortUrlData, { getState }): Promise<ShortUrl> => { + const { createShortUrl: shlinkCreateShortUrl } = buildShlinkApiClient(getState); + return shlinkCreateShortUrl(data); + }, +); -export const createShortUrl = (buildShlinkApiClient: ShlinkApiClientBuilder) => (data: ShortUrlData) => async ( - dispatch: Dispatch, - getState: GetState, -) => { - dispatch({ type: CREATE_SHORT_URL_START }); - const { createShortUrl: shlinkCreateShortUrl } = buildShlinkApiClient(getState); +export const shortUrlCreationReducerCreator = (createShortUrlThunk: ReturnType<typeof createShortUrl>) => { + const { reducer, actions } = createSlice({ + name: REDUCER_PREFIX, + initialState: initialState as ShortUrlCreation, // Without this casting it infers type ShortUrlCreationWaiting + reducers: { + resetCreateShortUrl: () => initialState, + }, + extraReducers: (builder) => { + builder.addCase(createShortUrlThunk.pending, () => ({ saving: true, saved: false, error: false })); + builder.addCase( + createShortUrlThunk.rejected, + (_, { error }) => ({ saving: false, saved: false, error: true, errorData: parseApiError(error) }), + ); + builder.addCase( + createShortUrlThunk.fulfilled, + (_, { payload: result }) => ({ result, saving: false, saved: true, error: false }), + ); + }, + }); - try { - const result = await shlinkCreateShortUrl(data); + const { resetCreateShortUrl } = actions; - dispatch<CreateShortUrlAction>({ type: CREATE_SHORT_URL, result }); - } catch (e: any) { - dispatch<ApiErrorAction>({ type: CREATE_SHORT_URL_ERROR, errorData: parseApiError(e) }); - - throw e; - } + return { + reducer, + resetCreateShortUrl, + }; }; - -export const resetCreateShortUrl = buildActionCreator(RESET_CREATE_SHORT_URL); diff --git a/src/short-urls/reducers/shortUrlDeletion.ts b/src/short-urls/reducers/shortUrlDeletion.ts index 24ec999d..294e1986 100644 --- a/src/short-urls/reducers/shortUrlDeletion.ts +++ b/src/short-urls/reducers/shortUrlDeletion.ts @@ -1,56 +1,60 @@ -import { Action, Dispatch } from 'redux'; -import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; -import { ProblemDetailsError } from '../../api/types'; -import { GetState } from '../../container/types'; +import { createAction, createSlice } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; import { parseApiError } from '../../api/utils'; -import { ApiErrorAction } from '../../api/types/actions'; +import { ProblemDetailsError } from '../../api/types/errors'; +import { ShortUrl, ShortUrlIdentifier } from '../data'; -export const DELETE_SHORT_URL_START = 'shlink/deleteShortUrl/DELETE_SHORT_URL_START'; -export const DELETE_SHORT_URL_ERROR = 'shlink/deleteShortUrl/DELETE_SHORT_URL_ERROR'; -export const SHORT_URL_DELETED = 'shlink/deleteShortUrl/SHORT_URL_DELETED'; -export const RESET_DELETE_SHORT_URL = 'shlink/deleteShortUrl/RESET_DELETE_SHORT_URL'; +const REDUCER_PREFIX = 'shlink/shortUrlDeletion'; export interface ShortUrlDeletion { shortCode: string; loading: boolean; + deleted: boolean; error: boolean; errorData?: ProblemDetailsError; } -export interface DeleteShortUrlAction extends Action<string> { - shortCode: string; - domain?: string | null; -} - const initialState: ShortUrlDeletion = { shortCode: '', loading: false, + deleted: false, error: false, }; -export default buildReducer<ShortUrlDeletion, DeleteShortUrlAction & ApiErrorAction>({ - [DELETE_SHORT_URL_START]: (state) => ({ ...state, loading: true, error: false }), - [DELETE_SHORT_URL_ERROR]: (state, { errorData }) => ({ ...state, errorData, loading: false, error: true }), - [SHORT_URL_DELETED]: (state, { shortCode }) => ({ ...state, shortCode, loading: false, error: false }), - [RESET_DELETE_SHORT_URL]: () => initialState, -}, initialState); - -export const deleteShortUrl = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - shortCode: string, - domain?: string | null, -) => async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: DELETE_SHORT_URL_START }); - const { deleteShortUrl: shlinkDeleteShortUrl } = buildShlinkApiClient(getState); - - try { +export const deleteShortUrl = (buildShlinkApiClient: ShlinkApiClientBuilder) => createAsyncThunk( + `${REDUCER_PREFIX}/deleteShortUrl`, + async ({ shortCode, domain }: ShortUrlIdentifier, { getState }): Promise<ShortUrlIdentifier> => { + const { deleteShortUrl: shlinkDeleteShortUrl } = buildShlinkApiClient(getState); await shlinkDeleteShortUrl(shortCode, domain); - dispatch<DeleteShortUrlAction>({ type: SHORT_URL_DELETED, shortCode, domain }); - } catch (e: any) { - dispatch<ApiErrorAction>({ type: DELETE_SHORT_URL_ERROR, errorData: parseApiError(e) }); + return { shortCode, domain }; + }, +); - throw e; - } +export const shortUrlDeleted = createAction<ShortUrl>(`${REDUCER_PREFIX}/shortUrlDeleted`); + +export const shortUrlDeletionReducerCreator = (deleteShortUrlThunk: ReturnType<typeof deleteShortUrl>) => { + const { actions, reducer } = createSlice({ + name: REDUCER_PREFIX, + initialState, + reducers: { + resetDeleteShortUrl: () => initialState, + }, + extraReducers: (builder) => { + builder.addCase( + deleteShortUrlThunk.pending, + (state) => ({ ...state, loading: true, error: false, deleted: false }), + ); + builder.addCase(deleteShortUrlThunk.rejected, (state, { error }) => ( + { ...state, errorData: parseApiError(error), loading: false, error: true, deleted: false } + )); + builder.addCase(deleteShortUrlThunk.fulfilled, (state, { payload }) => ( + { ...state, shortCode: payload.shortCode, loading: false, error: false, deleted: true } + )); + }, + }); + + const { resetDeleteShortUrl } = actions; + + return { reducer, resetDeleteShortUrl }; }; - -export const resetDeleteShortUrl = buildActionCreator(RESET_DELETE_SHORT_URL); diff --git a/src/short-urls/reducers/shortUrlDetail.ts b/src/short-urls/reducers/shortUrlDetail.ts index dd1bf005..4ad467f3 100644 --- a/src/short-urls/reducers/shortUrlDetail.ts +++ b/src/short-urls/reducers/shortUrlDetail.ts @@ -1,17 +1,12 @@ -import { Action, Dispatch } from 'redux'; -import { ShortUrl } from '../data'; -import { buildReducer } from '../../utils/helpers/redux'; +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { ShortUrl, ShortUrlIdentifier } from '../data'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { OptionalString } from '../../utils/utils'; -import { GetState } from '../../container/types'; import { shortUrlMatches } from '../helpers'; -import { ProblemDetailsError } from '../../api/types'; import { parseApiError } from '../../api/utils'; -import { ApiErrorAction } from '../../api/types/actions'; +import { ProblemDetailsError } from '../../api/types/errors'; -export const GET_SHORT_URL_DETAIL_START = 'shlink/shortUrlDetail/GET_SHORT_URL_DETAIL_START'; -export const GET_SHORT_URL_DETAIL_ERROR = 'shlink/shortUrlDetail/GET_SHORT_URL_DETAIL_ERROR'; -export const GET_SHORT_URL_DETAIL = 'shlink/shortUrlDetail/GET_SHORT_URL_DETAIL'; +const REDUCER_PREFIX = 'shlink/shortUrlDetail'; export interface ShortUrlDetail { shortUrl?: ShortUrl; @@ -20,35 +15,36 @@ export interface ShortUrlDetail { errorData?: ProblemDetailsError; } -export interface ShortUrlDetailAction extends Action<string> { - shortUrl: ShortUrl; -} +export type ShortUrlDetailAction = PayloadAction<ShortUrl>; const initialState: ShortUrlDetail = { loading: false, error: false, }; -export default buildReducer<ShortUrlDetail, ShortUrlDetailAction & ApiErrorAction>({ - [GET_SHORT_URL_DETAIL_START]: () => ({ loading: true, error: false }), - [GET_SHORT_URL_DETAIL_ERROR]: (_, { errorData }) => ({ loading: false, error: true, errorData }), - [GET_SHORT_URL_DETAIL]: (_, { shortUrl }) => ({ shortUrl, ...initialState }), -}, initialState); +export const shortUrlDetailReducerCreator = (buildShlinkApiClient: ShlinkApiClientBuilder) => { + const getShortUrlDetail = createAsyncThunk( + `${REDUCER_PREFIX}/getShortUrlDetail`, + async ({ shortCode, domain }: ShortUrlIdentifier, { getState }): Promise<ShortUrl> => { + const { shortUrlsList } = getState(); + const alreadyLoaded = shortUrlsList?.shortUrls?.data.find((url) => shortUrlMatches(url, shortCode, domain)); -export const getShortUrlDetail = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - shortCode: string, - domain: OptionalString, -) => async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: GET_SHORT_URL_DETAIL_START }); + return alreadyLoaded ?? await buildShlinkApiClient(getState).getShortUrl(shortCode, domain); + }, + ); - try { - const { shortUrlsList } = getState(); - const shortUrl = shortUrlsList?.shortUrls?.data.find( - (url) => shortUrlMatches(url, shortCode, domain), - ) ?? await buildShlinkApiClient(getState).getShortUrl(shortCode, domain); + const { reducer } = createSlice({ + name: REDUCER_PREFIX, + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(getShortUrlDetail.pending, () => ({ loading: true, error: false })); + builder.addCase(getShortUrlDetail.rejected, (_, { error }) => ( + { loading: false, error: true, errorData: parseApiError(error) } + )); + builder.addCase(getShortUrlDetail.fulfilled, (_, { payload: shortUrl }) => ({ ...initialState, shortUrl })); + }, + }); - dispatch<ShortUrlDetailAction>({ shortUrl, type: GET_SHORT_URL_DETAIL }); - } catch (e: any) { - dispatch<ApiErrorAction>({ type: GET_SHORT_URL_DETAIL_ERROR, errorData: parseApiError(e) }); - } + return { reducer, getShortUrlDetail }; }; diff --git a/src/short-urls/reducers/shortUrlEdition.ts b/src/short-urls/reducers/shortUrlEdition.ts index 6c530695..79ea145d 100644 --- a/src/short-urls/reducers/shortUrlEdition.ts +++ b/src/short-urls/reducers/shortUrlEdition.ts @@ -1,55 +1,53 @@ -import { Action, Dispatch } from 'redux'; -import { buildReducer } from '../../utils/helpers/redux'; -import { GetState } from '../../container/types'; -import { OptionalString } from '../../utils/utils'; -import { EditShortUrlData, ShortUrl } from '../data'; +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '../../utils/helpers/redux'; +import { EditShortUrlData, ShortUrl, ShortUrlIdentifier } from '../data'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { ProblemDetailsError } from '../../api/types'; import { parseApiError } from '../../api/utils'; -import { ApiErrorAction } from '../../api/types/actions'; +import { ProblemDetailsError } from '../../api/types/errors'; -export const EDIT_SHORT_URL_START = 'shlink/shortUrlEdition/EDIT_SHORT_URL_START'; -export const EDIT_SHORT_URL_ERROR = 'shlink/shortUrlEdition/EDIT_SHORT_URL_ERROR'; -export const SHORT_URL_EDITED = 'shlink/shortUrlEdition/SHORT_URL_EDITED'; +const REDUCER_PREFIX = 'shlink/shortUrlEdition'; export interface ShortUrlEdition { shortUrl?: ShortUrl; saving: boolean; + saved: boolean; error: boolean; errorData?: ProblemDetailsError; } -export interface ShortUrlEditedAction extends Action<string> { - shortUrl: ShortUrl; +export interface EditShortUrl extends ShortUrlIdentifier { + data: EditShortUrlData; } +export type ShortUrlEditedAction = PayloadAction<ShortUrl>; + const initialState: ShortUrlEdition = { saving: false, + saved: false, error: false, }; -export default buildReducer<ShortUrlEdition, ShortUrlEditedAction & ApiErrorAction>({ - [EDIT_SHORT_URL_START]: (state) => ({ ...state, saving: true, error: false }), - [EDIT_SHORT_URL_ERROR]: (state, { errorData }) => ({ ...state, saving: false, error: true, errorData }), - [SHORT_URL_EDITED]: (_, { shortUrl }) => ({ shortUrl, saving: false, error: false }), -}, initialState); +export const editShortUrl = (buildShlinkApiClient: ShlinkApiClientBuilder) => createAsyncThunk( + `${REDUCER_PREFIX}/editShortUrl`, + ({ shortCode, domain, data }: EditShortUrl, { getState }): Promise<ShortUrl> => { + const { updateShortUrl } = buildShlinkApiClient(getState); + return updateShortUrl(shortCode, domain, data as any); // FIXME parse dates + }, +); -export const editShortUrl = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - shortCode: string, - domain: OptionalString, - data: EditShortUrlData, -) => async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: EDIT_SHORT_URL_START }); - - const { updateShortUrl } = buildShlinkApiClient(getState); - - try { - const shortUrl = await updateShortUrl(shortCode, domain, data as any); // FIXME parse dates; - - dispatch<ShortUrlEditedAction>({ shortUrl, type: SHORT_URL_EDITED }); - } catch (e: any) { - dispatch<ApiErrorAction>({ type: EDIT_SHORT_URL_ERROR, errorData: parseApiError(e) }); - - throw e; - } -}; +export const shortUrlEditionReducerCreator = (editShortUrlThunk: ReturnType<typeof editShortUrl>) => createSlice({ + name: REDUCER_PREFIX, + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(editShortUrlThunk.pending, (state) => ({ ...state, saving: true, error: false, saved: false })); + builder.addCase( + editShortUrlThunk.rejected, + (state, { error }) => ({ ...state, saving: false, error: true, saved: false, errorData: parseApiError(error) }), + ); + builder.addCase( + editShortUrlThunk.fulfilled, + (_, { payload: shortUrl }) => ({ shortUrl, saving: false, error: false, saved: true }), + ); + }, +}); diff --git a/src/short-urls/reducers/shortUrlsList.ts b/src/short-urls/reducers/shortUrlsList.ts index be70885a..66ba341d 100644 --- a/src/short-urls/reducers/shortUrlsList.ts +++ b/src/short-urls/reducers/shortUrlsList.ts @@ -1,19 +1,16 @@ +import { createSlice } from '@reduxjs/toolkit'; import { assoc, assocPath, last, pipe, reject } from 'ramda'; -import { Action, Dispatch } from 'redux'; import { shortUrlMatches } from '../helpers'; -import { CREATE_VISITS, CreateVisitsAction } from '../../visits/reducers/visitCreation'; -import { buildReducer } from '../../utils/helpers/redux'; -import { GetState } from '../../container/types'; +import { createNewVisits } from '../../visits/reducers/visitCreation'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; import { ShlinkShortUrlsListParams, ShlinkShortUrlsResponse } from '../../api/types'; -import { DeleteShortUrlAction, SHORT_URL_DELETED } from './shortUrlDeletion'; -import { CREATE_SHORT_URL, CreateShortUrlAction } from './shortUrlCreation'; -import { SHORT_URL_EDITED, ShortUrlEditedAction } from './shortUrlEdition'; - -export const LIST_SHORT_URLS_START = 'shlink/shortUrlsList/LIST_SHORT_URLS_START'; -export const LIST_SHORT_URLS_ERROR = 'shlink/shortUrlsList/LIST_SHORT_URLS_ERROR'; -export const LIST_SHORT_URLS = 'shlink/shortUrlsList/LIST_SHORT_URLS'; +import { shortUrlDeleted } from './shortUrlDeletion'; +import { createShortUrl } from './shortUrlCreation'; +import { editShortUrl } from './shortUrlEdition'; +import { ShortUrl } from '../data'; +const REDUCER_PREFIX = 'shlink/shortUrlsList'; export const ITEMS_IN_OVERVIEW_PAGE = 5; export interface ShortUrlsList { @@ -22,94 +19,103 @@ export interface ShortUrlsList { error: boolean; } -export interface ListShortUrlsAction extends Action<string> { - shortUrls: ShlinkShortUrlsResponse; -} - -export type ListShortUrlsCombinedAction = ( - ListShortUrlsAction - & CreateVisitsAction - & CreateShortUrlAction - & DeleteShortUrlAction - & ShortUrlEditedAction -); - const initialState: ShortUrlsList = { loading: true, error: false, }; -export default buildReducer<ShortUrlsList, ListShortUrlsCombinedAction>({ - [LIST_SHORT_URLS_START]: (state) => ({ ...state, loading: true, error: false }), - [LIST_SHORT_URLS_ERROR]: () => ({ loading: false, error: true }), - [LIST_SHORT_URLS]: (_, { shortUrls }) => ({ loading: false, error: false, shortUrls }), - [SHORT_URL_DELETED]: pipe( - (state: ShortUrlsList, { shortCode, domain }: DeleteShortUrlAction) => (!state.shortUrls ? state : assocPath( - ['shortUrls', 'data'], - reject((shortUrl) => shortUrlMatches(shortUrl, shortCode, domain), state.shortUrls.data), - state, - )), - (state) => (!state.shortUrls ? state : assocPath( - ['shortUrls', 'pagination', 'totalItems'], - state.shortUrls.pagination.totalItems - 1, - state, - )), - ), - [CREATE_VISITS]: (state, { createdVisits }) => assocPath( - ['shortUrls', 'data'], - state.shortUrls?.data?.map( - (currentShortUrl) => { - // Find the last of the new visit for this short URL, and pick the amount of visits from it - const lastVisit = last( - createdVisits.filter( - ({ shortUrl }) => shortUrl && shortUrlMatches(currentShortUrl, shortUrl.shortCode, shortUrl.domain), - ), - ); +export const listShortUrls = (buildShlinkApiClient: ShlinkApiClientBuilder) => createAsyncThunk( + `${REDUCER_PREFIX}/listShortUrls`, + (params: ShlinkShortUrlsListParams | void, { getState }): Promise<ShlinkShortUrlsResponse> => { + const { listShortUrls: shlinkListShortUrls } = buildShlinkApiClient(getState); + return shlinkListShortUrls(params ?? {}); + }, +); - return lastVisit?.shortUrl - ? assoc('visitsCount', lastVisit.shortUrl.visitsCount, currentShortUrl) - : currentShortUrl; - }, - ), - state, - ), - [CREATE_SHORT_URL]: pipe( - // The only place where the list and the creation form coexist is the overview page. - // There we can assume we are displaying page 1, and therefore, we can safely prepend the new short URL. - // We can also remove the items above the amount that is displayed there. - (state: ShortUrlsList, { result }: CreateShortUrlAction) => (!state.shortUrls ? state : assocPath( - ['shortUrls', 'data'], - [result, ...state.shortUrls.data.slice(0, ITEMS_IN_OVERVIEW_PAGE - 1)], - state, - )), - (state: ShortUrlsList) => (!state.shortUrls ? state : assocPath( - ['shortUrls', 'pagination', 'totalItems'], - state.shortUrls.pagination.totalItems + 1, - state, - )), - ), - [SHORT_URL_EDITED]: (state, { shortUrl: editedShortUrl }) => (!state.shortUrls ? state : assocPath( - ['shortUrls', 'data'], - state.shortUrls.data.map((shortUrl) => { - const { shortCode, domain } = editedShortUrl; +export const shortUrlsListReducerCreator = ( + listShortUrlsThunk: ReturnType<typeof listShortUrls>, + editShortUrlThunk: ReturnType<typeof editShortUrl>, + createShortUrlThunk: ReturnType<typeof createShortUrl>, +) => createSlice({ + name: REDUCER_PREFIX, + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(listShortUrlsThunk.pending, (state) => ({ ...state, loading: true, error: false })); + builder.addCase(listShortUrlsThunk.rejected, () => ({ loading: false, error: true })); + builder.addCase( + listShortUrlsThunk.fulfilled, + (_, { payload: shortUrls }) => ({ loading: false, error: false, shortUrls }), + ); - return shortUrlMatches(shortUrl, shortCode, domain) ? editedShortUrl : shortUrl; - }), - state, - )), -}, initialState); + builder.addCase( + createShortUrlThunk.fulfilled, + pipe( + // The only place where the list and the creation form coexist is the overview page. + // There we can assume we are displaying page 1, and therefore, we can safely prepend the new short URL. + // We can also remove the items above the amount that is displayed there. + (state, { payload }) => (!state.shortUrls ? state : assocPath( + ['shortUrls', 'data'], + [payload, ...state.shortUrls.data.slice(0, ITEMS_IN_OVERVIEW_PAGE - 1)], + state, + )), + (state: ShortUrlsList) => (!state.shortUrls ? state : assocPath( + ['shortUrls', 'pagination', 'totalItems'], + state.shortUrls.pagination.totalItems + 1, + state, + )), + ), + ); -export const listShortUrls = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - params: ShlinkShortUrlsListParams = {}, -) => async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: LIST_SHORT_URLS_START }); - const { listShortUrls: shlinkListShortUrls } = buildShlinkApiClient(getState); + builder.addCase( + editShortUrlThunk.fulfilled, + (state, { payload: editedShortUrl }) => (!state.shortUrls ? state : assocPath( + ['shortUrls', 'data'], + state.shortUrls.data.map((shortUrl) => { + const { shortCode, domain } = editedShortUrl; + return shortUrlMatches(shortUrl, shortCode, domain) ? editedShortUrl : shortUrl; + }), + state, + )), + ); - try { - const shortUrls = await shlinkListShortUrls(params); + builder.addCase( + shortUrlDeleted, + pipe( + (state, { payload }) => (!state.shortUrls ? state : assocPath( + ['shortUrls', 'data'], + reject<ShortUrl, ShortUrl[]>((shortUrl) => + shortUrlMatches(shortUrl, payload.shortCode, payload.domain), state.shortUrls.data), + state, + )), + (state) => (!state.shortUrls ? state : assocPath( + ['shortUrls', 'pagination', 'totalItems'], + state.shortUrls.pagination.totalItems - 1, + state, + )), + ), + ); - dispatch<ListShortUrlsAction>({ type: LIST_SHORT_URLS, shortUrls }); - } catch (e) { - dispatch({ type: LIST_SHORT_URLS_ERROR }); - } -}; + builder.addCase( + createNewVisits, + (state, { payload }) => assocPath( + ['shortUrls', 'data'], + state.shortUrls?.data?.map( + (currentShortUrl) => { + // Find the last of the new visit for this short URL, and pick the amount of visits from it + const lastVisit = last( + payload.createdVisits.filter( + ({ shortUrl }) => shortUrl && shortUrlMatches(currentShortUrl, shortUrl.shortCode, shortUrl.domain), + ), + ); + + return lastVisit?.shortUrl + ? assoc('visitsCount', lastVisit.shortUrl.visitsCount, currentShortUrl) + : currentShortUrl; + }, + ), + state, + ), + ); + }, +}); diff --git a/src/short-urls/services/provideServices.ts b/src/short-urls/services/provideServices.ts index a19ca9b6..eeb10ce9 100644 --- a/src/short-urls/services/provideServices.ts +++ b/src/short-urls/services/provideServices.ts @@ -1,4 +1,5 @@ import Bottle from 'bottlejs'; +import { prop } from 'ramda'; import { ShortUrlsFilteringBar } from '../ShortUrlsFilteringBar'; import { ShortUrlsList } from '../ShortUrlsList'; import { ShortUrlsRow } from '../helpers/ShortUrlsRow'; @@ -6,16 +7,16 @@ import { ShortUrlsRowMenu } from '../helpers/ShortUrlsRowMenu'; import { CreateShortUrl } from '../CreateShortUrl'; import { DeleteShortUrlModal } from '../helpers/DeleteShortUrlModal'; import { CreateShortUrlResult } from '../helpers/CreateShortUrlResult'; -import { listShortUrls } from '../reducers/shortUrlsList'; -import { createShortUrl, resetCreateShortUrl } from '../reducers/shortUrlCreation'; -import { deleteShortUrl, resetDeleteShortUrl } from '../reducers/shortUrlDeletion'; -import { editShortUrl } from '../reducers/shortUrlEdition'; +import { listShortUrls, shortUrlsListReducerCreator } from '../reducers/shortUrlsList'; +import { shortUrlCreationReducerCreator, createShortUrl } from '../reducers/shortUrlCreation'; +import { shortUrlDeletionReducerCreator, deleteShortUrl, shortUrlDeleted } from '../reducers/shortUrlDeletion'; +import { editShortUrl, shortUrlEditionReducerCreator } from '../reducers/shortUrlEdition'; +import { shortUrlDetailReducerCreator } from '../reducers/shortUrlDetail'; import { ConnectDecorator } from '../../container/types'; import { ShortUrlsTable } from '../ShortUrlsTable'; -import { QrCodeModal } from '../helpers/QrCodeModal'; import { ShortUrlForm } from '../ShortUrlForm'; import { EditShortUrl } from '../EditShortUrl'; -import { getShortUrlDetail } from '../reducers/shortUrlDetail'; +import { QrCodeModal } from '../helpers/QrCodeModal'; import { ExportShortUrlsBtn } from '../helpers/ExportShortUrlsBtn'; const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { @@ -35,7 +36,7 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { bottle.serviceFactory('CreateShortUrl', CreateShortUrl, 'ShortUrlForm', 'CreateShortUrlResult'); bottle.decorator( 'CreateShortUrl', - connect(['shortUrlCreationResult', 'selectedServer', 'settings'], ['createShortUrl', 'resetCreateShortUrl']), + connect(['shortUrlCreation', 'selectedServer', 'settings'], ['createShortUrl', 'resetCreateShortUrl']), ); bottle.serviceFactory('EditShortUrl', EditShortUrl, 'ShortUrlForm'); @@ -45,7 +46,10 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { )); bottle.serviceFactory('DeleteShortUrlModal', () => DeleteShortUrlModal); - bottle.decorator('DeleteShortUrlModal', connect(['shortUrlDeletion'], ['deleteShortUrl', 'resetDeleteShortUrl'])); + bottle.decorator('DeleteShortUrlModal', connect( + ['shortUrlDeletion'], + ['deleteShortUrl', 'shortUrlDeleted', 'resetDeleteShortUrl'], + )); bottle.serviceFactory('QrCodeModal', QrCodeModal, 'ImageDownloader'); bottle.decorator('QrCodeModal', connect(['selectedServer'])); @@ -55,16 +59,39 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { bottle.serviceFactory('ExportShortUrlsBtn', ExportShortUrlsBtn, 'buildShlinkApiClient', 'ReportExporter'); bottle.decorator('ExportShortUrlsBtn', connect(['selectedServer'])); + // Reducers + bottle.serviceFactory( + 'shortUrlsListReducerCreator', + shortUrlsListReducerCreator, + 'listShortUrls', + 'editShortUrl', + 'createShortUrl', + ); + bottle.serviceFactory('shortUrlsListReducer', prop('reducer'), 'shortUrlsListReducerCreator'); + + bottle.serviceFactory('shortUrlCreationReducerCreator', shortUrlCreationReducerCreator, 'createShortUrl'); + bottle.serviceFactory('shortUrlCreationReducer', prop('reducer'), 'shortUrlCreationReducerCreator'); + + bottle.serviceFactory('shortUrlEditionReducerCreator', shortUrlEditionReducerCreator, 'editShortUrl'); + bottle.serviceFactory('shortUrlEditionReducer', prop('reducer'), 'shortUrlEditionReducerCreator'); + + bottle.serviceFactory('shortUrlDeletionReducerCreator', shortUrlDeletionReducerCreator, 'deleteShortUrl'); + bottle.serviceFactory('shortUrlDeletionReducer', prop('reducer'), 'shortUrlDeletionReducerCreator'); + + bottle.serviceFactory('shortUrlDetailReducerCreator', shortUrlDetailReducerCreator, 'buildShlinkApiClient'); + bottle.serviceFactory('shortUrlDetailReducer', prop('reducer'), 'shortUrlDetailReducerCreator'); + // Actions bottle.serviceFactory('listShortUrls', listShortUrls, 'buildShlinkApiClient'); bottle.serviceFactory('createShortUrl', createShortUrl, 'buildShlinkApiClient'); - bottle.serviceFactory('resetCreateShortUrl', () => resetCreateShortUrl); + bottle.serviceFactory('resetCreateShortUrl', prop('resetCreateShortUrl'), 'shortUrlCreationReducerCreator'); bottle.serviceFactory('deleteShortUrl', deleteShortUrl, 'buildShlinkApiClient'); - bottle.serviceFactory('resetDeleteShortUrl', () => resetDeleteShortUrl); + bottle.serviceFactory('resetDeleteShortUrl', prop('resetDeleteShortUrl'), 'shortUrlDeletionReducerCreator'); + bottle.serviceFactory('shortUrlDeleted', () => shortUrlDeleted); - bottle.serviceFactory('getShortUrlDetail', getShortUrlDetail, 'buildShlinkApiClient'); + bottle.serviceFactory('getShortUrlDetail', prop('getShortUrlDetail'), 'shortUrlDetailReducerCreator'); bottle.serviceFactory('editShortUrl', editShortUrl, 'buildShlinkApiClient'); }; diff --git a/src/tags/helpers/DeleteTagConfirmModal.tsx b/src/tags/helpers/DeleteTagConfirmModal.tsx index 6828af13..fd2cbfdb 100644 --- a/src/tags/helpers/DeleteTagConfirmModal.tsx +++ b/src/tags/helpers/DeleteTagConfirmModal.tsx @@ -13,15 +13,14 @@ interface DeleteTagConfirmModalProps extends TagModalProps { export const DeleteTagConfirmModal = ( { tag, toggle, isOpen, deleteTag, tagDelete, tagDeleted }: DeleteTagConfirmModalProps, ) => { - const { deleting, error, errorData } = tagDelete; + const { deleting, error, deleted, errorData } = tagDelete; const doDelete = async () => { await deleteTag(tag); - tagDeleted(tag); toggle(); }; return ( - <Modal toggle={toggle} isOpen={isOpen} centered> + <Modal toggle={toggle} isOpen={isOpen} centered onClosed={() => deleted && tagDeleted(tag)}> <ModalHeader toggle={toggle} className="text-danger">Delete tag</ModalHeader> <ModalBody> Are you sure you want to delete tag <b>{tag}</b>? diff --git a/src/tags/helpers/EditTagModal.tsx b/src/tags/helpers/EditTagModal.tsx index 4b6af3d7..06dbefe5 100644 --- a/src/tags/helpers/EditTagModal.tsx +++ b/src/tags/helpers/EditTagModal.tsx @@ -1,3 +1,4 @@ +import { pipe } from 'ramda'; import { useState } from 'react'; import { Button, Input, Modal, ModalBody, ModalFooter, ModalHeader, Popover, InputGroup } from 'reactstrap'; import { HexColorPicker } from 'react-colorful'; @@ -7,15 +8,15 @@ import { useToggle } from '../../utils/helpers/hooks'; import { handleEventPreventingDefault } from '../../utils/utils'; import { ColorGenerator } from '../../utils/services/ColorGenerator'; import { TagModalProps } from '../data'; -import { TagEdition } from '../reducers/tagEdit'; +import { EditTag, TagEdition } from '../reducers/tagEdit'; import { Result } from '../../utils/Result'; import { ShlinkApiError } from '../../api/ShlinkApiError'; import './EditTagModal.scss'; interface EditTagModalProps extends TagModalProps { tagEdit: TagEdition; - editTag: (oldName: string, newName: string, color: string) => Promise<void>; - tagEdited: (oldName: string, newName: string, color: string) => void; + editTag: (editTag: EditTag) => Promise<void>; + tagEdited: (tagEdited: EditTag) => void; } export const EditTagModal = ({ getColorForKey }: ColorGenerator) => ( @@ -24,16 +25,17 @@ export const EditTagModal = ({ getColorForKey }: ColorGenerator) => ( const [newTagName, setNewTagName] = useState(tag); const [color, setColor] = useState(getColorForKey(tag)); const [showColorPicker, toggleColorPicker, , hideColorPicker] = useToggle(); - const { editing, error, errorData } = tagEdit; + const { editing, error, edited, errorData } = tagEdit; const saveTag = handleEventPreventingDefault( - async () => editTag(tag, newTagName, color) - .then(() => tagEdited(tag, newTagName, color)) - .then(toggle) - .catch(() => {}), + async () => { + await editTag({ oldName: tag, newName: newTagName, color }); + toggle(); + }, ); + const onClosed = pipe(hideColorPicker, () => edited && tagEdited({ oldName: tag, newName: newTagName, color })); return ( - <Modal isOpen={isOpen} toggle={toggle} centered onClosed={hideColorPicker}> + <Modal isOpen={isOpen} toggle={toggle} centered onClosed={onClosed}> <form name="editTag" onSubmit={saveTag}> <ModalHeader toggle={toggle}>Edit tag</ModalHeader> <ModalBody> diff --git a/src/tags/reducers/tagDelete.ts b/src/tags/reducers/tagDelete.ts index 68002479..5bac50a8 100644 --- a/src/tags/reducers/tagDelete.ts +++ b/src/tags/reducers/tagDelete.ts @@ -1,52 +1,45 @@ -import { Action, Dispatch } from 'redux'; -import { buildReducer } from '../../utils/helpers/redux'; -import { GetState } from '../../container/types'; +import { createAction, createSlice } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { ProblemDetailsError } from '../../api/types'; import { parseApiError } from '../../api/utils'; -import { ApiErrorAction } from '../../api/types/actions'; +import { ProblemDetailsError } from '../../api/types/errors'; -export const DELETE_TAG_START = 'shlink/deleteTag/DELETE_TAG_START'; -export const DELETE_TAG_ERROR = 'shlink/deleteTag/DELETE_TAG_ERROR'; -export const DELETE_TAG = 'shlink/deleteTag/DELETE_TAG'; -export const TAG_DELETED = 'shlink/deleteTag/TAG_DELETED'; +const REDUCER_PREFIX = 'shlink/tagDelete'; export interface TagDeletion { deleting: boolean; + deleted: boolean; error: boolean; errorData?: ProblemDetailsError; } -export interface DeleteTagAction extends Action<string> { - tag: string; -} - const initialState: TagDeletion = { deleting: false, + deleted: false, error: false, }; -export default buildReducer<TagDeletion, ApiErrorAction>({ - [DELETE_TAG_START]: () => ({ deleting: true, error: false }), - [DELETE_TAG_ERROR]: (_, { errorData }) => ({ deleting: false, error: true, errorData }), - [DELETE_TAG]: () => ({ deleting: false, error: false }), -}, initialState); +export const tagDeleted = createAction<string>(`${REDUCER_PREFIX}/tagDeleted`); -export const deleteTag = (buildShlinkApiClient: ShlinkApiClientBuilder) => (tag: string) => async ( - dispatch: Dispatch, - getState: GetState, -) => { - dispatch({ type: DELETE_TAG_START }); - const { deleteTags } = buildShlinkApiClient(getState); - - try { +export const tagDeleteReducerCreator = (buildShlinkApiClient: ShlinkApiClientBuilder) => { + const deleteTag = createAsyncThunk(`${REDUCER_PREFIX}/deleteTag`, async (tag: string, { getState }): Promise<void> => { + const { deleteTags } = buildShlinkApiClient(getState); await deleteTags([tag]); - dispatch({ type: DELETE_TAG }); - } catch (e: any) { - dispatch<ApiErrorAction>({ type: DELETE_TAG_ERROR, errorData: parseApiError(e) }); + }); - throw e; - } + const { reducer } = createSlice({ + name: REDUCER_PREFIX, + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(deleteTag.pending, () => ({ deleting: true, deleted: false, error: false })); + builder.addCase( + deleteTag.rejected, + (_, { error }) => ({ deleting: false, deleted: false, error: true, errorData: parseApiError(error) }), + ); + builder.addCase(deleteTag.fulfilled, () => ({ deleting: false, deleted: true, error: false })); + }, + }); + + return { reducer, deleteTag }; }; - -export const tagDeleted = (tag: string): DeleteTagAction => ({ type: TAG_DELETED, tag }); diff --git a/src/tags/reducers/tagEdit.ts b/src/tags/reducers/tagEdit.ts index ea58ad8c..675f8898 100644 --- a/src/tags/reducers/tagEdit.ts +++ b/src/tags/reducers/tagEdit.ts @@ -1,72 +1,66 @@ import { pick } from 'ramda'; -import { Action, Dispatch } from 'redux'; -import { buildReducer } from '../../utils/helpers/redux'; -import { GetState } from '../../container/types'; +import { createAction, createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ColorGenerator } from '../../utils/services/ColorGenerator'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { ProblemDetailsError } from '../../api/types'; import { parseApiError } from '../../api/utils'; -import { ApiErrorAction } from '../../api/types/actions'; +import { ProblemDetailsError } from '../../api/types/errors'; -export const EDIT_TAG_START = 'shlink/editTag/EDIT_TAG_START'; -export const EDIT_TAG_ERROR = 'shlink/editTag/EDIT_TAG_ERROR'; -export const EDIT_TAG = 'shlink/editTag/EDIT_TAG'; - -export const TAG_EDITED = 'shlink/editTag/TAG_EDITED'; +const REDUCER_PREFIX = 'shlink/tagEdit'; export interface TagEdition { - oldName: string; - newName: string; + oldName?: string; + newName?: string; editing: boolean; + edited: boolean; error: boolean; errorData?: ProblemDetailsError; } -export interface EditTagAction extends Action<string> { +export interface EditTag { oldName: string; newName: string; color: string; } +export type EditTagAction = PayloadAction<EditTag>; + const initialState: TagEdition = { - oldName: '', - newName: '', editing: false, + edited: false, error: false, }; -export default buildReducer<TagEdition, EditTagAction & ApiErrorAction>({ - [EDIT_TAG_START]: (state) => ({ ...state, editing: true, error: false }), - [EDIT_TAG_ERROR]: (state, { errorData }) => ({ ...state, editing: false, error: true, errorData }), - [EDIT_TAG]: (_, action) => ({ - ...pick(['oldName', 'newName'], action), - editing: false, - error: false, - }), -}, initialState); +export const tagEdited = createAction<EditTag>(`${REDUCER_PREFIX}/tagEdited`); -export const editTag = (buildShlinkApiClient: ShlinkApiClientBuilder, colorGenerator: ColorGenerator) => ( - oldName: string, - newName: string, - color: string, -) => async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: EDIT_TAG_START }); - const { editTag: shlinkEditTag } = buildShlinkApiClient(getState); - - try { - await shlinkEditTag(oldName, newName); +export const editTag = ( + buildShlinkApiClient: ShlinkApiClientBuilder, + colorGenerator: ColorGenerator, +) => createAsyncThunk( + `${REDUCER_PREFIX}/editTag`, + async ({ oldName, newName, color }: EditTag, { getState }): Promise<EditTag> => { + await buildShlinkApiClient(getState).editTag(oldName, newName); colorGenerator.setColorForKey(newName, color); - dispatch({ type: EDIT_TAG, oldName, newName }); - } catch (e: any) { - dispatch<ApiErrorAction>({ type: EDIT_TAG_ERROR, errorData: parseApiError(e) }); - throw e; - } -}; + return { oldName, newName, color }; + }, +); -export const tagEdited = (oldName: string, newName: string, color: string): EditTagAction => ({ - type: TAG_EDITED, - oldName, - newName, - color, +export const tagEditReducerCreator = (editTagThunk: ReturnType<typeof editTag>) => createSlice({ + name: REDUCER_PREFIX, + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(editTagThunk.pending, () => ({ editing: true, edited: false, error: false })); + builder.addCase( + editTagThunk.rejected, + (_, { error }) => ({ editing: false, edited: false, error: true, errorData: parseApiError(error) }), + ); + builder.addCase(editTagThunk.fulfilled, (_, { payload }) => ({ + ...pick(['oldName', 'newName'], payload), + editing: false, + edited: true, + error: false, + })); + }, }); diff --git a/src/tags/reducers/tagsList.ts b/src/tags/reducers/tagsList.ts index de84c709..d348674c 100644 --- a/src/tags/reducers/tagsList.ts +++ b/src/tags/reducers/tagsList.ts @@ -1,22 +1,18 @@ +import { createAction, createSlice } from '@reduxjs/toolkit'; import { isEmpty, reject } from 'ramda'; -import { Action, Dispatch } from 'redux'; -import { CREATE_VISITS, CreateVisitsAction } from '../../visits/reducers/visitCreation'; -import { buildReducer } from '../../utils/helpers/redux'; -import { ProblemDetailsError, ShlinkTags } from '../../api/types'; -import { GetState } from '../../container/types'; +import { createNewVisits } from '../../visits/reducers/visitCreation'; +import { createAsyncThunk } from '../../utils/helpers/redux'; +import { ShlinkTags } from '../../api/types'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; import { CreateVisit, Stats } from '../../visits/types'; import { parseApiError } from '../../api/utils'; import { TagStats } from '../data'; -import { ApiErrorAction } from '../../api/types/actions'; -import { CREATE_SHORT_URL, CreateShortUrlAction } from '../../short-urls/reducers/shortUrlCreation'; -import { DeleteTagAction, TAG_DELETED } from './tagDelete'; -import { EditTagAction, TAG_EDITED } from './tagEdit'; +import { createShortUrl } from '../../short-urls/reducers/shortUrlCreation'; +import { tagDeleted } from './tagDelete'; +import { tagEdited } from './tagEdit'; +import { ProblemDetailsError } from '../../api/types/errors'; -export const LIST_TAGS_START = 'shlink/tagsList/LIST_TAGS_START'; -export const LIST_TAGS_ERROR = 'shlink/tagsList/LIST_TAGS_ERROR'; -export const LIST_TAGS = 'shlink/tagsList/LIST_TAGS'; -export const FILTER_TAGS = 'shlink/tagsList/FILTER_TAGS'; +const REDUCER_PREFIX = 'shlink/tagsList'; type TagsStatsMap = Record<string, TagStats>; @@ -29,24 +25,12 @@ export interface TagsList { errorData?: ProblemDetailsError; } -interface ListTagsAction extends Action<string> { +interface ListTags { tags: string[]; stats: TagsStatsMap; } -interface FilterTagsAction extends Action<string> { - searchTerm: string; -} - -type TagsCombinedAction = ListTagsAction -& DeleteTagAction -& CreateVisitsAction -& CreateShortUrlAction -& EditTagAction -& FilterTagsAction -& ApiErrorAction; - -const initialState = { +const initialState: TagsList = { tags: [], filteredTags: [], stats: {}, @@ -65,10 +49,13 @@ const increaseVisitsForTags = (tags: TagIncrease[], stats: TagsStatsMap) => tags const tagStats = theStats[tag]; - tagStats.visitsCount += increase; - theStats[tag] = tagStats; // eslint-disable-line no-param-reassign - - return theStats; + return { + ...theStats, + [tag]: { + ...tagStats, + visitsCount: tagStats.visitsCount + increase, + }, + }; }, { ...stats }); const calculateVisitsPerTag = (createdVisits: CreateVisit[]): TagIncrease[] => Object.entries( createdVisits.reduce<Stats>((acc, { shortUrl }) => { @@ -80,47 +67,15 @@ const calculateVisitsPerTag = (createdVisits: CreateVisit[]): TagIncrease[] => O }, {}), ); -export default buildReducer<TagsList, TagsCombinedAction>({ - [LIST_TAGS_START]: () => ({ ...initialState, loading: true }), - [LIST_TAGS_ERROR]: (_, { errorData }) => ({ ...initialState, error: true, errorData }), - [LIST_TAGS]: (_, { tags, stats }) => ({ ...initialState, stats, tags, filteredTags: tags }), - [TAG_DELETED]: (state, { tag }) => ({ - ...state, - tags: rejectTag(state.tags, tag), - filteredTags: rejectTag(state.filteredTags, tag), - }), - [TAG_EDITED]: (state, { oldName, newName }) => ({ - ...state, - tags: state.tags.map(renameTag(oldName, newName)).sort(), - filteredTags: state.filteredTags.map(renameTag(oldName, newName)).sort(), - }), - [FILTER_TAGS]: (state, { searchTerm }) => ({ - ...state, - filteredTags: state.tags.filter((tag) => tag.toLowerCase().match(searchTerm.toLowerCase())), - }), - [CREATE_VISITS]: (state, { createdVisits }) => ({ - ...state, - stats: increaseVisitsForTags(calculateVisitsPerTag(createdVisits), state.stats), - }), - [CREATE_SHORT_URL]: ({ tags: stateTags, ...rest }, { result }) => ({ - ...rest, - tags: stateTags.concat(result.tags.filter((tag) => !stateTags.includes(tag))), // More performant than [ ...new Set(...) ] - }), -}, initialState); +export const listTags = (buildShlinkApiClient: ShlinkApiClientBuilder, force = true) => createAsyncThunk( + `${REDUCER_PREFIX}/listTags`, + async (_: void, { getState }): Promise<ListTags> => { + const { tagsList } = getState(); -export const listTags = (buildShlinkApiClient: ShlinkApiClientBuilder, force = true) => () => async ( - dispatch: Dispatch, - getState: GetState, -) => { - const { tagsList } = getState(); + if (!force && !isEmpty(tagsList.tags)) { + return tagsList; + } - if (!force && (tagsList.loading || !isEmpty(tagsList.tags))) { - return; - } - - dispatch({ type: LIST_TAGS_START }); - - try { const { listTags: shlinkListTags } = buildShlinkApiClient(getState); const { tags, stats = [] }: ShlinkTags = await shlinkListTags(); const processedStats = stats.reduce<TagsStatsMap>((acc, { tag, shortUrlsCount, visitsCount }) => { @@ -129,10 +84,55 @@ export const listTags = (buildShlinkApiClient: ShlinkApiClientBuilder, force = t return acc; }, {}); - dispatch<ListTagsAction>({ tags, stats: processedStats, type: LIST_TAGS }); - } catch (e: any) { - dispatch<ApiErrorAction>({ type: LIST_TAGS_ERROR, errorData: parseApiError(e) }); - } -}; + return { tags, stats: processedStats }; + }, +); -export const filterTags = (searchTerm: string): FilterTagsAction => ({ type: FILTER_TAGS, searchTerm }); +export const filterTags = createAction<string>(`${REDUCER_PREFIX}/filterTags`); + +export const tagsListReducerCreator = ( + listTagsThunk: ReturnType<typeof listTags>, + createShortUrlThunk: ReturnType<typeof createShortUrl>, +) => createSlice({ + name: REDUCER_PREFIX, + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(filterTags, (state, { payload: searchTerm }) => ({ + ...state, + filteredTags: state.tags.filter((tag) => tag.toLowerCase().match(searchTerm.toLowerCase())), + })); + + builder.addCase(listTagsThunk.pending, (state) => ({ ...state, loading: true, error: false })); + builder.addCase(listTagsThunk.rejected, (_, { error }) => ( + { ...initialState, error: true, errorData: parseApiError(error) } + )); + builder.addCase(listTagsThunk.fulfilled, (_, { payload }) => ( + { ...initialState, stats: payload.stats, tags: payload.tags, filteredTags: payload.tags } + )); + + builder.addCase(tagDeleted, ({ tags, filteredTags, ...rest }, { payload: tag }) => ({ + ...rest, + tags: rejectTag(tags, tag), + filteredTags: rejectTag(filteredTags, tag), + })); + builder.addCase(tagEdited, ({ tags, filteredTags, stats, ...rest }, { payload }) => ({ + ...rest, + stats: { + ...stats, + [payload.newName]: stats[payload.oldName], + }, + tags: tags.map(renameTag(payload.oldName, payload.newName)).sort(), + filteredTags: filteredTags.map(renameTag(payload.oldName, payload.newName)).sort(), + })); + builder.addCase(createNewVisits, (state, { payload }) => ({ + ...state, + stats: increaseVisitsForTags(calculateVisitsPerTag(payload.createdVisits), state.stats), + })); + + builder.addCase(createShortUrlThunk.fulfilled, ({ tags: stateTags, ...rest }, { payload }) => ({ + ...rest, + tags: stateTags.concat(payload.tags.filter((tag: string) => !stateTags.includes(tag))), // More performant than [ ...new Set(...) ] + })); + }, +}); diff --git a/src/tags/services/provideServices.ts b/src/tags/services/provideServices.ts index e7d58453..2d81afb7 100644 --- a/src/tags/services/provideServices.ts +++ b/src/tags/services/provideServices.ts @@ -1,12 +1,13 @@ +import { prop } from 'ramda'; import Bottle, { IContainer } from 'bottlejs'; import { TagsSelector } from '../helpers/TagsSelector'; import { TagCard } from '../TagCard'; import { DeleteTagConfirmModal } from '../helpers/DeleteTagConfirmModal'; import { EditTagModal } from '../helpers/EditTagModal'; import { TagsList } from '../TagsList'; -import { filterTags, listTags } from '../reducers/tagsList'; -import { deleteTag, tagDeleted } from '../reducers/tagDelete'; -import { editTag, tagEdited } from '../reducers/tagEdit'; +import { filterTags, listTags, tagsListReducerCreator } from '../reducers/tagsList'; +import { tagDeleted, tagDeleteReducerCreator } from '../reducers/tagDelete'; +import { editTag, tagEdited, tagEditReducerCreator } from '../reducers/tagEdit'; import { ConnectDecorator } from '../../container/types'; import { TagsCards } from '../TagsCards'; import { TagsTable } from '../TagsTable'; @@ -36,6 +37,16 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { ['forceListTags', 'filterTags', 'createNewVisits', 'loadMercureInfo'], )); + // Reducers + bottle.serviceFactory('tagEditReducerCreator', tagEditReducerCreator, 'editTag'); + bottle.serviceFactory('tagEditReducer', prop('reducer'), 'tagEditReducerCreator'); + + bottle.serviceFactory('tagDeleteReducerCreator', tagDeleteReducerCreator, 'buildShlinkApiClient'); + bottle.serviceFactory('tagDeleteReducer', prop('reducer'), 'tagDeleteReducerCreator'); + + bottle.serviceFactory('tagsListReducerCreator', tagsListReducerCreator, 'listTags', 'createShortUrl'); + bottle.serviceFactory('tagsListReducer', prop('reducer'), 'tagsListReducerCreator'); + // Actions const listTagsActionFactory = (force: boolean) => ({ buildShlinkApiClient }: IContainer) => listTags(buildShlinkApiClient, force); @@ -43,11 +54,12 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { bottle.factory('listTags', listTagsActionFactory(false)); bottle.factory('forceListTags', listTagsActionFactory(true)); bottle.serviceFactory('filterTags', () => filterTags); - bottle.serviceFactory('tagDeleted', () => tagDeleted); - bottle.serviceFactory('tagEdited', () => tagEdited); - bottle.serviceFactory('deleteTag', deleteTag, 'buildShlinkApiClient'); + bottle.serviceFactory('deleteTag', prop('deleteTag'), 'tagDeleteReducerCreator'); + bottle.serviceFactory('tagDeleted', () => tagDeleted); + bottle.serviceFactory('editTag', editTag, 'buildShlinkApiClient', 'ColorGenerator'); + bottle.serviceFactory('tagEdited', () => tagEdited); }; export default provideServices; diff --git a/src/utils/DateInput.scss b/src/utils/dates/DateInput.scss similarity index 75% rename from src/utils/DateInput.scss rename to src/utils/dates/DateInput.scss index 8c0877b8..f68453dc 100644 --- a/src/utils/DateInput.scss +++ b/src/utils/dates/DateInput.scss @@ -1,5 +1,5 @@ -@import './mixins/vertical-align'; -@import './base'; +@import '../mixins/vertical-align'; +@import '../base'; .date-input-container { position: relative; @@ -51,8 +51,9 @@ } } +.react-datepicker__time.react-datepicker__time, .react-datepicker.react-datepicker { - background-color: var(--primary-color); + background-color: var(--primary-color) !important; color: var(--text-color); border-color: var(--border-color); } @@ -66,7 +67,7 @@ .react-datepicker-time__header.react-datepicker-time__header, .react-datepicker-year-header.react-datepicker-year-header, .react-datepicker__day-name.react-datepicker__day-name, -.react-datepicker__day:not(:hover).react-datepicker__day:not(:hover), +.react-datepicker__day.react-datepicker__day:not(:hover):not(.react-datepicker__day--selected), .react-datepicker__time-name.react-datepicker__time-name { color: inherit; } @@ -84,6 +85,31 @@ color: white !important; } +.react-datepicker__time-list-item.react-datepicker__time-list-item:hover { + color: #232323; +} + +.react-datepicker__time-container.react-datepicker__time-container { + border-color: var(--border-color); +} + +.react-datepicker__time-list.react-datepicker__time-list { + /* Forefox scrollbar */ + scrollbar-color: rgba(0, 0, 0, 0.5) var(--secondary-color); + scrollbar-width: thin; + + /* Chrome webkit scrollbar */ + &::-webkit-scrollbar { + width: 10px; + background-color: var(--secondary-color); + } + + &::-webkit-scrollbar-thumb { + background-color: rgba(0, 0, 0, 0.5); + border-radius: 0.5rem; + } +} + .react-datepicker-popper.react-datepicker-popper { z-index: 2; diff --git a/src/utils/DateInput.tsx b/src/utils/dates/DateInput.tsx similarity index 73% rename from src/utils/DateInput.tsx rename to src/utils/dates/DateInput.tsx index f2b7cc96..15a95851 100644 --- a/src/utils/DateInput.tsx +++ b/src/utils/dates/DateInput.tsx @@ -4,12 +4,13 @@ import DatePicker, { ReactDatePickerProps } from 'react-datepicker'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faCalendarAlt as calendarIcon } from '@fortawesome/free-regular-svg-icons'; import classNames from 'classnames'; +import { STANDARD_DATE_FORMAT } from '../helpers/date'; import './DateInput.scss'; export type DateInputProps = ReactDatePickerProps; export const DateInput = (props: DateInputProps) => { - const { className, isClearable, selected } = props; + const { className, isClearable, selected, dateFormat } = props; const showCalendarIcon = !isClearable || isNil(selected); const ref = useRef<{ input: HTMLInputElement }>(); @@ -17,7 +18,13 @@ export const DateInput = (props: DateInputProps) => { <div className="date-input-container"> <DatePicker {...props} - dateFormat="yyyy-MM-dd" + popperModifiers={[ + { + name: 'arrow', + options: { padding: 24 }, // This prevents the arrow to be placed on the very edge, which looks ugly + }, + ]} + dateFormat={dateFormat ?? STANDARD_DATE_FORMAT} className={classNames('date-input-container__input form-control', className)} // @ts-expect-error The DatePicker type definition is wrong. It has a ref prop ref={ref} diff --git a/src/utils/dates/DateIntervalDropdownItems.tsx b/src/utils/dates/DateIntervalDropdownItems.tsx index 57099496..bd2b8de4 100644 --- a/src/utils/dates/DateIntervalDropdownItems.tsx +++ b/src/utils/dates/DateIntervalDropdownItems.tsx @@ -1,6 +1,6 @@ import { DropdownItem } from 'reactstrap'; import { FC } from 'react'; -import { DATE_INTERVALS, DateInterval, rangeOrIntervalToString } from './types'; +import { DATE_INTERVALS, DateInterval, rangeOrIntervalToString } from '../helpers/dateIntervals'; export interface DateIntervalDropdownProps { active?: DateInterval; diff --git a/src/utils/dates/DateIntervalSelector.tsx b/src/utils/dates/DateIntervalSelector.tsx index 047fccf0..3f4bccb3 100644 --- a/src/utils/dates/DateIntervalSelector.tsx +++ b/src/utils/dates/DateIntervalSelector.tsx @@ -1,6 +1,6 @@ import { FC } from 'react'; import { DropdownBtn } from '../DropdownBtn'; -import { rangeOrIntervalToString } from './types'; +import { rangeOrIntervalToString } from '../helpers/dateIntervals'; import { DateIntervalDropdownItems, DateIntervalDropdownProps } from './DateIntervalDropdownItems'; export const DateIntervalSelector: FC<DateIntervalDropdownProps> = ({ onChange, active, allText }) => ( diff --git a/src/utils/dates/DateRangeRow.tsx b/src/utils/dates/DateRangeRow.tsx index 3712fb86..f5e33ff4 100644 --- a/src/utils/dates/DateRangeRow.tsx +++ b/src/utils/dates/DateRangeRow.tsx @@ -1,6 +1,6 @@ import { endOfDay } from 'date-fns'; -import { DateInput } from '../DateInput'; -import { DateRange } from './types'; +import { DateInput } from './DateInput'; +import { DateRange } from '../helpers/dateIntervals'; interface DateRangeRowProps extends DateRange { onStartDateChange: (date: Date | null) => void; diff --git a/src/utils/dates/DateRangeSelector.tsx b/src/utils/dates/DateRangeSelector.tsx index 1b2a89cd..652d3c11 100644 --- a/src/utils/dates/DateRangeSelector.tsx +++ b/src/utils/dates/DateRangeSelector.tsx @@ -9,7 +9,7 @@ import { intervalToDateRange, rangeIsInterval, dateRangeIsEmpty, -} from './types'; +} from '../helpers/dateIntervals'; import { DateRangeRow } from './DateRangeRow'; import { DateIntervalDropdownItems } from './DateIntervalDropdownItems'; @@ -25,7 +25,9 @@ export const DateRangeSelector = ( { onDatesChange, initialDateRange, defaultText, disabled, updatable = false }: DateRangeSelectorProps, ) => { const initialIntervalIsRange = rangeIsInterval(initialDateRange); - const [activeInterval, setActiveInterval] = useState(initialIntervalIsRange ? initialDateRange : undefined); + const [activeInterval, setActiveInterval] = useState<DateInterval | undefined>( + initialIntervalIsRange ? initialDateRange : undefined, + ); const [activeDateRange, setActiveDateRange] = useState(initialIntervalIsRange ? undefined : initialDateRange); const updateDateRange = (dateRange: DateRange) => { diff --git a/src/utils/dates/DateTimeInput.tsx b/src/utils/dates/DateTimeInput.tsx new file mode 100644 index 00000000..ddc45acb --- /dev/null +++ b/src/utils/dates/DateTimeInput.tsx @@ -0,0 +1,15 @@ +import { ReactDatePickerProps } from 'react-datepicker'; +import { FC } from 'react'; +import { DateInput } from './DateInput'; +import { STANDARD_DATE_AND_TIME_FORMAT } from '../helpers/date'; + +export type DateTimeInputProps = Omit<ReactDatePickerProps, 'showTimeSelect' | 'dateFormat' | 'timeIntervals'>; + +export const DateTimeInput: FC<DateTimeInputProps> = (props) => ( + <DateInput + {...props} + dateFormat={STANDARD_DATE_AND_TIME_FORMAT} + showTimeSelect + timeIntervals={10} + /> +); diff --git a/src/utils/Time.tsx b/src/utils/dates/Time.tsx similarity index 70% rename from src/utils/Time.tsx rename to src/utils/dates/Time.tsx index fc4c3571..a06381df 100644 --- a/src/utils/Time.tsx +++ b/src/utils/dates/Time.tsx @@ -1,5 +1,5 @@ import { parseISO, format as formatDate, getUnixTime, formatDistance } from 'date-fns'; -import { isDateObject } from './helpers/date'; +import { isDateObject, STANDARD_DATE_AND_TIME_FORMAT } from '../helpers/date'; export interface TimeProps { date: Date | string; @@ -7,7 +7,7 @@ export interface TimeProps { relative?: boolean; } -export const Time = ({ date, format = 'yyyy-MM-dd HH:mm', relative = false }: TimeProps) => { +export const Time = ({ date, format = STANDARD_DATE_AND_TIME_FORMAT, relative = false }: TimeProps) => { const dateObject = isDateObject(date) ? date : parseISO(date); return ( diff --git a/src/utils/helpers/date.ts b/src/utils/helpers/date.ts index 75c8b766..e9489193 100644 --- a/src/utils/helpers/date.ts +++ b/src/utils/helpers/date.ts @@ -1,6 +1,10 @@ import { format, formatISO, isBefore, isEqual, isWithinInterval, parse, parseISO as stdParseISO } from 'date-fns'; import { OptionalString } from '../utils'; +export const STANDARD_DATE_FORMAT = 'yyyy-MM-dd'; + +export const STANDARD_DATE_AND_TIME_FORMAT = 'yyyy-MM-dd HH:mm'; + export type DateOrString = Date | string; type NullableDate = DateOrString | null; @@ -15,7 +19,10 @@ const formatDateFromFormat = (date?: NullableDate, theFormat?: string): Optional return theFormat ? format(date, theFormat) : formatISO(date); }; -export const formatDate = (theFormat = 'yyyy-MM-dd') => (date?: NullableDate) => formatDateFromFormat(date, theFormat); +export const formatDate = (theFormat = STANDARD_DATE_FORMAT) => (date?: NullableDate) => formatDateFromFormat( + date, + theFormat, +); export const formatIsoDate = (date?: NullableDate) => formatDateFromFormat(date, undefined); @@ -25,6 +32,8 @@ export const parseDate = (date: string, theFormat: string) => parse(date, theFor export const parseISO = (date: DateOrString): Date => (isDateObject(date) ? date : stdParseISO(date)); +export const dateOrNull = (date?: string): Date | null => (date ? parseISO(date) : null); + export const isBetween = (date: DateOrString, start?: DateOrString, end?: DateOrString): boolean => { try { return isWithinInterval(parseISO(date), { start: parseISO(start ?? date), end: parseISO(end ?? date) }); diff --git a/src/utils/dates/types/index.ts b/src/utils/helpers/dateIntervals.ts similarity index 75% rename from src/utils/dates/types/index.ts rename to src/utils/helpers/dateIntervals.ts index d7d81d78..f81addb8 100644 --- a/src/utils/dates/types/index.ts +++ b/src/utils/helpers/dateIntervals.ts @@ -1,21 +1,14 @@ import { subDays, startOfDay, endOfDay } from 'date-fns'; import { cond, filter, isEmpty, T } from 'ramda'; -import { DateOrString, formatInternational, isBeforeOrEqual, parseISO } from '../../helpers/date'; +import { dateOrNull, DateOrString, formatInternational, isBeforeOrEqual, parseISO } from './date'; export interface DateRange { startDate?: Date | null; endDate?: Date | null; } -export type DateInterval = 'all' | 'today' | 'yesterday' | 'last7Days' | 'last30Days' | 'last90Days' | 'last180Days' | 'last365Days'; - -export const dateRangeIsEmpty = (dateRange?: DateRange): boolean => dateRange === undefined - || isEmpty(filter(Boolean, dateRange as any)); - -export const rangeIsInterval = (range?: DateRange | DateInterval): range is DateInterval => - typeof range === 'string'; - -const INTERVAL_TO_STRING_MAP: Record<DateInterval, string | undefined> = { +const ALL = 'all'; +const INTERVAL_TO_STRING_MAP = { today: 'Today', yesterday: 'Yesterday', last7Days: 'Last 7 days', @@ -23,10 +16,25 @@ const INTERVAL_TO_STRING_MAP: Record<DateInterval, string | undefined> = { last90Days: 'Last 90 days', last180Days: 'Last 180 days', last365Days: 'Last 365 days', - all: undefined, + [ALL]: undefined, }; -export const DATE_INTERVALS = Object.keys(INTERVAL_TO_STRING_MAP).filter((value) => value !== 'all') as DateInterval[]; +export type DateInterval = keyof typeof INTERVAL_TO_STRING_MAP; + +const INTERVALS = Object.keys(INTERVAL_TO_STRING_MAP) as DateInterval[]; + +export const dateRangeIsEmpty = (dateRange?: DateRange): boolean => dateRange === undefined + || isEmpty(filter(Boolean, dateRange as any)); + +export const rangeIsInterval = (range?: DateRange | DateInterval): range is DateInterval => + typeof range === 'string' && INTERVALS.includes(range); + +export const DATE_INTERVALS = INTERVALS.filter((value) => value !== ALL) as DateInterval[]; + +export const datesToDateRange = (startDate?: string, endDate?: string): DateRange => ({ + startDate: dateOrNull(startDate), + endDate: dateOrNull(endDate), +}); const dateRangeToString = (range?: DateRange): string | undefined => { if (!range || dateRangeIsEmpty(range)) { @@ -45,7 +53,7 @@ const dateRangeToString = (range?: DateRange): string | undefined => { }; export const rangeOrIntervalToString = (range?: DateRange | DateInterval): string | undefined => { - if (!range || range === 'all') { + if (!range || range === ALL) { return undefined; } @@ -60,7 +68,7 @@ const startOfDaysAgo = (daysAgo: number) => startOfDay(subDays(new Date(), daysA const endingToday = (startDate: Date): DateRange => ({ startDate, endDate: endOfDay(new Date()) }); export const intervalToDateRange = (dateInterval?: DateInterval): DateRange => { - if (!dateInterval || dateInterval === 'all') { + if (!dateInterval || dateInterval === ALL) { return {}; } @@ -95,6 +103,14 @@ export const dateToMatchingInterval = (date: DateOrString): DateInterval => { [() => isBeforeOrEqual(startOfDaysAgo(90), theDate), () => 'last90Days'], [() => isBeforeOrEqual(startOfDaysAgo(180), theDate), () => 'last180Days'], [() => isBeforeOrEqual(startOfDaysAgo(365), theDate), () => 'last365Days'], - [T, () => 'all'], + [T, () => ALL], ])(); }; + +export const toDateRange = (rangeOrInterval: DateRange | DateInterval): DateRange => { + if (rangeIsInterval(rangeOrInterval)) { + return intervalToDateRange(rangeOrInterval); + } + + return rangeOrInterval; +}; diff --git a/src/utils/helpers/hooks.ts b/src/utils/helpers/hooks.ts index 877f8412..2e033cd8 100644 --- a/src/utils/helpers/hooks.ts +++ b/src/utils/helpers/hooks.ts @@ -27,7 +27,7 @@ export const useTimeoutToggle = ( return [flag, callback]; }; -type ToggleResult = [ boolean, () => void, () => void, () => void ]; +type ToggleResult = [boolean, () => void, () => void, () => void]; export const useToggle = (initialValue = false): ToggleResult => { const [flag, setFlag] = useState<boolean>(initialValue); diff --git a/src/utils/helpers/ordering.ts b/src/utils/helpers/ordering.ts index d79a9898..dafe7b69 100644 --- a/src/utils/helpers/ordering.ts +++ b/src/utils/helpers/ordering.ts @@ -36,6 +36,6 @@ export const orderToString = <T>(order: Order<T>): string | undefined => ( ); export const stringToOrder = <T>(order: string): Order<T> => { - const [field, dir] = order.split('-') as [ T | undefined, OrderDir | undefined ]; + const [field, dir] = order.split('-') as [T | undefined, OrderDir | undefined]; return { field, dir }; }; diff --git a/src/utils/helpers/redux.ts b/src/utils/helpers/redux.ts index d2607707..69309bf9 100644 --- a/src/utils/helpers/redux.ts +++ b/src/utils/helpers/redux.ts @@ -1,17 +1,12 @@ -import { Action } from 'redux'; +import { createAsyncThunk as baseCreateAsyncThunk, AsyncThunkPayloadCreator } from '@reduxjs/toolkit'; +import { identity } from 'ramda'; +import { ShlinkState } from '../../container/types'; -type ActionHandler<State, AT> = (currentState: State, action: AT) => State; -type ActionHandlerMap<State, AT> = Record<string, ActionHandler<State, AT>>; - -export const buildReducer = <State, AT extends Action>(map: ActionHandlerMap<State, AT>, initialState: State) => ( - state: State | undefined, - action: AT, -): State => { - const { type } = action; - const actionHandler = map[type]; - const currentState = state ?? initialState; - - return actionHandler ? actionHandler(currentState, action) : currentState; -}; - -export const buildActionCreator = <T extends string>(type: T) => (): Action<T> => ({ type }); +export const createAsyncThunk = <Returned, ThunkArg>( + typePrefix: string, + payloadCreator: AsyncThunkPayloadCreator<Returned, ThunkArg, { state: ShlinkState, serializedErrorType: any }>, +) => baseCreateAsyncThunk( + typePrefix, + payloadCreator, + { serializeError: identity }, + ); diff --git a/src/utils/mixins/text-ellipsis.scss b/src/utils/mixins/text-ellipsis.scss new file mode 100644 index 00000000..ff44b434 --- /dev/null +++ b/src/utils/mixins/text-ellipsis.scss @@ -0,0 +1,5 @@ +@mixin text-ellipsis() { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} diff --git a/src/theme/theme.scss b/src/utils/theme/theme.scss similarity index 98% rename from src/theme/theme.scss rename to src/utils/theme/theme.scss index 7d797202..dd4c20d1 100644 --- a/src/theme/theme.scss +++ b/src/utils/theme/theme.scss @@ -1,4 +1,4 @@ -@import '../utils/base'; +@import '../base'; // Light theme colors $lightPrimaryColor: #ffffff; diff --git a/src/utils/types.ts b/src/utils/types.ts index 84bab12b..953c1981 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1 +1,3 @@ export type MediaMatcher = (query: string) => MediaQueryList; + +export type Fetch = typeof window.fetch; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 8f07a336..44654994 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -21,10 +21,6 @@ type Optional<T> = T | null | undefined; export type OptionalString = Optional<string>; -export type RecursivePartial<T> = { - [P in keyof T]?: RecursivePartial<T[P]>; -}; - export const nonEmptyValueOrNull = <T>(value: T): T | null => (isEmpty(value) ? null : value); export const capitalize = <T extends string>(value: T): string => `${value.charAt(0).toUpperCase()}${value.slice(1)}`; diff --git a/src/visits/DomainVisits.tsx b/src/visits/DomainVisits.tsx index b759f167..13232a69 100644 --- a/src/visits/DomainVisits.tsx +++ b/src/visits/DomainVisits.tsx @@ -1,7 +1,7 @@ import { useParams } from 'react-router-dom'; import { CommonVisitsProps } from './types/CommonVisitsProps'; import { ShlinkVisitsParams } from '../api/types'; -import { DomainVisits as DomainVisitsState } from './reducers/domainVisits'; +import { DomainVisits as DomainVisitsState, LoadDomainVisits } from './reducers/domainVisits'; import { ReportExporter } from '../common/services/ReportExporter'; import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub'; import { Topics } from '../mercure/helpers/Topics'; @@ -12,7 +12,7 @@ import { VisitsStats } from './VisitsStats'; import { VisitsHeader } from './VisitsHeader'; export interface DomainVisitsProps extends CommonVisitsProps { - getDomainVisits: (domain: string, query?: ShlinkVisitsParams, doIntervalFallback?: boolean) => void; + getDomainVisits: (params: LoadDomainVisits) => void; domainVisits: DomainVisitsState; cancelGetDomainVisits: () => void; } @@ -28,7 +28,7 @@ export const DomainVisits = ({ exportVisits }: ReportExporter) => boundToMercure const { domain = '' } = useParams(); const [authority, domainId = authority] = domain.split('_'); const loadVisits = (params: ShlinkVisitsParams, doIntervalFallback?: boolean) => - getDomainVisits(domainId, toApiParams(params), doIntervalFallback); + getDomainVisits({ domain: domainId, query: toApiParams(params), doIntervalFallback }); const exportCsv = (visits: NormalizedVisit[]) => exportVisits(`domain_${authority}_visits.csv`, visits); return ( diff --git a/src/visits/NonOrphanVisits.tsx b/src/visits/NonOrphanVisits.tsx index 6113cfd6..8c939558 100644 --- a/src/visits/NonOrphanVisits.tsx +++ b/src/visits/NonOrphanVisits.tsx @@ -1,16 +1,16 @@ import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub'; -import { ShlinkVisitsParams } from '../api/types'; import { Topics } from '../mercure/helpers/Topics'; import { useGoBack } from '../utils/helpers/hooks'; import { ReportExporter } from '../common/services/ReportExporter'; import { VisitsStats } from './VisitsStats'; -import { NormalizedVisit, VisitsInfo, VisitsParams } from './types'; +import { NormalizedVisit, VisitsParams } from './types'; import { CommonVisitsProps } from './types/CommonVisitsProps'; import { toApiParams } from './types/helpers'; import { VisitsHeader } from './VisitsHeader'; +import { LoadVisits, VisitsInfo } from './reducers/types'; export interface NonOrphanVisitsProps extends CommonVisitsProps { - getNonOrphanVisits: (params?: ShlinkVisitsParams, doIntervalFallback?: boolean) => void; + getNonOrphanVisits: (params: LoadVisits) => void; nonOrphanVisits: VisitsInfo; cancelGetNonOrphanVisits: () => void; } @@ -25,7 +25,7 @@ export const NonOrphanVisits = ({ exportVisits }: ReportExporter) => boundToMerc const goBack = useGoBack(); const exportCsv = (visits: NormalizedVisit[]) => exportVisits('non_orphan_visits.csv', visits); const loadVisits = (params: VisitsParams, doIntervalFallback?: boolean) => - getNonOrphanVisits(toApiParams(params), doIntervalFallback); + getNonOrphanVisits({ query: toApiParams(params), doIntervalFallback }); return ( <VisitsStats diff --git a/src/visits/OrphanVisits.tsx b/src/visits/OrphanVisits.tsx index dbd3d8ba..b35ed6d3 100644 --- a/src/visits/OrphanVisits.tsx +++ b/src/visits/OrphanVisits.tsx @@ -1,20 +1,17 @@ import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub'; -import { ShlinkVisitsParams } from '../api/types'; import { Topics } from '../mercure/helpers/Topics'; import { useGoBack } from '../utils/helpers/hooks'; import { ReportExporter } from '../common/services/ReportExporter'; import { VisitsStats } from './VisitsStats'; -import { NormalizedVisit, OrphanVisitType, VisitsInfo, VisitsParams } from './types'; +import { NormalizedVisit, VisitsParams } from './types'; import { CommonVisitsProps } from './types/CommonVisitsProps'; import { toApiParams } from './types/helpers'; import { VisitsHeader } from './VisitsHeader'; +import { VisitsInfo } from './reducers/types'; +import { LoadOrphanVisits } from './reducers/orphanVisits'; export interface OrphanVisitsProps extends CommonVisitsProps { - getOrphanVisits: ( - params?: ShlinkVisitsParams, - orphanVisitsType?: OrphanVisitType, - doIntervalFallback?: boolean, - ) => void; + getOrphanVisits: (params: LoadOrphanVisits) => void; orphanVisits: VisitsInfo; cancelGetOrphanVisits: () => void; } @@ -28,8 +25,9 @@ export const OrphanVisits = ({ exportVisits }: ReportExporter) => boundToMercure }: OrphanVisitsProps) => { const goBack = useGoBack(); const exportCsv = (visits: NormalizedVisit[]) => exportVisits('orphan_visits.csv', visits); - const loadVisits = (params: VisitsParams, doIntervalFallback?: boolean) => - getOrphanVisits(toApiParams(params), params.filter?.orphanVisitsType, doIntervalFallback); + const loadVisits = (params: VisitsParams, doIntervalFallback?: boolean) => getOrphanVisits( + { query: toApiParams(params), orphanVisitsType: params.filter?.orphanVisitsType, doIntervalFallback }, + ); return ( <VisitsStats diff --git a/src/visits/ShortUrlVisits.tsx b/src/visits/ShortUrlVisits.tsx index 99bed7d3..3e17ae46 100644 --- a/src/visits/ShortUrlVisits.tsx +++ b/src/visits/ShortUrlVisits.tsx @@ -1,24 +1,24 @@ import { useEffect } from 'react'; import { useLocation, useParams } from 'react-router-dom'; import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub'; -import { ShlinkVisitsParams } from '../api/types'; import { parseQuery } from '../utils/helpers/query'; import { Topics } from '../mercure/helpers/Topics'; import { ShortUrlDetail } from '../short-urls/reducers/shortUrlDetail'; import { useGoBack } from '../utils/helpers/hooks'; import { ReportExporter } from '../common/services/ReportExporter'; -import { ShortUrlVisits as ShortUrlVisitsState } from './reducers/shortUrlVisits'; +import { LoadShortUrlVisits, ShortUrlVisits as ShortUrlVisitsState } from './reducers/shortUrlVisits'; import { ShortUrlVisitsHeader } from './ShortUrlVisitsHeader'; import { VisitsStats } from './VisitsStats'; import { NormalizedVisit, VisitsParams } from './types'; import { CommonVisitsProps } from './types/CommonVisitsProps'; import { toApiParams } from './types/helpers'; import { urlDecodeShortCode } from '../short-urls/helpers'; +import { ShortUrlIdentifier } from '../short-urls/data'; export interface ShortUrlVisitsProps extends CommonVisitsProps { - getShortUrlVisits: (shortCode: string, query?: ShlinkVisitsParams, doIntervalFallback?: boolean) => void; + getShortUrlVisits: (params: LoadShortUrlVisits) => void; shortUrlVisits: ShortUrlVisitsState; - getShortUrlDetail: Function; + getShortUrlDetail: (shortUrl: ShortUrlIdentifier) => void; shortUrlDetail: ShortUrlDetail; cancelGetShortUrlVisits: () => void; } @@ -36,15 +36,18 @@ export const ShortUrlVisits = ({ exportVisits }: ReportExporter) => boundToMercu const { search } = useLocation(); const goBack = useGoBack(); const { domain } = parseQuery<{ domain?: string }>(search); - const loadVisits = (params: VisitsParams, doIntervalFallback?: boolean) => - getShortUrlVisits(urlDecodeShortCode(shortCode), { ...toApiParams(params), domain }, doIntervalFallback); + const loadVisits = (params: VisitsParams, doIntervalFallback?: boolean) => getShortUrlVisits({ + shortCode: urlDecodeShortCode(shortCode), + query: { ...toApiParams(params), domain }, + doIntervalFallback, + }); const exportCsv = (visits: NormalizedVisit[]) => exportVisits( `short-url_${shortUrlDetail.shortUrl?.shortUrl.replace(/https?:\/\//g, '')}_visits.csv`, visits, ); useEffect(() => { - getShortUrlDetail(urlDecodeShortCode(shortCode), domain); + getShortUrlDetail({ shortCode: urlDecodeShortCode(shortCode), domain }); }, []); return ( diff --git a/src/visits/ShortUrlVisitsHeader.tsx b/src/visits/ShortUrlVisitsHeader.tsx index 96046d9f..bac9587f 100644 --- a/src/visits/ShortUrlVisitsHeader.tsx +++ b/src/visits/ShortUrlVisitsHeader.tsx @@ -1,7 +1,7 @@ import { UncontrolledTooltip } from 'reactstrap'; import { ExternalLink } from 'react-external-link'; import { ShortUrlDetail } from '../short-urls/reducers/shortUrlDetail'; -import { Time } from '../utils/Time'; +import { Time } from '../utils/dates/Time'; import { ShortUrlVisits } from './reducers/shortUrlVisits'; import { VisitsHeader } from './VisitsHeader'; import './ShortUrlVisitsHeader.scss'; diff --git a/src/visits/TagVisits.tsx b/src/visits/TagVisits.tsx index a7ce5ba1..ff70f1bf 100644 --- a/src/visits/TagVisits.tsx +++ b/src/visits/TagVisits.tsx @@ -5,7 +5,7 @@ import { ShlinkVisitsParams } from '../api/types'; import { Topics } from '../mercure/helpers/Topics'; import { useGoBack } from '../utils/helpers/hooks'; import { ReportExporter } from '../common/services/ReportExporter'; -import { TagVisits as TagVisitsState } from './reducers/tagVisits'; +import { LoadTagVisits, TagVisits as TagVisitsState } from './reducers/tagVisits'; import { TagVisitsHeader } from './TagVisitsHeader'; import { VisitsStats } from './VisitsStats'; import { NormalizedVisit } from './types'; @@ -13,7 +13,7 @@ import { CommonVisitsProps } from './types/CommonVisitsProps'; import { toApiParams } from './types/helpers'; export interface TagVisitsProps extends CommonVisitsProps { - getTagVisits: (tag: string, query?: ShlinkVisitsParams, doIntervalFallback?: boolean) => void; + getTagVisits: (params: LoadTagVisits) => void; tagVisits: TagVisitsState; cancelGetTagVisits: () => void; } @@ -28,7 +28,7 @@ export const TagVisits = (colorGenerator: ColorGenerator, { exportVisits }: Repo const goBack = useGoBack(); const { tag = '' } = useParams(); const loadVisits = (params: ShlinkVisitsParams, doIntervalFallback?: boolean) => - getTagVisits(tag, toApiParams(params), doIntervalFallback); + getTagVisits({ tag, query: toApiParams(params), doIntervalFallback }); const exportCsv = (visits: NormalizedVisit[]) => exportVisits(`tag_${tag}_visits.csv`, visits); return ( diff --git a/src/visits/VisitsStats.tsx b/src/visits/VisitsStats.tsx index 1980ded8..a6110bc4 100644 --- a/src/visits/VisitsStats.tsx +++ b/src/visits/VisitsStats.tsx @@ -1,4 +1,4 @@ -import { isEmpty, propEq, values } from 'ramda'; +import { isEmpty, pipe, propEq, values } from 'ramda'; import { useState, useEffect, useMemo, FC, useRef, PropsWithChildren } from 'react'; import { Button, Progress, Row } from 'reactstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -8,7 +8,6 @@ import { Route, Routes, Navigate } from 'react-router-dom'; import classNames from 'classnames'; import { DateRangeSelector } from '../utils/dates/DateRangeSelector'; import { Message } from '../utils/Message'; -import { DateInterval, DateRange, intervalToDateRange } from '../utils/dates/types'; import { Result } from '../utils/Result'; import { ShlinkApiError } from '../api/ShlinkApiError'; import { Settings } from '../settings/reducers/settings'; @@ -19,13 +18,16 @@ import { NavPillItem, NavPills } from '../utils/NavPills'; import { ExportBtn } from '../utils/ExportBtn'; import { LineChartCard } from './charts/LineChartCard'; import { VisitsTable } from './VisitsTable'; -import { NormalizedOrphanVisit, NormalizedVisit, VisitsFilter, VisitsInfo, VisitsParams } from './types'; +import { NormalizedOrphanVisit, NormalizedVisit, VisitsParams } from './types'; import { OpenMapModalBtn } from './helpers/OpenMapModalBtn'; import { normalizeVisits, processStatsFromVisits } from './services/VisitsParser'; import { VisitsFilterDropdown } from './helpers/VisitsFilterDropdown'; import { HighlightableProps, highlightedVisitsToStats } from './types/helpers'; import { DoughnutChartCard } from './charts/DoughnutChartCard'; import { SortableBarChartCard } from './charts/SortableBarChartCard'; +import { VisitsInfo } from './reducers/types'; +import { useVisitsQuery } from './helpers/hooks'; +import { DateInterval, DateRange, toDateRange } from '../utils/helpers/dateIntervals'; export type VisitsStatsProps = PropsWithChildren<{ getVisits: (params: VisitsParams, doIntervalFallback?: boolean) => void; @@ -67,19 +69,26 @@ export const VisitsStats: FC<VisitsStatsProps> = ({ isOrphanVisits = false, }) => { const { visits, loading, loadingLarge, error, errorData, progress, fallbackInterval } = visitsInfo; - const [initialInterval, setInitialInterval] = useState<DateInterval>( - fallbackInterval ?? settings.visits?.defaultInterval ?? 'last30Days', + const [{ dateRange, visitsFilter }, updateFiltering] = useVisitsQuery(); + const setDates = pipe( + ({ startDate: theStartDate, endDate: theEndDate }: DateRange) => ({ + dateRange: { + startDate: theStartDate ?? undefined, + endDate: theEndDate ?? undefined, + }, + }), + updateFiltering, + ); + const initialInterval = useRef<DateRange | DateInterval>( + dateRange ?? fallbackInterval ?? settings.visits?.defaultInterval ?? 'last30Days', ); - const [dateRange, setDateRange] = useState<DateRange>(intervalToDateRange(initialInterval)); const [highlightedVisits, setHighlightedVisits] = useState<NormalizedVisit[]>([]); const [highlightedLabel, setHighlightedLabel] = useState<string | undefined>(); - const [visitsFilter, setVisitsFilter] = useState<VisitsFilter>({}); const botsSupported = supportsBotVisits(selectedServer); const isFirstLoad = useRef(true); const buildSectionUrl = (subPath?: string) => { const query = domain ? `?domain=${domain}` : ''; - return !subPath ? `${query}` : `${subPath}${query}`; }; const normalizedVisits = useMemo(() => normalizeVisits(visits), [visits]); @@ -109,12 +118,10 @@ export const VisitsStats: FC<VisitsStatsProps> = ({ useEffect(() => cancelGetVisits, []); useEffect(() => { - getVisits({ dateRange, filter: visitsFilter }, isFirstLoad.current); + const resolvedDateRange = !isFirstLoad.current ? dateRange : (dateRange ?? toDateRange(initialInterval.current)); + getVisits({ dateRange: resolvedDateRange, filter: visitsFilter }, isFirstLoad.current); isFirstLoad.current = false; }, [dateRange, visitsFilter]); - useEffect(() => { - fallbackInterval && setInitialInterval(fallbackInterval); - }, [fallbackInterval]); const renderVisitsContent = () => { if (loadingLarge) { @@ -283,9 +290,9 @@ export const VisitsStats: FC<VisitsStatsProps> = ({ <DateRangeSelector updatable disabled={loading} - initialDateRange={initialInterval} + initialDateRange={initialInterval.current} defaultText="All visits" - onDatesChange={setDateRange} + onDatesChange={setDates} /> </div> <VisitsFilterDropdown @@ -293,7 +300,7 @@ export const VisitsStats: FC<VisitsStatsProps> = ({ isOrphanVisits={isOrphanVisits} botsSupported={botsSupported} selected={visitsFilter} - onChange={setVisitsFilter} + onChange={(newVisitsFilter) => updateFiltering({ visitsFilter: newVisitsFilter })} /> </div> </div> diff --git a/src/visits/VisitsTable.tsx b/src/visits/VisitsTable.tsx index 39e30c48..16181b49 100644 --- a/src/visits/VisitsTable.tsx +++ b/src/visits/VisitsTable.tsx @@ -10,7 +10,7 @@ import { determineOrderDir, Order, sortList } from '../utils/helpers/ordering'; import { prettify } from '../utils/helpers/numbers'; import { supportsBotVisits } from '../utils/helpers/features'; import { SelectedServer } from '../servers/data'; -import { Time } from '../utils/Time'; +import { Time } from '../utils/dates/Time'; import { TableOrderIcon } from '../utils/table/TableOrderIcon'; import { MediaMatcher } from '../utils/types'; import { NormalizedOrphanVisit, NormalizedVisit } from './types'; diff --git a/src/visits/charts/LineChartCard.tsx b/src/visits/charts/LineChartCard.tsx index a6e4b4ba..8554ff71 100644 --- a/src/visits/charts/LineChartCard.tsx +++ b/src/visits/charts/LineChartCard.tsx @@ -31,6 +31,7 @@ import { prettify } from '../../utils/helpers/numbers'; import { pointerOnHover, renderChartLabel } from '../../utils/helpers/charts'; import { HIGHLIGHTED_COLOR, MAIN_COLOR } from '../../utils/theme'; import './LineChartCard.scss'; +import { STANDARD_DATE_FORMAT } from '../../utils/helpers/date'; interface LineChartCardProps { title: string; @@ -65,10 +66,10 @@ const STEP_TO_DIFF_FUNC_MAP: Record<Step, (dateLeft: Date, dateRight: Date) => n const STEP_TO_DATE_FORMAT: Record<Step, (date: Date) => string> = { hourly: (date) => format(date, 'yyyy-MM-dd HH:00'), - daily: (date) => format(date, 'yyyy-MM-dd'), + daily: (date) => format(date, STANDARD_DATE_FORMAT), weekly(date) { - const firstWeekDay = format(startOfISOWeek(date), 'yyyy-MM-dd'); - const lastWeekDay = format(endOfISOWeek(date), 'yyyy-MM-dd'); + const firstWeekDay = format(startOfISOWeek(date), STANDARD_DATE_FORMAT); + const lastWeekDay = format(endOfISOWeek(date), STANDARD_DATE_FORMAT); return `${firstWeekDay} - ${lastWeekDay}`; }, diff --git a/src/visits/charts/SortableBarChartCard.tsx b/src/visits/charts/SortableBarChartCard.tsx index 8d43bdb3..04ac4f33 100644 --- a/src/visits/charts/SortableBarChartCard.tsx +++ b/src/visits/charts/SortableBarChartCard.tsx @@ -37,7 +37,7 @@ export const SortableBarChartCard: FC<SortableBarChartCardProps> = ({ const getSortedPairsForStats = (statsToSort: Stats, sorting: Record<string, string>) => { const pairs = toPairs(statsToSort); const sortedPairs = !order.field ? pairs : sortBy( - pipe<StatsRow, string | number, string | number>( + pipe<StatsRow[], string | number, string | number>( order.field === Object.keys(sorting)[0] ? pickKeyFromPair : pickValueFromPair, toLowerIfString, ), diff --git a/src/visits/helpers/MapModal.tsx b/src/visits/helpers/MapModal.tsx index 27296ff9..c2118031 100644 --- a/src/visits/helpers/MapModal.tsx +++ b/src/visits/helpers/MapModal.tsx @@ -14,7 +14,7 @@ interface MapModalProps { const OpenStreetMapTile: FC = () => ( <TileLayer - attribution='&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' + attribution='&copy <a href="https://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> ); diff --git a/src/visits/helpers/VisitsFilterDropdown.tsx b/src/visits/helpers/VisitsFilterDropdown.tsx index 19824a4b..58bb4ff5 100644 --- a/src/visits/helpers/VisitsFilterDropdown.tsx +++ b/src/visits/helpers/VisitsFilterDropdown.tsx @@ -46,7 +46,12 @@ export const VisitsFilterDropdown = ( )} <DropdownItem divider /> - <DropdownItem disabled={!hasValue(selected)} onClick={() => onChange({})}><i>Clear filters</i></DropdownItem> + <DropdownItem + disabled={!hasValue(selected)} + onClick={() => onChange({ excludeBots: false, orphanVisitsType: undefined })} + > + <i>Clear filters</i> + </DropdownItem> </DropdownBtn> ); }; diff --git a/src/visits/helpers/hooks.ts b/src/visits/helpers/hooks.ts new file mode 100644 index 00000000..af19d9c8 --- /dev/null +++ b/src/visits/helpers/hooks.ts @@ -0,0 +1,63 @@ +import { DeepPartial } from '@reduxjs/toolkit'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { useMemo } from 'react'; +import { isEmpty, mergeDeepRight, pipe } from 'ramda'; +import { DateRange, datesToDateRange } from '../../utils/helpers/dateIntervals'; +import { OrphanVisitType, VisitsFilter } from '../types'; +import { parseQuery, stringifyQuery } from '../../utils/helpers/query'; +import { formatIsoDate } from '../../utils/helpers/date'; + +interface VisitsQuery { + startDate?: string; + endDate?: string; + orphanVisitsType?: OrphanVisitType; + excludeBots?: 'true'; + domain?: string; +} + +interface VisitsFiltering { + dateRange?: DateRange; + visitsFilter: VisitsFilter; +} + +interface VisitsFilteringAndDomain { + filtering: VisitsFiltering; + domain?: string; +} + +type UpdateFiltering = (extra: DeepPartial<VisitsFiltering>) => void; + +export const useVisitsQuery = (): [VisitsFiltering, UpdateFiltering] => { + const navigate = useNavigate(); + const { search } = useLocation(); + + const { filtering, domain: theDomain } = useMemo( + pipe( + () => parseQuery<VisitsQuery>(search), + ({ startDate, endDate, orphanVisitsType, excludeBots, domain }: VisitsQuery): VisitsFilteringAndDomain => ({ + domain, + filtering: { + dateRange: startDate || endDate ? datesToDateRange(startDate, endDate) : undefined, + visitsFilter: { orphanVisitsType, excludeBots: excludeBots === 'true' }, + }, + }), + ), + [search], + ); + const updateFiltering = (extra: DeepPartial<VisitsFiltering>) => { + const { dateRange, visitsFilter } = mergeDeepRight(filtering, extra); + const query: VisitsQuery = { + startDate: (dateRange?.startDate && formatIsoDate(dateRange.startDate)) || undefined, + endDate: (dateRange?.endDate && formatIsoDate(dateRange.endDate)) || undefined, + excludeBots: visitsFilter.excludeBots ? 'true' : undefined, + orphanVisitsType: visitsFilter.orphanVisitsType, + domain: theDomain, + }; + const stringifiedQuery = stringifyQuery(query); + const queryString = isEmpty(stringifiedQuery) ? '' : `?${stringifiedQuery}`; + + navigate(queryString, { replace: true, relative: 'route' }); + }; + + return [filtering, updateFiltering]; +}; diff --git a/src/visits/reducers/common.ts b/src/visits/reducers/common.ts index 1a08d7a7..f64078cd 100644 --- a/src/visits/reducers/common.ts +++ b/src/visits/reducers/common.ts @@ -1,10 +1,13 @@ import { flatten, prop, range, splitEvery } from 'ramda'; -import { Action, Dispatch } from 'redux'; +import { createAction, createSlice } from '@reduxjs/toolkit'; import { ShlinkPaginator, ShlinkVisits, ShlinkVisitsParams } from '../../api/types'; -import { Visit } from '../types'; +import { CreateVisit, Visit } from '../types'; +import { DateInterval, dateToMatchingInterval } from '../../utils/helpers/dateIntervals'; +import { LoadVisits, VisitsInfo, VisitsLoaded } from './types'; +import { createAsyncThunk } from '../../utils/helpers/redux'; +import { ShlinkState } from '../../container/types'; import { parseApiError } from '../../api/utils'; -import { ApiErrorAction } from '../../api/types/actions'; -import { dateToMatchingInterval } from '../../utils/dates/types'; +import { createNewVisits } from './visitCreation'; const ITEMS_PER_PAGE = 5000; const PARALLEL_REQUESTS_COUNT = 4; @@ -15,74 +18,72 @@ const calcProgress = (total: number, current: number): number => (current * 100) type VisitsLoader = (page: number, itemsPerPage: number) => Promise<ShlinkVisits>; type LastVisitLoader = () => Promise<Visit | undefined>; -interface ActionMap { - start: string; - large: string; - finish: string; - error: string; - progress: string; - fallbackToInterval: string; + +interface VisitsAsyncThunkOptions<T extends LoadVisits = LoadVisits, R extends VisitsLoaded = VisitsLoaded> { + typePrefix: string; + createLoaders: (params: T, getState: () => ShlinkState) => [VisitsLoader, LastVisitLoader]; + getExtraFulfilledPayload: (params: T) => Partial<R>; + shouldCancel: (getState: () => ShlinkState) => boolean; } -export const getVisitsWithLoader = async <T extends Action<string> & { visits: Visit[] }>( - visitsLoader: VisitsLoader, - lastVisitLoader: LastVisitLoader, - extraFinishActionData: Partial<T>, - actionMap: ActionMap, - dispatch: Dispatch, - shouldCancel: () => boolean, +export const createVisitsAsyncThunk = <T extends LoadVisits = LoadVisits, R extends VisitsLoaded = VisitsLoaded>( + { typePrefix, createLoaders, getExtraFulfilledPayload, shouldCancel }: VisitsAsyncThunkOptions<T, R>, ) => { - dispatch({ type: actionMap.start }); + const progressChangedAction = createAction<number>(`${typePrefix}/progressChanged`); + const largeAction = createAction<void>(`${typePrefix}/large`); + const fallbackToIntervalAction = createAction<DateInterval>(`${typePrefix}/fallbackToInterval`); - const loadVisitsInParallel = async (pages: number[]): Promise<Visit[]> => - Promise.all(pages.map(async (page) => visitsLoader(page, ITEMS_PER_PAGE).then(prop('data')))).then(flatten); + const asyncThunk = createAsyncThunk(typePrefix, async (params: T, { getState, dispatch }): Promise<R> => { + const [visitsLoader, lastVisitLoader] = createLoaders(params, getState); - const loadPagesBlocks = async (pagesBlocks: number[][], index = 0): Promise<Visit[]> => { - if (shouldCancel()) { - return []; - } + const loadVisitsInParallel = async (pages: number[]): Promise<Visit[]> => + Promise.all(pages.map(async (page) => visitsLoader(page, ITEMS_PER_PAGE).then(prop('data')))).then(flatten); - const data = await loadVisitsInParallel(pagesBlocks[index]); + const loadPagesBlocks = async (pagesBlocks: number[][], index = 0): Promise<Visit[]> => { + if (shouldCancel(getState)) { + return []; + } - dispatch({ type: actionMap.progress, progress: calcProgress(pagesBlocks.length, index + PARALLEL_STARTING_PAGE) }); + const data = await loadVisitsInParallel(pagesBlocks[index]); - if (index < pagesBlocks.length - 1) { - return data.concat(await loadPagesBlocks(pagesBlocks, index + 1)); - } + dispatch(progressChangedAction(calcProgress(pagesBlocks.length, index + PARALLEL_STARTING_PAGE))); - return data; - }; + if (index < pagesBlocks.length - 1) { + return data.concat(await loadPagesBlocks(pagesBlocks, index + 1)); + } - const loadVisits = async (page = 1) => { - const { pagination, data } = await visitsLoader(page, ITEMS_PER_PAGE); - - // If pagination was not returned, then this is an old shlink version. Just return data - if (!pagination || isLastPage(pagination)) { return data; - } + }; - // If there are more pages, make requests in blocks of 4 - const pagesRange = range(PARALLEL_STARTING_PAGE, pagination.pagesCount + 1); - const pagesBlocks = splitEvery(PARALLEL_REQUESTS_COUNT, pagesRange); + const loadVisits = async (page = 1) => { + const { pagination, data } = await visitsLoader(page, ITEMS_PER_PAGE); - if (pagination.pagesCount - 1 > PARALLEL_REQUESTS_COUNT) { - dispatch({ type: actionMap.large }); - } + // If pagination was not returned, then this is an old shlink version. Just return data + if (!pagination || isLastPage(pagination)) { + return data; + } - return data.concat(await loadPagesBlocks(pagesBlocks)); - }; + // If there are more pages, make requests in blocks of 4 + const pagesRange = range(PARALLEL_STARTING_PAGE, pagination.pagesCount + 1); + const pagesBlocks = splitEvery(PARALLEL_REQUESTS_COUNT, pagesRange); + + if (pagination.pagesCount - 1 > PARALLEL_REQUESTS_COUNT) { + dispatch(largeAction()); + } + + return data.concat(await loadPagesBlocks(pagesBlocks)); + }; - try { const [visits, lastVisit] = await Promise.all([loadVisits(), lastVisitLoader()]); - dispatch( - !visits.length && lastVisit - ? { type: actionMap.fallbackToInterval, fallbackInterval: dateToMatchingInterval(lastVisit.date) } - : { ...extraFinishActionData, visits, type: actionMap.finish }, - ); - } catch (e: any) { - dispatch<ApiErrorAction>({ type: actionMap.error, errorData: parseApiError(e) }); - } + if (!visits.length && lastVisit) { + dispatch(fallbackToIntervalAction(dateToMatchingInterval(lastVisit.date))); + } + + return { ...getExtraFulfilledPayload(params), visits } as any; // TODO Get rid of this casting + }); + + return { asyncThunk, progressChangedAction, largeAction, fallbackToIntervalAction }; }; export const lastVisitLoaderForLoader = ( @@ -93,5 +94,51 @@ export const lastVisitLoaderForLoader = ( return async () => Promise.resolve(undefined); } - return async () => loader({ page: 1, itemsPerPage: 1 }).then((result) => result.data[0]); + return async () => loader({ page: 1, itemsPerPage: 1 }).then(({ data }) => data[0]); +}; + +interface VisitsReducerOptions<State extends VisitsInfo, AT extends ReturnType<typeof createVisitsAsyncThunk>> { + name: string; + asyncThunkCreator: AT; + initialState: State; + filterCreatedVisits: (state: State, createdVisits: CreateVisit[]) => CreateVisit[]; +} + +export const createVisitsReducer = <State extends VisitsInfo, AT extends ReturnType<typeof createVisitsAsyncThunk>>( + { name, asyncThunkCreator, initialState, filterCreatedVisits }: VisitsReducerOptions<State, AT>, +) => { + const { asyncThunk, largeAction, fallbackToIntervalAction, progressChangedAction } = asyncThunkCreator; + const { reducer, actions } = createSlice({ + name, + initialState, + reducers: { + cancelGetVisits: (state) => ({ ...state, cancelLoad: true }), + }, + extraReducers: (builder) => { + builder.addCase(asyncThunk.pending, () => ({ ...initialState, loading: true })); + builder.addCase(asyncThunk.rejected, (_, { error }) => ( + { ...initialState, error: true, errorData: parseApiError(error) } + )); + builder.addCase(asyncThunk.fulfilled, (state, { payload }) => ( + { ...state, ...payload, loading: false, loadingLarge: false, error: false } + )); + + builder.addCase(largeAction, (state) => ({ ...state, loadingLarge: true })); + builder.addCase(progressChangedAction, (state, { payload: progress }) => ({ ...state, progress })); + builder.addCase(fallbackToIntervalAction, (state, { payload: fallbackInterval }) => ( + { ...state, fallbackInterval } + )); + + builder.addCase(createNewVisits, (state, { payload }) => { + const { visits } = state; + // @ts-expect-error TODO Fix type inference + const newVisits = filterCreatedVisits(state, payload.createdVisits).map(({ visit }) => visit); + + return !newVisits.length ? state : { ...state, visits: [...newVisits, ...visits] }; + }); + }, + }); + const { cancelGetVisits } = actions; + + return { reducer, cancelGetVisits }; }; diff --git a/src/visits/reducers/domainVisits.ts b/src/visits/reducers/domainVisits.ts index 17ee4f63..a44d1cfc 100644 --- a/src/visits/reducers/domainVisits.ts +++ b/src/visits/reducers/domainVisits.ts @@ -1,40 +1,20 @@ -import { Action, Dispatch } from 'redux'; -import { Visit, VisitsFallbackIntervalAction, VisitsInfo, VisitsLoadProgressChangedAction } from '../types'; -import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { GetState } from '../../container/types'; -import { ShlinkVisitsParams } from '../../api/types'; -import { ApiErrorAction } from '../../api/types/actions'; import { isBetween } from '../../utils/helpers/date'; -import { getVisitsWithLoader, lastVisitLoaderForLoader } from './common'; -import { CREATE_VISITS, CreateVisitsAction } from './visitCreation'; +import { createVisitsAsyncThunk, createVisitsReducer, lastVisitLoaderForLoader } from './common'; import { domainMatches } from '../../short-urls/helpers'; +import { LoadVisits, VisitsInfo } from './types'; -export const GET_DOMAIN_VISITS_START = 'shlink/domainVisits/GET_DOMAIN_VISITS_START'; -export const GET_DOMAIN_VISITS_ERROR = 'shlink/domainVisits/GET_DOMAIN_VISITS_ERROR'; -export const GET_DOMAIN_VISITS = 'shlink/domainVisits/GET_DOMAIN_VISITS'; -export const GET_DOMAIN_VISITS_LARGE = 'shlink/domainVisits/GET_DOMAIN_VISITS_LARGE'; -export const GET_DOMAIN_VISITS_CANCEL = 'shlink/domainVisits/GET_DOMAIN_VISITS_CANCEL'; -export const GET_DOMAIN_VISITS_PROGRESS_CHANGED = 'shlink/domainVisits/GET_DOMAIN_VISITS_PROGRESS_CHANGED'; -export const GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL = 'shlink/domainVisits/GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL'; +const REDUCER_PREFIX = 'shlink/domainVisits'; export const DEFAULT_DOMAIN = 'DEFAULT'; -export interface DomainVisits extends VisitsInfo { +interface WithDomain { domain: string; } -export interface DomainVisitsAction extends Action<string> { - visits: Visit[]; - domain: string; - query?: ShlinkVisitsParams; -} +export interface DomainVisits extends VisitsInfo, WithDomain {} -type DomainVisitsCombinedAction = DomainVisitsAction -& VisitsLoadProgressChangedAction -& VisitsFallbackIntervalAction -& CreateVisitsAction -& ApiErrorAction; +export interface LoadDomainVisits extends LoadVisits, WithDomain {} const initialState: DomainVisits = { visits: [], @@ -46,51 +26,34 @@ const initialState: DomainVisits = { progress: 0, }; -export default buildReducer<DomainVisits, DomainVisitsCombinedAction>({ - [GET_DOMAIN_VISITS_START]: () => ({ ...initialState, loading: true }), - [GET_DOMAIN_VISITS_ERROR]: (_, { errorData }) => ({ ...initialState, error: true, errorData }), - [GET_DOMAIN_VISITS]: (state, { visits, domain, query }) => ( - { ...state, visits, domain, query, loading: false, loadingLarge: false, error: false } - ), - [GET_DOMAIN_VISITS_LARGE]: (state) => ({ ...state, loadingLarge: true }), - [GET_DOMAIN_VISITS_CANCEL]: (state) => ({ ...state, cancelLoad: true }), - [GET_DOMAIN_VISITS_PROGRESS_CHANGED]: (state, { progress }) => ({ ...state, progress }), - [GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL]: (state, { fallbackInterval }) => ({ ...state, fallbackInterval }), - [CREATE_VISITS]: (state, { createdVisits }) => { - const { domain, visits, query = {} } = state; - const { startDate, endDate } = query; - const newVisits = createdVisits - .filter(({ shortUrl, visit }) => - shortUrl && domainMatches(shortUrl, domain) && isBetween(visit.date, startDate, endDate)) - .map(({ visit }) => visit); +export const getDomainVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => createVisitsAsyncThunk({ + typePrefix: `${REDUCER_PREFIX}/getDomainVisits`, + createLoaders: ({ domain, query = {}, doIntervalFallback = false }: LoadDomainVisits, getState) => { + const { getDomainVisits: getVisits } = buildShlinkApiClient(getState); + const visitsLoader = async (page: number, itemsPerPage: number) => getVisits( + domain, + { ...query, page, itemsPerPage }, + ); + const lastVisitLoader = lastVisitLoaderForLoader(doIntervalFallback, async (params) => getVisits(domain, params)); - return { ...state, visits: [...newVisits, ...visits] }; + return [visitsLoader, lastVisitLoader]; }, -}, initialState); + getExtraFulfilledPayload: ({ domain, query = {} }: LoadDomainVisits) => ({ domain, query }), + shouldCancel: (getState) => getState().domainVisits.cancelLoad, +}); -export const getDomainVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - domain: string, - query: ShlinkVisitsParams = {}, - doIntervalFallback = false, -) => async (dispatch: Dispatch, getState: GetState) => { - const { getDomainVisits: getVisits } = buildShlinkApiClient(getState); - const visitsLoader = async (page: number, itemsPerPage: number) => getVisits( - domain, - { ...query, page, itemsPerPage }, - ); - const lastVisitLoader = lastVisitLoaderForLoader(doIntervalFallback, async (params) => getVisits(domain, params)); - const shouldCancel = () => getState().domainVisits.cancelLoad; - const extraFinishActionData: Partial<DomainVisitsAction> = { domain, query }; - const actionMap = { - start: GET_DOMAIN_VISITS_START, - large: GET_DOMAIN_VISITS_LARGE, - finish: GET_DOMAIN_VISITS, - error: GET_DOMAIN_VISITS_ERROR, - progress: GET_DOMAIN_VISITS_PROGRESS_CHANGED, - fallbackToInterval: GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, - }; - - return getVisitsWithLoader(visitsLoader, lastVisitLoader, extraFinishActionData, actionMap, dispatch, shouldCancel); -}; - -export const cancelGetDomainVisits = buildActionCreator(GET_DOMAIN_VISITS_CANCEL); +export const domainVisitsReducerCreator = ( + asyncThunkCreator: ReturnType<typeof getDomainVisits>, +) => createVisitsReducer({ + name: REDUCER_PREFIX, + initialState, + // @ts-expect-error TODO Fix type inference + asyncThunkCreator, + filterCreatedVisits: ({ domain, query = {} }, createdVisits) => { + const { startDate, endDate } = query; + return createdVisits.filter( + ({ shortUrl, visit }) => + shortUrl && domainMatches(shortUrl, domain) && isBetween(visit.date, startDate, endDate), + ); + }, +}); diff --git a/src/visits/reducers/nonOrphanVisits.ts b/src/visits/reducers/nonOrphanVisits.ts index 05133800..83db3f43 100644 --- a/src/visits/reducers/nonOrphanVisits.ts +++ b/src/visits/reducers/nonOrphanVisits.ts @@ -1,37 +1,9 @@ -import { Action, Dispatch } from 'redux'; -import { - Visit, - VisitsFallbackIntervalAction, - VisitsInfo, - VisitsLoadProgressChangedAction, -} from '../types'; -import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { GetState } from '../../container/types'; -import { ShlinkVisitsParams } from '../../api/types'; -import { ApiErrorAction } from '../../api/types/actions'; import { isBetween } from '../../utils/helpers/date'; -import { getVisitsWithLoader, lastVisitLoaderForLoader } from './common'; -import { CREATE_VISITS, CreateVisitsAction } from './visitCreation'; +import { createVisitsAsyncThunk, createVisitsReducer, lastVisitLoaderForLoader } from './common'; +import { VisitsInfo } from './types'; -export const GET_NON_ORPHAN_VISITS_START = 'shlink/orphanVisits/GET_NON_ORPHAN_VISITS_START'; -export const GET_NON_ORPHAN_VISITS_ERROR = 'shlink/orphanVisits/GET_NON_ORPHAN_VISITS_ERROR'; -export const GET_NON_ORPHAN_VISITS = 'shlink/orphanVisits/GET_NON_ORPHAN_VISITS'; -export const GET_NON_ORPHAN_VISITS_LARGE = 'shlink/orphanVisits/GET_NON_ORPHAN_VISITS_LARGE'; -export const GET_NON_ORPHAN_VISITS_CANCEL = 'shlink/orphanVisits/GET_NON_ORPHAN_VISITS_CANCEL'; -export const GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED = 'shlink/orphanVisits/GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED'; -export const GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL = 'shlink/orphanVisits/GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL'; - -export interface NonOrphanVisitsAction extends Action<string> { - visits: Visit[]; - query?: ShlinkVisitsParams; -} - -type NonOrphanVisitsCombinedAction = NonOrphanVisitsAction -& VisitsLoadProgressChangedAction -& VisitsFallbackIntervalAction -& CreateVisitsAction -& ApiErrorAction; +const REDUCER_PREFIX = 'shlink/orphanVisits'; const initialState: VisitsInfo = { visits: [], @@ -42,47 +14,28 @@ const initialState: VisitsInfo = { progress: 0, }; -export default buildReducer<VisitsInfo, NonOrphanVisitsCombinedAction>({ - [GET_NON_ORPHAN_VISITS_START]: () => ({ ...initialState, loading: true }), - [GET_NON_ORPHAN_VISITS_ERROR]: (_, { errorData }) => ({ ...initialState, error: true, errorData }), - [GET_NON_ORPHAN_VISITS]: (state, { visits, query }) => ( - { ...state, visits, query, loading: false, loadingLarge: false, error: false } - ), - [GET_NON_ORPHAN_VISITS_LARGE]: (state) => ({ ...state, loadingLarge: true }), - [GET_NON_ORPHAN_VISITS_CANCEL]: (state) => ({ ...state, cancelLoad: true }), - [GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED]: (state, { progress }) => ({ ...state, progress }), - [GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL]: (state, { fallbackInterval }) => ({ ...state, fallbackInterval }), - [CREATE_VISITS]: (state, { createdVisits }) => { - const { visits, query = {} } = state; - const { startDate, endDate } = query; - const newVisits = createdVisits - .filter(({ visit }) => isBetween(visit.date, startDate, endDate)) - .map(({ visit }) => visit); +export const getNonOrphanVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => createVisitsAsyncThunk({ + typePrefix: `${REDUCER_PREFIX}/getNonOrphanVisits`, + createLoaders: ({ query = {}, doIntervalFallback = false }, getState) => { + const { getNonOrphanVisits: shlinkGetNonOrphanVisits } = buildShlinkApiClient(getState); + const visitsLoader = async (page: number, itemsPerPage: number) => + shlinkGetNonOrphanVisits({ ...query, page, itemsPerPage }); + const lastVisitLoader = lastVisitLoaderForLoader(doIntervalFallback, shlinkGetNonOrphanVisits); - return { ...state, visits: [...newVisits, ...visits] }; + return [visitsLoader, lastVisitLoader]; }, -}, initialState); + getExtraFulfilledPayload: ({ query = {} }) => ({ query }), + shouldCancel: (getState) => getState().orphanVisits.cancelLoad, +}); -export const getNonOrphanVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - query: ShlinkVisitsParams = {}, - doIntervalFallback = false, -) => async (dispatch: Dispatch, getState: GetState) => { - const { getNonOrphanVisits: shlinkGetNonOrphanVisits } = buildShlinkApiClient(getState); - const visitsLoader = async (page: number, itemsPerPage: number) => - shlinkGetNonOrphanVisits({ ...query, page, itemsPerPage }); - const lastVisitLoader = lastVisitLoaderForLoader(doIntervalFallback, shlinkGetNonOrphanVisits); - const shouldCancel = () => getState().orphanVisits.cancelLoad; - const extraFinishActionData: Partial<NonOrphanVisitsAction> = { query }; - const actionMap = { - start: GET_NON_ORPHAN_VISITS_START, - large: GET_NON_ORPHAN_VISITS_LARGE, - finish: GET_NON_ORPHAN_VISITS, - error: GET_NON_ORPHAN_VISITS_ERROR, - progress: GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED, - fallbackToInterval: GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, - }; - - return getVisitsWithLoader(visitsLoader, lastVisitLoader, extraFinishActionData, actionMap, dispatch, shouldCancel); -}; - -export const cancelGetNonOrphanVisits = buildActionCreator(GET_NON_ORPHAN_VISITS_CANCEL); +export const nonOrphanVisitsReducerCreator = ( + asyncThunkCreator: ReturnType<typeof getNonOrphanVisits>, +) => createVisitsReducer({ + name: REDUCER_PREFIX, + initialState, + asyncThunkCreator, + filterCreatedVisits: ({ query = {} }, createdVisits) => { + const { startDate, endDate } = query; + return createdVisits.filter(({ visit }) => isBetween(visit.date, startDate, endDate)); + }, +}); diff --git a/src/visits/reducers/orphanVisits.ts b/src/visits/reducers/orphanVisits.ts index 8b6aee65..269aa764 100644 --- a/src/visits/reducers/orphanVisits.ts +++ b/src/visits/reducers/orphanVisits.ts @@ -1,41 +1,16 @@ -import { Action, Dispatch } from 'redux'; -import { - OrphanVisit, - OrphanVisitType, - Visit, - VisitsFallbackIntervalAction, - VisitsInfo, - VisitsLoadProgressChangedAction, -} from '../types'; -import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; +import { OrphanVisit, OrphanVisitType } from '../types'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { GetState } from '../../container/types'; -import { ShlinkVisitsParams } from '../../api/types'; import { isOrphanVisit } from '../types/helpers'; -import { ApiErrorAction } from '../../api/types/actions'; import { isBetween } from '../../utils/helpers/date'; -import { getVisitsWithLoader, lastVisitLoaderForLoader } from './common'; -import { CREATE_VISITS, CreateVisitsAction } from './visitCreation'; +import { createVisitsAsyncThunk, createVisitsReducer, lastVisitLoaderForLoader } from './common'; +import { LoadVisits, VisitsInfo } from './types'; -export const GET_ORPHAN_VISITS_START = 'shlink/orphanVisits/GET_ORPHAN_VISITS_START'; -export const GET_ORPHAN_VISITS_ERROR = 'shlink/orphanVisits/GET_ORPHAN_VISITS_ERROR'; -export const GET_ORPHAN_VISITS = 'shlink/orphanVisits/GET_ORPHAN_VISITS'; -export const GET_ORPHAN_VISITS_LARGE = 'shlink/orphanVisits/GET_ORPHAN_VISITS_LARGE'; -export const GET_ORPHAN_VISITS_CANCEL = 'shlink/orphanVisits/GET_ORPHAN_VISITS_CANCEL'; -export const GET_ORPHAN_VISITS_PROGRESS_CHANGED = 'shlink/orphanVisits/GET_ORPHAN_VISITS_PROGRESS_CHANGED'; -export const GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL = 'shlink/orphanVisits/GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL'; +const REDUCER_PREFIX = 'shlink/orphanVisits'; -export interface OrphanVisitsAction extends Action<string> { - visits: Visit[]; - query?: ShlinkVisitsParams; +export interface LoadOrphanVisits extends LoadVisits { + orphanVisitsType?: OrphanVisitType; } -type OrphanVisitsCombinedAction = OrphanVisitsAction -& VisitsLoadProgressChangedAction -& VisitsFallbackIntervalAction -& CreateVisitsAction -& ApiErrorAction; - const initialState: VisitsInfo = { visits: [], loading: false, @@ -45,55 +20,34 @@ const initialState: VisitsInfo = { progress: 0, }; -export default buildReducer<VisitsInfo, OrphanVisitsCombinedAction>({ - [GET_ORPHAN_VISITS_START]: () => ({ ...initialState, loading: true }), - [GET_ORPHAN_VISITS_ERROR]: (_, { errorData }) => ({ ...initialState, error: true, errorData }), - [GET_ORPHAN_VISITS]: (state, { visits, query }) => ( - { ...state, visits, query, loading: false, loadingLarge: false, error: false } - ), - [GET_ORPHAN_VISITS_LARGE]: (state) => ({ ...state, loadingLarge: true }), - [GET_ORPHAN_VISITS_CANCEL]: (state) => ({ ...state, cancelLoad: true }), - [GET_ORPHAN_VISITS_PROGRESS_CHANGED]: (state, { progress }) => ({ ...state, progress }), - [GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL]: (state, { fallbackInterval }) => ({ ...state, fallbackInterval }), - [CREATE_VISITS]: (state, { createdVisits }) => { - const { visits, query = {} } = state; - const { startDate, endDate } = query; - const newVisits = createdVisits - .filter(({ visit, shortUrl }) => !shortUrl && isBetween(visit.date, startDate, endDate)) - .map(({ visit }) => visit); - - return { ...state, visits: [...newVisits, ...visits] }; - }, -}, initialState); - const matchesType = (visit: OrphanVisit, orphanVisitsType?: OrphanVisitType) => !orphanVisitsType || orphanVisitsType === visit.type; -export const getOrphanVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - query: ShlinkVisitsParams = {}, - orphanVisitsType?: OrphanVisitType, - doIntervalFallback = false, -) => async (dispatch: Dispatch, getState: GetState) => { - const { getOrphanVisits: getVisits } = buildShlinkApiClient(getState); - const visitsLoader = async (page: number, itemsPerPage: number) => getVisits({ ...query, page, itemsPerPage }) - .then((result) => { - const visits = result.data.filter((visit) => isOrphanVisit(visit) && matchesType(visit, orphanVisitsType)); +export const getOrphanVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => createVisitsAsyncThunk({ + typePrefix: `${REDUCER_PREFIX}/getOrphanVisits`, + createLoaders: ({ orphanVisitsType, query = {}, doIntervalFallback = false }: LoadOrphanVisits, getState) => { + const { getOrphanVisits: getVisits } = buildShlinkApiClient(getState); + const visitsLoader = async (page: number, itemsPerPage: number) => getVisits({ ...query, page, itemsPerPage }) + .then((result) => { + const visits = result.data.filter((visit) => isOrphanVisit(visit) && matchesType(visit, orphanVisitsType)); + return { ...result, data: visits }; + }); + const lastVisitLoader = lastVisitLoaderForLoader(doIntervalFallback, getVisits); - return { ...result, data: visits }; - }); - const lastVisitLoader = lastVisitLoaderForLoader(doIntervalFallback, getVisits); - const shouldCancel = () => getState().orphanVisits.cancelLoad; - const extraFinishActionData: Partial<OrphanVisitsAction> = { query }; - const actionMap = { - start: GET_ORPHAN_VISITS_START, - large: GET_ORPHAN_VISITS_LARGE, - finish: GET_ORPHAN_VISITS, - error: GET_ORPHAN_VISITS_ERROR, - progress: GET_ORPHAN_VISITS_PROGRESS_CHANGED, - fallbackToInterval: GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, - }; + return [visitsLoader, lastVisitLoader]; + }, + getExtraFulfilledPayload: ({ query = {} }: LoadOrphanVisits) => ({ query }), + shouldCancel: (getState) => getState().orphanVisits.cancelLoad, +}); - return getVisitsWithLoader(visitsLoader, lastVisitLoader, extraFinishActionData, actionMap, dispatch, shouldCancel); -}; - -export const cancelGetOrphanVisits = buildActionCreator(GET_ORPHAN_VISITS_CANCEL); +export const orphanVisitsReducerCreator = ( + asyncThunkCreator: ReturnType<typeof getOrphanVisits>, +) => createVisitsReducer({ + name: REDUCER_PREFIX, + initialState, + asyncThunkCreator, + filterCreatedVisits: ({ query = {} }, createdVisits) => { + const { startDate, endDate } = query; + return createdVisits.filter(({ visit, shortUrl }) => !shortUrl && isBetween(visit.date, startDate, endDate)); + }, +}); diff --git a/src/visits/reducers/shortUrlVisits.ts b/src/visits/reducers/shortUrlVisits.ts index 00327c46..1c434787 100644 --- a/src/visits/reducers/shortUrlVisits.ts +++ b/src/visits/reducers/shortUrlVisits.ts @@ -1,37 +1,18 @@ -import { Action, Dispatch } from 'redux'; import { shortUrlMatches } from '../../short-urls/helpers'; -import { Visit, VisitsFallbackIntervalAction, VisitsInfo, VisitsLoadProgressChangedAction } from '../types'; import { ShortUrlIdentifier } from '../../short-urls/data'; -import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { GetState } from '../../container/types'; -import { ShlinkVisitsParams } from '../../api/types'; -import { ApiErrorAction } from '../../api/types/actions'; import { isBetween } from '../../utils/helpers/date'; -import { getVisitsWithLoader, lastVisitLoaderForLoader } from './common'; -import { CREATE_VISITS, CreateVisitsAction } from './visitCreation'; +import { createVisitsAsyncThunk, createVisitsReducer, lastVisitLoaderForLoader } from './common'; +import { LoadVisits, VisitsInfo } from './types'; -export const GET_SHORT_URL_VISITS_START = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS_START'; -export const GET_SHORT_URL_VISITS_ERROR = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS_ERROR'; -export const GET_SHORT_URL_VISITS = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS'; -export const GET_SHORT_URL_VISITS_LARGE = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS_LARGE'; -export const GET_SHORT_URL_VISITS_CANCEL = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS_CANCEL'; -export const GET_SHORT_URL_VISITS_PROGRESS_CHANGED = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS_PROGRESS_CHANGED'; -export const GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL'; +const REDUCER_PREFIX = 'shlink/shortUrlVisits'; export interface ShortUrlVisits extends VisitsInfo, ShortUrlIdentifier {} -interface ShortUrlVisitsAction extends Action<string>, ShortUrlIdentifier { - visits: Visit[]; - query?: ShlinkVisitsParams; +export interface LoadShortUrlVisits extends LoadVisits { + shortCode: string; } -type ShortUrlVisitsCombinedAction = ShortUrlVisitsAction -& VisitsLoadProgressChangedAction -& VisitsFallbackIntervalAction -& CreateVisitsAction -& ApiErrorAction; - const initialState: ShortUrlVisits = { visits: [], shortCode: '', @@ -43,63 +24,39 @@ const initialState: ShortUrlVisits = { progress: 0, }; -export default buildReducer<ShortUrlVisits, ShortUrlVisitsCombinedAction>({ - [GET_SHORT_URL_VISITS_START]: () => ({ ...initialState, loading: true }), - [GET_SHORT_URL_VISITS_ERROR]: (_, { errorData }) => ({ ...initialState, error: true, errorData }), - [GET_SHORT_URL_VISITS]: (state, { visits, query, shortCode, domain }) => ({ - ...state, - visits, - shortCode, - domain, - query, - loading: false, - loadingLarge: false, - error: false, - }), - [GET_SHORT_URL_VISITS_LARGE]: (state) => ({ ...state, loadingLarge: true }), - [GET_SHORT_URL_VISITS_CANCEL]: (state) => ({ ...state, cancelLoad: true }), - [GET_SHORT_URL_VISITS_PROGRESS_CHANGED]: (state, { progress }) => ({ ...state, progress }), - [GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL]: (state, { fallbackInterval }) => ({ ...state, fallbackInterval }), - [CREATE_VISITS]: (state, { createdVisits }) => { - const { shortCode, domain, visits, query = {} } = state; - const { startDate, endDate } = query; - const newVisits = createdVisits - .filter( - ({ shortUrl, visit }) => - shortUrl && shortUrlMatches(shortUrl, shortCode, domain) && isBetween(visit.date, startDate, endDate), - ) - .map(({ visit }) => visit); +export const getShortUrlVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => createVisitsAsyncThunk({ + typePrefix: `${REDUCER_PREFIX}/getShortUrlVisits`, + createLoaders: ({ shortCode, query = {}, doIntervalFallback = false }: LoadShortUrlVisits, getState) => { + const { getShortUrlVisits: shlinkGetShortUrlVisits } = buildShlinkApiClient(getState); + const visitsLoader = async (page: number, itemsPerPage: number) => shlinkGetShortUrlVisits( + shortCode, + { ...query, page, itemsPerPage }, + ); + const lastVisitLoader = lastVisitLoaderForLoader( + doIntervalFallback, + async (params) => shlinkGetShortUrlVisits(shortCode, { ...params, domain: query.domain }), + ); - return newVisits.length === 0 ? state : { ...state, visits: [...newVisits, ...visits] }; + return [visitsLoader, lastVisitLoader]; }, -}, initialState); + getExtraFulfilledPayload: ({ shortCode, query = {} }: LoadShortUrlVisits) => ( + { shortCode, query, domain: query.domain } + ), + shouldCancel: (getState) => getState().shortUrlVisits.cancelLoad, +}); -export const getShortUrlVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - shortCode: string, - query: ShlinkVisitsParams = {}, - doIntervalFallback = false, -) => async (dispatch: Dispatch, getState: GetState) => { - const { getShortUrlVisits: shlinkGetShortUrlVisits } = buildShlinkApiClient(getState); - const visitsLoader = async (page: number, itemsPerPage: number) => shlinkGetShortUrlVisits( - shortCode, - { ...query, page, itemsPerPage }, - ); - const lastVisitLoader = lastVisitLoaderForLoader( - doIntervalFallback, - async (params) => shlinkGetShortUrlVisits(shortCode, { ...params, domain: query.domain }), - ); - const shouldCancel = () => getState().shortUrlVisits.cancelLoad; - const extraFinishActionData: Partial<ShortUrlVisitsAction> = { shortCode, query, domain: query.domain }; - const actionMap = { - start: GET_SHORT_URL_VISITS_START, - large: GET_SHORT_URL_VISITS_LARGE, - finish: GET_SHORT_URL_VISITS, - error: GET_SHORT_URL_VISITS_ERROR, - progress: GET_SHORT_URL_VISITS_PROGRESS_CHANGED, - fallbackToInterval: GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, - }; - - return getVisitsWithLoader(visitsLoader, lastVisitLoader, extraFinishActionData, actionMap, dispatch, shouldCancel); -}; - -export const cancelGetShortUrlVisits = buildActionCreator(GET_SHORT_URL_VISITS_CANCEL); +export const shortUrlVisitsReducerCreator = ( + asyncThunkCreator: ReturnType<typeof getShortUrlVisits>, +) => createVisitsReducer({ + name: REDUCER_PREFIX, + initialState, + // @ts-expect-error TODO Fix type inference + asyncThunkCreator, + filterCreatedVisits: ({ shortCode, domain, query = {} }: ShortUrlVisits, createdVisits) => { + const { startDate, endDate } = query; + return createdVisits.filter( + ({ shortUrl, visit }) => + shortUrl && shortUrlMatches(shortUrl, shortCode, domain) && isBetween(visit.date, startDate, endDate), + ); + }, +}); diff --git a/src/visits/reducers/tagVisits.ts b/src/visits/reducers/tagVisits.ts index f2fe6b85..66b86ca0 100644 --- a/src/visits/reducers/tagVisits.ts +++ b/src/visits/reducers/tagVisits.ts @@ -1,37 +1,17 @@ -import { Action, Dispatch } from 'redux'; -import { Visit, VisitsFallbackIntervalAction, VisitsInfo, VisitsLoadProgressChangedAction } from '../types'; -import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { GetState } from '../../container/types'; -import { ShlinkVisitsParams } from '../../api/types'; -import { ApiErrorAction } from '../../api/types/actions'; import { isBetween } from '../../utils/helpers/date'; -import { getVisitsWithLoader, lastVisitLoaderForLoader } from './common'; -import { CREATE_VISITS, CreateVisitsAction } from './visitCreation'; +import { createVisitsAsyncThunk, createVisitsReducer, lastVisitLoaderForLoader } from './common'; +import { LoadVisits, VisitsInfo } from './types'; -export const GET_TAG_VISITS_START = 'shlink/tagVisits/GET_TAG_VISITS_START'; -export const GET_TAG_VISITS_ERROR = 'shlink/tagVisits/GET_TAG_VISITS_ERROR'; -export const GET_TAG_VISITS = 'shlink/tagVisits/GET_TAG_VISITS'; -export const GET_TAG_VISITS_LARGE = 'shlink/tagVisits/GET_TAG_VISITS_LARGE'; -export const GET_TAG_VISITS_CANCEL = 'shlink/tagVisits/GET_TAG_VISITS_CANCEL'; -export const GET_TAG_VISITS_PROGRESS_CHANGED = 'shlink/tagVisits/GET_TAG_VISITS_PROGRESS_CHANGED'; -export const GET_TAG_VISITS_FALLBACK_TO_INTERVAL = 'shlink/tagVisits/GET_TAG_VISITS_FALLBACK_TO_INTERVAL'; +const REDUCER_PREFIX = 'shlink/tagVisits'; -export interface TagVisits extends VisitsInfo { +interface WithTag { tag: string; } -export interface TagVisitsAction extends Action<string> { - visits: Visit[]; - tag: string; - query?: ShlinkVisitsParams; -} +export interface TagVisits extends VisitsInfo, WithTag {} -type TagsVisitsCombinedAction = TagVisitsAction -& VisitsLoadProgressChangedAction -& VisitsFallbackIntervalAction -& CreateVisitsAction -& ApiErrorAction; +export interface LoadTagVisits extends LoadVisits, WithTag {} const initialState: TagVisits = { visits: [], @@ -43,50 +23,31 @@ const initialState: TagVisits = { progress: 0, }; -export default buildReducer<TagVisits, TagsVisitsCombinedAction>({ - [GET_TAG_VISITS_START]: () => ({ ...initialState, loading: true }), - [GET_TAG_VISITS_ERROR]: (_, { errorData }) => ({ ...initialState, error: true, errorData }), - [GET_TAG_VISITS]: (state, { visits, tag, query }) => ( - { ...state, visits, tag, query, loading: false, loadingLarge: false, error: false } - ), - [GET_TAG_VISITS_LARGE]: (state) => ({ ...state, loadingLarge: true }), - [GET_TAG_VISITS_CANCEL]: (state) => ({ ...state, cancelLoad: true }), - [GET_TAG_VISITS_PROGRESS_CHANGED]: (state, { progress }) => ({ ...state, progress }), - [GET_TAG_VISITS_FALLBACK_TO_INTERVAL]: (state, { fallbackInterval }) => ({ ...state, fallbackInterval }), - [CREATE_VISITS]: (state, { createdVisits }) => { - const { tag, visits, query = {} } = state; - const { startDate, endDate } = query; - const newVisits = createdVisits - .filter(({ shortUrl, visit }) => shortUrl?.tags.includes(tag) && isBetween(visit.date, startDate, endDate)) - .map(({ visit }) => visit); +export const getTagVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => createVisitsAsyncThunk({ + typePrefix: `${REDUCER_PREFIX}/getTagVisits`, + createLoaders: ({ tag, query = {}, doIntervalFallback = false }: LoadTagVisits, getState) => { + const { getTagVisits: getVisits } = buildShlinkApiClient(getState); + const visitsLoader = async (page: number, itemsPerPage: number) => getVisits( + tag, + { ...query, page, itemsPerPage }, + ); + const lastVisitLoader = lastVisitLoaderForLoader(doIntervalFallback, async (params) => getVisits(tag, params)); - return { ...state, visits: [...newVisits, ...visits] }; + return [visitsLoader, lastVisitLoader]; }, -}, initialState); + getExtraFulfilledPayload: ({ tag, query = {} }: LoadTagVisits) => ({ tag, query }), + shouldCancel: (getState) => getState().tagVisits.cancelLoad, +}); -export const getTagVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - tag: string, - query: ShlinkVisitsParams = {}, - doIntervalFallback = false, -) => async (dispatch: Dispatch, getState: GetState) => { - const { getTagVisits: getVisits } = buildShlinkApiClient(getState); - const visitsLoader = async (page: number, itemsPerPage: number) => getVisits( - tag, - { ...query, page, itemsPerPage }, - ); - const lastVisitLoader = lastVisitLoaderForLoader(doIntervalFallback, async (params) => getVisits(tag, params)); - const shouldCancel = () => getState().tagVisits.cancelLoad; - const extraFinishActionData: Partial<TagVisitsAction> = { tag, query }; - const actionMap = { - start: GET_TAG_VISITS_START, - large: GET_TAG_VISITS_LARGE, - finish: GET_TAG_VISITS, - error: GET_TAG_VISITS_ERROR, - progress: GET_TAG_VISITS_PROGRESS_CHANGED, - fallbackToInterval: GET_TAG_VISITS_FALLBACK_TO_INTERVAL, - }; - - return getVisitsWithLoader(visitsLoader, lastVisitLoader, extraFinishActionData, actionMap, dispatch, shouldCancel); -}; - -export const cancelGetTagVisits = buildActionCreator(GET_TAG_VISITS_CANCEL); +export const tagVisitsReducerCreator = (asyncThunkCreator: ReturnType<typeof getTagVisits>) => createVisitsReducer({ + name: REDUCER_PREFIX, + initialState, + // @ts-expect-error TODO Fix type inference + asyncThunkCreator, + filterCreatedVisits: ({ tag, query = {} }: TagVisits, createdVisits) => { + const { startDate, endDate } = query; + return createdVisits.filter( + ({ shortUrl, visit }) => shortUrl?.tags.includes(tag) && isBetween(visit.date, startDate, endDate), + ); + }, +}); diff --git a/src/visits/reducers/types/index.ts b/src/visits/reducers/types/index.ts new file mode 100644 index 00000000..f3e0e353 --- /dev/null +++ b/src/visits/reducers/types/index.ts @@ -0,0 +1,26 @@ +import { ShlinkVisitsParams } from '../../../api/types'; +import { DateInterval } from '../../../utils/helpers/dateIntervals'; +import { ProblemDetailsError } from '../../../api/types/errors'; +import { Visit } from '../../types'; + +export interface VisitsInfo { + visits: Visit[]; + loading: boolean; + loadingLarge: boolean; + error: boolean; + errorData?: ProblemDetailsError; + progress: number; + cancelLoad: boolean; + query?: ShlinkVisitsParams; + fallbackInterval?: DateInterval; +} + +export interface LoadVisits { + query?: ShlinkVisitsParams; + doIntervalFallback?: boolean; +} + +export type VisitsLoaded<T = {}> = T & { + visits: Visit[]; + query?: ShlinkVisitsParams; +}; diff --git a/src/visits/reducers/visitCreation.ts b/src/visits/reducers/visitCreation.ts index e2335fc4..eb037bd7 100644 --- a/src/visits/reducers/visitCreation.ts +++ b/src/visits/reducers/visitCreation.ts @@ -1,13 +1,11 @@ -import { Action } from 'redux'; +import { createAction, PayloadAction } from '@reduxjs/toolkit'; import { CreateVisit } from '../types'; -export const CREATE_VISITS = 'shlink/visitCreation/CREATE_VISITS'; - -export interface CreateVisitsAction extends Action<typeof CREATE_VISITS> { +export type CreateVisitsAction = PayloadAction<{ createdVisits: CreateVisit[]; -} +}>; -export const createNewVisits = (createdVisits: CreateVisit[]): CreateVisitsAction => ({ - type: CREATE_VISITS, - createdVisits, -}); +export const createNewVisits = createAction( + 'shlink/visitCreation/createNewVisits', + (createdVisits: CreateVisit[]) => ({ payload: { createdVisits } }), +); diff --git a/src/visits/reducers/visitsOverview.ts b/src/visits/reducers/visitsOverview.ts index ec5d8fec..105bfd2b 100644 --- a/src/visits/reducers/visitsOverview.ts +++ b/src/visits/reducers/visitsOverview.ts @@ -1,14 +1,11 @@ -import { Action, Dispatch } from 'redux'; +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { ShlinkVisitsOverview } from '../../api/types'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { GetState } from '../../container/types'; -import { buildReducer } from '../../utils/helpers/redux'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { groupNewVisitsByType } from '../types/helpers'; -import { CREATE_VISITS, CreateVisitsAction } from './visitCreation'; +import { createNewVisits } from './visitCreation'; -export const GET_OVERVIEW_START = 'shlink/visitsOverview/GET_OVERVIEW_START'; -export const GET_OVERVIEW_ERROR = 'shlink/visitsOverview/GET_OVERVIEW_ERROR'; -export const GET_OVERVIEW = 'shlink/visitsOverview/GET_OVERVIEW'; +const REDUCER_PREFIX = 'shlink/visitsOverview'; export interface VisitsOverview { visitsCount: number; @@ -17,7 +14,7 @@ export interface VisitsOverview { error: boolean; } -export type GetVisitsOverviewAction = ShlinkVisitsOverview & Action<string>; +export type GetVisitsOverviewAction = PayloadAction<ShlinkVisitsOverview>; const initialState: VisitsOverview = { visitsCount: 0, @@ -26,33 +23,30 @@ const initialState: VisitsOverview = { error: false, }; -export default buildReducer<VisitsOverview, GetVisitsOverviewAction & CreateVisitsAction>({ - [GET_OVERVIEW_START]: () => ({ ...initialState, loading: true }), - [GET_OVERVIEW_ERROR]: () => ({ ...initialState, error: true }), - [GET_OVERVIEW]: (_, { visitsCount, orphanVisitsCount }) => ({ ...initialState, visitsCount, orphanVisitsCount }), - [CREATE_VISITS]: ({ visitsCount, orphanVisitsCount = 0, ...rest }, { createdVisits }) => { - const { regularVisits, orphanVisits } = groupNewVisitsByType(createdVisits); +export const loadVisitsOverview = (buildShlinkApiClient: ShlinkApiClientBuilder) => createAsyncThunk( + `${REDUCER_PREFIX}/loadVisitsOverview`, + (_: void, { getState }): Promise<ShlinkVisitsOverview> => buildShlinkApiClient(getState).getVisitsOverview(), +); - return { - ...rest, - visitsCount: visitsCount + regularVisits.length, - orphanVisitsCount: orphanVisitsCount + orphanVisits.length, - }; +export const visitsOverviewReducerCreator = ( + loadVisitsOverviewThunk: ReturnType<typeof loadVisitsOverview>, +) => createSlice({ + name: REDUCER_PREFIX, + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(loadVisitsOverviewThunk.pending, () => ({ ...initialState, loading: true })); + builder.addCase(loadVisitsOverviewThunk.rejected, () => ({ ...initialState, error: true })); + builder.addCase(loadVisitsOverviewThunk.fulfilled, (_, { payload }) => ({ ...initialState, ...payload })); + + builder.addCase(createNewVisits, ({ visitsCount, orphanVisitsCount = 0, ...rest }, { payload }) => { + const { createdVisits } = payload; + const { regularVisits, orphanVisits } = groupNewVisitsByType(createdVisits); + return { + ...rest, + visitsCount: visitsCount + regularVisits.length, + orphanVisitsCount: orphanVisitsCount + orphanVisits.length, + }; + }); }, -}, initialState); - -export const loadVisitsOverview = (buildShlinkApiClient: ShlinkApiClientBuilder) => () => async ( - dispatch: Dispatch, - getState: GetState, -) => { - dispatch({ type: GET_OVERVIEW_START }); - - try { - const { getVisitsOverview } = buildShlinkApiClient(getState); - const result = await getVisitsOverview(); - - dispatch({ type: GET_OVERVIEW, ...result }); - } catch (e) { - dispatch({ type: GET_OVERVIEW_ERROR }); - } -}; +}); diff --git a/src/visits/services/provideServices.ts b/src/visits/services/provideServices.ts index a6b0d931..19cadd4c 100644 --- a/src/visits/services/provideServices.ts +++ b/src/visits/services/provideServices.ts @@ -1,17 +1,18 @@ import Bottle from 'bottlejs'; +import { prop } from 'ramda'; import { MapModal } from '../helpers/MapModal'; import { createNewVisits } from '../reducers/visitCreation'; import { ShortUrlVisits } from '../ShortUrlVisits'; import { TagVisits } from '../TagVisits'; import { OrphanVisits } from '../OrphanVisits'; import { NonOrphanVisits } from '../NonOrphanVisits'; -import { cancelGetShortUrlVisits, getShortUrlVisits } from '../reducers/shortUrlVisits'; -import { cancelGetTagVisits, getTagVisits } from '../reducers/tagVisits'; -import { cancelGetDomainVisits, getDomainVisits } from '../reducers/domainVisits'; -import { cancelGetOrphanVisits, getOrphanVisits } from '../reducers/orphanVisits'; -import { cancelGetNonOrphanVisits, getNonOrphanVisits } from '../reducers/nonOrphanVisits'; +import { getShortUrlVisits, shortUrlVisitsReducerCreator } from '../reducers/shortUrlVisits'; +import { getTagVisits, tagVisitsReducerCreator } from '../reducers/tagVisits'; +import { getDomainVisits, domainVisitsReducerCreator } from '../reducers/domainVisits'; +import { getOrphanVisits, orphanVisitsReducerCreator } from '../reducers/orphanVisits'; +import { getNonOrphanVisits, nonOrphanVisitsReducerCreator } from '../reducers/nonOrphanVisits'; import { ConnectDecorator } from '../../container/types'; -import { loadVisitsOverview } from '../reducers/visitsOverview'; +import { loadVisitsOverview, visitsOverviewReducerCreator } from '../reducers/visitsOverview'; import * as visitsParser from './VisitsParser'; import { DomainVisits } from '../DomainVisits'; @@ -53,23 +54,47 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { bottle.serviceFactory('VisitsParser', () => visitsParser); // Actions - bottle.serviceFactory('getShortUrlVisits', getShortUrlVisits, 'buildShlinkApiClient'); - bottle.serviceFactory('cancelGetShortUrlVisits', () => cancelGetShortUrlVisits); + bottle.serviceFactory('getShortUrlVisitsCreator', getShortUrlVisits, 'buildShlinkApiClient'); + bottle.serviceFactory('getShortUrlVisits', prop('asyncThunk'), 'getShortUrlVisitsCreator'); + bottle.serviceFactory('cancelGetShortUrlVisits', prop('cancelGetVisits'), 'shortUrlVisitsReducerCreator'); - bottle.serviceFactory('getTagVisits', getTagVisits, 'buildShlinkApiClient'); - bottle.serviceFactory('cancelGetTagVisits', () => cancelGetTagVisits); + bottle.serviceFactory('getTagVisitsCreator', getTagVisits, 'buildShlinkApiClient'); + bottle.serviceFactory('getTagVisits', prop('asyncThunk'), 'getTagVisitsCreator'); + bottle.serviceFactory('cancelGetTagVisits', prop('cancelGetVisits'), 'tagVisitsReducerCreator'); - bottle.serviceFactory('getDomainVisits', getDomainVisits, 'buildShlinkApiClient'); - bottle.serviceFactory('cancelGetDomainVisits', () => cancelGetDomainVisits); + bottle.serviceFactory('getDomainVisitsCreator', getDomainVisits, 'buildShlinkApiClient'); + bottle.serviceFactory('getDomainVisits', prop('asyncThunk'), 'getDomainVisitsCreator'); + bottle.serviceFactory('cancelGetDomainVisits', prop('cancelGetVisits'), 'domainVisitsReducerCreator'); - bottle.serviceFactory('getOrphanVisits', getOrphanVisits, 'buildShlinkApiClient'); - bottle.serviceFactory('cancelGetOrphanVisits', () => cancelGetOrphanVisits); + bottle.serviceFactory('getOrphanVisitsCreator', getOrphanVisits, 'buildShlinkApiClient'); + bottle.serviceFactory('getOrphanVisits', prop('asyncThunk'), 'getOrphanVisitsCreator'); + bottle.serviceFactory('cancelGetOrphanVisits', prop('cancelGetVisits'), 'orphanVisitsReducerCreator'); - bottle.serviceFactory('getNonOrphanVisits', getNonOrphanVisits, 'buildShlinkApiClient'); - bottle.serviceFactory('cancelGetNonOrphanVisits', () => cancelGetNonOrphanVisits); + bottle.serviceFactory('getNonOrphanVisitsCreator', getNonOrphanVisits, 'buildShlinkApiClient'); + bottle.serviceFactory('getNonOrphanVisits', prop('asyncThunk'), 'getNonOrphanVisitsCreator'); + bottle.serviceFactory('cancelGetNonOrphanVisits', prop('cancelGetVisits'), 'nonOrphanVisitsReducerCreator'); bottle.serviceFactory('createNewVisits', () => createNewVisits); bottle.serviceFactory('loadVisitsOverview', loadVisitsOverview, 'buildShlinkApiClient'); + + // Reducers + bottle.serviceFactory('visitsOverviewReducerCreator', visitsOverviewReducerCreator, 'loadVisitsOverview'); + bottle.serviceFactory('visitsOverviewReducer', prop('reducer'), 'visitsOverviewReducerCreator'); + + bottle.serviceFactory('domainVisitsReducerCreator', domainVisitsReducerCreator, 'getDomainVisitsCreator'); + bottle.serviceFactory('domainVisitsReducer', prop('reducer'), 'domainVisitsReducerCreator'); + + bottle.serviceFactory('nonOrphanVisitsReducerCreator', nonOrphanVisitsReducerCreator, 'getNonOrphanVisitsCreator'); + bottle.serviceFactory('nonOrphanVisitsReducer', prop('reducer'), 'nonOrphanVisitsReducerCreator'); + + bottle.serviceFactory('orphanVisitsReducerCreator', orphanVisitsReducerCreator, 'getOrphanVisitsCreator'); + bottle.serviceFactory('orphanVisitsReducer', prop('reducer'), 'orphanVisitsReducerCreator'); + + bottle.serviceFactory('shortUrlVisitsReducerCreator', shortUrlVisitsReducerCreator, 'getShortUrlVisitsCreator'); + bottle.serviceFactory('shortUrlVisitsReducer', prop('reducer'), 'shortUrlVisitsReducerCreator'); + + bottle.serviceFactory('tagVisitsReducerCreator', tagVisitsReducerCreator, 'getTagVisitsCreator'); + bottle.serviceFactory('tagVisitsReducer', prop('reducer'), 'tagVisitsReducerCreator'); }; export default provideServices; diff --git a/src/visits/types/index.ts b/src/visits/types/index.ts index 03789a28..14b844f1 100644 --- a/src/visits/types/index.ts +++ b/src/visits/types/index.ts @@ -1,27 +1,5 @@ -import { Action } from 'redux'; import { ShortUrl } from '../../short-urls/data'; -import { ProblemDetailsError, ShlinkVisitsParams } from '../../api/types'; -import { DateInterval, DateRange } from '../../utils/dates/types'; - -export interface VisitsInfo { - visits: Visit[]; - loading: boolean; - loadingLarge: boolean; - error: boolean; - errorData?: ProblemDetailsError; - progress: number; - cancelLoad: boolean; - query?: ShlinkVisitsParams; - fallbackInterval?: DateInterval; -} - -export interface VisitsLoadProgressChangedAction extends Action<string> { - progress: number; -} - -export interface VisitsFallbackIntervalAction extends Action<string> { - fallbackInterval: DateInterval; -} +import { DateRange } from '../../utils/helpers/dateIntervals'; export type OrphanVisitType = 'base_url' | 'invalid_short_url' | 'regular_404'; diff --git a/test/__helpers__/TestModalWrapper.tsx b/test/__helpers__/TestModalWrapper.tsx new file mode 100644 index 00000000..e2364192 --- /dev/null +++ b/test/__helpers__/TestModalWrapper.tsx @@ -0,0 +1,14 @@ +import { FC, ReactElement } from 'react'; +import { useToggle } from '../../src/utils/helpers/hooks'; + +interface RenderModalArgs { + isOpen: boolean; + toggle: () => void; +} + +export const TestModalWrapper: FC<{ renderModal: (args: RenderModalArgs) => ReactElement }> = ( + { renderModal }, +) => { + const [isOpen, toggle] = useToggle(true); + return renderModal({ isOpen, toggle }); +}; diff --git a/test/api/ShlinkApiError.test.tsx b/test/api/ShlinkApiError.test.tsx index fe04fe47..a7aaebc1 100644 --- a/test/api/ShlinkApiError.test.tsx +++ b/test/api/ShlinkApiError.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react'; import { Mock } from 'ts-mockery'; import { ShlinkApiError, ShlinkApiErrorProps } from '../../src/api/ShlinkApiError'; -import { InvalidArgumentError, ProblemDetailsError } from '../../src/api/types'; +import { ErrorTypeV2, ErrorTypeV3, InvalidArgumentError, ProblemDetailsError } from '../../src/api/types/errors'; describe('<ShlinkApiError />', () => { const setUp = (props: ShlinkApiErrorProps) => render(<ShlinkApiError {...props} />); @@ -20,7 +20,8 @@ describe('<ShlinkApiError />', () => { it.each([ [undefined, 0], [Mock.all<ProblemDetailsError>(), 0], - [Mock.of<InvalidArgumentError>({ type: 'INVALID_ARGUMENT', invalidElements: [] }), 1], + [Mock.of<InvalidArgumentError>({ type: ErrorTypeV2.INVALID_ARGUMENT, invalidElements: [] }), 1], + [Mock.of<InvalidArgumentError>({ type: ErrorTypeV3.INVALID_ARGUMENT, invalidElements: [] }), 1], ])('renders list of invalid elements when provided error is an InvalidError', (errorData, expectedElementsCount) => { setUp({ errorData }); expect(screen.queryAllByText(/^Invalid elements/)).toHaveLength(expectedElementsCount); diff --git a/test/api/services/ShlinkApiClient.test.ts b/test/api/services/ShlinkApiClient.test.ts index f5f7b647..0b15299e 100644 --- a/test/api/services/ShlinkApiClient.test.ts +++ b/test/api/services/ShlinkApiClient.test.ts @@ -1,30 +1,30 @@ -import { AxiosInstance, AxiosRequestConfig } from 'axios'; import { Mock } from 'ts-mockery'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { OptionalString } from '../../../src/utils/utils'; -import { ShlinkDomain, ShlinkVisitsOverview } from '../../../src/api/types'; +import { ShlinkDomain, ShlinkVisits, ShlinkVisitsOverview } from '../../../src/api/types'; import { ShortUrl, ShortUrlsOrder } from '../../../src/short-urls/data'; -import { Visit } from '../../../src/visits/types'; +import { ErrorTypeV2, ErrorTypeV3 } from '../../../src/api/types/errors'; +import { HttpClient } from '../../../src/common/services/HttpClient'; describe('ShlinkApiClient', () => { - const createAxios = (data: AxiosRequestConfig) => (async () => Promise.resolve(data)) as unknown as AxiosInstance; - const createAxiosMock = (data: AxiosRequestConfig = {}) => jest.fn(createAxios(data)) as unknown as AxiosInstance; - const createApiClient = (data: AxiosRequestConfig) => new ShlinkApiClient(createAxios(data), '', ''); - const shortCodesWithDomainCombinations: [ string, OptionalString ][] = [ + const fetchJson = jest.fn().mockResolvedValue({}); + const fetchEmpty = jest.fn().mockResolvedValue(undefined); + const httpClient = Mock.of<HttpClient>({ fetchJson, fetchEmpty }); + const buildApiClient = () => new ShlinkApiClient(httpClient, '', ''); + const shortCodesWithDomainCombinations: [string, OptionalString][] = [ ['abc123', null], ['abc123', undefined], ['abc123', 'example.com'], ]; + beforeEach(jest.clearAllMocks); + describe('listShortUrls', () => { const expectedList = ['foo', 'bar']; it('properly returns short URLs list', async () => { - const { listShortUrls } = createApiClient({ - data: { - shortUrls: expectedList, - }, - }); + fetchJson.mockResolvedValue({ shortUrls: expectedList }); + const { listShortUrls } = buildApiClient(); const actualList = await listShortUrls(); @@ -32,20 +32,19 @@ describe('ShlinkApiClient', () => { }); it.each([ - [{ field: 'visits', dir: 'DESC' } as ShortUrlsOrder, 'visits-DESC'], - [{ field: 'longUrl', dir: 'ASC' } as ShortUrlsOrder, 'longUrl-ASC'], - [{ field: 'longUrl', dir: undefined } as ShortUrlsOrder, undefined], + [{ field: 'visits', dir: 'DESC' } as ShortUrlsOrder, '?orderBy=visits-DESC'], + [{ field: 'longUrl', dir: 'ASC' } as ShortUrlsOrder, '?orderBy=longUrl-ASC'], + [{ field: 'longUrl', dir: undefined } as ShortUrlsOrder, ''], ])('parses orderBy in params', async (orderBy, expectedOrderBy) => { - const axiosSpy = createAxiosMock({ - data: expectedList, - }); - const { listShortUrls } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue({ data: expectedList }); + const { listShortUrls } = buildApiClient(); await listShortUrls({ orderBy }); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ - params: { orderBy: expectedOrderBy }, - })); + expect(fetchJson).toHaveBeenCalledWith( + expect.stringContaining(`/short-urls${expectedOrderBy}`), + expect.anything(), + ); }); }); @@ -55,61 +54,59 @@ describe('ShlinkApiClient', () => { }; it('returns create short URL', async () => { - const { createShortUrl } = createApiClient({ data: shortUrl }); + fetchJson.mockResolvedValue(shortUrl); + const { createShortUrl } = buildApiClient(); const result = await createShortUrl({ longUrl: '' }); expect(result).toEqual(shortUrl); }); it('removes all empty options', async () => { - const axiosSpy = createAxiosMock({ data: shortUrl }); - const { createShortUrl } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue({ data: shortUrl }); + const { createShortUrl } = buildApiClient(); await createShortUrl({ longUrl: 'bar', customSlug: undefined, maxVisits: null }); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ data: { longUrl: 'bar' } })); + expect(fetchJson).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ + body: JSON.stringify({ longUrl: 'bar' }), + })); }); }); describe('getShortUrlVisits', () => { it('properly returns short URL visits', async () => { const expectedVisits = ['foo', 'bar']; - const axiosSpy = createAxiosMock({ - data: { - visits: { - data: expectedVisits, - }, + fetchJson.mockResolvedValue({ + visits: { + data: expectedVisits, }, }); - const { getShortUrlVisits } = new ShlinkApiClient(axiosSpy, '', ''); + const { getShortUrlVisits } = buildApiClient(); const actualVisits = await getShortUrlVisits('abc123', {}); expect({ data: expectedVisits }).toEqual(actualVisits); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ - url: '/short-urls/abc123/visits', - method: 'GET', - })); + expect(fetchJson).toHaveBeenCalledWith( + expect.stringContaining('/short-urls/abc123/visits'), + expect.objectContaining({ method: 'GET' }), + ); }); }); describe('getTagVisits', () => { it('properly returns tag visits', async () => { const expectedVisits = ['foo', 'bar']; - const axiosSpy = createAxiosMock({ - data: { - visits: { - data: expectedVisits, - }, + fetchJson.mockResolvedValue({ + visits: { + data: expectedVisits, }, }); - const { getTagVisits } = new ShlinkApiClient(axiosSpy, '', ''); + const { getTagVisits } = buildApiClient(); const actualVisits = await getTagVisits('foo', {}); expect({ data: expectedVisits }).toEqual(actualVisits); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ - url: '/tags/foo/visits', + expect(fetchJson).toHaveBeenCalledWith(expect.stringContaining('/tags/foo/visits'), expect.objectContaining({ method: 'GET', })); }); @@ -118,41 +115,37 @@ describe('ShlinkApiClient', () => { describe('getDomainVisits', () => { it('properly returns domain visits', async () => { const expectedVisits = ['foo', 'bar']; - const axiosSpy = createAxiosMock({ - data: { - visits: { - data: expectedVisits, - }, + fetchJson.mockResolvedValue({ + visits: { + data: expectedVisits, }, }); - const { getDomainVisits } = new ShlinkApiClient(axiosSpy, '', ''); + const { getDomainVisits } = buildApiClient(); const actualVisits = await getDomainVisits('foo.com', {}); expect({ data: expectedVisits }).toEqual(actualVisits); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ - url: '/domains/foo.com/visits', - method: 'GET', - })); + expect(fetchJson).toHaveBeenCalledWith( + expect.stringContaining('/domains/foo.com/visits'), + expect.objectContaining({ method: 'GET' }), + ); }); }); describe('getShortUrl', () => { it.each(shortCodesWithDomainCombinations)('properly returns short URL', async (shortCode, domain) => { const expectedShortUrl = { foo: 'bar' }; - const axiosSpy = createAxiosMock({ - data: expectedShortUrl, - }); - const { getShortUrl } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue(expectedShortUrl); + const { getShortUrl } = buildApiClient(); + const expectedQuery = domain ? `?domain=${domain}` : ''; const result = await getShortUrl(shortCode, domain); expect(expectedShortUrl).toEqual(result); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ - url: `/short-urls/${shortCode}`, - method: 'GET', - params: domain ? { domain } : {}, - })); + expect(fetchJson).toHaveBeenCalledWith( + expect.stringContaining(`/short-urls/${shortCode}${expectedQuery}`), + expect.objectContaining({ method: 'GET' }), + ); }); }); @@ -163,50 +156,51 @@ describe('ShlinkApiClient', () => { validSince: '2025-01-01T10:00:00+01:00', }; const expectedResp = Mock.of<ShortUrl>(); - const axiosSpy = createAxiosMock({ data: expectedResp }); - const { updateShortUrl } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue(expectedResp); + const { updateShortUrl } = buildApiClient(); + const expectedQuery = domain ? `?domain=${domain}` : ''; const result = await updateShortUrl(shortCode, domain, meta); expect(expectedResp).toEqual(result); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ - url: `/short-urls/${shortCode}`, - method: 'PATCH', - params: domain ? { domain } : {}, - })); + expect(fetchJson).toHaveBeenCalledWith( + expect.stringContaining(`/short-urls/${shortCode}${expectedQuery}`), + expect.objectContaining({ method: 'PATCH' }), + ); }); }); describe('listTags', () => { it('properly returns list of tags', async () => { const expectedTags = ['foo', 'bar']; - const axiosSpy = createAxiosMock({ - data: { - tags: { data: expectedTags }, + fetchJson.mockResolvedValue({ + tags: { + data: expectedTags, }, }); - const { listTags } = new ShlinkApiClient(axiosSpy, '', ''); + const { listTags } = buildApiClient(); const result = await listTags(); expect({ tags: expectedTags }).toEqual(result); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ url: '/tags', method: 'GET' })); + expect(fetchJson).toHaveBeenCalledWith( + expect.stringContaining('/tags'), + expect.objectContaining({ method: 'GET' }), + ); }); }); describe('deleteTags', () => { it('properly deletes provided tags', async () => { const tags = ['foo', 'bar']; - const axiosSpy = createAxiosMock(); - const { deleteTags } = new ShlinkApiClient(axiosSpy, '', ''); + const { deleteTags } = buildApiClient(); await deleteTags(tags); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ - url: '/tags', - method: 'DELETE', - params: { tags }, - })); + expect(fetchEmpty).toHaveBeenCalledWith( + expect.stringContaining(`/tags?${tags.map((tag) => `tags%5B%5D=${tag}`).join('&')}`), + expect.objectContaining({ method: 'DELETE' }), + ); }); }); @@ -214,31 +208,28 @@ describe('ShlinkApiClient', () => { it('properly edits provided tag', async () => { const oldName = 'foo'; const newName = 'bar'; - const axiosSpy = createAxiosMock(); - const { editTag } = new ShlinkApiClient(axiosSpy, '', ''); + const { editTag } = buildApiClient(); await editTag(oldName, newName); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ - url: '/tags', + expect(fetchEmpty).toHaveBeenCalledWith(expect.stringContaining('/tags'), expect.objectContaining({ method: 'PUT', - data: { oldName, newName }, + body: JSON.stringify({ oldName, newName }), })); }); }); describe('deleteShortUrl', () => { it.each(shortCodesWithDomainCombinations)('properly deletes provided short URL', async (shortCode, domain) => { - const axiosSpy = createAxiosMock({}); - const { deleteShortUrl } = new ShlinkApiClient(axiosSpy, '', ''); + const { deleteShortUrl } = buildApiClient(); + const expectedQuery = domain ? `?domain=${domain}` : ''; await deleteShortUrl(shortCode, domain); - expect(axiosSpy).toHaveBeenCalledWith(expect.objectContaining({ - url: `/short-urls/${shortCode}`, - method: 'DELETE', - params: domain ? { domain } : {}, - })); + expect(fetchEmpty).toHaveBeenCalledWith( + expect.stringContaining(`/short-urls/${shortCode}${expectedQuery}`), + expect.objectContaining({ method: 'DELETE' }), + ); }); }); @@ -248,12 +239,12 @@ describe('ShlinkApiClient', () => { status: 'pass', version: '1.19.0', }; - const axiosSpy = createAxiosMock({ data: expectedData }); - const { health } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue(expectedData); + const { health } = buildApiClient(); const result = await health(); - expect(axiosSpy).toHaveBeenCalled(); + expect(fetchJson).toHaveBeenCalled(); expect(result).toEqual(expectedData); }); }); @@ -264,12 +255,12 @@ describe('ShlinkApiClient', () => { token: 'abc.123.def', mercureHubUrl: 'http://example.com/.well-known/mercure', }; - const axiosSpy = createAxiosMock({ data: expectedData }); - const { mercureInfo } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue(expectedData); + const { mercureInfo } = buildApiClient(); const result = await mercureInfo(); - expect(axiosSpy).toHaveBeenCalled(); + expect(fetchJson).toHaveBeenCalled(); expect(result).toEqual(expectedData); }); }); @@ -277,13 +268,12 @@ describe('ShlinkApiClient', () => { describe('listDomains', () => { it('returns domains', async () => { const expectedData = { data: [Mock.all<ShlinkDomain>(), Mock.all<ShlinkDomain>()] }; - const resp = { domains: expectedData }; - const axiosSpy = createAxiosMock({ data: resp }); - const { listDomains } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue({ domains: expectedData }); + const { listDomains } = buildApiClient(); const result = await listDomains(); - expect(axiosSpy).toHaveBeenCalled(); + expect(fetchJson).toHaveBeenCalled(); expect(result).toEqual(expectedData); }); }); @@ -291,55 +281,67 @@ describe('ShlinkApiClient', () => { describe('getVisitsOverview', () => { it('returns visits overview', async () => { const expectedData = Mock.all<ShlinkVisitsOverview>(); - const resp = { visits: expectedData }; - const axiosSpy = createAxiosMock({ data: resp }); - const { getVisitsOverview } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue({ visits: expectedData }); + const { getVisitsOverview } = buildApiClient(); const result = await getVisitsOverview(); - expect(axiosSpy).toHaveBeenCalled(); + expect(fetchJson).toHaveBeenCalled(); expect(result).toEqual(expectedData); }); }); describe('getOrphanVisits', () => { it('returns orphan visits', async () => { - const expectedData: Visit[] = []; - const resp = { visits: expectedData }; - const axiosSpy = createAxiosMock({ data: resp }); - const { getOrphanVisits } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue({ visits: Mock.of<ShlinkVisits>({ data: [] }) }); + const { getOrphanVisits } = buildApiClient(); const result = await getOrphanVisits(); - expect(axiosSpy).toHaveBeenCalled(); - expect(result).toEqual(expectedData); + expect(fetchJson).toHaveBeenCalled(); + expect(result).toEqual({ data: [] }); }); }); describe('getNonOrphanVisits', () => { it('returns non-orphan visits', async () => { - const expectedData: Visit[] = []; - const resp = { visits: expectedData }; - const axiosSpy = createAxiosMock({ data: resp }); - const { getNonOrphanVisits } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue({ visits: Mock.of<ShlinkVisits>({ data: [] }) }); + const { getNonOrphanVisits } = buildApiClient(); const result = await getNonOrphanVisits(); - expect(axiosSpy).toHaveBeenCalled(); - expect(result).toEqual(expectedData); + expect(fetchJson).toHaveBeenCalled(); + expect(result).toEqual({ data: [] }); }); }); describe('editDomainRedirects', () => { it('returns the redirects', async () => { const resp = { baseUrlRedirect: null, regular404Redirect: 'foo', invalidShortUrlRedirect: 'bar' }; - const axiosSpy = createAxiosMock({ data: resp }); - const { editDomainRedirects } = new ShlinkApiClient(axiosSpy, '', ''); + fetchJson.mockResolvedValue(resp); + const { editDomainRedirects } = buildApiClient(); const result = await editDomainRedirects({ domain: 'foo' }); - expect(axiosSpy).toHaveBeenCalled(); + expect(fetchJson).toHaveBeenCalled(); expect(result).toEqual(resp); }); + + it.each([ + ['NOT_FOUND'], + [ErrorTypeV2.NOT_FOUND], + [ErrorTypeV3.NOT_FOUND], + ])('retries request if API version is not supported', async (type) => { + fetchJson + .mockRejectedValueOnce({ type, detail: 'detail', title: 'title', status: 404 }) + .mockResolvedValue({}); + const { editDomainRedirects } = buildApiClient(); + + await editDomainRedirects({ domain: 'foo' }); + + expect(fetchJson).toHaveBeenCalledTimes(2); + expect(fetchJson).toHaveBeenNthCalledWith(1, expect.stringContaining('/v3/'), expect.anything()); + expect(fetchJson).toHaveBeenNthCalledWith(2, expect.stringContaining('/v2/'), expect.anything()); + }); }); }); diff --git a/test/api/services/ShlinkApiClientBuilder.test.ts b/test/api/services/ShlinkApiClientBuilder.test.ts index b67bd7e6..18c29ebf 100644 --- a/test/api/services/ShlinkApiClientBuilder.test.ts +++ b/test/api/services/ShlinkApiClientBuilder.test.ts @@ -1,16 +1,14 @@ import { Mock } from 'ts-mockery'; -import { AxiosInstance } from 'axios'; import { buildShlinkApiClient } from '../../../src/api/services/ShlinkApiClientBuilder'; import { ReachableServer, SelectedServer } from '../../../src/servers/data'; import { ShlinkState } from '../../../src/container/types'; +import { HttpClient } from '../../../src/common/services/HttpClient'; describe('ShlinkApiClientBuilder', () => { - const axiosMock = Mock.all<AxiosInstance>(); const server = (data: Partial<ReachableServer>) => Mock.of<ReachableServer>(data); const createBuilder = () => { - const builder = buildShlinkApiClient(axiosMock); - + const builder = buildShlinkApiClient(Mock.of<HttpClient>()); return (selectedServer: SelectedServer) => builder(() => Mock.of<ShlinkState>({ selectedServer })); }; @@ -44,7 +42,7 @@ describe('ShlinkApiClientBuilder', () => { it('does not fetch from state when provided param is already selected server', () => { const url = 'url'; const apiKey = 'apiKey'; - const apiClient = buildShlinkApiClient(axiosMock)(server({ url, apiKey })); + const apiClient = buildShlinkApiClient(Mock.of<HttpClient>())(server({ url, apiKey })); expect(apiClient['baseUrl']).toEqual(url); // eslint-disable-line @typescript-eslint/dot-notation expect(apiClient['apiKey']).toEqual(apiKey); // eslint-disable-line @typescript-eslint/dot-notation diff --git a/test/app/reducers/appUpdates.test.ts b/test/app/reducers/appUpdates.test.ts index 82a11f91..32070612 100644 --- a/test/app/reducers/appUpdates.test.ts +++ b/test/app/reducers/appUpdates.test.ts @@ -1,30 +1,25 @@ -import reducer, { - APP_UPDATE_AVAILABLE, - RESET_APP_UPDATE, - appUpdateAvailable, - resetAppUpdate, -} from '../../../src/app/reducers/appUpdates'; +import { appUpdatesReducer, appUpdateAvailable, resetAppUpdate } from '../../../src/app/reducers/appUpdates'; describe('appUpdatesReducer', () => { describe('reducer', () => { it('returns true on APP_UPDATE_AVAILABLE', () => { - expect(reducer(undefined, { type: APP_UPDATE_AVAILABLE })).toEqual(true); + expect(appUpdatesReducer(undefined, { type: appUpdateAvailable.toString() })).toEqual(true); }); it('returns false on RESET_APP_UPDATE', () => { - expect(reducer(undefined, { type: RESET_APP_UPDATE })).toEqual(false); + expect(appUpdatesReducer(undefined, { type: resetAppUpdate.toString() })).toEqual(false); }); }); describe('appUpdateAvailable', () => { it('creates expected action', () => { - expect(appUpdateAvailable()).toEqual({ type: APP_UPDATE_AVAILABLE }); + expect(appUpdateAvailable()).toEqual({ type: appUpdateAvailable.toString() }); }); }); describe('resetAppUpdate', () => { it('creates expected action', () => { - expect(resetAppUpdate()).toEqual({ type: RESET_APP_UPDATE }); + expect(resetAppUpdate()).toEqual({ type: resetAppUpdate.toString() }); }); }); }); diff --git a/test/common/reducer/sidebar.test.ts b/test/common/reducer/sidebar.test.ts index ecaa95da..db59f510 100644 --- a/test/common/reducer/sidebar.test.ts +++ b/test/common/reducer/sidebar.test.ts @@ -1,31 +1,24 @@ -import { Mock } from 'ts-mockery'; -import reducer, { - Sidebar, - SIDEBAR_NOT_PRESENT, - SIDEBAR_PRESENT, - sidebarNotPresent, - sidebarPresent, -} from '../../../src/common/reducers/sidebar'; +import { sidebarReducer, sidebarNotPresent, sidebarPresent } from '../../../src/common/reducers/sidebar'; describe('sidebarReducer', () => { describe('reducer', () => { it.each([ - [SIDEBAR_PRESENT, { sidebarPresent: true }], - [SIDEBAR_NOT_PRESENT, { sidebarPresent: false }], + [sidebarPresent.toString(), { sidebarPresent: true }], + [sidebarNotPresent.toString(), { sidebarPresent: false }], ])('returns expected on %s', (type, expected) => { - expect(reducer(Mock.all<Sidebar>(), { type })).toEqual(expected); + expect(sidebarReducer(undefined, { type })).toEqual(expected); }); }); describe('sidebarPresent', () => { it('returns expected action', () => { - expect(sidebarPresent()).toEqual({ type: SIDEBAR_PRESENT }); + expect(sidebarPresent()).toEqual({ type: sidebarPresent.toString() }); }); }); describe('sidebarNotPresent', () => { it('returns expected action', () => { - expect(sidebarNotPresent()).toEqual({ type: SIDEBAR_NOT_PRESENT }); + expect(sidebarNotPresent()).toEqual({ type: sidebarNotPresent.toString() }); }); }); }); diff --git a/test/common/services/HttpClient.test.ts b/test/common/services/HttpClient.test.ts new file mode 100644 index 00000000..b894cd32 --- /dev/null +++ b/test/common/services/HttpClient.test.ts @@ -0,0 +1,54 @@ +import { HttpClient } from '../../../src/common/services/HttpClient'; + +describe('HttpClient', () => { + const fetch = jest.fn(); + const httpClient = new HttpClient(fetch); + + beforeEach(jest.clearAllMocks); + + describe('fetchJson', () => { + it('throws json on success', async () => { + const theError = { error: true, foo: 'bar' }; + fetch.mockResolvedValue({ json: () => theError, ok: false }); + + await expect(httpClient.fetchJson('')).rejects.toEqual(theError); + }); + + it('return json on failure', async () => { + const theJson = { foo: 'bar' }; + fetch.mockResolvedValue({ json: () => theJson, ok: true }); + + const result = await httpClient.fetchJson(''); + + expect(result).toEqual(theJson); + }); + }); + + describe('fetchEmpty', () => { + it('returns empty on success', async () => { + fetch.mockResolvedValue({ ok: true }); + + const result = await httpClient.fetchEmpty(''); + + expect(result).not.toBeDefined(); + }); + + it('throws error on failure', async () => { + const theError = { error: true, foo: 'bar' }; + fetch.mockResolvedValue({ json: () => theError, ok: false }); + + await expect(httpClient.fetchJson('')).rejects.toEqual(theError); + }); + }); + + describe('fetchBlob', () => { + it('returns response as blob', async () => { + const theBlob = new Blob(); + fetch.mockResolvedValue({ blob: () => theBlob }); + + const result = await httpClient.fetchBlob(''); + + expect(result).toEqual(theBlob); + }); + }); +}); diff --git a/test/common/services/ImageDownloader.test.ts b/test/common/services/ImageDownloader.test.ts index 20a381cf..e33c4ecf 100644 --- a/test/common/services/ImageDownloader.test.ts +++ b/test/common/services/ImageDownloader.test.ts @@ -1,25 +1,25 @@ import { Mock } from 'ts-mockery'; -import { AxiosInstance } from 'axios'; import { ImageDownloader } from '../../../src/common/services/ImageDownloader'; +import { HttpClient } from '../../../src/common/services/HttpClient'; import { windowMock } from '../../__mocks__/Window.mock'; describe('ImageDownloader', () => { - const get = jest.fn(); - const axios = Mock.of<AxiosInstance>({ get }); + const fetchBlob = jest.fn(); + const httpClient = Mock.of<HttpClient>({ fetchBlob }); let imageDownloader: ImageDownloader; beforeEach(() => { jest.clearAllMocks(); (global as any).URL = { createObjectURL: () => '' }; - imageDownloader = new ImageDownloader(axios, windowMock); + imageDownloader = new ImageDownloader(httpClient, windowMock); }); it('calls URL with response type blob', async () => { - get.mockResolvedValue({ data: {} }); + fetchBlob.mockResolvedValue(new Blob()); await imageDownloader.saveImage('/foo/bar.png', 'my-image.png'); - expect(get).toHaveBeenCalledWith('/foo/bar.png', { responseType: 'blob' }); + expect(fetchBlob).toHaveBeenCalledWith('/foo/bar.png'); }); }); diff --git a/test/domains/ManageDomains.test.tsx b/test/domains/ManageDomains.test.tsx index 509ee2c7..4726ed4e 100644 --- a/test/domains/ManageDomains.test.tsx +++ b/test/domains/ManageDomains.test.tsx @@ -2,9 +2,10 @@ import { screen, waitFor } from '@testing-library/react'; import { Mock } from 'ts-mockery'; import { DomainsList } from '../../src/domains/reducers/domainsList'; import { ManageDomains } from '../../src/domains/ManageDomains'; -import { ProblemDetailsError, ShlinkDomain } from '../../src/api/types'; +import { ShlinkDomain } from '../../src/api/types'; import { SelectedServer } from '../../src/servers/data'; import { renderWithEvents } from '../__helpers__/setUpTest'; +import { ProblemDetailsError } from '../../src/api/types/errors'; describe('<ManageDomains />', () => { const listDomains = jest.fn(); diff --git a/test/domains/helpers/DomainDropdown.test.tsx b/test/domains/helpers/DomainDropdown.test.tsx index 90b5658b..1efd1a5e 100644 --- a/test/domains/helpers/DomainDropdown.test.tsx +++ b/test/domains/helpers/DomainDropdown.test.tsx @@ -71,7 +71,7 @@ describe('<DomainDropdown />', () => { expect(editDomainRedirects).not.toHaveBeenCalled(); await user.click(screen.getByText('Save')); - expect(editDomainRedirects).toHaveBeenCalledWith(domain, expect.anything()); + expect(editDomainRedirects).toHaveBeenCalledWith(expect.objectContaining({ domain })); await waitForElementToBeRemoved(() => screen.queryByRole('dialog')); }); diff --git a/test/domains/helpers/EditDomainRedirectsModal.test.tsx b/test/domains/helpers/EditDomainRedirectsModal.test.tsx index 6f402350..a83ddcbb 100644 --- a/test/domains/helpers/EditDomainRedirectsModal.test.tsx +++ b/test/domains/helpers/EditDomainRedirectsModal.test.tsx @@ -40,37 +40,49 @@ describe('<EditDomainRedirectsModal />', () => { expect(editDomainRedirects).not.toHaveBeenCalled(); submitForm(); - await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith('foo.com', { - baseUrlRedirect: 'baz', - regular404Redirect: null, - invalidShortUrlRedirect: null, + await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith({ + domain: 'foo.com', + redirects: { + baseUrlRedirect: 'baz', + regular404Redirect: null, + invalidShortUrlRedirect: null, + }, })); await user.clear(screen.getByDisplayValue('baz')); await user.type(screen.getAllByPlaceholderText('No redirect')[0], 'new_base_url'); await user.type(screen.getAllByPlaceholderText('No redirect')[2], 'new_invalid_short_url'); submitForm(); - await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith('foo.com', { - baseUrlRedirect: 'new_base_url', - regular404Redirect: null, - invalidShortUrlRedirect: 'new_invalid_short_url', + await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith({ + domain: 'foo.com', + redirects: { + baseUrlRedirect: 'new_base_url', + regular404Redirect: null, + invalidShortUrlRedirect: 'new_invalid_short_url', + }, })); await user.type(screen.getAllByPlaceholderText('No redirect')[1], 'new_regular_404'); await user.clear(screen.getByDisplayValue('new_invalid_short_url')); submitForm(); - await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith('foo.com', { - baseUrlRedirect: 'new_base_url', - regular404Redirect: 'new_regular_404', - invalidShortUrlRedirect: null, + await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith({ + domain: 'foo.com', + redirects: { + baseUrlRedirect: 'new_base_url', + regular404Redirect: 'new_regular_404', + invalidShortUrlRedirect: null, + }, })); await Promise.all(screen.getAllByPlaceholderText('No redirect').map((element) => user.clear(element))); submitForm(); - await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith('foo.com', { - baseUrlRedirect: null, - regular404Redirect: null, - invalidShortUrlRedirect: null, + await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith({ + domain: 'foo.com', + redirects: { + baseUrlRedirect: null, + regular404Redirect: null, + invalidShortUrlRedirect: null, + }, })); }); }); diff --git a/test/domains/helpers/__snapshots__/DomainStatusIcon.test.tsx.snap b/test/domains/helpers/__snapshots__/DomainStatusIcon.test.tsx.snap index 0b4d6173..7513f536 100644 --- a/test/domains/helpers/__snapshots__/DomainStatusIcon.test.tsx.snap +++ b/test/domains/helpers/__snapshots__/DomainStatusIcon.test.tsx.snap @@ -12,7 +12,7 @@ exports[`<DomainStatusIcon /> renders expected icon and tooltip when status is n xmlns="http://www.w3.org/2000/svg" > <path - d="M222.7 32.15C227.7 49.08 218.1 66.9 201.1 71.94C121.8 95.55 64 169.1 64 255.1C64 362 149.1 447.1 256 447.1C362 447.1 448 362 448 255.1C448 169.1 390.2 95.55 310.9 71.94C293.9 66.9 284.3 49.08 289.3 32.15C294.4 15.21 312.2 5.562 329.1 10.6C434.9 42.07 512 139.1 512 255.1C512 397.4 397.4 511.1 256 511.1C114.6 511.1 0 397.4 0 255.1C0 139.1 77.15 42.07 182.9 10.6C199.8 5.562 217.6 15.21 222.7 32.15V32.15z" + d="M222.7 32.1c5 16.9-4.6 34.8-21.5 39.8C121.8 95.6 64 169.1 64 256c0 106 86 192 192 192s192-86 192-192c0-86.9-57.8-160.4-137.1-184.1c-16.9-5-26.6-22.9-21.5-39.8s22.9-26.6 39.8-21.5C434.9 42.1 512 140 512 256c0 141.4-114.6 256-256 256S0 397.4 0 256C0 140 77.1 42.1 182.9 10.6c16.9-5 34.8 4.6 39.8 21.5z" fill="currentColor" /> </svg> @@ -31,7 +31,7 @@ exports[`<DomainStatusIcon /> renders expected icon and tooltip when status is n xmlns="http://www.w3.org/2000/svg" > <path - d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z" + d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z" fill="currentColor" /> </svg> @@ -47,11 +47,11 @@ exports[`<DomainStatusIcon /> renders expected icon and tooltip when status is n data-prefix="fas" focusable="false" role="img" - viewBox="0 0 448 512" + viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" > <path - d="M438.6 105.4C451.1 117.9 451.1 138.1 438.6 150.6L182.6 406.6C170.1 419.1 149.9 419.1 137.4 406.6L9.372 278.6C-3.124 266.1-3.124 245.9 9.372 233.4C21.87 220.9 42.13 220.9 54.63 233.4L159.1 338.7L393.4 105.4C405.9 92.88 426.1 92.88 438.6 105.4H438.6z" + d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z" fill="currentColor" /> </svg> diff --git a/test/domains/reducers/domainRedirects.test.ts b/test/domains/reducers/domainRedirects.test.ts index f77f8377..567e0c1f 100644 --- a/test/domains/reducers/domainRedirects.test.ts +++ b/test/domains/reducers/domainRedirects.test.ts @@ -1,11 +1,6 @@ import { Mock } from 'ts-mockery'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; -import { - EDIT_DOMAIN_REDIRECTS, - EDIT_DOMAIN_REDIRECTS_ERROR, - EDIT_DOMAIN_REDIRECTS_START, - editDomainRedirects as editDomainRedirectsAction, -} from '../../../src/domains/reducers/domainRedirects'; +import { EditDomainRedirects, editDomainRedirects } from '../../../src/domains/reducers/domainRedirects'; import { ShlinkDomainRedirects } from '../../../src/api/types'; describe('domainRedirectsReducer', () => { @@ -16,29 +11,33 @@ describe('domainRedirectsReducer', () => { const redirects = Mock.all<ShlinkDomainRedirects>(); const dispatch = jest.fn(); const getState = jest.fn(); - const editDomainRedirects = jest.fn(); - const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ editDomainRedirects }); + const editDomainRedirectsCall = jest.fn(); + const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ editDomainRedirects: editDomainRedirectsCall }); + const editDomainRedirectsAction = editDomainRedirects(buildShlinkApiClient); it('dispatches error when loading domains fails', async () => { - editDomainRedirects.mockRejectedValue(new Error('error')); + editDomainRedirectsCall.mockRejectedValue(new Error('error')); - await editDomainRedirectsAction(buildShlinkApiClient)(domain, {})(dispatch, getState); + await editDomainRedirectsAction(Mock.of<EditDomainRedirects>({ domain }))(dispatch, getState, {}); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_DOMAIN_REDIRECTS_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: EDIT_DOMAIN_REDIRECTS_ERROR }); - expect(editDomainRedirects).toHaveBeenCalledTimes(1); + expect(dispatch).toHaveBeenLastCalledWith(expect.objectContaining({ + type: editDomainRedirectsAction.rejected.toString(), + })); + expect(editDomainRedirectsCall).toHaveBeenCalledTimes(1); }); it('dispatches domain and redirects once loaded', async () => { - editDomainRedirects.mockResolvedValue(redirects); + editDomainRedirectsCall.mockResolvedValue(redirects); - await editDomainRedirectsAction(buildShlinkApiClient)(domain, {})(dispatch, getState); + await editDomainRedirectsAction(Mock.of<EditDomainRedirects>({ domain }))(dispatch, getState, {}); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_DOMAIN_REDIRECTS_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: EDIT_DOMAIN_REDIRECTS, domain, redirects }); - expect(editDomainRedirects).toHaveBeenCalledTimes(1); + expect(dispatch).toHaveBeenLastCalledWith(expect.objectContaining({ + type: editDomainRedirectsAction.fulfilled.toString(), + payload: { domain, redirects }, + })); + expect(editDomainRedirectsCall).toHaveBeenCalledTimes(1); }); }); }); diff --git a/test/domains/reducers/domainsList.test.ts b/test/domains/reducers/domainsList.test.ts index b00704bd..b96a37d0 100644 --- a/test/domains/reducers/domainsList.test.ts +++ b/test/domains/reducers/domainsList.test.ts @@ -1,24 +1,17 @@ import { Mock } from 'ts-mockery'; -import reducer, { - LIST_DOMAINS, - LIST_DOMAINS_ERROR, - LIST_DOMAINS_START, - FILTER_DOMAINS, - VALIDATE_DOMAIN, - DomainsCombinedAction, +import { DomainsList, - listDomains as listDomainsAction, - filterDomains as filterDomainsAction, replaceRedirectsOnDomain, - checkDomainHealth, replaceStatusOnDomain, + domainsListReducerCreator, } from '../../../src/domains/reducers/domainsList'; -import { EDIT_DOMAIN_REDIRECTS } from '../../../src/domains/reducers/domainRedirects'; +import { editDomainRedirects } from '../../../src/domains/reducers/domainRedirects'; import { ShlinkDomainRedirects } from '../../../src/api/types'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { Domain } from '../../../src/domains/data'; import { ShlinkState } from '../../../src/container/types'; import { SelectedServer, ServerData } from '../../../src/servers/data'; +import { parseApiError } from '../../../src/api/utils'; describe('domainsListReducer', () => { const dispatch = jest.fn(); @@ -31,36 +24,38 @@ describe('domainsListReducer', () => { Mock.of<Domain>({ domain: 'Boo', status: 'validating' }), ]; const domains = [...filteredDomains, Mock.of<Domain>({ domain: 'bar', status: 'validating' })]; + const error = { type: 'NOT_FOUND', status: 404 }; + const editDomainRedirectsThunk = editDomainRedirects(buildShlinkApiClient); + const { reducer, listDomains: listDomainsAction, checkDomainHealth, filterDomains } = domainsListReducerCreator( + buildShlinkApiClient, + editDomainRedirectsThunk, + ); beforeEach(jest.clearAllMocks); describe('reducer', () => { - const action = (type: string, args: Partial<DomainsCombinedAction> = {}) => Mock.of<DomainsCombinedAction>( - { type, ...args }, - ); - it('returns loading on LIST_DOMAINS_START', () => { - expect(reducer(undefined, action(LIST_DOMAINS_START))).toEqual( + expect(reducer(undefined, { type: listDomainsAction.pending.toString() })).toEqual( { domains: [], filteredDomains: [], loading: true, error: false }, ); }); it('returns error on LIST_DOMAINS_ERROR', () => { - expect(reducer(undefined, action(LIST_DOMAINS_ERROR))).toEqual( - { domains: [], filteredDomains: [], loading: false, error: true }, + expect(reducer(undefined, { type: listDomainsAction.rejected.toString(), error })).toEqual( + { domains: [], filteredDomains: [], loading: false, error: true, errorData: parseApiError(error) }, ); }); it('returns domains on LIST_DOMAINS', () => { - expect(reducer(undefined, action(LIST_DOMAINS, { domains }))).toEqual( - { domains, filteredDomains: domains, loading: false, error: false }, - ); + expect( + reducer(undefined, { type: listDomainsAction.fulfilled.toString(), payload: { domains } }), + ).toEqual({ domains, filteredDomains: domains, loading: false, error: false }); }); it('filters domains on FILTER_DOMAINS', () => { - expect(reducer(Mock.of<DomainsList>({ domains }), action(FILTER_DOMAINS, { searchTerm: 'oO' }))).toEqual( - { domains, filteredDomains }, - ); + expect( + reducer(Mock.of<DomainsList>({ domains }), { type: filterDomains.toString(), payload: 'oO' }), + ).toEqual({ domains, filteredDomains }); }); it.each([ @@ -74,12 +69,12 @@ describe('domainsListReducer', () => { invalidShortUrlRedirect: null, }; - expect(reducer( - Mock.of<DomainsList>({ domains, filteredDomains }), - action(EDIT_DOMAIN_REDIRECTS, { domain, redirects }), - )).toEqual({ - domains: domains.map(replaceRedirectsOnDomain(domain, redirects)), - filteredDomains: filteredDomains.map(replaceRedirectsOnDomain(domain, redirects)), + expect(reducer(Mock.of<DomainsList>({ domains, filteredDomains }), { + type: editDomainRedirectsThunk.fulfilled.toString(), + payload: { domain, redirects }, + })).toEqual({ + domains: domains.map(replaceRedirectsOnDomain({ domain, redirects })), + filteredDomains: filteredDomains.map(replaceRedirectsOnDomain({ domain, redirects })), }); }); @@ -90,7 +85,10 @@ describe('domainsListReducer', () => { ])('replaces status on proper domain on VALIDATE_DOMAIN', (domain) => { expect(reducer( Mock.of<DomainsList>({ domains, filteredDomains }), - action(VALIDATE_DOMAIN, { domain, status: 'valid' }), + { + type: checkDomainHealth.fulfilled.toString(), + payload: { domain, status: 'valid' }, + }, )).toEqual({ domains: domains.map(replaceStatusOnDomain(domain, 'valid')), filteredDomains: filteredDomains.map(replaceStatusOnDomain(domain, 'valid')), @@ -102,22 +100,31 @@ describe('domainsListReducer', () => { it('dispatches error when loading domains fails', async () => { listDomains.mockRejectedValue(new Error('error')); - await listDomainsAction(buildShlinkApiClient)()(dispatch, getState); + await listDomainsAction()(dispatch, getState, {}); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: LIST_DOMAINS_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: LIST_DOMAINS_ERROR }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: listDomainsAction.pending.toString(), + })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: listDomainsAction.rejected.toString(), + })); expect(listDomains).toHaveBeenCalledTimes(1); }); it('dispatches domains once loaded', async () => { listDomains.mockResolvedValue({ data: domains }); - await listDomainsAction(buildShlinkApiClient)()(dispatch, getState); + await listDomainsAction()(dispatch, getState, {}); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: LIST_DOMAINS_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: LIST_DOMAINS, domains, defaultRedirects: undefined }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: listDomainsAction.pending.toString(), + })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: listDomainsAction.fulfilled.toString(), + payload: { domains }, + })); expect(listDomains).toHaveBeenCalledTimes(1); }); }); @@ -128,7 +135,9 @@ describe('domainsListReducer', () => { ['bar'], ['something'], ])('creates action as expected', (searchTerm) => { - expect(filterDomainsAction(searchTerm)).toEqual({ type: FILTER_DOMAINS, searchTerm }); + expect(filterDomains(searchTerm)).toEqual( + expect.objectContaining({ type: filterDomains.toString(), payload: searchTerm }), + ); }); }); @@ -140,12 +149,14 @@ describe('domainsListReducer', () => { selectedServer: Mock.all<SelectedServer>(), })); - await checkDomainHealth(buildShlinkApiClient)(domain)(dispatch, getState); + await checkDomainHealth(domain)(dispatch, getState, {}); expect(getState).toHaveBeenCalledTimes(1); expect(health).not.toHaveBeenCalled(); - expect(dispatch).toHaveBeenCalledTimes(1); - expect(dispatch).toHaveBeenCalledWith({ type: VALIDATE_DOMAIN, domain, status: 'invalid' }); + expect(dispatch).toHaveBeenLastCalledWith(expect.objectContaining({ + type: checkDomainHealth.fulfilled.toString(), + payload: { domain, status: 'invalid' }, + })); }); it('dispatches invalid status when health endpoint returns an error', async () => { @@ -157,12 +168,14 @@ describe('domainsListReducer', () => { })); health.mockRejectedValue({}); - await checkDomainHealth(buildShlinkApiClient)(domain)(dispatch, getState); + await checkDomainHealth(domain)(dispatch, getState, {}); expect(getState).toHaveBeenCalledTimes(1); expect(health).toHaveBeenCalledTimes(1); - expect(dispatch).toHaveBeenCalledTimes(1); - expect(dispatch).toHaveBeenCalledWith({ type: VALIDATE_DOMAIN, domain, status: 'invalid' }); + expect(dispatch).toHaveBeenLastCalledWith(expect.objectContaining({ + type: checkDomainHealth.fulfilled.toString(), + payload: { domain, status: 'invalid' }, + })); }); it.each([ @@ -180,12 +193,14 @@ describe('domainsListReducer', () => { })); health.mockResolvedValue({ status: healthStatus }); - await checkDomainHealth(buildShlinkApiClient)(domain)(dispatch, getState); + await checkDomainHealth(domain)(dispatch, getState, {}); expect(getState).toHaveBeenCalledTimes(1); expect(health).toHaveBeenCalledTimes(1); - expect(dispatch).toHaveBeenCalledTimes(1); - expect(dispatch).toHaveBeenCalledWith({ type: VALIDATE_DOMAIN, domain, status: expectedStatus }); + expect(dispatch).toHaveBeenLastCalledWith(expect.objectContaining({ + type: checkDomainHealth.fulfilled.toString(), + payload: { domain, status: expectedStatus }, + })); }); }); }); diff --git a/test/mercure/reducers/mercureInfo.test.ts b/test/mercure/reducers/mercureInfo.test.ts index d5cb2972..2dcc71b0 100644 --- a/test/mercure/reducers/mercureInfo.test.ts +++ b/test/mercure/reducers/mercureInfo.test.ts @@ -1,12 +1,5 @@ import { Mock } from 'ts-mockery'; -import reducer, { - GET_MERCURE_INFO_START, - GET_MERCURE_INFO_ERROR, - GET_MERCURE_INFO, - loadMercureInfo, - GetMercureInfoAction, -} from '../../../src/mercure/reducers/mercureInfo'; -import { ShlinkMercureInfo } from '../../../src/api/types'; +import { mercureInfoReducerCreator } from '../../../src/mercure/reducers/mercureInfo'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { GetState } from '../../../src/container/types'; @@ -15,39 +8,35 @@ describe('mercureInfoReducer', () => { mercureHubUrl: 'http://example.com/.well-known/mercure', token: 'abc.123.def', }; + const getMercureInfo = jest.fn(); + const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ mercureInfo: getMercureInfo }); + const { loadMercureInfo, reducer } = mercureInfoReducerCreator(buildShlinkApiClient); + + beforeEach(jest.resetAllMocks); describe('reducer', () => { - const action = (type: string, args: Partial<ShlinkMercureInfo> = {}) => Mock.of<GetMercureInfoAction>( - { type, ...args }, - ); - it('returns loading on GET_MERCURE_INFO_START', () => { - expect(reducer(undefined, action(GET_MERCURE_INFO_START))).toEqual({ + expect(reducer(undefined, { type: loadMercureInfo.pending.toString() })).toEqual({ loading: true, error: false, }); }); it('returns error on GET_MERCURE_INFO_ERROR', () => { - expect(reducer(undefined, action(GET_MERCURE_INFO_ERROR))).toEqual({ + expect(reducer(undefined, { type: loadMercureInfo.rejected.toString() })).toEqual({ loading: false, error: true, }); }); it('returns mercure info on GET_MERCURE_INFO', () => { - expect(reducer(undefined, { type: GET_MERCURE_INFO, ...mercureInfo })).toEqual(expect.objectContaining({ - ...mercureInfo, - loading: false, - error: false, - })); + expect(reducer(undefined, { type: loadMercureInfo.fulfilled.toString(), payload: mercureInfo })).toEqual( + expect.objectContaining({ ...mercureInfo, loading: false, error: false }), + ); }); }); describe('loadMercureInfo', () => { - const createApiClientMock = (result: Promise<ShlinkMercureInfo>) => Mock.of<ShlinkApiClient>({ - mercureInfo: jest.fn().mockReturnValue(result), - }); const dispatch = jest.fn(); const createGetStateMock = (enabled: boolean): GetState => jest.fn().mockReturnValue({ settings: { @@ -55,43 +44,55 @@ describe('mercureInfoReducer', () => { }, }); - afterEach(jest.resetAllMocks); - it('dispatches error when real time updates are disabled', async () => { - const apiClientMock = createApiClientMock(Promise.resolve(mercureInfo)); + getMercureInfo.mockResolvedValue(mercureInfo); const getState = createGetStateMock(false); - await loadMercureInfo(() => apiClientMock)()(dispatch, getState); + await loadMercureInfo()(dispatch, getState, {}); - expect(apiClientMock.mercureInfo).not.toHaveBeenCalled(); + expect(getMercureInfo).not.toHaveBeenCalled(); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: GET_MERCURE_INFO_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: GET_MERCURE_INFO_ERROR }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: loadMercureInfo.pending.toString(), + })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: loadMercureInfo.rejected.toString(), + })); }); it('calls API on success', async () => { - const apiClientMock = createApiClientMock(Promise.resolve(mercureInfo)); + getMercureInfo.mockResolvedValue(mercureInfo); const getState = createGetStateMock(true); - await loadMercureInfo(() => apiClientMock)()(dispatch, getState); + await loadMercureInfo()(dispatch, getState, {}); - expect(apiClientMock.mercureInfo).toHaveBeenCalledTimes(1); + expect(getMercureInfo).toHaveBeenCalledTimes(1); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: GET_MERCURE_INFO_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: GET_MERCURE_INFO, ...mercureInfo }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: loadMercureInfo.pending.toString(), + })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: loadMercureInfo.fulfilled.toString(), + payload: mercureInfo, + })); }); it('throws error on failure', async () => { const error = 'Error'; - const apiClientMock = createApiClientMock(Promise.reject(error)); const getState = createGetStateMock(true); - await loadMercureInfo(() => apiClientMock)()(dispatch, getState); + getMercureInfo.mockRejectedValue(error); - expect(apiClientMock.mercureInfo).toHaveBeenCalledTimes(1); + await loadMercureInfo()(dispatch, getState, {}); + + expect(getMercureInfo).toHaveBeenCalledTimes(1); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: GET_MERCURE_INFO_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: GET_MERCURE_INFO_ERROR }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: loadMercureInfo.pending.toString(), + })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: loadMercureInfo.rejected.toString(), + })); }); }); }); diff --git a/test/servers/CreateServer.test.tsx b/test/servers/CreateServer.test.tsx index dd559dc3..a5cbc674 100644 --- a/test/servers/CreateServer.test.tsx +++ b/test/servers/CreateServer.test.tsx @@ -8,7 +8,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn() })); describe('<CreateServer />', () => { - const createServerMock = jest.fn(); + const createServersMock = jest.fn(); const navigate = jest.fn(); const servers = { foo: Mock.of<ServerWithId>({ url: 'https://existing_url.com', apiKey: 'existing_api_key' }) }; const setUp = (serversImported = false, importFailed = false) => { @@ -22,7 +22,7 @@ describe('<CreateServer />', () => { }); const CreateServer = createCreateServer(() => <>ImportServersBtn</>, useTimeoutToggle); - return renderWithEvents(<CreateServer createServer={createServerMock} servers={servers} />); + return renderWithEvents(<CreateServer createServers={createServersMock} servers={servers} />); }; beforeEach(jest.clearAllMocks); @@ -48,18 +48,18 @@ describe('<CreateServer />', () => { it('creates server data when form is submitted', async () => { const { user } = setUp(); - expect(createServerMock).not.toHaveBeenCalled(); + expect(createServersMock).not.toHaveBeenCalled(); await user.type(screen.getByLabelText(/^Name/), 'the_name'); await user.type(screen.getByLabelText(/^URL/), 'https://the_url.com'); await user.type(screen.getByLabelText(/^API key/), 'the_api_key'); fireEvent.submit(screen.getByRole('form')); - expect(createServerMock).toHaveBeenCalledWith(expect.objectContaining({ + expect(createServersMock).toHaveBeenCalledWith([expect.objectContaining({ name: 'the_name', url: 'https://the_url.com', apiKey: 'the_api_key', - })); + })]); expect(navigate).toHaveBeenCalledWith(expect.stringMatching(/^\/server\//)); expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); }); @@ -75,7 +75,7 @@ describe('<CreateServer />', () => { await waitFor(() => expect(screen.getByRole('dialog')).toBeInTheDocument()); await user.click(screen.getByRole('button', { name: 'Discard' })); - expect(createServerMock).not.toHaveBeenCalled(); + expect(createServersMock).not.toHaveBeenCalled(); expect(navigate).toHaveBeenCalledWith(-1); }); }); diff --git a/test/servers/DeleteServerModal.test.tsx b/test/servers/DeleteServerModal.test.tsx index cf509b41..0a5affe5 100644 --- a/test/servers/DeleteServerModal.test.tsx +++ b/test/servers/DeleteServerModal.test.tsx @@ -1,26 +1,29 @@ -import { screen } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import { Mock } from 'ts-mockery'; import { useNavigate } from 'react-router-dom'; import { DeleteServerModal } from '../../src/servers/DeleteServerModal'; import { ServerWithId } from '../../src/servers/data'; import { renderWithEvents } from '../__helpers__/setUpTest'; +import { TestModalWrapper } from '../__helpers__/TestModalWrapper'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn() })); describe('<DeleteServerModal />', () => { const deleteServerMock = jest.fn(); const navigate = jest.fn(); - const toggleMock = jest.fn(); const serverName = 'the_server_name'; const setUp = () => { (useNavigate as any).mockReturnValue(navigate); return renderWithEvents( - <DeleteServerModal - server={Mock.of<ServerWithId>({ name: serverName })} - toggle={toggleMock} - isOpen - deleteServer={deleteServerMock} + <TestModalWrapper + renderModal={(args) => ( + <DeleteServerModal + {...args} + server={Mock.of<ServerWithId>({ name: serverName })} + deleteServer={deleteServerMock} + /> + )} />, ); }; @@ -47,10 +50,8 @@ describe('<DeleteServerModal />', () => { ])('toggles when clicking cancel button', async (getButton) => { const { user } = setUp(); - expect(toggleMock).not.toHaveBeenCalled(); await user.click(getButton()); - expect(toggleMock).toHaveBeenCalledTimes(1); expect(deleteServerMock).not.toHaveBeenCalled(); expect(navigate).not.toHaveBeenCalled(); }); @@ -58,13 +59,11 @@ describe('<DeleteServerModal />', () => { it('deletes server when clicking accept button', async () => { const { user } = setUp(); - expect(toggleMock).not.toHaveBeenCalled(); expect(deleteServerMock).not.toHaveBeenCalled(); expect(navigate).not.toHaveBeenCalled(); await user.click(screen.getByRole('button', { name: 'Delete' })); - expect(toggleMock).toHaveBeenCalledTimes(1); - expect(deleteServerMock).toHaveBeenCalledTimes(1); - expect(navigate).toHaveBeenCalledTimes(1); + await waitFor(() => expect(deleteServerMock).toHaveBeenCalledTimes(1)); + await waitFor(() => expect(navigate).toHaveBeenCalledTimes(1)); }); }); diff --git a/test/servers/__snapshots__/DeleteServerButton.test.tsx.snap b/test/servers/__snapshots__/DeleteServerButton.test.tsx.snap index 380ccbc4..f47cfe0e 100644 --- a/test/servers/__snapshots__/DeleteServerButton.test.tsx.snap +++ b/test/servers/__snapshots__/DeleteServerButton.test.tsx.snap @@ -43,7 +43,7 @@ exports[`<DeleteServerButton /> renders expected content 4`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M0 256C0 114.6 114.6 0 256 0C397.4 0 512 114.6 512 256C512 397.4 397.4 512 256 512C114.6 512 0 397.4 0 256zM168 232C154.7 232 144 242.7 144 256C144 269.3 154.7 280 168 280H344C357.3 280 368 269.3 368 256C368 242.7 357.3 232 344 232H168z" + d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM184 232H328c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z" fill="currentColor" /> </svg> diff --git a/test/servers/__snapshots__/ManageServersRow.test.tsx.snap b/test/servers/__snapshots__/ManageServersRow.test.tsx.snap index 850ff084..9ebc2a4c 100644 --- a/test/servers/__snapshots__/ManageServersRow.test.tsx.snap +++ b/test/servers/__snapshots__/ManageServersRow.test.tsx.snap @@ -19,11 +19,11 @@ exports[`<ManageServersRow /> renders auto-connect icon only if server is autoCo focusable="false" id="autoConnectIcon" role="img" - viewBox="0 0 448 512" + viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" > <path - d="M438.6 105.4C451.1 117.9 451.1 138.1 438.6 150.6L182.6 406.6C170.1 419.1 149.9 419.1 137.4 406.6L9.372 278.6C-3.124 266.1-3.124 245.9 9.372 233.4C21.87 220.9 42.13 220.9 54.63 233.4L159.1 338.7L393.4 105.4C405.9 92.88 426.1 92.88 438.6 105.4H438.6z" + d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z" fill="currentColor" /> </svg> diff --git a/test/servers/reducers/remoteServers.test.ts b/test/servers/reducers/remoteServers.test.ts index 56310e09..2c717696 100644 --- a/test/servers/reducers/remoteServers.test.ts +++ b/test/servers/reducers/remoteServers.test.ts @@ -1,34 +1,32 @@ import { Mock } from 'ts-mockery'; -import { AxiosInstance } from 'axios'; import { fetchServers } from '../../../src/servers/reducers/remoteServers'; -import { CREATE_SERVERS } from '../../../src/servers/reducers/servers'; +import { createServers } from '../../../src/servers/reducers/servers'; +import { HttpClient } from '../../../src/common/services/HttpClient'; describe('remoteServersReducer', () => { afterEach(jest.clearAllMocks); describe('fetchServers', () => { - const get = jest.fn(); - const axios = Mock.of<AxiosInstance>({ get }); const dispatch = jest.fn(); + const fetchJson = jest.fn(); + const httpClient = Mock.of<HttpClient>({ fetchJson }); it.each([ [ - { - data: [ - { - id: '111', - name: 'acel.me from servers.json', - url: 'https://acel.me', - apiKey: '07fb8a96-8059-4094-a24c-80a7d5e7e9b0', - }, - { - id: '222', - name: 'Local from servers.json', - url: 'http://localhost:8000', - apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a', - }, - ], - }, + [ + { + id: '111', + name: 'acel.me from servers.json', + url: 'https://acel.me', + apiKey: '07fb8a96-8059-4094-a24c-80a7d5e7e9b0', + }, + { + id: '222', + name: 'Local from servers.json', + url: 'http://localhost:8000', + apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a', + }, + ], { 111: { id: '111', @@ -45,26 +43,24 @@ describe('remoteServersReducer', () => { }, ], [ - { - data: [ - { - id: '111', - name: 'acel.me from servers.json', - url: 'https://acel.me', - apiKey: '07fb8a96-8059-4094-a24c-80a7d5e7e9b0', - }, - { - id: '222', - name: 'Invalid', - }, - { - id: '333', - name: 'Local from servers.json', - url: 'http://localhost:8000', - apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a', - }, - ], - }, + [ + { + id: '111', + name: 'acel.me from servers.json', + url: 'https://acel.me', + apiKey: '07fb8a96-8059-4094-a24c-80a7d5e7e9b0', + }, + { + id: '222', + name: 'Invalid', + }, + { + id: '333', + name: 'Local from servers.json', + url: 'http://localhost:8000', + apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a', + }, + ], { 111: { id: '111', @@ -83,12 +79,19 @@ describe('remoteServersReducer', () => { ['<html></html>', {}], [{}, {}], ])('tries to fetch servers from remote', async (mockedValue, expectedNewServers) => { - get.mockResolvedValue(mockedValue); + fetchJson.mockResolvedValue(mockedValue); + const doFetchServers = fetchServers(httpClient); - await fetchServers(axios)()(dispatch); + await doFetchServers()(dispatch, jest.fn(), {}); - expect(dispatch).toHaveBeenCalledWith({ type: CREATE_SERVERS, newServers: expectedNewServers }); - expect(get).toHaveBeenCalledTimes(1); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: doFetchServers.pending.toString(), + })); + expect(dispatch).toHaveBeenNthCalledWith(2, { type: createServers.toString(), payload: expectedNewServers }); + expect(dispatch).toHaveBeenNthCalledWith(3, expect.objectContaining({ + type: doFetchServers.fulfilled.toString(), + })); + expect(fetchJson).toHaveBeenCalledTimes(1); }); }); }); diff --git a/test/servers/reducers/selectedServer.test.ts b/test/servers/reducers/selectedServer.test.ts index 2074bcd3..a8db0c95 100644 --- a/test/servers/reducers/selectedServer.test.ts +++ b/test/servers/reducers/selectedServer.test.ts @@ -1,31 +1,40 @@ import { v4 as uuid } from 'uuid'; import { Mock } from 'ts-mockery'; -import reducer, { - selectServer, +import { + selectServer as selectServerCreator, resetSelectedServer, - RESET_SELECTED_SERVER, - SELECT_SERVER, + selectedServerReducerCreator, + selectServerListener, MAX_FALLBACK_VERSION, MIN_FALLBACK_VERSION, } from '../../../src/servers/reducers/selectedServer'; import { ShlinkState } from '../../../src/container/types'; -import { NonReachableServer, NotFoundServer, RegularServer } from '../../../src/servers/data'; +import { NonReachableServer, NotFoundServer, ReachableServer, RegularServer } from '../../../src/servers/data'; +import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; describe('selectedServerReducer', () => { + const dispatch = jest.fn(); + const health = jest.fn(); + const buildApiClient = jest.fn().mockReturnValue(Mock.of<ShlinkApiClient>({ health })); + const selectServer = selectServerCreator(buildApiClient); + const { reducer } = selectedServerReducerCreator(selectServer); + + afterEach(jest.clearAllMocks); + describe('reducer', () => { it('returns default when action is RESET_SELECTED_SERVER', () => - expect(reducer(null, { type: RESET_SELECTED_SERVER, selectedServer: null })).toBeNull()); + expect(reducer(null, { type: resetSelectedServer.toString(), payload: null })).toBeNull()); it('returns selected server when action is SELECT_SERVER', () => { - const selectedServer = Mock.of<RegularServer>({ id: 'abc123' }); + const payload = Mock.of<RegularServer>({ id: 'abc123' }); - expect(reducer(null, { type: SELECT_SERVER, selectedServer })).toEqual(selectedServer); + expect(reducer(null, { type: selectServer.fulfilled.toString(), payload })).toEqual(payload); }); }); describe('resetSelectedServer', () => { it('returns proper action', () => { - expect(resetSelectedServer()).toEqual({ type: RESET_SELECTED_SERVER }); + expect(resetSelectedServer()).toEqual({ type: resetSelectedServer.toString() }); }); }); @@ -35,14 +44,6 @@ describe('selectedServerReducer', () => { }; const version = '1.19.0'; const createGetStateMock = (id: string) => jest.fn().mockReturnValue({ servers: { [id]: selectedServer } }); - const apiClientMock = { - health: jest.fn(), - }; - const buildApiClient = jest.fn().mockReturnValue(apiClientMock); - const dispatch = jest.fn(); - const loadMercureInfo = jest.fn(); - - afterEach(jest.clearAllMocks); it.each([ [version, version, `v${version}`], @@ -57,21 +58,24 @@ describe('selectedServerReducer', () => { printableVersion: expectedPrintableVersion, }; - apiClientMock.health.mockResolvedValue({ version: serverVersion }); + health.mockResolvedValue({ version: serverVersion }); - await selectServer(buildApiClient, loadMercureInfo)(id)(dispatch, getState); + await selectServer(id)(dispatch, getState, {}); expect(dispatch).toHaveBeenCalledTimes(3); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: RESET_SELECTED_SERVER }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: SELECT_SERVER, selectedServer: expectedSelectedServer }); - expect(loadMercureInfo).toHaveBeenCalledTimes(1); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: selectServer.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ type: resetSelectedServer.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(3, expect.objectContaining({ + type: selectServer.fulfilled.toString(), + payload: expectedSelectedServer, + })); }); it('invokes dependencies', async () => { const id = uuid(); const getState = createGetStateMock(id); - await selectServer(buildApiClient, loadMercureInfo)(id)(jest.fn(), getState); + await selectServer(id)(jest.fn(), getState, {}); expect(getState).toHaveBeenCalledTimes(1); expect(buildApiClient).toHaveBeenCalledTimes(1); @@ -82,13 +86,15 @@ describe('selectedServerReducer', () => { const getState = createGetStateMock(id); const expectedSelectedServer = Mock.of<NonReachableServer>({ ...selectedServer, serverNotReachable: true }); - apiClientMock.health.mockRejectedValue({}); + health.mockRejectedValue({}); - await selectServer(buildApiClient, loadMercureInfo)(id)(dispatch, getState); + await selectServer(id)(dispatch, getState, {}); - expect(apiClientMock.health).toHaveBeenCalled(); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: SELECT_SERVER, selectedServer: expectedSelectedServer }); - expect(loadMercureInfo).not.toHaveBeenCalled(); + expect(health).toHaveBeenCalled(); + expect(dispatch).toHaveBeenNthCalledWith(3, expect.objectContaining({ + type: selectServer.fulfilled.toString(), + payload: expectedSelectedServer, + })); }); it('dispatches error when server is not found', async () => { @@ -96,11 +102,43 @@ describe('selectedServerReducer', () => { const getState = jest.fn(() => Mock.of<ShlinkState>({ servers: {} })); const expectedSelectedServer: NotFoundServer = { serverNotFound: true }; - await selectServer(buildApiClient, loadMercureInfo)(id)(dispatch, getState); + await selectServer(id)(dispatch, getState, {}); expect(getState).toHaveBeenCalled(); - expect(apiClientMock.health).not.toHaveBeenCalled(); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: SELECT_SERVER, selectedServer: expectedSelectedServer }); + expect(health).not.toHaveBeenCalled(); + expect(dispatch).toHaveBeenNthCalledWith(3, expect.objectContaining({ + type: selectServer.fulfilled.toString(), + payload: expectedSelectedServer, + })); + }); + }); + + describe('selectServerListener', () => { + const getState = jest.fn(() => ({})); + const loadMercureInfo = jest.fn(); + const { middleware } = selectServerListener(selectServer, loadMercureInfo); + + it.each([ + [Mock.of<ReachableServer>({ version: '1.2.3' }), 1], + [Mock.of<NotFoundServer>({ serverNotFound: true }), 0], + [Mock.of<NonReachableServer>({ serverNotReachable: true }), 0], + ])('dispatches loadMercureInfo when provided server is reachable', (payload, expectedCalls) => { + middleware({ dispatch, getState })(jest.fn())({ + payload, + type: selectServer.fulfilled.toString(), + }); + + expect(dispatch).toHaveBeenCalledTimes(expectedCalls); + expect(loadMercureInfo).toHaveBeenCalledTimes(expectedCalls); + }); + + it('does not dispatch loadMercureInfo when action is not of the proper type', () => { + middleware({ dispatch, getState })(jest.fn())({ + payload: Mock.of<ReachableServer>({ version: '1.2.3' }), + type: 'something_else', + }); + + expect(dispatch).not.toHaveBeenCalled(); expect(loadMercureInfo).not.toHaveBeenCalled(); }); }); diff --git a/test/servers/reducers/servers.test.ts b/test/servers/reducers/servers.test.ts index e39d3561..81695779 100644 --- a/test/servers/reducers/servers.test.ts +++ b/test/servers/reducers/servers.test.ts @@ -1,19 +1,15 @@ import { dissoc, values } from 'ramda'; import { Mock } from 'ts-mockery'; -import reducer, { - createServer, +import { deleteServer, createServers, editServer, setAutoConnect, - EDIT_SERVER, - DELETE_SERVER, - CREATE_SERVERS, - SET_AUTO_CONNECT, + serversReducer, } from '../../../src/servers/reducers/servers'; import { RegularServer } from '../../../src/servers/data'; -describe('serverReducer', () => { +describe('serversReducer', () => { const list = { abc123: Mock.of<RegularServer>({ id: 'abc123' }), def456: Mock.of<RegularServer>({ id: 'def456' }), @@ -23,35 +19,38 @@ describe('serverReducer', () => { describe('reducer', () => { it('returns edited server when action is EDIT_SERVER', () => - expect(reducer( - list, - { type: EDIT_SERVER, serverId: 'abc123', serverData: { foo: 'foo' } } as any, - )).toEqual({ + expect(serversReducer(list, { + type: editServer.toString(), + payload: { serverId: 'abc123', serverData: { foo: 'foo' } }, + })).toEqual({ abc123: { id: 'abc123', foo: 'foo' }, def456: { id: 'def456' }, })); it('returns as it is when action is EDIT_SERVER and server does not exist', () => - expect(reducer( - list, - { type: EDIT_SERVER, serverId: 'invalid', serverData: { foo: 'foo' } } as any, - )).toEqual({ + expect(serversReducer(list, { + type: editServer.toString(), + payload: { serverId: 'invalid', serverData: { foo: 'foo' } }, + })).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, })); it('removes server when action is DELETE_SERVER', () => - expect(reducer(list, { type: DELETE_SERVER, serverId: 'abc123' } as any)).toEqual({ + expect(serversReducer(list, { + type: deleteServer.toString(), + payload: { id: 'abc123' }, + })).toEqual({ def456: { id: 'def456' }, })); it('appends server when action is CREATE_SERVERS', () => - expect(reducer(list, { - type: CREATE_SERVERS, - newServers: { + expect(serversReducer(list, { + type: createServers.toString(), + payload: { ghi789: { id: 'ghi789' }, }, - } as any)).toEqual({ + })).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, ghi789: { id: 'ghi789' }, @@ -61,11 +60,10 @@ describe('serverReducer', () => { [true], [false], ])('returns state as it is when trying to set auto-connect on invalid server', (autoConnect) => - expect(reducer(list, { - type: SET_AUTO_CONNECT, - serverId: 'invalid', - autoConnect, - } as any)).toEqual({ + expect(serversReducer(list, { + type: setAutoConnect.toString(), + payload: { serverId: 'invalid', autoConnect }, + })).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, })); @@ -76,11 +74,10 @@ describe('serverReducer', () => { abc123: { ...list.abc123, autoConnect: true }, }; - expect(reducer(listWithDisabledAutoConnect, { - type: SET_AUTO_CONNECT, - serverId: 'abc123', - autoConnect: false, - } as any)).toEqual({ + expect(serversReducer(listWithDisabledAutoConnect, { + type: setAutoConnect.toString(), + payload: { serverId: 'abc123', autoConnect: false }, + })).toEqual({ abc123: { id: 'abc123', autoConnect: false }, def456: { id: 'def456' }, }); @@ -92,11 +89,10 @@ describe('serverReducer', () => { abc123: { ...list.abc123, autoConnect: true }, }; - expect(reducer(listWithEnabledAutoConnect, { - type: SET_AUTO_CONNECT, - serverId: 'def456', - autoConnect: true, - } as any)).toEqual({ + expect(serversReducer(listWithEnabledAutoConnect, { + type: setAutoConnect.toString(), + payload: { serverId: 'def456', autoConnect: true }, + })).toEqual({ abc123: { id: 'abc123', autoConnect: false }, def456: { id: 'def456', autoConnect: true }, }); @@ -104,21 +100,15 @@ describe('serverReducer', () => { }); describe('action creators', () => { - describe('createServer', () => { - it('returns expected action', () => { - const serverToCreate = Mock.of<RegularServer>({ id: 'abc123' }); - const result = createServer(serverToCreate); - - expect(result).toEqual(expect.objectContaining({ type: CREATE_SERVERS })); - }); - }); - describe('editServer', () => { it('returns expected action', () => { const serverData = { name: 'edited' }; const result = editServer('123', serverData); - expect(result).toEqual({ type: EDIT_SERVER, serverId: '123', serverData }); + expect(result).toEqual({ + type: editServer.toString(), + payload: { serverId: '123', serverData }, + }); }); }); @@ -127,7 +117,10 @@ describe('serverReducer', () => { const serverToDelete = Mock.of<RegularServer>({ id: 'abc123' }); const result = deleteServer(serverToDelete); - expect(result).toEqual({ type: DELETE_SERVER, serverId: 'abc123' }); + expect(result).toEqual({ + type: deleteServer.toString(), + payload: { id: 'abc123' }, + }); }); }); @@ -136,14 +129,14 @@ describe('serverReducer', () => { const newServers = values(list); const result = createServers(newServers); - expect(result).toEqual(expect.objectContaining({ type: CREATE_SERVERS })); + expect(result).toEqual(expect.objectContaining({ type: createServers.toString() })); }); it('generates an id for every provided server if they do not have it', () => { const servers = values(list).map(dissoc('id')); - const { newServers } = createServers(servers); + const { payload } = createServers(servers); - expect(values(newServers).every(({ id }) => !!id)).toEqual(true); + expect(values(payload).every(({ id }) => !!id)).toEqual(true); }); }); @@ -155,7 +148,10 @@ describe('serverReducer', () => { const serverToEdit = Mock.of<RegularServer>({ id: 'abc123' }); const result = setAutoConnect(serverToEdit, autoConnect); - expect(result).toEqual({ type: SET_AUTO_CONNECT, serverId: 'abc123', autoConnect }); + expect(result).toEqual({ + type: setAutoConnect.toString(), + payload: { serverId: 'abc123', autoConnect }, + }); }); }); }); diff --git a/test/settings/__snapshots__/UserInterfaceSettings.test.tsx.snap b/test/settings/__snapshots__/UserInterfaceSettings.test.tsx.snap index 907a8b66..0e8a383d 100644 --- a/test/settings/__snapshots__/UserInterfaceSettings.test.tsx.snap +++ b/test/settings/__snapshots__/UserInterfaceSettings.test.tsx.snap @@ -8,11 +8,11 @@ exports[`<UserInterfaceSettings /> shows different icons based on theme 1`] = ` data-prefix="fas" focusable="false" role="img" - viewBox="0 0 512 512" + viewBox="0 0 384 512" xmlns="http://www.w3.org/2000/svg" > <path - d="M32 256c0-123.8 100.3-224 223.8-224c11.36 0 29.7 1.668 40.9 3.746c9.616 1.777 11.75 14.63 3.279 19.44C245 86.5 211.2 144.6 211.2 207.8c0 109.7 99.71 193 208.3 172.3c9.561-1.805 16.28 9.324 10.11 16.95C387.9 448.6 324.8 480 255.8 480C132.1 480 32 379.6 32 256z" + d="M223.5 32C100 32 0 132.3 0 256S100 480 223.5 480c60.6 0 115.5-24.2 155.8-63.4c5-4.9 6.3-12.5 3.1-18.7s-10.1-9.7-17-8.5c-9.8 1.7-19.8 2.6-30.1 2.6c-96.9 0-175.5-78.8-175.5-176c0-65.8 36-123.1 89.3-153.3c6.1-3.5 9.2-10.5 7.7-17.3s-7.3-11.9-14.3-12.5c-6.3-.5-12.6-.8-19-.8z" fill="currentColor" /> </svg> @@ -30,7 +30,7 @@ exports[`<UserInterfaceSettings /> shows different icons based on theme 2`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M256 159.1c-53.02 0-95.1 42.98-95.1 95.1S202.1 351.1 256 351.1s95.1-42.98 95.1-95.1S309 159.1 256 159.1zM509.3 347L446.1 255.1l63.15-91.01c6.332-9.125 1.104-21.74-9.826-23.72l-109-19.7l-19.7-109c-1.975-10.93-14.59-16.16-23.72-9.824L256 65.89L164.1 2.736c-9.125-6.332-21.74-1.107-23.72 9.824L121.6 121.6L12.56 141.3C1.633 143.2-3.596 155.9 2.736 164.1L65.89 256l-63.15 91.01c-6.332 9.125-1.105 21.74 9.824 23.72l109 19.7l19.7 109c1.975 10.93 14.59 16.16 23.72 9.824L256 446.1l91.01 63.15c9.127 6.334 21.75 1.107 23.72-9.822l19.7-109l109-19.7C510.4 368.8 515.6 356.1 509.3 347zM256 383.1c-70.69 0-127.1-57.31-127.1-127.1c0-70.69 57.31-127.1 127.1-127.1s127.1 57.3 127.1 127.1C383.1 326.7 326.7 383.1 256 383.1z" + d="M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM352 256c0 53-43 96-96 96s-96-43-96-96s43-96 96-96s96 43 96 96zm32 0c0-70.7-57.3-128-128-128s-128 57.3-128 128s57.3 128 128 128s128-57.3 128-128z" fill="currentColor" /> </svg> @@ -48,7 +48,7 @@ exports[`<UserInterfaceSettings /> shows different icons based on theme 3`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M256 159.1c-53.02 0-95.1 42.98-95.1 95.1S202.1 351.1 256 351.1s95.1-42.98 95.1-95.1S309 159.1 256 159.1zM509.3 347L446.1 255.1l63.15-91.01c6.332-9.125 1.104-21.74-9.826-23.72l-109-19.7l-19.7-109c-1.975-10.93-14.59-16.16-23.72-9.824L256 65.89L164.1 2.736c-9.125-6.332-21.74-1.107-23.72 9.824L121.6 121.6L12.56 141.3C1.633 143.2-3.596 155.9 2.736 164.1L65.89 256l-63.15 91.01c-6.332 9.125-1.105 21.74 9.824 23.72l109 19.7l19.7 109c1.975 10.93 14.59 16.16 23.72 9.824L256 446.1l91.01 63.15c9.127 6.334 21.75 1.107 23.72-9.822l19.7-109l109-19.7C510.4 368.8 515.6 356.1 509.3 347zM256 383.1c-70.69 0-127.1-57.31-127.1-127.1c0-70.69 57.31-127.1 127.1-127.1s127.1 57.3 127.1 127.1C383.1 326.7 326.7 383.1 256 383.1z" + d="M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM352 256c0 53-43 96-96 96s-96-43-96-96s43-96 96-96s96 43 96 96zm32 0c0-70.7-57.3-128-128-128s-128 57.3-128 128s57.3 128 128 128s128-57.3 128-128z" fill="currentColor" /> </svg> diff --git a/test/settings/reducers/settings.test.ts b/test/settings/reducers/settings.test.ts index 427eec21..50d31ac1 100644 --- a/test/settings/reducers/settings.test.ts +++ b/test/settings/reducers/settings.test.ts @@ -1,6 +1,6 @@ -import reducer, { - SET_SETTINGS, +import { DEFAULT_SHORT_URLS_ORDERING, + settingsReducer, toggleRealTimeUpdates, setRealTimeUpdatesInterval, setShortUrlCreationSettings, @@ -20,7 +20,9 @@ describe('settingsReducer', () => { describe('reducer', () => { it('returns realTimeUpdates when action is SET_SETTINGS', () => { - expect(reducer(undefined, { type: SET_SETTINGS, realTimeUpdates })).toEqual(settings); + expect( + settingsReducer(undefined, { type: toggleRealTimeUpdates.toString(), payload: { realTimeUpdates } }), + ).toEqual(settings); }); }); @@ -28,7 +30,10 @@ describe('settingsReducer', () => { it.each([[true], [false]])('updates settings with provided value and then loads updates again', (enabled) => { const result = toggleRealTimeUpdates(enabled); - expect(result).toEqual({ type: SET_SETTINGS, realTimeUpdates: { enabled } }); + expect(result).toEqual({ + type: toggleRealTimeUpdates.toString(), + payload: { realTimeUpdates: { enabled } }, + }); }); }); @@ -36,7 +41,10 @@ describe('settingsReducer', () => { it.each([[0], [1], [2], [10]])('updates settings with provided value and then loads updates again', (interval) => { const result = setRealTimeUpdatesInterval(interval); - expect(result).toEqual({ type: SET_SETTINGS, realTimeUpdates: { interval } }); + expect(result).toEqual({ + type: setRealTimeUpdatesInterval.toString(), + payload: { realTimeUpdates: { interval } }, + }); }); }); @@ -44,7 +52,10 @@ describe('settingsReducer', () => { it('creates action to set shortUrlCreation settings', () => { const result = setShortUrlCreationSettings({ validateUrls: true }); - expect(result).toEqual({ type: SET_SETTINGS, shortUrlCreation: { validateUrls: true } }); + expect(result).toEqual({ + type: setShortUrlCreationSettings.toString(), + payload: { shortUrlCreation: { validateUrls: true } }, + }); }); }); @@ -52,7 +63,10 @@ describe('settingsReducer', () => { it('creates action to set ui settings', () => { const result = setUiSettings({ theme: 'dark' }); - expect(result).toEqual({ type: SET_SETTINGS, ui: { theme: 'dark' } }); + expect(result).toEqual({ + type: setUiSettings.toString(), + payload: { ui: { theme: 'dark' } }, + }); }); }); @@ -60,7 +74,10 @@ describe('settingsReducer', () => { it('creates action to set visits settings', () => { const result = setVisitsSettings({ defaultInterval: 'last180Days' }); - expect(result).toEqual({ type: SET_SETTINGS, visits: { defaultInterval: 'last180Days' } }); + expect(result).toEqual({ + type: setVisitsSettings.toString(), + payload: { visits: { defaultInterval: 'last180Days' } }, + }); }); }); @@ -68,7 +85,10 @@ describe('settingsReducer', () => { it('creates action to set tags settings', () => { const result = setTagsSettings({ defaultMode: 'list' }); - expect(result).toEqual({ type: SET_SETTINGS, tags: { defaultMode: 'list' } }); + expect(result).toEqual({ + type: setTagsSettings.toString(), + payload: { tags: { defaultMode: 'list' } }, + }); }); }); @@ -76,7 +96,10 @@ describe('settingsReducer', () => { it('creates action to set short URLs list settings', () => { const result = setShortUrlsListSettings({ defaultOrdering: DEFAULT_SHORT_URLS_ORDERING }); - expect(result).toEqual({ type: SET_SETTINGS, shortUrlsList: { defaultOrdering: DEFAULT_SHORT_URLS_ORDERING } }); + expect(result).toEqual({ + type: setShortUrlsListSettings.toString(), + payload: { shortUrlsList: { defaultOrdering: DEFAULT_SHORT_URLS_ORDERING } }, + }); }); }); }); diff --git a/test/short-urls/CreateShortUrl.test.tsx b/test/short-urls/CreateShortUrl.test.tsx index 553d1a65..2e53e8dc 100644 --- a/test/short-urls/CreateShortUrl.test.tsx +++ b/test/short-urls/CreateShortUrl.test.tsx @@ -13,7 +13,7 @@ describe('<CreateShortUrl />', () => { const CreateShortUrl = createShortUrlsCreator(ShortUrlForm, CreateShortUrlResult); const setUp = () => render( <CreateShortUrl - shortUrlCreationResult={shortUrlCreationResult} + shortUrlCreation={shortUrlCreationResult} createShortUrl={createShortUrl} selectedServer={null} resetCreateShortUrl={() => {}} diff --git a/test/short-urls/EditShortUrl.test.tsx b/test/short-urls/EditShortUrl.test.tsx index e97152fd..8af59969 100644 --- a/test/short-urls/EditShortUrl.test.tsx +++ b/test/short-urls/EditShortUrl.test.tsx @@ -46,9 +46,16 @@ describe('<EditShortUrl />', () => { }); it('shows error when saving data has failed', () => { - setUp({}, { error: true }); + setUp({}, { error: true, saved: true }); expect(screen.getByText('An error occurred while updating short URL :(')).toBeInTheDocument(); expect(screen.getByText('ShortUrlForm')).toBeInTheDocument(); }); + + it('shows message when saving data succeeds', () => { + setUp({}, { error: false, saved: true }); + + expect(screen.getByText('Short URL properly edited.')).toBeInTheDocument(); + expect(screen.getByText('ShortUrlForm')).toBeInTheDocument(); + }); }); diff --git a/test/short-urls/ShortUrlForm.test.tsx b/test/short-urls/ShortUrlForm.test.tsx index 60b983c4..b0c5dc47 100644 --- a/test/short-urls/ShortUrlForm.test.tsx +++ b/test/short-urls/ShortUrlForm.test.tsx @@ -1,5 +1,5 @@ import { screen } from '@testing-library/react'; -import { UserEvent } from '@testing-library/user-event/dist/types/setup'; +import { UserEvent } from '@testing-library/user-event/setup/setup'; import { formatISO } from 'date-fns'; import { Mock } from 'ts-mockery'; import { ShortUrlForm as createShortUrlForm, Mode } from '../../src/short-urls/ShortUrlForm'; diff --git a/test/short-urls/ShortUrlsFilteringBar.test.tsx b/test/short-urls/ShortUrlsFilteringBar.test.tsx index 10adb9fc..d8f30942 100644 --- a/test/short-urls/ShortUrlsFilteringBar.test.tsx +++ b/test/short-urls/ShortUrlsFilteringBar.test.tsx @@ -4,7 +4,7 @@ import { endOfDay, formatISO, startOfDay } from 'date-fns'; import { MemoryRouter, useLocation, useNavigate } from 'react-router-dom'; import { ShortUrlsFilteringBar as filteringBarCreator } from '../../src/short-urls/ShortUrlsFilteringBar'; import { ReachableServer, SelectedServer } from '../../src/servers/data'; -import { DateRange } from '../../src/utils/dates/types'; +import { DateRange } from '../../src/utils/helpers/dateIntervals'; import { formatDate } from '../../src/utils/helpers/date'; import { renderWithEvents } from '../__helpers__/setUpTest'; diff --git a/test/short-urls/helpers/CreateShortUrlResult.test.tsx b/test/short-urls/helpers/CreateShortUrlResult.test.tsx index 03082a93..d9cbba96 100644 --- a/test/short-urls/helpers/CreateShortUrlResult.test.tsx +++ b/test/short-urls/helpers/CreateShortUrlResult.test.tsx @@ -4,34 +4,39 @@ import { CreateShortUrlResult as createResult } from '../../../src/short-urls/he import { ShortUrl } from '../../../src/short-urls/data'; import { TimeoutToggle } from '../../../src/utils/helpers/hooks'; import { renderWithEvents } from '../../__helpers__/setUpTest'; +import { ShortUrlCreation } from '../../../src/short-urls/reducers/shortUrlCreation'; describe('<CreateShortUrlResult />', () => { const copyToClipboard = jest.fn(); const useTimeoutToggle = jest.fn(() => [false, copyToClipboard]) as TimeoutToggle; const CreateShortUrlResult = createResult(useTimeoutToggle); - const setUp = (result: ShortUrl | null = null, error = false) => renderWithEvents( - <CreateShortUrlResult resetCreateShortUrl={() => {}} result={result} error={error} saving={false} />, + const setUp = (creation: ShortUrlCreation) => renderWithEvents( + <CreateShortUrlResult resetCreateShortUrl={() => {}} creation={creation} />, ); afterEach(jest.clearAllMocks); it('renders an error when error is true', () => { - setUp(Mock.all<ShortUrl>(), true); + setUp({ error: true, saved: false, saving: false }); expect(screen.getByText('An error occurred while creating the URL :(')).toBeInTheDocument(); }); - it('renders nothing when no result is provided', () => { - const { container } = setUp(); + it.each([[true], [false]])('renders nothing when not saved yet', (saving) => { + const { container } = setUp({ error: false, saved: false, saving }); expect(container.firstChild).toBeNull(); }); it('renders a result message when result is provided', () => { - setUp(Mock.of<ShortUrl>({ shortUrl: 'https://doma.in/abc123' })); + setUp( + { result: Mock.of<ShortUrl>({ shortUrl: 'https://doma.in/abc123' }), saving: false, saved: true, error: false }, + ); expect(screen.getByText(/The short URL is/)).toHaveTextContent('Great! The short URL is https://doma.in/abc123'); }); it('Invokes tooltip timeout when copy to clipboard button is clicked', async () => { - const { user } = setUp(Mock.of<ShortUrl>({ shortUrl: 'https://doma.in/abc123' })); + const { user } = setUp( + { result: Mock.of<ShortUrl>({ shortUrl: 'https://doma.in/abc123' }), saving: false, saved: true, error: false }, + ); expect(copyToClipboard).not.toHaveBeenCalled(); await user.click(screen.getByRole('button')); diff --git a/test/short-urls/helpers/DeleteShortUrlModal.test.tsx b/test/short-urls/helpers/DeleteShortUrlModal.test.tsx index c3a3bd51..a71cd977 100644 --- a/test/short-urls/helpers/DeleteShortUrlModal.test.tsx +++ b/test/short-urls/helpers/DeleteShortUrlModal.test.tsx @@ -1,10 +1,11 @@ -import { screen } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import { Mock } from 'ts-mockery'; import { DeleteShortUrlModal } from '../../../src/short-urls/helpers/DeleteShortUrlModal'; import { ShortUrl } from '../../../src/short-urls/data'; import { ShortUrlDeletion } from '../../../src/short-urls/reducers/shortUrlDeletion'; -import { ProblemDetailsError } from '../../../src/api/types'; import { renderWithEvents } from '../../__helpers__/setUpTest'; +import { ErrorTypeV2, ErrorTypeV3, InvalidShortUrlDeletion, ProblemDetailsError } from '../../../src/api/types/errors'; +import { TestModalWrapper } from '../../__helpers__/TestModalWrapper'; describe('<DeleteShortUrlModal />', () => { const shortUrl = Mock.of<ShortUrl>({ @@ -12,15 +13,20 @@ describe('<DeleteShortUrlModal />', () => { shortCode: 'abc123', longUrl: 'https://long-domain.com/foo/bar', }); - const deleteShortUrl = jest.fn(async () => Promise.resolve()); + const deleteShortUrl = jest.fn().mockResolvedValue(undefined); + const shortUrlDeleted = jest.fn(); const setUp = (shortUrlDeletion: Partial<ShortUrlDeletion>) => renderWithEvents( - <DeleteShortUrlModal - isOpen - shortUrl={shortUrl} - shortUrlDeletion={Mock.of<ShortUrlDeletion>(shortUrlDeletion)} - deleteShortUrl={deleteShortUrl} - toggle={() => {}} - resetDeleteShortUrl={() => {}} + <TestModalWrapper + renderModal={(args) => ( + <DeleteShortUrlModal + {...args} + shortUrl={shortUrl} + shortUrlDeletion={Mock.of<ShortUrlDeletion>(shortUrlDeletion)} + deleteShortUrl={deleteShortUrl} + shortUrlDeleted={shortUrlDeleted} + resetDeleteShortUrl={jest.fn()} + /> + )} />, ); @@ -33,7 +39,17 @@ describe('<DeleteShortUrlModal />', () => { shortCode: 'abc123', errorData: Mock.of<ProblemDetailsError>({ type: 'OTHER_ERROR' }), }); - expect(screen.getByText('Something went wrong while deleting the URL :(')).toBeInTheDocument(); + expect(screen.getByText('Something went wrong while deleting the URL :(').parentElement).not.toHaveClass( + 'bg-warning', + ); + }); + + it.each([ + [Mock.of<InvalidShortUrlDeletion>({ type: ErrorTypeV3.INVALID_SHORT_URL_DELETION })], + [Mock.of<InvalidShortUrlDeletion>({ type: ErrorTypeV2.INVALID_SHORT_URL_DELETION })], + ])('shows specific error when threshold error occurs', (errorData) => { + setUp({ loading: false, error: true, shortCode: 'abc123', errorData }); + expect(screen.getByText('Something went wrong while deleting the URL :(').parentElement).toHaveClass('bg-warning'); }); it('disables submit button when loading', () => { @@ -46,30 +62,30 @@ describe('<DeleteShortUrlModal />', () => { }); it('enables submit button when proper short code is provided', async () => { - const shortCode = 'abc123'; const { user } = setUp({ loading: false, error: false, - shortCode, + shortCode: 'abc123', }); const getDeleteBtn = () => screen.getByRole('button', { name: 'Delete' }); expect(getDeleteBtn()).toHaveAttribute('disabled'); - await user.type(screen.getByPlaceholderText(/^Insert the short code/), shortCode); + await user.type(screen.getByPlaceholderText('Insert delete'), 'delete'); expect(getDeleteBtn()).not.toHaveAttribute('disabled'); }); it('tries to delete short URL when form is submit', async () => { - const shortCode = 'abc123'; const { user } = setUp({ loading: false, error: false, - shortCode, + deleted: true, + shortCode: 'abc123', }); expect(deleteShortUrl).not.toHaveBeenCalled(); - await user.type(screen.getByPlaceholderText(/^Insert the short code/), shortCode); + await user.type(screen.getByPlaceholderText('Insert delete'), 'delete'); await user.click(screen.getByRole('button', { name: 'Delete' })); expect(deleteShortUrl).toHaveBeenCalledTimes(1); + await waitFor(() => expect(shortUrlDeleted).toHaveBeenCalledTimes(1)); }); }); diff --git a/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx b/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx index c3abad98..e2af62af 100644 --- a/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx +++ b/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx @@ -1,5 +1,5 @@ import { Mock } from 'ts-mockery'; -import { screen, waitForElementToBeRemoved } from '@testing-library/react'; +import { screen } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; import { ReportExporter } from '../../../src/common/services/ReportExporter'; import { ExportShortUrlsBtn as createExportShortUrlsBtn } from '../../../src/short-urls/helpers/ExportShortUrlsBtn'; @@ -52,7 +52,6 @@ describe('<ExportShortUrlsBtn />', () => { const { user } = setUp(amount, Mock.of<ReachableServer>({ id: '123' })); await user.click(screen.getByRole('button')); - await waitForElementToBeRemoved(() => screen.getByText('Exporting...')); expect(listShortUrls).toHaveBeenCalledTimes(expectedPageLoads); expect(exportShortUrls).toHaveBeenCalled(); diff --git a/test/short-urls/reducers/shortUrlCreation.test.ts b/test/short-urls/reducers/shortUrlCreation.test.ts index 25128bc4..f7815b4a 100644 --- a/test/short-urls/reducers/shortUrlCreation.test.ts +++ b/test/short-urls/reducers/shortUrlCreation.test.ts @@ -1,19 +1,21 @@ import { Mock } from 'ts-mockery'; -import reducer, { - CREATE_SHORT_URL_START, - CREATE_SHORT_URL_ERROR, - CREATE_SHORT_URL, - RESET_CREATE_SHORT_URL, - createShortUrl, - resetCreateShortUrl, +import { CreateShortUrlAction, + shortUrlCreationReducerCreator, + createShortUrl as createShortUrlCreator, } from '../../../src/short-urls/reducers/shortUrlCreation'; import { ShortUrl } from '../../../src/short-urls/data'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { ShlinkState } from '../../../src/container/types'; describe('shortUrlCreationReducer', () => { - const shortUrl = Mock.all<ShortUrl>(); + const shortUrl = Mock.of<ShortUrl>(); + const createShortUrlCall = jest.fn(); + const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ createShortUrl: createShortUrlCall }); + const createShortUrl = createShortUrlCreator(buildShlinkApiClient); + const { reducer, resetCreateShortUrl } = shortUrlCreationReducerCreator(createShortUrl); + + afterEach(jest.resetAllMocks); describe('reducer', () => { const action = (type: string, args: Partial<CreateShortUrlAction> = {}) => Mock.of<CreateShortUrlAction>( @@ -21,80 +23,77 @@ describe('shortUrlCreationReducer', () => { ); it('returns loading on CREATE_SHORT_URL_START', () => { - expect(reducer(undefined, action(CREATE_SHORT_URL_START))).toEqual({ - result: null, + expect(reducer(undefined, action(createShortUrl.pending.toString()))).toEqual({ saving: true, + saved: false, error: false, }); }); it('returns error on CREATE_SHORT_URL_ERROR', () => { - expect(reducer(undefined, action(CREATE_SHORT_URL_ERROR))).toEqual({ - result: null, + expect(reducer(undefined, action(createShortUrl.rejected.toString()))).toEqual({ saving: false, + saved: false, error: true, }); }); it('returns result on CREATE_SHORT_URL', () => { - expect(reducer(undefined, action(CREATE_SHORT_URL, { result: shortUrl }))).toEqual({ + expect(reducer(undefined, action(createShortUrl.fulfilled.toString(), { payload: shortUrl }))).toEqual({ result: shortUrl, saving: false, + saved: true, error: false, }); }); it('returns default state on RESET_CREATE_SHORT_URL', () => { - expect(reducer(undefined, action(RESET_CREATE_SHORT_URL))).toEqual({ - result: null, + expect(reducer(undefined, action(resetCreateShortUrl.toString()))).toEqual({ saving: false, + saved: false, error: false, }); }); }); describe('resetCreateShortUrl', () => { - it('returns proper action', () => expect(resetCreateShortUrl()).toEqual({ type: RESET_CREATE_SHORT_URL })); + it('returns proper action', () => expect(resetCreateShortUrl()).toEqual({ type: resetCreateShortUrl.toString() })); }); describe('createShortUrl', () => { - const createApiClientMock = (result: Promise<ShortUrl>) => Mock.of<ShlinkApiClient>({ - createShortUrl: jest.fn().mockReturnValue(result), - }); const dispatch = jest.fn(); const getState = () => Mock.all<ShlinkState>(); - afterEach(jest.resetAllMocks); - it('calls API on success', async () => { - const apiClientMock = createApiClientMock(Promise.resolve(shortUrl)); - const dispatchable = createShortUrl(() => apiClientMock)({ longUrl: 'foo' }); + createShortUrlCall.mockResolvedValue(shortUrl); + await createShortUrl({ longUrl: 'foo' })(dispatch, getState, {}); - await dispatchable(dispatch, getState); - - expect(apiClientMock.createShortUrl).toHaveBeenCalledTimes(1); + expect(createShortUrlCall).toHaveBeenCalledTimes(1); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: CREATE_SHORT_URL_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: CREATE_SHORT_URL, result: shortUrl }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: createShortUrl.pending.toString(), + })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: createShortUrl.fulfilled.toString(), + payload: shortUrl, + })); }); it('throws on error', async () => { - const error = 'Error'; - const apiClientMock = createApiClientMock(Promise.reject(error)); - const dispatchable = createShortUrl(() => apiClientMock)({ longUrl: 'foo' }); + const error = new Error('Error message'); + createShortUrlCall.mockRejectedValue(error); - expect.assertions(5); + await createShortUrl({ longUrl: 'foo' })(dispatch, getState, {}); - try { - await dispatchable(dispatch, getState); - } catch (e) { - expect(e).toEqual(error); - } - - expect(apiClientMock.createShortUrl).toHaveBeenCalledTimes(1); + expect(createShortUrlCall).toHaveBeenCalledTimes(1); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: CREATE_SHORT_URL_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: CREATE_SHORT_URL_ERROR }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: createShortUrl.pending.toString(), + })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: createShortUrl.rejected.toString(), + error: expect.objectContaining({ message: 'Error message' }), + })); }); }); }); diff --git a/test/short-urls/reducers/shortUrlDeletion.test.ts b/test/short-urls/reducers/shortUrlDeletion.test.ts index 0eb61b25..e6bd8162 100644 --- a/test/short-urls/reducers/shortUrlDeletion.test.ts +++ b/test/short-urls/reducers/shortUrlDeletion.test.ts @@ -1,45 +1,56 @@ import { Mock } from 'ts-mockery'; -import reducer, { - DELETE_SHORT_URL_ERROR, - DELETE_SHORT_URL_START, - RESET_DELETE_SHORT_URL, - SHORT_URL_DELETED, - resetDeleteShortUrl, - deleteShortUrl, +import { + shortUrlDeletionReducerCreator, + deleteShortUrl as deleteShortUrlCretor, } from '../../../src/short-urls/reducers/shortUrlDeletion'; -import { ProblemDetailsError } from '../../../src/api/types'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; +import { ProblemDetailsError } from '../../../src/api/types/errors'; describe('shortUrlDeletionReducer', () => { + const deleteShortUrlCall = jest.fn(); + const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ deleteShortUrl: deleteShortUrlCall }); + const deleteShortUrl = deleteShortUrlCretor(buildShlinkApiClient); + const { reducer, resetDeleteShortUrl } = shortUrlDeletionReducerCreator(deleteShortUrl); + + beforeEach(jest.clearAllMocks); + describe('reducer', () => { it('returns loading on DELETE_SHORT_URL_START', () => - expect(reducer(undefined, { type: DELETE_SHORT_URL_START } as any)).toEqual({ + expect(reducer(undefined, { type: deleteShortUrl.pending.toString() })).toEqual({ shortCode: '', loading: true, error: false, + deleted: false, })); it('returns default on RESET_DELETE_SHORT_URL', () => - expect(reducer(undefined, { type: RESET_DELETE_SHORT_URL } as any)).toEqual({ + expect(reducer(undefined, { type: resetDeleteShortUrl.toString() })).toEqual({ shortCode: '', loading: false, error: false, + deleted: false, })); it('returns shortCode on SHORT_URL_DELETED', () => - expect(reducer(undefined, { type: SHORT_URL_DELETED, shortCode: 'foo' } as any)).toEqual({ + expect(reducer(undefined, { + type: deleteShortUrl.fulfilled.toString(), + payload: { shortCode: 'foo' }, + })).toEqual({ shortCode: 'foo', loading: false, error: false, + deleted: true, })); it('returns errorData on DELETE_SHORT_URL_ERROR', () => { - const errorData = Mock.of<ProblemDetailsError>({ type: 'bar' }); + const errorData = Mock.of<ProblemDetailsError>({ type: 'bar', detail: 'detail', title: 'title', status: 400 }); + const error = errorData; - expect(reducer(undefined, { type: DELETE_SHORT_URL_ERROR, errorData } as any)).toEqual({ + expect(reducer(undefined, { type: deleteShortUrl.rejected.toString(), error })).toEqual({ shortCode: '', loading: false, error: true, + deleted: false, errorData, }); }); @@ -47,56 +58,47 @@ describe('shortUrlDeletionReducer', () => { describe('resetDeleteShortUrl', () => { it('returns expected action', () => - expect(resetDeleteShortUrl()).toEqual({ type: RESET_DELETE_SHORT_URL })); + expect(resetDeleteShortUrl()).toEqual({ type: resetDeleteShortUrl.toString() })); }); describe('deleteShortUrl', () => { const dispatch = jest.fn(); const getState = jest.fn().mockReturnValue({ selectedServer: {} }); - afterEach(() => { - dispatch.mockReset(); - getState.mockClear(); - }); - it.each( [[undefined], [null], ['example.com']], )('dispatches proper actions if API client request succeeds', async (domain) => { - const apiClientMock = Mock.of<ShlinkApiClient>({ - deleteShortUrl: jest.fn(() => ''), - }); const shortCode = 'abc123'; - await deleteShortUrl(() => apiClientMock)(shortCode, domain)(dispatch, getState); + await deleteShortUrl({ shortCode, domain })(dispatch, getState, {}); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: DELETE_SHORT_URL_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: SHORT_URL_DELETED, shortCode, domain }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: deleteShortUrl.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: deleteShortUrl.fulfilled.toString(), + payload: { shortCode, domain }, + })); - expect(apiClientMock.deleteShortUrl).toHaveBeenCalledTimes(1); - expect(apiClientMock.deleteShortUrl).toHaveBeenCalledWith(shortCode, domain); + expect(deleteShortUrlCall).toHaveBeenCalledTimes(1); + expect(deleteShortUrlCall).toHaveBeenCalledWith(shortCode, domain); }); it('dispatches proper actions if API client request fails', async () => { const data = { foo: 'bar' }; - const error = { response: { data } }; - const apiClientMock = Mock.of<ShlinkApiClient>({ - deleteShortUrl: jest.fn(async () => Promise.reject(error)), - }); const shortCode = 'abc123'; - try { - await deleteShortUrl(() => apiClientMock)(shortCode)(dispatch, getState); - } catch (e) { - expect(e).toEqual(error); - } + deleteShortUrlCall.mockRejectedValue({ response: { data } }); + + await deleteShortUrl({ shortCode })(dispatch, getState, {}); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: DELETE_SHORT_URL_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: DELETE_SHORT_URL_ERROR, errorData: data }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: deleteShortUrl.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: deleteShortUrl.rejected.toString(), + })); - expect(apiClientMock.deleteShortUrl).toHaveBeenCalledTimes(1); - expect(apiClientMock.deleteShortUrl).toHaveBeenCalledWith(shortCode, undefined); + expect(deleteShortUrlCall).toHaveBeenCalledTimes(1); + expect(deleteShortUrlCall).toHaveBeenCalledWith(shortCode, undefined); }); }); }); diff --git a/test/short-urls/reducers/shortUrlDetail.test.ts b/test/short-urls/reducers/shortUrlDetail.test.ts index 2a6b9df7..cb745724 100644 --- a/test/short-urls/reducers/shortUrlDetail.test.ts +++ b/test/short-urls/reducers/shortUrlDetail.test.ts @@ -1,31 +1,29 @@ import { Mock } from 'ts-mockery'; -import reducer, { - getShortUrlDetail, - GET_SHORT_URL_DETAIL_START, - GET_SHORT_URL_DETAIL_ERROR, - GET_SHORT_URL_DETAIL, - ShortUrlDetailAction, -} from '../../../src/short-urls/reducers/shortUrlDetail'; +import { ShortUrlDetailAction, shortUrlDetailReducerCreator } from '../../../src/short-urls/reducers/shortUrlDetail'; import { ShortUrl } from '../../../src/short-urls/data'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { ShlinkState } from '../../../src/container/types'; import { ShortUrlsList } from '../../../src/short-urls/reducers/shortUrlsList'; describe('shortUrlDetailReducer', () => { + const getShortUrlCall = jest.fn(); + const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ getShortUrl: getShortUrlCall }); + const { reducer, getShortUrlDetail } = shortUrlDetailReducerCreator(buildShlinkApiClient); + beforeEach(jest.clearAllMocks); describe('reducer', () => { const action = (type: string) => Mock.of<ShortUrlDetailAction>({ type }); it('returns loading on GET_SHORT_URL_DETAIL_START', () => { - const state = reducer({ loading: false, error: false }, action(GET_SHORT_URL_DETAIL_START)); + const state = reducer({ loading: false, error: false }, action(getShortUrlDetail.pending.toString())); const { loading } = state; expect(loading).toEqual(true); }); it('stops loading and returns error on GET_SHORT_URL_DETAIL_ERROR', () => { - const state = reducer({ loading: true, error: false }, action(GET_SHORT_URL_DETAIL_ERROR)); + const state = reducer({ loading: true, error: false }, action(getShortUrlDetail.rejected.toString())); const { loading, error } = state; expect(loading).toEqual(false); @@ -34,7 +32,10 @@ describe('shortUrlDetailReducer', () => { it('return short URL on GET_SHORT_URL_DETAIL', () => { const actionShortUrl = Mock.of<ShortUrl>({ longUrl: 'foo', shortCode: 'bar' }); - const state = reducer({ loading: true, error: false }, { type: GET_SHORT_URL_DETAIL, shortUrl: actionShortUrl }); + const state = reducer( + { loading: true, error: false }, + { type: getShortUrlDetail.fulfilled.toString(), payload: actionShortUrl }, + ); const { loading, error, shortUrl } = state; expect(loading).toEqual(false); @@ -44,21 +45,22 @@ describe('shortUrlDetailReducer', () => { }); describe('getShortUrlDetail', () => { - const buildApiClientMock = (returned: Promise<ShortUrl>) => Mock.of<ShlinkApiClient>({ - getShortUrl: jest.fn(async () => returned), - }); const dispatchMock = jest.fn(); const buildGetState = (shortUrlsList?: ShortUrlsList) => () => Mock.of<ShlinkState>({ shortUrlsList }); it('dispatches start and error when promise is rejected', async () => { - const ShlinkApiClient = buildApiClientMock(Promise.reject({})); + getShortUrlCall.mockRejectedValue({}); - await getShortUrlDetail(() => ShlinkApiClient)('abc123', '')(dispatchMock, buildGetState()); + await getShortUrlDetail({ shortCode: 'abc123', domain: '' })(dispatchMock, buildGetState(), {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_SHORT_URL_DETAIL_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_SHORT_URL_DETAIL_ERROR }); - expect(ShlinkApiClient.getShortUrl).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getShortUrlDetail.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getShortUrlDetail.rejected.toString(), + })); + expect(getShortUrlCall).toHaveBeenCalledTimes(1); }); it.each([ @@ -78,33 +80,44 @@ describe('shortUrlDetailReducer', () => { ], ])('performs API call when short URL is not found in local state', async (shortUrlsList?: ShortUrlsList) => { const resolvedShortUrl = Mock.of<ShortUrl>({ longUrl: 'foo', shortCode: 'abc123' }); - const ShlinkApiClient = buildApiClientMock(Promise.resolve(resolvedShortUrl)); + getShortUrlCall.mockResolvedValue(resolvedShortUrl); - await getShortUrlDetail(() => ShlinkApiClient)('abc123', '')(dispatchMock, buildGetState(shortUrlsList)); + await getShortUrlDetail({ shortCode: 'abc123', domain: '' })(dispatchMock, buildGetState(shortUrlsList), {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_SHORT_URL_DETAIL_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_SHORT_URL_DETAIL, shortUrl: resolvedShortUrl }); - expect(ShlinkApiClient.getShortUrl).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getShortUrlDetail.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getShortUrlDetail.fulfilled.toString(), + payload: resolvedShortUrl, + })); + expect(getShortUrlCall).toHaveBeenCalledTimes(1); }); it('avoids API calls when short URL is found in local state', async () => { const foundShortUrl = Mock.of<ShortUrl>({ longUrl: 'foo', shortCode: 'abc123' }); - const ShlinkApiClient = buildApiClientMock(Promise.resolve(Mock.all<ShortUrl>())); + getShortUrlCall.mockResolvedValue(Mock.all<ShortUrl>()); - await getShortUrlDetail(() => ShlinkApiClient)(foundShortUrl.shortCode, foundShortUrl.domain)( + await getShortUrlDetail(foundShortUrl)( dispatchMock, buildGetState(Mock.of<ShortUrlsList>({ shortUrls: { data: [foundShortUrl], }, })), + {}, ); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_SHORT_URL_DETAIL_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_SHORT_URL_DETAIL, shortUrl: foundShortUrl }); - expect(ShlinkApiClient.getShortUrl).not.toHaveBeenCalled(); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getShortUrlDetail.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getShortUrlDetail.fulfilled.toString(), + payload: foundShortUrl, + })); + expect(getShortUrlCall).not.toHaveBeenCalled(); }); }); }); diff --git a/test/short-urls/reducers/shortUrlEdition.test.ts b/test/short-urls/reducers/shortUrlEdition.test.ts index 313d7556..941328c8 100644 --- a/test/short-urls/reducers/shortUrlEdition.test.ts +++ b/test/short-urls/reducers/shortUrlEdition.test.ts @@ -1,10 +1,8 @@ import { Mock } from 'ts-mockery'; -import reducer, { - EDIT_SHORT_URL_START, - EDIT_SHORT_URL_ERROR, - SHORT_URL_EDITED, - editShortUrl, +import { ShortUrlEditedAction, + shortUrlEditionReducerCreator, + editShortUrl as editShortUrlCreator, } from '../../../src/short-urls/reducers/shortUrlEdition'; import { ShlinkState } from '../../../src/container/types'; import { ShortUrl } from '../../../src/short-urls/data'; @@ -14,48 +12,60 @@ describe('shortUrlEditionReducer', () => { const longUrl = 'https://shlink.io'; const shortCode = 'abc123'; const shortUrl = Mock.of<ShortUrl>({ longUrl, shortCode }); + const updateShortUrl = jest.fn().mockResolvedValue(shortUrl); + const buildShlinkApiClient = jest.fn().mockReturnValue({ updateShortUrl }); + const editShortUrl = editShortUrlCreator(buildShlinkApiClient); + const { reducer } = shortUrlEditionReducerCreator(editShortUrl); + + afterEach(jest.clearAllMocks); describe('reducer', () => { it('returns loading on EDIT_SHORT_URL_START', () => { - expect(reducer(undefined, Mock.of<ShortUrlEditedAction>({ type: EDIT_SHORT_URL_START }))).toEqual({ + expect(reducer(undefined, Mock.of<ShortUrlEditedAction>({ type: editShortUrl.pending.toString() }))).toEqual({ saving: true, + saved: false, error: false, }); }); it('returns error on EDIT_SHORT_URL_ERROR', () => { - expect(reducer(undefined, Mock.of<ShortUrlEditedAction>({ type: EDIT_SHORT_URL_ERROR }))).toEqual({ + expect(reducer(undefined, Mock.of<ShortUrlEditedAction>({ type: editShortUrl.rejected.toString() }))).toEqual({ saving: false, + saved: false, error: true, }); }); it('returns provided tags and shortCode on SHORT_URL_EDITED', () => { - expect(reducer(undefined, { type: SHORT_URL_EDITED, shortUrl })).toEqual({ + expect(reducer(undefined, { type: editShortUrl.fulfilled.toString(), payload: shortUrl })).toEqual({ shortUrl, saving: false, + saved: true, error: false, }); }); }); describe('editShortUrl', () => { - const updateShortUrl = jest.fn().mockResolvedValue(shortUrl); - const buildShlinkApiClient = jest.fn().mockReturnValue({ updateShortUrl }); const dispatch = jest.fn(); const createGetState = (selectedServer: SelectedServer = null) => () => Mock.of<ShlinkState>({ selectedServer }); afterEach(jest.clearAllMocks); it.each([[undefined], [null], ['example.com']])('dispatches short URL on success', async (domain) => { - await editShortUrl(buildShlinkApiClient)(shortCode, domain, { longUrl })(dispatch, createGetState()); + await editShortUrl({ shortCode, domain, data: { longUrl } })(dispatch, createGetState(), {}); expect(buildShlinkApiClient).toHaveBeenCalledTimes(1); expect(updateShortUrl).toHaveBeenCalledTimes(1); expect(updateShortUrl).toHaveBeenCalledWith(shortCode, domain, { longUrl }); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_SHORT_URL_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: SHORT_URL_EDITED, shortUrl }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: editShortUrl.pending.toString(), + })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: editShortUrl.fulfilled.toString(), + payload: shortUrl, + })); }); it('dispatches error on failure', async () => { @@ -63,18 +73,14 @@ describe('shortUrlEditionReducer', () => { updateShortUrl.mockRejectedValue(error); - try { - await editShortUrl(buildShlinkApiClient)(shortCode, undefined, { longUrl })(dispatch, createGetState()); - } catch (e) { - expect(e).toBe(error); - } + await editShortUrl({ shortCode, data: { longUrl } })(dispatch, createGetState(), {}); expect(buildShlinkApiClient).toHaveBeenCalledTimes(1); expect(updateShortUrl).toHaveBeenCalledTimes(1); expect(updateShortUrl).toHaveBeenCalledWith(shortCode, undefined, { longUrl }); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_SHORT_URL_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: EDIT_SHORT_URL_ERROR }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: editShortUrl.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ type: editShortUrl.rejected.toString() })); }); }); }); diff --git a/test/short-urls/reducers/shortUrlsList.test.ts b/test/short-urls/reducers/shortUrlsList.test.ts index fbff5de0..8e639603 100644 --- a/test/short-urls/reducers/shortUrlsList.test.ts +++ b/test/short-urls/reducers/shortUrlsList.test.ts @@ -1,37 +1,43 @@ import { Mock } from 'ts-mockery'; -import reducer, { - LIST_SHORT_URLS, - LIST_SHORT_URLS_ERROR, - LIST_SHORT_URLS_START, - listShortUrls, +import { + listShortUrls as listShortUrlsCreator, + shortUrlsListReducerCreator, } from '../../../src/short-urls/reducers/shortUrlsList'; -import { SHORT_URL_DELETED } from '../../../src/short-urls/reducers/shortUrlDeletion'; -import { CREATE_VISITS } from '../../../src/visits/reducers/visitCreation'; +import { shortUrlDeleted } from '../../../src/short-urls/reducers/shortUrlDeletion'; +import { ShlinkPaginator, ShlinkShortUrlsResponse } from '../../../src/api/types'; +import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation'; +import { editShortUrl as editShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlEdition'; +import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; import { ShortUrl } from '../../../src/short-urls/data'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; -import { ShlinkPaginator, ShlinkShortUrlsResponse } from '../../../src/api/types'; -import { CREATE_SHORT_URL } from '../../../src/short-urls/reducers/shortUrlCreation'; -import { SHORT_URL_EDITED } from '../../../src/short-urls/reducers/shortUrlEdition'; describe('shortUrlsListReducer', () => { const shortCode = 'abc123'; + const listShortUrlsMock = jest.fn(); + const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ listShortUrls: listShortUrlsMock }); + const listShortUrls = listShortUrlsCreator(buildShlinkApiClient); + const editShortUrl = editShortUrlCreator(buildShlinkApiClient); + const createShortUrl = createShortUrlCreator(buildShlinkApiClient); + const { reducer } = shortUrlsListReducerCreator(listShortUrls, editShortUrl, createShortUrl); + + afterEach(jest.clearAllMocks); describe('reducer', () => { it('returns loading on LIST_SHORT_URLS_START', () => - expect(reducer(undefined, { type: LIST_SHORT_URLS_START } as any)).toEqual({ + expect(reducer(undefined, { type: listShortUrls.pending.toString() })).toEqual({ loading: true, error: false, })); it('returns short URLs on LIST_SHORT_URLS', () => - expect(reducer(undefined, { type: LIST_SHORT_URLS, shortUrls: { data: [] } } as any)).toEqual({ + expect(reducer(undefined, { type: listShortUrls.fulfilled.toString(), payload: { data: [] } })).toEqual({ shortUrls: { data: [] }, loading: false, error: false, })); it('returns error on LIST_SHORT_URLS_ERROR', () => - expect(reducer(undefined, { type: LIST_SHORT_URLS_ERROR } as any)).toEqual({ + expect(reducer(undefined, { type: listShortUrls.rejected.toString() })).toEqual({ loading: false, error: true, })); @@ -52,7 +58,7 @@ describe('shortUrlsListReducer', () => { error: false, }; - expect(reducer(state, { type: SHORT_URL_DELETED, shortCode } as any)).toEqual({ + expect(reducer(state, { type: shortUrlDeleted.toString(), payload: { shortCode } })).toEqual({ shortUrls: { data: [{ shortCode, domain: 'example.com' }, { shortCode: 'foo' }], pagination: { totalItems: 9 }, @@ -85,7 +91,7 @@ describe('shortUrlsListReducer', () => { error: false, }; - expect(reducer(state, { type: CREATE_VISITS, createdVisits } as any)).toEqual({ + expect(reducer(state, { type: createNewVisits.toString(), payload: { createdVisits } })).toEqual({ shortUrls: { data: [ { shortCode, domain: 'example.com', visitsCount: 5 }, @@ -142,7 +148,7 @@ describe('shortUrlsListReducer', () => { error: false, }; - expect(reducer(state, { type: CREATE_SHORT_URL, result: newShortUrl } as any)).toEqual({ + expect(reducer(state, { type: createShortUrl.fulfilled.toString(), payload: newShortUrl })).toEqual({ shortUrls: { data: expectedData, pagination: { totalItems: 16 }, @@ -181,7 +187,7 @@ describe('shortUrlsListReducer', () => { error: false, }; - const result = reducer(state, { type: SHORT_URL_EDITED, shortUrl: editedShortUrl } as any); + const result = reducer(state, { type: editShortUrl.fulfilled.toString(), payload: editedShortUrl }); expect(result.shortUrls?.data).toEqual(expectedList); }); @@ -191,30 +197,29 @@ describe('shortUrlsListReducer', () => { const dispatch = jest.fn(); const getState = jest.fn().mockReturnValue({ selectedServer: {} }); - afterEach(jest.clearAllMocks); - it('dispatches proper actions if API client request succeeds', async () => { - const listShortUrlsMock = jest.fn().mockResolvedValue([]); - const apiClientMock = Mock.of<ShlinkApiClient>({ listShortUrls: listShortUrlsMock }); + listShortUrlsMock.mockResolvedValue({}); - await listShortUrls(() => apiClientMock)()(dispatch, getState); + await listShortUrls()(dispatch, getState, {}); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: LIST_SHORT_URLS_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: LIST_SHORT_URLS, shortUrls: [] }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: listShortUrls.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: listShortUrls.fulfilled.toString(), + payload: {}, + })); expect(listShortUrlsMock).toHaveBeenCalledTimes(1); }); it('dispatches proper actions if API client request fails', async () => { - const listShortUrlsMock = jest.fn().mockRejectedValue(undefined); - const apiClientMock = Mock.of<ShlinkApiClient>({ listShortUrls: listShortUrlsMock }); + listShortUrlsMock.mockRejectedValue(undefined); - await listShortUrls(() => apiClientMock)()(dispatch, getState); + await listShortUrls()(dispatch, getState, {}); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: LIST_SHORT_URLS_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: LIST_SHORT_URLS_ERROR }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: listShortUrls.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ type: listShortUrls.rejected.toString() })); expect(listShortUrlsMock).toHaveBeenCalledTimes(1); }); diff --git a/test/tags/helpers/DeleteTagConfirmModal.test.tsx b/test/tags/helpers/DeleteTagConfirmModal.test.tsx index 8ca667ea..00a7cdf1 100644 --- a/test/tags/helpers/DeleteTagConfirmModal.test.tsx +++ b/test/tags/helpers/DeleteTagConfirmModal.test.tsx @@ -6,14 +6,14 @@ import { renderWithEvents } from '../../__helpers__/setUpTest'; describe('<DeleteTagConfirmModal />', () => { const tag = 'nodejs'; const deleteTag = jest.fn(); - const tagDeleted = jest.fn(); + const toggle = jest.fn(); const setUp = (tagDelete: TagDeletion) => renderWithEvents( <DeleteTagConfirmModal tag={tag} - toggle={() => ''} + toggle={toggle} isOpen deleteTag={deleteTag} - tagDeleted={tagDeleted} + tagDeleted={jest.fn()} tagDelete={tagDelete} />, ); @@ -21,7 +21,7 @@ describe('<DeleteTagConfirmModal />', () => { afterEach(jest.resetAllMocks); it('asks confirmation for provided tag to be deleted', () => { - setUp({ error: false, deleting: false }); + setUp({ error: false, deleted: false, deleting: false }); const delBtn = screen.getByRole('button', { name: 'Delete tag' }); @@ -33,12 +33,12 @@ describe('<DeleteTagConfirmModal />', () => { }); it('shows error message when deletion failed', () => { - setUp({ error: true, deleting: false }); + setUp({ error: true, deleted: false, deleting: false }); expect(screen.getByText('Something went wrong while deleting the tag :(')).toBeInTheDocument(); }); it('shows loading status while deleting', () => { - setUp({ error: false, deleting: true }); + setUp({ error: false, deleted: false, deleting: true }); const delBtn = screen.getByRole('button', { name: 'Deleting tag...' }); @@ -48,22 +48,21 @@ describe('<DeleteTagConfirmModal />', () => { }); it('hides tag modal when btn is clicked', async () => { - const { user } = setUp({ error: false, deleting: false }); + const { user } = setUp({ error: false, deleted: true, deleting: false }); await user.click(screen.getByRole('button', { name: 'Delete tag' })); expect(deleteTag).toHaveBeenCalledTimes(1); expect(deleteTag).toHaveBeenCalledWith(tag); - expect(tagDeleted).toHaveBeenCalledTimes(1); - expect(tagDeleted).toHaveBeenCalledWith(tag); + expect(toggle).toHaveBeenCalledTimes(1); }); it('does no further actions when modal is closed without deleting tag', async () => { - const { user } = setUp({ error: false, deleting: false }); + const { user } = setUp({ error: false, deleted: true, deleting: false }); await user.click(screen.getByLabelText('Close')); expect(deleteTag).not.toHaveBeenCalled(); - expect(tagDeleted).not.toHaveBeenCalled(); + expect(toggle).toHaveBeenCalled(); }); }); diff --git a/test/tags/helpers/EditTagModal.test.tsx b/test/tags/helpers/EditTagModal.test.tsx index d3f11979..b4bc1dbf 100644 --- a/test/tags/helpers/EditTagModal.test.tsx +++ b/test/tags/helpers/EditTagModal.test.tsx @@ -3,18 +3,17 @@ import { Mock } from 'ts-mockery'; import { TagEdition } from '../../../src/tags/reducers/tagEdit'; import { EditTagModal as createEditTagModal } from '../../../src/tags/helpers/EditTagModal'; import { ColorGenerator } from '../../../src/utils/services/ColorGenerator'; -import { ProblemDetailsError } from '../../../src/api/types'; import { renderWithEvents } from '../../__helpers__/setUpTest'; +import { ProblemDetailsError } from '../../../src/api/types/errors'; describe('<EditTagModal />', () => { const EditTagModal = createEditTagModal(Mock.of<ColorGenerator>({ getColorForKey: jest.fn(() => 'green') })); const editTag = jest.fn().mockReturnValue(Promise.resolve()); - const tagEdited = jest.fn().mockReturnValue(Promise.resolve()); const toggle = jest.fn(); const setUp = (tagEdit: Partial<TagEdition> = {}) => { const edition = Mock.of<TagEdition>(tagEdit); return renderWithEvents( - <EditTagModal isOpen tag="foo" tagEdit={edition} editTag={editTag} tagEdited={tagEdited} toggle={toggle} />, + <EditTagModal isOpen tag="foo" tagEdit={edition} editTag={editTag} tagEdited={jest.fn()} toggle={toggle} />, ); }; @@ -30,7 +29,6 @@ describe('<EditTagModal />', () => { expect(toggle).toHaveBeenCalledTimes(2); expect(editTag).not.toHaveBeenCalled(); - expect(tagEdited).not.toHaveBeenCalled(); }); it.each([ @@ -63,12 +61,12 @@ describe('<EditTagModal />', () => { const { user } = setUp(); expect(editTag).not.toHaveBeenCalled(); - expect(tagEdited).not.toHaveBeenCalled(); + expect(toggle).not.toHaveBeenCalled(); await user.click(screen.getByRole('button', { name: 'Save' })); expect(editTag).toHaveBeenCalled(); - expect(tagEdited).toHaveBeenCalled(); + expect(toggle).toHaveBeenCalled(); }); it('changes color when changing on color picker', async () => { diff --git a/test/tags/reducers/tagDelete.test.ts b/test/tags/reducers/tagDelete.test.ts index a4726bf1..3b4bf655 100644 --- a/test/tags/reducers/tagDelete.test.ts +++ b/test/tags/reducers/tagDelete.test.ts @@ -1,34 +1,36 @@ import { Mock } from 'ts-mockery'; -import reducer, { - DELETE_TAG_START, - DELETE_TAG_ERROR, - DELETE_TAG, - TAG_DELETED, - tagDeleted, - deleteTag, -} from '../../../src/tags/reducers/tagDelete'; +import { tagDeleted, tagDeleteReducerCreator } from '../../../src/tags/reducers/tagDelete'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { ShlinkState } from '../../../src/container/types'; describe('tagDeleteReducer', () => { + const deleteTagsCall = jest.fn(); + const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ deleteTags: deleteTagsCall }); + const { reducer, deleteTag } = tagDeleteReducerCreator(buildShlinkApiClient); + + beforeEach(jest.clearAllMocks); + describe('reducer', () => { it('returns loading on DELETE_TAG_START', () => { - expect(reducer(undefined, { type: DELETE_TAG_START })).toEqual({ + expect(reducer(undefined, { type: deleteTag.pending.toString() })).toEqual({ deleting: true, + deleted: false, error: false, }); }); it('returns error on DELETE_TAG_ERROR', () => { - expect(reducer(undefined, { type: DELETE_TAG_ERROR })).toEqual({ + expect(reducer(undefined, { type: deleteTag.rejected.toString() })).toEqual({ deleting: false, + deleted: false, error: true, }); }); it('returns tag names on DELETE_TAG', () => { - expect(reducer(undefined, { type: DELETE_TAG })).toEqual({ + expect(reducer(undefined, { type: deleteTag.fulfilled.toString() })).toEqual({ deleting: false, + deleted: true, error: false, }); }); @@ -37,53 +39,46 @@ describe('tagDeleteReducer', () => { describe('tagDeleted', () => { it('returns action based on provided params', () => expect(tagDeleted('foo')).toEqual({ - type: TAG_DELETED, - tag: 'foo', + type: tagDeleted.toString(), + payload: 'foo', })); }); describe('deleteTag', () => { - const createApiClientMock = (result: Promise<any>) => Mock.of<ShlinkApiClient>({ - deleteTags: jest.fn(async () => result), - }); const dispatch = jest.fn(); const getState = () => Mock.all<ShlinkState>(); - afterEach(() => dispatch.mockReset()); - it('calls API on success', async () => { const tag = 'foo'; - const apiClientMock = createApiClientMock(Promise.resolve()); - const dispatchable = deleteTag(() => apiClientMock)(tag); + deleteTagsCall.mockResolvedValue(undefined); - await dispatchable(dispatch, getState); + await deleteTag(tag)(dispatch, getState, {}); - expect(apiClientMock.deleteTags).toHaveBeenCalledTimes(1); - expect(apiClientMock.deleteTags).toHaveBeenNthCalledWith(1, [tag]); + expect(deleteTagsCall).toHaveBeenCalledTimes(1); + expect(deleteTagsCall).toHaveBeenNthCalledWith(1, [tag]); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: DELETE_TAG_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: DELETE_TAG }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: deleteTag.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ type: deleteTag.fulfilled.toString() })); }); it('throws on error', async () => { const error = 'Error'; const tag = 'foo'; - const apiClientMock = createApiClientMock(Promise.reject(error)); - const dispatchable = deleteTag(() => apiClientMock)(tag); + deleteTagsCall.mockRejectedValue(error); try { - await dispatchable(dispatch, getState); + await deleteTag(tag)(dispatch, getState, {}); } catch (e) { expect(e).toEqual(error); } - expect(apiClientMock.deleteTags).toHaveBeenCalledTimes(1); - expect(apiClientMock.deleteTags).toHaveBeenNthCalledWith(1, [tag]); + expect(deleteTagsCall).toHaveBeenCalledTimes(1); + expect(deleteTagsCall).toHaveBeenNthCalledWith(1, [tag]); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: DELETE_TAG_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: DELETE_TAG_ERROR }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: deleteTag.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ type: deleteTag.rejected.toString() })); }); }); }); diff --git a/test/tags/reducers/tagEdit.test.ts b/test/tags/reducers/tagEdit.test.ts index d000b343..b421c579 100644 --- a/test/tags/reducers/tagEdit.test.ts +++ b/test/tags/reducers/tagEdit.test.ts @@ -1,13 +1,5 @@ import { Mock } from 'ts-mockery'; -import reducer, { - EDIT_TAG_START, - EDIT_TAG_ERROR, - EDIT_TAG, - TAG_EDITED, - tagEdited, - editTag, - EditTagAction, -} from '../../../src/tags/reducers/tagEdit'; +import { tagEdited, editTag as editTagCreator, EditTagAction, tagEditReducerCreator } from '../../../src/tags/reducers/tagEdit'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { ColorGenerator } from '../../../src/utils/services/ColorGenerator'; import { ShlinkState } from '../../../src/container/types'; @@ -16,29 +8,36 @@ describe('tagEditReducer', () => { const oldName = 'foo'; const newName = 'bar'; const color = '#ff0000'; + const editTagCall = jest.fn(); + const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ editTag: editTagCall }); + const colorGenerator = Mock.of<ColorGenerator>({ setColorForKey: jest.fn() }); + const editTag = editTagCreator(buildShlinkApiClient, colorGenerator); + const { reducer } = tagEditReducerCreator(editTag); describe('reducer', () => { it('returns loading on EDIT_TAG_START', () => { - expect(reducer(undefined, Mock.of<EditTagAction>({ type: EDIT_TAG_START }))).toEqual({ + expect(reducer(undefined, Mock.of<EditTagAction>({ type: editTag.pending.toString() }))).toEqual({ editing: true, + edited: false, error: false, - oldName: '', - newName: '', }); }); it('returns error on EDIT_TAG_ERROR', () => { - expect(reducer(undefined, Mock.of<EditTagAction>({ type: EDIT_TAG_ERROR }))).toEqual({ + expect(reducer(undefined, Mock.of<EditTagAction>({ type: editTag.rejected.toString() }))).toEqual({ editing: false, + edited: false, error: true, - oldName: '', - newName: '', }); }); it('returns tag names on EDIT_TAG', () => { - expect(reducer(undefined, { type: EDIT_TAG, oldName, newName, color })).toEqual({ + expect(reducer(undefined, { + type: editTag.fulfilled.toString(), + payload: { oldName, newName, color }, + })).toEqual({ editing: false, + edited: true, error: false, oldName: 'foo', newName: 'bar', @@ -48,62 +47,59 @@ describe('tagEditReducer', () => { describe('tagEdited', () => { it('returns action based on provided params', () => - expect(tagEdited('foo', 'bar', '#ff0000')).toEqual({ - type: TAG_EDITED, - oldName: 'foo', - newName: 'bar', - color: '#ff0000', + expect(tagEdited({ oldName: 'foo', newName: 'bar', color: '#ff0000' })).toEqual({ + type: tagEdited.toString(), + payload: { + oldName: 'foo', + newName: 'bar', + color: '#ff0000', + }, })); }); describe('editTag', () => { - const createApiClientMock = (result: Promise<any>) => Mock.of<ShlinkApiClient>({ - editTag: jest.fn(async () => result), - }); - const colorGenerator = Mock.of<ColorGenerator>({ - setColorForKey: jest.fn(), - }); const dispatch = jest.fn(); const getState = () => Mock.of<ShlinkState>(); afterEach(jest.clearAllMocks); it('calls API on success', async () => { - const apiClientMock = createApiClientMock(Promise.resolve()); - const dispatchable = editTag(() => apiClientMock, colorGenerator)(oldName, newName, color); + editTagCall.mockResolvedValue(undefined); - await dispatchable(dispatch, getState); + await editTag({ oldName, newName, color })(dispatch, getState, {}); - expect(apiClientMock.editTag).toHaveBeenCalledTimes(1); - expect(apiClientMock.editTag).toHaveBeenCalledWith(oldName, newName); + expect(editTagCall).toHaveBeenCalledTimes(1); + expect(editTagCall).toHaveBeenCalledWith(oldName, newName); expect(colorGenerator.setColorForKey).toHaveBeenCalledTimes(1); expect(colorGenerator.setColorForKey).toHaveBeenCalledWith(newName, color); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_TAG_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: EDIT_TAG, oldName, newName }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: editTag.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: editTag.fulfilled.toString(), + payload: { oldName, newName, color }, + })); }); it('throws on error', async () => { const error = 'Error'; - const apiClientMock = createApiClientMock(Promise.reject(error)); - const dispatchable = editTag(() => apiClientMock, colorGenerator)(oldName, newName, color); + editTagCall.mockRejectedValue(error); try { - await dispatchable(dispatch, getState); + await editTag({ oldName, newName, color })(dispatch, getState, {}); } catch (e) { expect(e).toEqual(error); } - expect(apiClientMock.editTag).toHaveBeenCalledTimes(1); - expect(apiClientMock.editTag).toHaveBeenCalledWith(oldName, newName); + expect(editTagCall).toHaveBeenCalledTimes(1); + expect(editTagCall).toHaveBeenCalledWith(oldName, newName); expect(colorGenerator.setColorForKey).not.toHaveBeenCalled(); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_TAG_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: EDIT_TAG_ERROR }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: editTag.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ type: editTag.rejected.toString() })); }); }); }); diff --git a/test/tags/reducers/tagsList.test.ts b/test/tags/reducers/tagsList.test.ts index 767cdc3d..2bea89bf 100644 --- a/test/tags/reducers/tagsList.test.ts +++ b/test/tags/reducers/tagsList.test.ts @@ -1,32 +1,35 @@ import { Mock } from 'ts-mockery'; -import reducer, { - FILTER_TAGS, - filterTags, - LIST_TAGS, - LIST_TAGS_ERROR, - LIST_TAGS_START, - listTags, +import { TagsList, + filterTags, + listTags as listTagsCreator, + tagsListReducerCreator, } from '../../../src/tags/reducers/tagsList'; -import { TAG_DELETED } from '../../../src/tags/reducers/tagDelete'; -import { TAG_EDITED } from '../../../src/tags/reducers/tagEdit'; import { ShlinkState } from '../../../src/container/types'; import { ShortUrl } from '../../../src/short-urls/data'; -import { CREATE_SHORT_URL } from '../../../src/short-urls/reducers/shortUrlCreation'; +import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation'; +import { tagEdited } from '../../../src/tags/reducers/tagEdit'; +import { tagDeleted } from '../../../src/tags/reducers/tagDelete'; describe('tagsListReducer', () => { const state = (props: Partial<TagsList>) => Mock.of<TagsList>(props); + const buildShlinkApiClient = jest.fn(); + const listTags = listTagsCreator(buildShlinkApiClient, true); + const createShortUrl = createShortUrlCreator(buildShlinkApiClient); + const { reducer } = tagsListReducerCreator(listTags, createShortUrl); + + afterEach(jest.clearAllMocks); describe('reducer', () => { it('returns loading on LIST_TAGS_START', () => { - expect(reducer(undefined, { type: LIST_TAGS_START } as any)).toEqual(expect.objectContaining({ + expect(reducer(undefined, { type: listTags.pending.toString() })).toEqual(expect.objectContaining({ loading: true, error: false, })); }); it('returns error on LIST_TAGS_ERROR', () => { - expect(reducer(undefined, { type: LIST_TAGS_ERROR } as any)).toEqual(expect.objectContaining({ + expect(reducer(undefined, { type: listTags.rejected.toString() })).toEqual(expect.objectContaining({ loading: false, error: true, })); @@ -35,7 +38,10 @@ describe('tagsListReducer', () => { it('returns provided tags as filtered and regular tags on LIST_TAGS', () => { const tags = ['foo', 'bar', 'baz']; - expect(reducer(undefined, { type: LIST_TAGS, tags } as any)).toEqual({ + expect(reducer(undefined, { + type: listTags.fulfilled.toString(), + payload: { tags }, + })).toEqual({ tags, filteredTags: tags, loading: false, @@ -48,7 +54,10 @@ describe('tagsListReducer', () => { const tag = 'foo'; const expectedTags = ['bar', 'baz']; - expect(reducer(state({ tags, filteredTags: tags }), { type: TAG_DELETED, tag } as any)).toEqual({ + expect(reducer( + state({ tags, filteredTags: tags }), + { type: tagDeleted.toString(), payload: tag }, + )).toEqual({ tags: expectedTags, filteredTags: expectedTags, }); @@ -60,18 +69,40 @@ describe('tagsListReducer', () => { const newName = 'renamed'; const expectedTags = ['foo', 'renamed', 'baz'].sort(); - expect(reducer(state({ tags, filteredTags: tags }), { type: TAG_EDITED, oldName, newName } as any)).toEqual({ + expect(reducer( + state({ + tags, + filteredTags: tags, + stats: { + [oldName]: { + shortUrlsCount: 35, + visitsCount: 35, + }, + }, + }), + { type: tagEdited.toString(), payload: { oldName, newName } }, + )).toEqual({ tags: expectedTags, filteredTags: expectedTags, + stats: { + [oldName]: { + shortUrlsCount: 35, + visitsCount: 35, + }, + [newName]: { + shortUrlsCount: 35, + visitsCount: 35, + }, + }, }); }); it('filters original list of tags by provided search term on FILTER_TAGS', () => { const tags = ['foo', 'bar', 'baz', 'Foo2', 'fo']; - const searchTerm = 'Fo'; + const payload = 'Fo'; const filteredTags = ['foo', 'Foo2', 'fo']; - expect(reducer(state({ tags }), { type: FILTER_TAGS, searchTerm } as any)).toEqual({ + expect(reducer(state({ tags }), { type: filterTags.toString(), payload })).toEqual({ tags, filteredTags, }); @@ -83,33 +114,30 @@ describe('tagsListReducer', () => { [['new', 'tag'], ['foo', 'bar', 'baz', 'foo2', 'fo', 'new', 'tag']], ])('appends new short URL\'s tags to the list of tags on CREATE_SHORT_URL', (shortUrlTags, expectedTags) => { const tags = ['foo', 'bar', 'baz', 'foo2', 'fo']; - const result = Mock.of<ShortUrl>({ tags: shortUrlTags }); + const payload = Mock.of<ShortUrl>({ tags: shortUrlTags }); - expect(reducer(state({ tags }), { type: CREATE_SHORT_URL, result } as any)).toEqual({ + expect(reducer(state({ tags }), { type: createShortUrl.fulfilled.toString(), payload })).toEqual({ tags: expectedTags, }); }); }); describe('filterTags', () => { - it('creates expected action', () => expect(filterTags('foo')).toEqual({ type: FILTER_TAGS, searchTerm: 'foo' })); + it('creates expected action', () => expect(filterTags('foo')).toEqual({ type: filterTags.toString(), payload: 'foo' })); }); describe('listTags', () => { const dispatch = jest.fn(); const getState = jest.fn(() => Mock.all<ShlinkState>()); - const buildShlinkApiClient = jest.fn(); const listTagsMock = jest.fn(); - afterEach(jest.clearAllMocks); - const assertNoAction = async (tagsList: TagsList) => { getState.mockReturnValue(Mock.of<ShlinkState>({ tagsList })); - await listTags(buildShlinkApiClient, false)()(dispatch, getState); + await listTagsCreator(buildShlinkApiClient, false)()(dispatch, getState, {}); expect(buildShlinkApiClient).not.toHaveBeenCalled(); - expect(dispatch).not.toHaveBeenCalled(); + expect(dispatch).toHaveBeenCalledTimes(2); expect(getState).toHaveBeenCalledTimes(1); }; @@ -125,23 +153,26 @@ describe('tagsListReducer', () => { listTagsMock.mockResolvedValue({ tags, stats: [] }); buildShlinkApiClient.mockReturnValue({ listTags: listTagsMock }); - await listTags(buildShlinkApiClient, true)()(dispatch, getState); + await listTags()(dispatch, getState, {}); expect(buildShlinkApiClient).toHaveBeenCalledTimes(1); expect(getState).toHaveBeenCalledTimes(1); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: LIST_TAGS_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: LIST_TAGS, tags, stats: {} }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: listTags.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: listTags.fulfilled.toString(), + payload: { tags, stats: {} }, + })); }); const assertErrorResult = async () => { - await listTags(buildShlinkApiClient, true)()(dispatch, getState); + await listTags()(dispatch, getState, {}); expect(buildShlinkApiClient).toHaveBeenCalledTimes(1); expect(getState).toHaveBeenCalledTimes(1); expect(dispatch).toHaveBeenCalledTimes(2); - expect(dispatch).toHaveBeenNthCalledWith(1, { type: LIST_TAGS_START }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: LIST_TAGS_ERROR }); + expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: listTags.pending.toString() })); + expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ type: listTags.rejected.toString() })); }; it('dispatches error when error occurs on list call', async () => { @@ -159,7 +190,6 @@ describe('tagsListReducer', () => { }); await assertErrorResult(); - expect(listTagsMock).not.toHaveBeenCalled(); }); }); diff --git a/test/utils/DropdownBtn.test.tsx b/test/utils/DropdownBtn.test.tsx index cfca2128..36d820a8 100644 --- a/test/utils/DropdownBtn.test.tsx +++ b/test/utils/DropdownBtn.test.tsx @@ -40,7 +40,7 @@ describe('<DropdownBtn />', () => { await user.click(screen.getByRole('button')); expect(screen.getByRole('menu')).toHaveAttribute( 'style', - `${expectedStyle}position: absolute; left: 0px; top: 0px;`, + `${expectedStyle}position: absolute; left: 0px; top: 0px; transform: translate(0px, 0px);`, ); }); }); diff --git a/test/utils/__snapshots__/ExportBtn.test.tsx.snap b/test/utils/__snapshots__/ExportBtn.test.tsx.snap index 7484fe5b..466ba0f7 100644 --- a/test/utils/__snapshots__/ExportBtn.test.tsx.snap +++ b/test/utils/__snapshots__/ExportBtn.test.tsx.snap @@ -12,7 +12,7 @@ exports[`<ExportBtn /> renders expected icon 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M256 0v128h128L256 0zM224 128L224 0H48C21.49 0 0 21.49 0 48v416C0 490.5 21.49 512 48 512h288c26.51 0 48-21.49 48-48V160h-127.1C238.3 160 224 145.7 224 128zM128 280C128 284.4 124.4 288 120 288H112C103.1 288 96 295.1 96 304v32C96 344.9 103.1 352 112 352h8C124.4 352 128 355.6 128 360v16C128 380.4 124.4 384 120 384H112C85.5 384 64 362.5 64 336v-32C64 277.5 85.5 256 112 256h8C124.4 256 128 259.6 128 264V280zM172.3 384H160c-4.375 0-8-3.625-8-8v-16C152 355.6 155.6 352 160 352h12.25c6 0 10.38-3.5 10.38-6.625c0-1.25-.75-2.625-2.125-3.875l-21.88-18.75C150.3 315.5 145.4 305.3 145.4 294.6C145.4 273.4 164.4 256 187.8 256H200c4.375 0 8 3.625 8 8v16C208 284.4 204.4 288 200 288H187.8c-6 0-10.38 3.5-10.38 6.625c0 1.25 .75 2.625 2.125 3.875l21.88 18.75c8.375 7.25 13.25 17.5 13.25 28.12C214.6 366.6 195.6 384 172.3 384zM288 284.8V264C288 259.6 291.6 256 296 256h16C316.4 256 320 259.6 320 264v20.75c0 35.5-12.88 69-36.25 94.13C280.8 382.1 276.5 384 272 384s-8.75-1.875-11.75-5.125C236.9 353.8 224 320.3 224 284.8V264C224 259.6 227.6 256 232 256h16C252.4 256 256 259.6 256 264v20.75c0 20.38 5.75 40.25 16 56.88C282.3 325 288 305.1 288 284.8z" + d="M64 0C28.7 0 0 28.7 0 64V448c0 35.3 28.7 64 64 64H320c35.3 0 64-28.7 64-64V160H256c-17.7 0-32-14.3-32-32V0H64zM256 0V128H384L256 0zM80 224H96c22.1 0 40 17.9 40 40v8c0 8.8-7.2 16-16 16s-16-7.2-16-16v-8c0-4.4-3.6-8-8-8H80c-4.4 0-8 3.6-8 8v80c0 4.4 3.6 8 8 8H96c4.4 0 8-3.6 8-8v-8c0-8.8 7.2-16 16-16s16 7.2 16 16v8c0 22.1-17.9 40-40 40H80c-22.1 0-40-17.9-40-40V264c0-22.1 17.9-40 40-40zm72 46.4c0-25.6 20.8-46.4 46.4-46.4H216c8.8 0 16 7.2 16 16s-7.2 16-16 16H198.4c-7.9 0-14.4 6.4-14.4 14.4c0 5.2 2.8 9.9 7.2 12.5l25.4 14.5c14.4 8.3 23.4 23.6 23.4 40.3c0 25.6-20.8 46.4-46.4 46.4H168c-8.8 0-16-7.2-16-16s7.2-16 16-16h25.6c7.9 0 14.4-6.4 14.4-14.4c0-5.2-2.8-9.9-7.2-12.5l-25.4-14.5C160.9 302.4 152 287 152 270.4zM280 240v31.6c0 23 5.5 45.6 16 66c10.5-20.3 16-42.9 16-66V240c0-8.8 7.2-16 16-16s16 7.2 16 16v31.6c0 34.7-10.3 68.7-29.6 97.6l-5.1 7.7c-3 4.5-8 7.1-13.3 7.1s-10.3-2.7-13.3-7.1l-5.1-7.7c-19.3-28.9-29.6-62.9-29.6-97.6V240c0-8.8 7.2-16 16-16s16 7.2 16 16z" fill="currentColor" /> </svg> diff --git a/test/utils/DateInput.test.tsx b/test/utils/dates/DateInput.test.tsx similarity index 68% rename from test/utils/DateInput.test.tsx rename to test/utils/dates/DateInput.test.tsx index e036433c..525b0652 100644 --- a/test/utils/DateInput.test.tsx +++ b/test/utils/dates/DateInput.test.tsx @@ -1,7 +1,8 @@ import { screen, waitFor } from '@testing-library/react'; import { Mock } from 'ts-mockery'; -import { DateInput, DateInputProps } from '../../src/utils/DateInput'; -import { renderWithEvents } from '../__helpers__/setUpTest'; +import { parseISO } from 'date-fns'; +import { DateInput, DateInputProps } from '../../../src/utils/dates/DateInput'; +import { renderWithEvents } from '../../__helpers__/setUpTest'; describe('<DateInput />', () => { const setUp = (props: Partial<DateInputProps> = {}) => renderWithEvents( @@ -30,4 +31,14 @@ describe('<DateInput />', () => { await user.click(screen.getByPlaceholderText('foo')); await waitFor(() => expect(container.querySelector('.react-datepicker')).toBeInTheDocument()); }); + + it.each([ + [undefined, '2022-01-01'], + ['yyyy-MM-dd', '2022-01-01'], + ['yyyy-MM-dd HH:mm', '2022-01-01 15:18'], + ['HH:mm:ss', '15:18:36'], + ])('shows date in expected format', (dateFormat, expectedValue) => { + setUp({ placeholderText: 'foo', selected: parseISO('2022-01-01T15:18:36'), dateFormat }); + expect(screen.getByPlaceholderText('foo')).toHaveValue(expectedValue); + }); }); diff --git a/test/utils/dates/DateIntervalDropdownItems.test.tsx b/test/utils/dates/DateIntervalDropdownItems.test.tsx index 0e9ec52f..66a909aa 100644 --- a/test/utils/dates/DateIntervalDropdownItems.test.tsx +++ b/test/utils/dates/DateIntervalDropdownItems.test.tsx @@ -1,6 +1,6 @@ import { screen, waitFor } from '@testing-library/react'; import { DateIntervalDropdownItems } from '../../../src/utils/dates/DateIntervalDropdownItems'; -import { DATE_INTERVALS, DateInterval, rangeOrIntervalToString } from '../../../src/utils/dates/types'; +import { DATE_INTERVALS, DateInterval, rangeOrIntervalToString } from '../../../src/utils/helpers/dateIntervals'; import { DropdownBtn } from '../../../src/utils/DropdownBtn'; import { renderWithEvents } from '../../__helpers__/setUpTest'; diff --git a/test/utils/dates/DateIntervalSelector.test.tsx b/test/utils/dates/DateIntervalSelector.test.tsx index ebff24a1..975159c7 100644 --- a/test/utils/dates/DateIntervalSelector.test.tsx +++ b/test/utils/dates/DateIntervalSelector.test.tsx @@ -1,5 +1,5 @@ import { screen, waitFor } from '@testing-library/react'; -import { DateInterval, rangeOrIntervalToString } from '../../../src/utils/dates/types'; +import { DateInterval, rangeOrIntervalToString } from '../../../src/utils/helpers/dateIntervals'; import { DateIntervalSelector } from '../../../src/utils/dates/DateIntervalSelector'; import { renderWithEvents } from '../../__helpers__/setUpTest'; diff --git a/test/utils/dates/DateRangeSelector.test.tsx b/test/utils/dates/DateRangeSelector.test.tsx index c776cec9..858d06c0 100644 --- a/test/utils/dates/DateRangeSelector.test.tsx +++ b/test/utils/dates/DateRangeSelector.test.tsx @@ -1,7 +1,7 @@ import { screen, waitFor } from '@testing-library/react'; import { Mock } from 'ts-mockery'; import { DateRangeSelector, DateRangeSelectorProps } from '../../../src/utils/dates/DateRangeSelector'; -import { DateInterval } from '../../../src/utils/dates/types'; +import { DateInterval } from '../../../src/utils/helpers/dateIntervals'; import { renderWithEvents } from '../../__helpers__/setUpTest'; describe('<DateRangeSelector />', () => { diff --git a/test/utils/Time.test.tsx b/test/utils/dates/Time.test.tsx similarity index 87% rename from test/utils/Time.test.tsx rename to test/utils/dates/Time.test.tsx index cb1f9c8f..38b38a47 100644 --- a/test/utils/Time.test.tsx +++ b/test/utils/dates/Time.test.tsx @@ -1,6 +1,6 @@ import { render } from '@testing-library/react'; -import { TimeProps, Time } from '../../src/utils/Time'; -import { parseDate } from '../../src/utils/helpers/date'; +import { TimeProps, Time } from '../../../src/utils/dates/Time'; +import { parseDate } from '../../../src/utils/helpers/date'; describe('<Time />', () => { const setUp = (props: TimeProps) => render(<Time {...props} />); diff --git a/test/utils/dates/types/index.test.ts b/test/utils/helpers/dateIntervals.test.ts similarity index 80% rename from test/utils/dates/types/index.test.ts rename to test/utils/helpers/dateIntervals.test.ts index 7d436bae..37ebe6ff 100644 --- a/test/utils/dates/types/index.test.ts +++ b/test/utils/helpers/dateIntervals.test.ts @@ -6,8 +6,9 @@ import { intervalToDateRange, rangeIsInterval, rangeOrIntervalToString, -} from '../../../../src/utils/dates/types'; -import { parseDate } from '../../../../src/utils/helpers/date'; + toDateRange, +} from '../../../src/utils/helpers/dateIntervals'; +import { parseDate } from '../../../src/utils/helpers/date'; describe('date-types', () => { const now = () => new Date(); @@ -116,4 +117,23 @@ describe('date-types', () => { expect(dateToMatchingInterval(date)).toEqual(expectedInterval); }); }); + + describe('toDateRange', () => { + it.each([ + ['today' as DateInterval, intervalToDateRange('today')], + ['yesterday' as DateInterval, intervalToDateRange('yesterday')], + ['last7Days' as DateInterval, intervalToDateRange('last7Days')], + ['last30Days' as DateInterval, intervalToDateRange('last30Days')], + ['last90Days' as DateInterval, intervalToDateRange('last90Days')], + ['last180Days' as DateInterval, intervalToDateRange('last180Days')], + ['last365Days' as DateInterval, intervalToDateRange('last365Days')], + ['all' as DateInterval, intervalToDateRange('all')], + [{}, {}], + [{ startDate: now() }, { startDate: now() }], + [{ endDate: now() }, { endDate: now() }], + [{ startDate: daysBack(10), endDate: now() }, { startDate: daysBack(10), endDate: now() }], + ])('returns properly parsed interval or range', (rangeOrInterval, expectedResult) => { + expect(toDateRange(rangeOrInterval)).toEqual(expectedResult); + }); + }); }); diff --git a/test/utils/helpers/redux.test.ts b/test/utils/helpers/redux.test.ts deleted file mode 100644 index 69c0bc82..00000000 --- a/test/utils/helpers/redux.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Action } from 'redux'; -import { buildActionCreator, buildReducer } from '../../../src/utils/helpers/redux'; - -describe('redux', () => { - beforeEach(jest.clearAllMocks); - - describe('buildActionCreator', () => { - it.each([ - ['foo', { type: 'foo' }], - ['bar', { type: 'bar' }], - ['something', { type: 'something' }], - ])('returns an action creator', (type, expected) => { - const actionCreator = buildActionCreator(type); - - expect(actionCreator).toBeInstanceOf(Function); - expect(actionCreator()).toEqual(expected); - }); - }); - - describe('buildReducer', () => { - const fooActionHandler = jest.fn(() => 'foo result'); - const barActionHandler = jest.fn(() => 'bar result'); - const initialState = 'initial state'; - let reducer: Function; - - beforeEach(() => { - reducer = buildReducer<string, Action>({ - foo: fooActionHandler, - bar: barActionHandler, - }, initialState); - }); - - it('returns a reducer which returns initial state when provided with unknown action', () => { - expect(reducer(undefined, { type: 'unknown action' })).toEqual(initialState); - expect(fooActionHandler).not.toHaveBeenCalled(); - expect(barActionHandler).not.toHaveBeenCalled(); - }); - - it.each([ - ['foo', 'foo result', fooActionHandler, barActionHandler], - ['bar', 'bar result', barActionHandler, fooActionHandler], - ])( - 'returns a reducer which calls corresponding action handler', - (type, expected, invokedActionHandler, notInvokedActionHandler) => { - expect(reducer(undefined, { type })).toEqual(expected); - expect(invokedActionHandler).toHaveBeenCalled(); - expect(notInvokedActionHandler).not.toHaveBeenCalled(); - }, - ); - - it.each([ - [undefined, initialState], - ['foo', 'foo'], - ['something', 'something'], - ])('returns a reducer which calls action handler with provided state or initial', (state, expected) => { - reducer(state, { type: 'foo' }); - - expect(fooActionHandler).toHaveBeenCalledWith(expected, expect.anything()); - }); - }); -}); diff --git a/test/utils/table/__snapshots__/TableOrderIcon.test.tsx.snap b/test/utils/table/__snapshots__/TableOrderIcon.test.tsx.snap index ba31f4f9..b5a3a467 100644 --- a/test/utils/table/__snapshots__/TableOrderIcon.test.tsx.snap +++ b/test/utils/table/__snapshots__/TableOrderIcon.test.tsx.snap @@ -12,7 +12,7 @@ exports[`<TableOrderIcon /> renders an icon when all conditions are met 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M310.6 246.6l-127.1 128C176.4 380.9 168.2 384 160 384s-16.38-3.125-22.63-9.375l-127.1-128C.2244 237.5-2.516 223.7 2.438 211.8S19.07 192 32 192h255.1c12.94 0 24.62 7.781 29.58 19.75S319.8 237.5 310.6 246.6z" + d="M137.4 374.6c12.5 12.5 32.8 12.5 45.3 0l128-128c9.2-9.2 11.9-22.9 6.9-34.9s-16.6-19.8-29.6-19.8L32 192c-12.9 0-24.6 7.8-29.6 19.8s-2.2 25.7 6.9 34.9l128 128z" fill="currentColor" /> </svg> @@ -30,7 +30,7 @@ exports[`<TableOrderIcon /> renders an icon when all conditions are met 2`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M9.39 265.4l127.1-128C143.6 131.1 151.8 128 160 128s16.38 3.125 22.63 9.375l127.1 128c9.156 9.156 11.9 22.91 6.943 34.88S300.9 320 287.1 320H32.01c-12.94 0-24.62-7.781-29.58-19.75S.2333 274.5 9.39 265.4z" + d="M182.6 137.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8H288c12.9 0 24.6-7.8 29.6-19.8s2.2-25.7-6.9-34.9l-128-128z" fill="currentColor" /> </svg> diff --git a/test/visits/DomainVisits.test.tsx b/test/visits/DomainVisits.test.tsx index 19be1892..c8b17e0b 100644 --- a/test/visits/DomainVisits.test.tsx +++ b/test/visits/DomainVisits.test.tsx @@ -38,7 +38,7 @@ describe('<DomainVisits />', () => { it('wraps visits stats and header', () => { setUp(); expect(screen.getByRole('heading', { name: '"foo.com" visits' })).toBeInTheDocument(); - expect(getDomainVisits).toHaveBeenCalledWith('DEFAULT', expect.anything(), expect.anything()); + expect(getDomainVisits).toHaveBeenCalledWith(expect.objectContaining({ domain: 'DEFAULT' })); }); it('exports visits when clicking the button', async () => { diff --git a/test/visits/NonOrphanVisits.test.tsx b/test/visits/NonOrphanVisits.test.tsx index 1c3572de..a4eb1a9b 100644 --- a/test/visits/NonOrphanVisits.test.tsx +++ b/test/visits/NonOrphanVisits.test.tsx @@ -4,11 +4,12 @@ import { Mock } from 'ts-mockery'; import { formatISO } from 'date-fns'; import { NonOrphanVisits as createNonOrphanVisits } from '../../src/visits/NonOrphanVisits'; import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub'; -import { Visit, VisitsInfo } from '../../src/visits/types'; +import { Visit } from '../../src/visits/types'; import { Settings } from '../../src/settings/reducers/settings'; import { ReportExporter } from '../../src/common/services/ReportExporter'; import { SelectedServer } from '../../src/servers/data'; import { renderWithEvents } from '../__helpers__/setUpTest'; +import { VisitsInfo } from '../../src/visits/reducers/types'; describe('<NonOrphanVisits />', () => { const exportVisits = jest.fn(); diff --git a/test/visits/OrphanVisits.test.tsx b/test/visits/OrphanVisits.test.tsx index 6f92edf4..005445cf 100644 --- a/test/visits/OrphanVisits.test.tsx +++ b/test/visits/OrphanVisits.test.tsx @@ -4,11 +4,12 @@ import { Mock } from 'ts-mockery'; import { formatISO } from 'date-fns'; import { OrphanVisits as createOrphanVisits } from '../../src/visits/OrphanVisits'; import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub'; -import { Visit, VisitsInfo } from '../../src/visits/types'; +import { Visit } from '../../src/visits/types'; import { Settings } from '../../src/settings/reducers/settings'; import { ReportExporter } from '../../src/common/services/ReportExporter'; import { SelectedServer } from '../../src/servers/data'; import { renderWithEvents } from '../__helpers__/setUpTest'; +import { VisitsInfo } from '../../src/visits/reducers/types'; describe('<OrphanVisits />', () => { const getOrphanVisits = jest.fn(); diff --git a/test/visits/VisitsStats.test.tsx b/test/visits/VisitsStats.test.tsx index 8bd2fb8f..7498ddec 100644 --- a/test/visits/VisitsStats.test.tsx +++ b/test/visits/VisitsStats.test.tsx @@ -1,13 +1,14 @@ -import { screen } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import { Mock } from 'ts-mockery'; import { Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import { VisitsStats } from '../../src/visits/VisitsStats'; -import { Visit, VisitsInfo } from '../../src/visits/types'; +import { Visit } from '../../src/visits/types'; import { Settings } from '../../src/settings/reducers/settings'; -import { SelectedServer } from '../../src/servers/data'; +import { ReachableServer } from '../../src/servers/data'; import { renderWithEvents } from '../__helpers__/setUpTest'; import { rangeOf } from '../../src/utils/utils'; +import { VisitsInfo } from '../../src/visits/reducers/types'; describe('<VisitsStats />', () => { const visits = rangeOf(3, () => Mock.of<Visit>({ date: '2020-01-01' })); @@ -17,18 +18,21 @@ describe('<VisitsStats />', () => { const history = createMemoryHistory(); history.push(activeRoute); - return renderWithEvents( - <Router location={history.location} navigator={history}> - <VisitsStats - getVisits={getVisitsMock} - visitsInfo={Mock.of<VisitsInfo>(visitsInfo)} - cancelGetVisits={() => {}} - settings={Mock.all<Settings>()} - exportCsv={exportCsv} - selectedServer={Mock.all<SelectedServer>()} - /> - </Router>, - ); + return { + history, + ...renderWithEvents( + <Router location={history.location} navigator={history}> + <VisitsStats + getVisits={getVisitsMock} + visitsInfo={Mock.of<VisitsInfo>(visitsInfo)} + cancelGetVisits={() => {}} + settings={Mock.all<Settings>()} + exportCsv={exportCsv} + selectedServer={Mock.of<ReachableServer>({ version: '3.0.0' })} + /> + </Router>, + ), + }; }; it('renders a preloader when visits are loading', () => { @@ -80,4 +84,24 @@ describe('<VisitsStats />', () => { await user.click(screen.getByRole('button', { name: /Export/ })); expect(exportCsv).toHaveBeenCalled(); }); + + it('sets filters in query string', async () => { + const { history, user } = setUp({ visits }); + const expectSearchContains = (contains: string[]) => { + expect(contains).not.toHaveLength(0); + contains.forEach((entry) => expect(history.location.search).toContain(entry)); + }; + + expect(history.location.search).toEqual(''); + + await user.click(screen.getByRole('button', { name: /Filters/ })); + await waitFor(() => screen.getByRole('menu')); + await user.click(screen.getByRole('menuitem', { name: 'Exclude potential bots' })); + expectSearchContains(['excludeBots=true']); + + await user.click(screen.getByRole('button', { name: /Last 30 days/ })); + await waitFor(() => screen.getByRole('menu')); + await user.click(screen.getByRole('menuitem', { name: /Last 180 days/ })); + expectSearchContains(['startDate', 'endDate']); + }); }); diff --git a/test/visits/charts/__snapshots__/DoughnutChart.test.tsx.snap b/test/visits/charts/__snapshots__/DoughnutChart.test.tsx.snap index dc824989..2bfc371b 100644 --- a/test/visits/charts/__snapshots__/DoughnutChart.test.tsx.snap +++ b/test/visits/charts/__snapshots__/DoughnutChart.test.tsx.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`<DoughnutChart /> renders Doughnut with expected props 1`] = ` -Array [ - Object { - "props": Object { +[ + { + "props": { "a": 1, "b": 0, "c": 0, @@ -11,7 +11,7 @@ Array [ "e": 0, "f": 0, }, - "transform": Array [ + "transform": [ 1, 0, 0, diff --git a/test/visits/charts/__snapshots__/HorizontalBarChart.test.tsx.snap b/test/visits/charts/__snapshots__/HorizontalBarChart.test.tsx.snap index 62b5e81f..28b01a3f 100644 --- a/test/visits/charts/__snapshots__/HorizontalBarChart.test.tsx.snap +++ b/test/visits/charts/__snapshots__/HorizontalBarChart.test.tsx.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`<HorizontalBarChart /> renders chart with expected canvas 1`] = ` -Array [ - Object { - "props": Object { +[ + { + "props": { "a": 1, "b": 0, "c": 0, @@ -11,7 +11,7 @@ Array [ "e": 0, "f": 0, }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -21,11 +21,11 @@ Array [ ], "type": "setTransform", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -35,11 +35,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "foo", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -49,11 +49,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -63,11 +63,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "bar", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -77,11 +77,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -91,11 +91,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -105,11 +105,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "0", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -119,11 +119,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -133,11 +133,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "500", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -147,11 +147,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -165,9 +165,9 @@ Array [ `; exports[`<HorizontalBarChart /> renders chart with expected canvas 2`] = ` -Array [ - Object { - "props": Object { +[ + { + "props": { "a": 1, "b": 0, "c": 0, @@ -175,7 +175,7 @@ Array [ "e": 0, "f": 0, }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -185,11 +185,11 @@ Array [ ], "type": "setTransform", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -199,11 +199,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "one", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -213,11 +213,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -227,11 +227,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "two", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -241,11 +241,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -255,11 +255,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -269,11 +269,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "0", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -283,11 +283,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -297,11 +297,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "200,000", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -311,11 +311,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -329,9 +329,9 @@ Array [ `; exports[`<HorizontalBarChart /> renders chart with expected canvas 3`] = ` -Array [ - Object { - "props": Object { +[ + { + "props": { "a": 1, "b": 0, "c": 0, @@ -339,7 +339,7 @@ Array [ "e": 0, "f": 0, }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -349,11 +349,11 @@ Array [ ], "type": "setTransform", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -363,11 +363,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "one", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -377,11 +377,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -391,11 +391,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "two", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -405,11 +405,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -419,11 +419,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "max", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -433,11 +433,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -447,11 +447,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -461,11 +461,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "0", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -475,11 +475,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -489,11 +489,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "200,000", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -503,11 +503,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, diff --git a/test/visits/charts/__snapshots__/LineChartCard.test.tsx.snap b/test/visits/charts/__snapshots__/LineChartCard.test.tsx.snap index 105b15cf..6e049e38 100644 --- a/test/visits/charts/__snapshots__/LineChartCard.test.tsx.snap +++ b/test/visits/charts/__snapshots__/LineChartCard.test.tsx.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`<LineChartCard /> renders chart with expected data 1`] = ` -Array [ - Object { - "props": Object { +[ + { + "props": { "a": 1, "b": 0, "c": 0, @@ -11,7 +11,7 @@ Array [ "e": 0, "f": 0, }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -21,11 +21,11 @@ Array [ ], "type": "setTransform", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -35,11 +35,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "0", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -49,11 +49,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -63,11 +63,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "1", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -77,11 +77,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -95,9 +95,9 @@ Array [ `; exports[`<LineChartCard /> renders chart with expected data 2`] = ` -Array [ - Object { - "props": Object { +[ + { + "props": { "a": 1, "b": 0, "c": 0, @@ -105,7 +105,7 @@ Array [ "e": 0, "f": 0, }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -115,11 +115,11 @@ Array [ ], "type": "setTransform", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -129,11 +129,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "0", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -143,11 +143,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -157,11 +157,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "1", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -171,11 +171,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -189,9 +189,9 @@ Array [ `; exports[`<LineChartCard /> renders chart with expected data 3`] = ` -Array [ - Object { - "props": Object { +[ + { + "props": { "a": 1, "b": 0, "c": 0, @@ -199,7 +199,7 @@ Array [ "e": 0, "f": 0, }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -209,11 +209,11 @@ Array [ ], "type": "setTransform", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -223,11 +223,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "0", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -237,11 +237,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -251,11 +251,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "1", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -265,11 +265,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -279,11 +279,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -293,11 +293,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "2016-04", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -307,11 +307,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -325,9 +325,9 @@ Array [ `; exports[`<LineChartCard /> renders chart with expected data 4`] = ` -Array [ - Object { - "props": Object { +[ + { + "props": { "a": 1, "b": 0, "c": 0, @@ -335,7 +335,7 @@ Array [ "e": 0, "f": 0, }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -345,11 +345,11 @@ Array [ ], "type": "setTransform", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -359,11 +359,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "0", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -373,11 +373,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -387,11 +387,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "1", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -401,11 +401,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -415,11 +415,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -429,11 +429,11 @@ Array [ ], "type": "font", }, - Object { - "props": Object { + { + "props": { "text": "2016-04", }, - "transform": Array [ + "transform": [ 1, 0, 0, @@ -443,11 +443,11 @@ Array [ ], "type": "measureText", }, - Object { - "props": Object { - "value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif", + { + "props": { + "value": "12px "Helvetica Neue", 'Helvetica', 'Arial', sans-serif", }, - "transform": Array [ + "transform": [ 1, 0, 0, diff --git a/test/visits/charts/__snapshots__/SortableBarChartCard.test.tsx.snap b/test/visits/charts/__snapshots__/SortableBarChartCard.test.tsx.snap index a5274662..175b4f45 100644 --- a/test/visits/charts/__snapshots__/SortableBarChartCard.test.tsx.snap +++ b/test/visits/charts/__snapshots__/SortableBarChartCard.test.tsx.snap @@ -47,7 +47,7 @@ exports[`<SortableBarChartCard /> renders properly ordered stats when ordering i xmlns="http://www.w3.org/2000/svg" > <path - d="M416 288h-95.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H416c17.67 0 32-14.33 32-32S433.7 288 416 288zM352 416h-32c-17.67 0-32 14.33-32 32s14.33 32 32 32h32c17.67 0 31.1-14.33 31.1-32S369.7 416 352 416zM480 160h-159.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H480c17.67 0 32-14.33 32-32S497.7 160 480 160zM544 32h-223.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H544c17.67 0 32-14.33 32-32S561.7 32 544 32zM151.6 41.95c-12.12-13.26-35.06-13.26-47.19 0l-87.1 96.09C4.475 151.1 5.35 171.4 18.38 183.3c6.141 5.629 13.89 8.414 21.61 8.414c8.672 0 17.3-3.504 23.61-10.39L96 145.9v302C96 465.7 110.3 480 128 480s32-14.33 32-32.03V145.9L192.4 181.3C204.4 194.3 224.6 195.3 237.6 183.3c13.03-11.95 13.9-32.22 1.969-45.27L151.6 41.95z" + d="M151.6 42.4C145.5 35.8 137 32 128 32s-17.5 3.8-23.6 10.4l-88 96c-11.9 13-11.1 33.3 2 45.2s33.3 11.1 45.2-2L96 146.3V448c0 17.7 14.3 32 32 32s32-14.3 32-32V146.3l32.4 35.4c11.9 13 32.2 13.9 45.2 2s13.9-32.2 2-45.2l-88-96zM320 480h32c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128H544c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32z" fill="currentColor" /> </svg> @@ -146,7 +146,7 @@ exports[`<SortableBarChartCard /> renders properly ordered stats when ordering i xmlns="http://www.w3.org/2000/svg" > <path - d="M416 288h-95.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H416c17.67 0 32-14.33 32-32S433.7 288 416 288zM352 416h-32c-17.67 0-32 14.33-32 32s14.33 32 32 32h32c17.67 0 31.1-14.33 31.1-32S369.7 416 352 416zM480 160h-159.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H480c17.67 0 32-14.33 32-32S497.7 160 480 160zM544 32h-223.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H544c17.67 0 32-14.33 32-32S561.7 32 544 32zM151.6 41.95c-12.12-13.26-35.06-13.26-47.19 0l-87.1 96.09C4.475 151.1 5.35 171.4 18.38 183.3c6.141 5.629 13.89 8.414 21.61 8.414c8.672 0 17.3-3.504 23.61-10.39L96 145.9v302C96 465.7 110.3 480 128 480s32-14.33 32-32.03V145.9L192.4 181.3C204.4 194.3 224.6 195.3 237.6 183.3c13.03-11.95 13.9-32.22 1.969-45.27L151.6 41.95z" + d="M151.6 42.4C145.5 35.8 137 32 128 32s-17.5 3.8-23.6 10.4l-88 96c-11.9 13-11.1 33.3 2 45.2s33.3 11.1 45.2-2L96 146.3V448c0 17.7 14.3 32 32 32s32-14.3 32-32V146.3l32.4 35.4c11.9 13 32.2 13.9 45.2 2s13.9-32.2 2-45.2l-88-96zM320 480h32c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128H544c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32z" fill="currentColor" /> </svg> @@ -229,7 +229,7 @@ exports[`<SortableBarChartCard /> renders properly ordered stats when ordering i xmlns="http://www.w3.org/2000/svg" > <path - d="M416 288h-95.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H416c17.67 0 32-14.33 32-32S433.7 288 416 288zM352 416h-32c-17.67 0-32 14.33-32 32s14.33 32 32 32h32c17.67 0 31.1-14.33 31.1-32S369.7 416 352 416zM480 160h-159.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H480c17.67 0 32-14.33 32-32S497.7 160 480 160zM544 32h-223.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H544c17.67 0 32-14.33 32-32S561.7 32 544 32zM151.6 41.95c-12.12-13.26-35.06-13.26-47.19 0l-87.1 96.09C4.475 151.1 5.35 171.4 18.38 183.3c6.141 5.629 13.89 8.414 21.61 8.414c8.672 0 17.3-3.504 23.61-10.39L96 145.9v302C96 465.7 110.3 480 128 480s32-14.33 32-32.03V145.9L192.4 181.3C204.4 194.3 224.6 195.3 237.6 183.3c13.03-11.95 13.9-32.22 1.969-45.27L151.6 41.95z" + d="M151.6 42.4C145.5 35.8 137 32 128 32s-17.5 3.8-23.6 10.4l-88 96c-11.9 13-11.1 33.3 2 45.2s33.3 11.1 45.2-2L96 146.3V448c0 17.7 14.3 32 32 32s32-14.3 32-32V146.3l32.4 35.4c11.9 13 32.2 13.9 45.2 2s13.9-32.2 2-45.2l-88-96zM320 480h32c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128H544c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32z" fill="currentColor" /> </svg> @@ -328,7 +328,7 @@ exports[`<SortableBarChartCard /> renders properly ordered stats when ordering i xmlns="http://www.w3.org/2000/svg" > <path - d="M416 288h-95.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H416c17.67 0 32-14.33 32-32S433.7 288 416 288zM352 416h-32c-17.67 0-32 14.33-32 32s14.33 32 32 32h32c17.67 0 31.1-14.33 31.1-32S369.7 416 352 416zM480 160h-159.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H480c17.67 0 32-14.33 32-32S497.7 160 480 160zM544 32h-223.1c-17.67 0-32 14.33-32 32s14.33 32 32 32H544c17.67 0 32-14.33 32-32S561.7 32 544 32zM151.6 41.95c-12.12-13.26-35.06-13.26-47.19 0l-87.1 96.09C4.475 151.1 5.35 171.4 18.38 183.3c6.141 5.629 13.89 8.414 21.61 8.414c8.672 0 17.3-3.504 23.61-10.39L96 145.9v302C96 465.7 110.3 480 128 480s32-14.33 32-32.03V145.9L192.4 181.3C204.4 194.3 224.6 195.3 237.6 183.3c13.03-11.95 13.9-32.22 1.969-45.27L151.6 41.95z" + d="M151.6 42.4C145.5 35.8 137 32 128 32s-17.5 3.8-23.6 10.4l-88 96c-11.9 13-11.1 33.3 2 45.2s33.3 11.1 45.2-2L96 146.3V448c0 17.7 14.3 32 32 32s32-14.3 32-32V146.3l32.4 35.4c11.9 13 32.2 13.9 45.2 2s13.9-32.2 2-45.2l-88-96zM320 480h32c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128H544c17.7 0 32-14.3 32-32s-14.3-32-32-32H320c-17.7 0-32 14.3-32 32s14.3 32 32 32z" fill="currentColor" /> </svg> diff --git a/test/visits/helpers/VisitsFilterDropdown.test.tsx b/test/visits/helpers/VisitsFilterDropdown.test.tsx index eb3f38a2..a3729dca 100644 --- a/test/visits/helpers/VisitsFilterDropdown.test.tsx +++ b/test/visits/helpers/VisitsFilterDropdown.test.tsx @@ -60,7 +60,7 @@ describe('<VisitsFilterDropdown />', () => { [1, { orphanVisitsType: 'base_url' }, {}], [2, { orphanVisitsType: 'invalid_short_url' }, {}], [3, { orphanVisitsType: 'regular_404' }, {}], - [4, {}, { excludeBots: true }], + [4, { orphanVisitsType: undefined, excludeBots: false }, { excludeBots: true }], ])('invokes onChange with proper selection when an item is clicked', async (index, expectedSelection, selected) => { const { user } = setUp(selected); diff --git a/test/visits/helpers/__snapshots__/MapModal.test.tsx.snap b/test/visits/helpers/__snapshots__/MapModal.test.tsx.snap index 73591165..9a95d69d 100644 --- a/test/visits/helpers/__snapshots__/MapModal.test.tsx.snap +++ b/test/visits/helpers/__snapshots__/MapModal.test.tsx.snap @@ -50,7 +50,6 @@ exports[`<MapModal /> renders expected map 1`] = ` <img alt="" class="leaflet-tile" - role="presentation" src="https://a.tile.openstreetmap.org/0/0/0.png" style="width: 256px; height: 256px; left: -101px; top: -96px;" /> @@ -168,7 +167,7 @@ exports[`<MapModal /> renders expected map 1`] = ` </span> © <a - href="http://osm.org/copyright" + href="https://osm.org/copyright" > OpenStreetMap </a> diff --git a/test/visits/helpers/__snapshots__/OpenMapModalBtn.test.tsx.snap b/test/visits/helpers/__snapshots__/OpenMapModalBtn.test.tsx.snap index 9d7c396b..079cd283 100644 --- a/test/visits/helpers/__snapshots__/OpenMapModalBtn.test.tsx.snap +++ b/test/visits/helpers/__snapshots__/OpenMapModalBtn.test.tsx.snap @@ -50,7 +50,6 @@ exports[`<OpenMapModalBtn /> filters out non-active cities from list of location <img alt="" class="leaflet-tile" - role="presentation" src="https://a.tile.openstreetmap.org/0/0/0.png" style="width: 256px; height: 256px; left: -161px; top: -62px;" /> @@ -168,7 +167,7 @@ exports[`<OpenMapModalBtn /> filters out non-active cities from list of location </span> © <a - href="http://osm.org/copyright" + href="https://osm.org/copyright" > OpenStreetMap </a> @@ -233,7 +232,6 @@ exports[`<OpenMapModalBtn /> filters out non-active cities from list of location <img alt="" class="leaflet-tile" - role="presentation" src="https://a.tile.openstreetmap.org/10/762/0.png" style="width: 256px; height: 256px; left: -80px; top: 0px;" /> @@ -337,7 +335,7 @@ exports[`<OpenMapModalBtn /> filters out non-active cities from list of location </span> © <a - href="http://osm.org/copyright" + href="https://osm.org/copyright" > OpenStreetMap </a> diff --git a/test/visits/reducers/domainVisits.test.ts b/test/visits/reducers/domainVisits.test.ts index 8c9bfccd..db52ba06 100644 --- a/test/visits/reducers/domainVisits.test.ts +++ b/test/visits/reducers/domainVisits.test.ts @@ -1,58 +1,52 @@ import { Mock } from 'ts-mockery'; import { addDays, formatISO, subDays } from 'date-fns'; -import reducer, { - getDomainVisits, - cancelGetDomainVisits, - GET_DOMAIN_VISITS_START, - GET_DOMAIN_VISITS_ERROR, - GET_DOMAIN_VISITS, - GET_DOMAIN_VISITS_LARGE, - GET_DOMAIN_VISITS_CANCEL, - GET_DOMAIN_VISITS_PROGRESS_CHANGED, - GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, +import { + getDomainVisits as getDomainVisitsCreator, DomainVisits, DEFAULT_DOMAIN, + domainVisitsReducerCreator, } from '../../../src/visits/reducers/domainVisits'; -import { CREATE_VISITS } from '../../../src/visits/reducers/visitCreation'; import { rangeOf } from '../../../src/utils/utils'; import { Visit } from '../../../src/visits/types'; import { ShlinkVisits } from '../../../src/api/types'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { ShlinkState } from '../../../src/container/types'; import { formatIsoDate } from '../../../src/utils/helpers/date'; -import { DateInterval } from '../../../src/utils/dates/types'; +import { DateInterval } from '../../../src/utils/helpers/dateIntervals'; import { ShortUrl } from '../../../src/short-urls/data'; +import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; describe('domainVisitsReducer', () => { const now = new Date(); const visitsMocks = rangeOf(2, () => Mock.all<Visit>()); + const getDomainVisitsCall = jest.fn(); + const buildApiClientMock = () => Mock.of<ShlinkApiClient>({ getDomainVisits: getDomainVisitsCall }); + const creator = getDomainVisitsCreator(buildApiClientMock); + const { asyncThunk: getDomainVisits, progressChangedAction, largeAction, fallbackToIntervalAction } = creator; + const { reducer, cancelGetVisits: cancelGetDomainVisits } = domainVisitsReducerCreator(creator); + + beforeEach(jest.clearAllMocks); describe('reducer', () => { const buildState = (data: Partial<DomainVisits>) => Mock.of<DomainVisits>(data); it('returns loading on GET_DOMAIN_VISITS_START', () => { - const state = reducer(buildState({ loading: false }), { type: GET_DOMAIN_VISITS_START } as any); - const { loading } = state; - + const { loading } = reducer(buildState({ loading: false }), { type: getDomainVisits.pending.toString() }); expect(loading).toEqual(true); }); it('returns loadingLarge on GET_DOMAIN_VISITS_LARGE', () => { - const state = reducer(buildState({ loadingLarge: false }), { type: GET_DOMAIN_VISITS_LARGE } as any); - const { loadingLarge } = state; - + const { loadingLarge } = reducer(buildState({ loadingLarge: false }), { type: largeAction.toString() }); expect(loadingLarge).toEqual(true); }); it('returns cancelLoad on GET_DOMAIN_VISITS_CANCEL', () => { - const state = reducer(buildState({ cancelLoad: false }), { type: GET_DOMAIN_VISITS_CANCEL } as any); - const { cancelLoad } = state; - + const { cancelLoad } = reducer(buildState({ cancelLoad: false }), { type: cancelGetDomainVisits.toString() }); expect(cancelLoad).toEqual(true); }); it('stops loading and returns error on GET_DOMAIN_VISITS_ERROR', () => { - const state = reducer(buildState({ loading: true, error: false }), { type: GET_DOMAIN_VISITS_ERROR } as any); + const state = reducer(buildState({ loading: true, error: false }), { type: getDomainVisits.rejected.toString() }); const { loading, error } = state; expect(loading).toEqual(false); @@ -61,11 +55,10 @@ describe('domainVisitsReducer', () => { it('return visits on GET_DOMAIN_VISITS', () => { const actionVisits = [{}, {}]; - const state = reducer( - buildState({ loading: true, error: false }), - { type: GET_DOMAIN_VISITS, visits: actionVisits } as any, - ); - const { loading, error, visits } = state; + const { loading, error, visits } = reducer(buildState({ loading: true, error: false }), { + type: getDomainVisits.fulfilled.toString(), + payload: { visits: actionVisits }, + }); expect(loading).toEqual(false); expect(error).toEqual(false); @@ -128,56 +121,51 @@ describe('domainVisitsReducer', () => { ], ])('prepends new visits on CREATE_VISIT', (state, shortUrlDomain, expectedVisits) => { const shortUrl = Mock.of<ShortUrl>({ domain: shortUrlDomain }); - const prevState = buildState({ - ...state, - visits: visitsMocks, + const { visits } = reducer(buildState({ ...state, visits: visitsMocks }), { + type: createNewVisits.toString(), + payload: { createdVisits: [{ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }] }, }); - const { visits } = reducer(prevState, { - type: CREATE_VISITS, - createdVisits: [{ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }], - } as any); - expect(visits).toHaveLength(expectedVisits); }); it('returns new progress on GET_DOMAIN_VISITS_PROGRESS_CHANGED', () => { - const state = reducer(undefined, { type: GET_DOMAIN_VISITS_PROGRESS_CHANGED, progress: 85 } as any); + const state = reducer(undefined, { type: progressChangedAction.toString(), payload: 85 }); expect(state).toEqual(expect.objectContaining({ progress: 85 })); }); it('returns fallbackInterval on GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL', () => { const fallbackInterval: DateInterval = 'last30Days'; - const state = reducer(undefined, { type: GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval } as any); + const state = reducer( + undefined, + { type: fallbackToIntervalAction.toString(), payload: fallbackInterval }, + ); expect(state).toEqual(expect.objectContaining({ fallbackInterval })); }); }); describe('getDomainVisits', () => { - type GetVisitsReturn = Promise<ShlinkVisits> | ((shortCode: string, query: any) => Promise<ShlinkVisits>); - - const buildApiClientMock = (returned: GetVisitsReturn) => Mock.of<ShlinkApiClient>({ - getDomainVisits: jest.fn(typeof returned === 'function' ? returned : async () => returned), - }); const dispatchMock = jest.fn(); const getState = () => Mock.of<ShlinkState>({ domainVisits: { cancelLoad: false }, }); const domain = 'foo.com'; - beforeEach(jest.clearAllMocks); - it('dispatches start and error when promise is rejected', async () => { - const shlinkApiClient = buildApiClientMock(Promise.reject(new Error())); + getDomainVisitsCall.mockRejectedValue(new Error()); - await getDomainVisits(() => shlinkApiClient)('foo.com')(dispatchMock, getState); + await getDomainVisits({ domain })(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_DOMAIN_VISITS_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_DOMAIN_VISITS_ERROR }); - expect(shlinkApiClient.getDomainVisits).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getDomainVisits.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getDomainVisits.rejected.toString(), + })); + expect(getDomainVisitsCall).toHaveBeenCalledTimes(1); }); it.each([ @@ -185,34 +173,45 @@ describe('domainVisitsReducer', () => { [{}], ])('dispatches start and success when promise is resolved', async (query) => { const visits = visitsMocks; - const shlinkApiClient = buildApiClientMock(Promise.resolve({ + getDomainVisitsCall.mockResolvedValue({ data: visitsMocks, pagination: { currentPage: 1, pagesCount: 1, totalItems: 1, }, - })); + }); - await getDomainVisits(() => shlinkApiClient)(domain, query)(dispatchMock, getState); + await getDomainVisits({ domain, query })(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_DOMAIN_VISITS_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_DOMAIN_VISITS, visits, domain, query: query ?? {} }); - expect(shlinkApiClient.getDomainVisits).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getDomainVisits.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getDomainVisits.fulfilled.toString(), + payload: { visits, domain, query: query ?? {} }, + })); + expect(getDomainVisitsCall).toHaveBeenCalledTimes(1); }); it.each([ [ [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 20)) })], - { type: GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last30Days' }, + { type: fallbackToIntervalAction.toString(), payload: 'last30Days' }, + 3, ], [ [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 100)) })], - { type: GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last180Days' }, + { type: fallbackToIntervalAction.toString(), payload: 'last180Days' }, + 3, ], - [[], expect.objectContaining({ type: GET_DOMAIN_VISITS })], - ])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => { + [[], expect.objectContaining({ type: getDomainVisits.fulfilled.toString() }), 2], + ])('dispatches fallback interval when the list of visits is empty', async ( + lastVisits, + expectedSecondDispatch, + expectedDispatchCalls, + ) => { const buildVisitsResult = (data: Visit[] = []): ShlinkVisits => ({ data, pagination: { @@ -221,22 +220,23 @@ describe('domainVisitsReducer', () => { totalItems: 1, }, }); - const getShlinkDomainVisits = jest.fn() + getDomainVisitsCall .mockResolvedValueOnce(buildVisitsResult()) .mockResolvedValueOnce(buildVisitsResult(lastVisits)); - const ShlinkApiClient = Mock.of<ShlinkApiClient>({ getDomainVisits: getShlinkDomainVisits }); - await getDomainVisits(() => ShlinkApiClient)(domain, {}, true)(dispatchMock, getState); + await getDomainVisits({ domain, doIntervalFallback: true })(dispatchMock, getState, {}); - expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_DOMAIN_VISITS_START }); + expect(dispatchMock).toHaveBeenCalledTimes(expectedDispatchCalls); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getDomainVisits.pending.toString(), + })); expect(dispatchMock).toHaveBeenNthCalledWith(2, expectedSecondDispatch); - expect(getShlinkDomainVisits).toHaveBeenCalledTimes(2); + expect(getDomainVisitsCall).toHaveBeenCalledTimes(2); }); }); describe('cancelGetDomainVisits', () => { it('just returns the action with proper type', () => - expect(cancelGetDomainVisits()).toEqual({ type: GET_DOMAIN_VISITS_CANCEL })); + expect(cancelGetDomainVisits()).toEqual(expect.objectContaining({ type: cancelGetDomainVisits.toString() }))); }); }); diff --git a/test/visits/reducers/nonOrphanVisits.test.ts b/test/visits/reducers/nonOrphanVisits.test.ts index 7e6c2911..e62a6d10 100644 --- a/test/visits/reducers/nonOrphanVisits.test.ts +++ b/test/visits/reducers/nonOrphanVisits.test.ts @@ -1,56 +1,53 @@ import { Mock } from 'ts-mockery'; import { addDays, formatISO, subDays } from 'date-fns'; -import reducer, { - getNonOrphanVisits, - cancelGetNonOrphanVisits, - GET_NON_ORPHAN_VISITS_START, - GET_NON_ORPHAN_VISITS_ERROR, - GET_NON_ORPHAN_VISITS, - GET_NON_ORPHAN_VISITS_LARGE, - GET_NON_ORPHAN_VISITS_CANCEL, - GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED, - GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, +import { + getNonOrphanVisits as getNonOrphanVisitsCreator, + nonOrphanVisitsReducerCreator, } from '../../../src/visits/reducers/nonOrphanVisits'; -import { CREATE_VISITS } from '../../../src/visits/reducers/visitCreation'; import { rangeOf } from '../../../src/utils/utils'; -import { Visit, VisitsInfo } from '../../../src/visits/types'; +import { Visit } from '../../../src/visits/types'; import { ShlinkVisits } from '../../../src/api/types'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { ShlinkState } from '../../../src/container/types'; import { formatIsoDate } from '../../../src/utils/helpers/date'; -import { DateInterval } from '../../../src/utils/dates/types'; +import { DateInterval } from '../../../src/utils/helpers/dateIntervals'; +import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; +import { VisitsInfo } from '../../../src/visits/reducers/types'; describe('nonOrphanVisitsReducer', () => { const now = new Date(); const visitsMocks = rangeOf(2, () => Mock.all<Visit>()); + const getNonOrphanVisitsCall = jest.fn(); + const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ getNonOrphanVisits: getNonOrphanVisitsCall }); + const creator = getNonOrphanVisitsCreator(buildShlinkApiClient); + const { asyncThunk: getNonOrphanVisits, progressChangedAction, largeAction, fallbackToIntervalAction } = creator; + const { reducer, cancelGetVisits: cancelGetNonOrphanVisits } = nonOrphanVisitsReducerCreator(creator); + + beforeEach(jest.clearAllMocks); describe('reducer', () => { const buildState = (data: Partial<VisitsInfo>) => Mock.of<VisitsInfo>(data); it('returns loading on GET_NON_ORPHAN_VISITS_START', () => { - const state = reducer(buildState({ loading: false }), { type: GET_NON_ORPHAN_VISITS_START } as any); - const { loading } = state; - + const { loading } = reducer(buildState({ loading: false }), { type: getNonOrphanVisits.pending.toString() }); expect(loading).toEqual(true); }); it('returns loadingLarge on GET_NON_ORPHAN_VISITS_LARGE', () => { - const state = reducer(buildState({ loadingLarge: false }), { type: GET_NON_ORPHAN_VISITS_LARGE } as any); - const { loadingLarge } = state; - + const { loadingLarge } = reducer(buildState({ loadingLarge: false }), { type: largeAction.toString() }); expect(loadingLarge).toEqual(true); }); it('returns cancelLoad on GET_NON_ORPHAN_VISITS_CANCEL', () => { - const state = reducer(buildState({ cancelLoad: false }), { type: GET_NON_ORPHAN_VISITS_CANCEL } as any); - const { cancelLoad } = state; - + const { cancelLoad } = reducer(buildState({ cancelLoad: false }), { type: cancelGetNonOrphanVisits.toString() }); expect(cancelLoad).toEqual(true); }); it('stops loading and returns error on GET_NON_ORPHAN_VISITS_ERROR', () => { - const state = reducer(buildState({ loading: true, error: false }), { type: GET_NON_ORPHAN_VISITS_ERROR } as any); - const { loading, error } = state; + const { loading, error } = reducer( + buildState({ loading: true, error: false }), + { type: getNonOrphanVisits.rejected.toString() }, + ); expect(loading).toEqual(false); expect(error).toEqual(true); @@ -58,11 +55,10 @@ describe('nonOrphanVisitsReducer', () => { it('return visits on GET_NON_ORPHAN_VISITS', () => { const actionVisits = [{}, {}]; - const state = reducer( - buildState({ loading: true, error: false }), - { type: GET_NON_ORPHAN_VISITS, visits: actionVisits } as any, - ); - const { loading, error, visits } = state; + const { loading, error, visits } = reducer(buildState({ loading: true, error: false }), { + type: getNonOrphanVisits.fulfilled.toString(), + payload: { visits: actionVisits }, + }); expect(loading).toEqual(false); expect(error).toEqual(false); @@ -105,34 +101,31 @@ describe('nonOrphanVisitsReducer', () => { const prevState = buildState({ ...state, visits: visitsMocks }); const visit = Mock.of<Visit>({ date: formatIsoDate(now) ?? undefined }); - const { visits } = reducer( - prevState, - { type: CREATE_VISITS, createdVisits: [{ visit }, { visit }] } as any, - ); + const { visits } = reducer(prevState, { + type: createNewVisits.toString(), + payload: { createdVisits: [{ visit }, { visit }] }, + }); expect(visits).toHaveLength(expectedVisits); }); it('returns new progress on GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED', () => { - const state = reducer(undefined, { type: GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED, progress: 85 } as any); - + const state = reducer(undefined, { type: progressChangedAction.toString(), payload: 85 }); expect(state).toEqual(expect.objectContaining({ progress: 85 })); }); it('returns fallbackInterval on GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL', () => { const fallbackInterval: DateInterval = 'last30Days'; - const state = reducer(undefined, { type: GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval } as any); + const state = reducer( + undefined, + { type: fallbackToIntervalAction.toString(), payload: fallbackInterval }, + ); expect(state).toEqual(expect.objectContaining({ fallbackInterval })); }); }); describe('getNonOrphanVisits', () => { - type GetVisitsReturn = Promise<ShlinkVisits> | ((query: any) => Promise<ShlinkVisits>); - - const buildApiClientMock = (returned: GetVisitsReturn) => Mock.of<ShlinkApiClient>({ - getNonOrphanVisits: jest.fn(typeof returned === 'function' ? returned : async () => returned), - }); const dispatchMock = jest.fn(); const getState = () => Mock.of<ShlinkState>({ orphanVisits: { cancelLoad: false }, @@ -141,14 +134,18 @@ describe('nonOrphanVisitsReducer', () => { beforeEach(jest.resetAllMocks); it('dispatches start and error when promise is rejected', async () => { - const ShlinkApiClient = buildApiClientMock(Promise.reject({})); + getNonOrphanVisitsCall.mockRejectedValue({}); - await getNonOrphanVisits(() => ShlinkApiClient)()(dispatchMock, getState); + await getNonOrphanVisits({})(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_NON_ORPHAN_VISITS_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_NON_ORPHAN_VISITS_ERROR }); - expect(ShlinkApiClient.getNonOrphanVisits).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getNonOrphanVisits.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getNonOrphanVisits.rejected.toString(), + })); + expect(getNonOrphanVisitsCall).toHaveBeenCalledTimes(1); }); it.each([ @@ -156,34 +153,45 @@ describe('nonOrphanVisitsReducer', () => { [{}], ])('dispatches start and success when promise is resolved', async (query) => { const visits = visitsMocks.map((visit) => ({ ...visit, visitedUrl: '' })); - const ShlinkApiClient = buildApiClientMock(Promise.resolve({ + getNonOrphanVisitsCall.mockResolvedValue({ data: visits, pagination: { currentPage: 1, pagesCount: 1, totalItems: 1, }, - })); + }); - await getNonOrphanVisits(() => ShlinkApiClient)(query)(dispatchMock, getState); + await getNonOrphanVisits({ query })(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_NON_ORPHAN_VISITS_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_NON_ORPHAN_VISITS, visits, query: query ?? {} }); - expect(ShlinkApiClient.getNonOrphanVisits).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining( + { type: getNonOrphanVisits.pending.toString() }, + )); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getNonOrphanVisits.fulfilled.toString(), + payload: { visits, query: query ?? {} }, + })); + expect(getNonOrphanVisitsCall).toHaveBeenCalledTimes(1); }); it.each([ [ [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 5)) })], - { type: GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last7Days' }, + { type: fallbackToIntervalAction.toString(), payload: 'last7Days' }, + 3, ], [ [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 200)) })], - { type: GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last365Days' }, + { type: fallbackToIntervalAction.toString(), payload: 'last365Days' }, + 3, ], - [[], expect.objectContaining({ type: GET_NON_ORPHAN_VISITS })], - ])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => { + [[], expect.objectContaining({ type: getNonOrphanVisits.fulfilled.toString() }), 2], + ])('dispatches fallback interval when the list of visits is empty', async ( + lastVisits, + expectedSecondDispatch, + expectedAmountOfDispatches, + ) => { const buildVisitsResult = (data: Visit[] = []): ShlinkVisits => ({ data, pagination: { @@ -192,22 +200,23 @@ describe('nonOrphanVisitsReducer', () => { totalItems: 1, }, }); - const getShlinkOrphanVisits = jest.fn() + getNonOrphanVisitsCall .mockResolvedValueOnce(buildVisitsResult()) .mockResolvedValueOnce(buildVisitsResult(lastVisits)); - const ShlinkApiClient = Mock.of<ShlinkApiClient>({ getNonOrphanVisits: getShlinkOrphanVisits }); - await getNonOrphanVisits(() => ShlinkApiClient)({}, true)(dispatchMock, getState); + await getNonOrphanVisits({ doIntervalFallback: true })(dispatchMock, getState, {}); - expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_NON_ORPHAN_VISITS_START }); + expect(dispatchMock).toHaveBeenCalledTimes(expectedAmountOfDispatches); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getNonOrphanVisits.pending.toString(), + })); expect(dispatchMock).toHaveBeenNthCalledWith(2, expectedSecondDispatch); - expect(getShlinkOrphanVisits).toHaveBeenCalledTimes(2); + expect(getNonOrphanVisitsCall).toHaveBeenCalledTimes(2); }); }); describe('cancelGetNonOrphanVisits', () => { it('just returns the action with proper type', () => - expect(cancelGetNonOrphanVisits()).toEqual({ type: GET_NON_ORPHAN_VISITS_CANCEL })); + expect(cancelGetNonOrphanVisits()).toEqual({ type: cancelGetNonOrphanVisits.toString() })); }); }); diff --git a/test/visits/reducers/orphanVisits.test.ts b/test/visits/reducers/orphanVisits.test.ts index d57eff5c..0b728929 100644 --- a/test/visits/reducers/orphanVisits.test.ts +++ b/test/visits/reducers/orphanVisits.test.ts @@ -1,56 +1,53 @@ import { Mock } from 'ts-mockery'; import { addDays, formatISO, subDays } from 'date-fns'; -import reducer, { - getOrphanVisits, - cancelGetOrphanVisits, - GET_ORPHAN_VISITS_START, - GET_ORPHAN_VISITS_ERROR, - GET_ORPHAN_VISITS, - GET_ORPHAN_VISITS_LARGE, - GET_ORPHAN_VISITS_CANCEL, - GET_ORPHAN_VISITS_PROGRESS_CHANGED, - GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, +import { + getOrphanVisits as getOrphanVisitsCreator, + orphanVisitsReducerCreator, } from '../../../src/visits/reducers/orphanVisits'; -import { CREATE_VISITS } from '../../../src/visits/reducers/visitCreation'; import { rangeOf } from '../../../src/utils/utils'; -import { Visit, VisitsInfo } from '../../../src/visits/types'; +import { Visit } from '../../../src/visits/types'; import { ShlinkVisits } from '../../../src/api/types'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { ShlinkState } from '../../../src/container/types'; import { formatIsoDate } from '../../../src/utils/helpers/date'; -import { DateInterval } from '../../../src/utils/dates/types'; +import { DateInterval } from '../../../src/utils/helpers/dateIntervals'; +import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; +import { VisitsInfo } from '../../../src/visits/reducers/types'; describe('orphanVisitsReducer', () => { const now = new Date(); const visitsMocks = rangeOf(2, () => Mock.all<Visit>()); + const getOrphanVisitsCall = jest.fn(); + const buildShlinkApiClientMock = () => Mock.of<ShlinkApiClient>({ getOrphanVisits: getOrphanVisitsCall }); + const creator = getOrphanVisitsCreator(buildShlinkApiClientMock); + const { asyncThunk: getOrphanVisits, largeAction, progressChangedAction, fallbackToIntervalAction } = creator; + const { reducer, cancelGetVisits: cancelGetOrphanVisits } = orphanVisitsReducerCreator(creator); + + beforeEach(jest.clearAllMocks); describe('reducer', () => { const buildState = (data: Partial<VisitsInfo>) => Mock.of<VisitsInfo>(data); it('returns loading on GET_ORPHAN_VISITS_START', () => { - const state = reducer(buildState({ loading: false }), { type: GET_ORPHAN_VISITS_START } as any); - const { loading } = state; - + const { loading } = reducer(buildState({ loading: false }), { type: getOrphanVisits.pending.toString() }); expect(loading).toEqual(true); }); it('returns loadingLarge on GET_ORPHAN_VISITS_LARGE', () => { - const state = reducer(buildState({ loadingLarge: false }), { type: GET_ORPHAN_VISITS_LARGE } as any); - const { loadingLarge } = state; - + const { loadingLarge } = reducer(buildState({ loadingLarge: false }), { type: largeAction.toString() }); expect(loadingLarge).toEqual(true); }); it('returns cancelLoad on GET_ORPHAN_VISITS_CANCEL', () => { - const state = reducer(buildState({ cancelLoad: false }), { type: GET_ORPHAN_VISITS_CANCEL } as any); - const { cancelLoad } = state; - + const { cancelLoad } = reducer(buildState({ cancelLoad: false }), { type: cancelGetOrphanVisits.toString() }); expect(cancelLoad).toEqual(true); }); it('stops loading and returns error on GET_ORPHAN_VISITS_ERROR', () => { - const state = reducer(buildState({ loading: true, error: false }), { type: GET_ORPHAN_VISITS_ERROR } as any); - const { loading, error } = state; + const { loading, error } = reducer( + buildState({ loading: true, error: false }), + { type: getOrphanVisits.rejected.toString() }, + ); expect(loading).toEqual(false); expect(error).toEqual(true); @@ -58,11 +55,10 @@ describe('orphanVisitsReducer', () => { it('return visits on GET_ORPHAN_VISITS', () => { const actionVisits = [{}, {}]; - const state = reducer( - buildState({ loading: true, error: false }), - { type: GET_ORPHAN_VISITS, visits: actionVisits } as any, - ); - const { loading, error, visits } = state; + const { loading, error, visits } = reducer(buildState({ loading: true, error: false }), { + type: getOrphanVisits.fulfilled.toString(), + payload: { visits: actionVisits }, + }); expect(loading).toEqual(false); expect(error).toEqual(false); @@ -105,50 +101,49 @@ describe('orphanVisitsReducer', () => { const prevState = buildState({ ...state, visits: visitsMocks }); const visit = Mock.of<Visit>({ date: formatIsoDate(now) ?? undefined }); - const { visits } = reducer( - prevState, - { type: CREATE_VISITS, createdVisits: [{ visit }, { visit }] } as any, - ); + const { visits } = reducer(prevState, { + type: createNewVisits.toString(), + payload: { createdVisits: [{ visit }, { visit }] }, + }); expect(visits).toHaveLength(expectedVisits); }); it('returns new progress on GET_ORPHAN_VISITS_PROGRESS_CHANGED', () => { - const state = reducer(undefined, { type: GET_ORPHAN_VISITS_PROGRESS_CHANGED, progress: 85 } as any); - + const state = reducer(undefined, { type: progressChangedAction.toString(), payload: 85 }); expect(state).toEqual(expect.objectContaining({ progress: 85 })); }); it('returns fallbackInterval on GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL', () => { const fallbackInterval: DateInterval = 'last30Days'; - const state = reducer(undefined, { type: GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval } as any); + const state = reducer( + undefined, + { type: fallbackToIntervalAction.toString(), payload: fallbackInterval }, + ); expect(state).toEqual(expect.objectContaining({ fallbackInterval })); }); }); describe('getOrphanVisits', () => { - type GetVisitsReturn = Promise<ShlinkVisits> | ((query: any) => Promise<ShlinkVisits>); - - const buildApiClientMock = (returned: GetVisitsReturn) => Mock.of<ShlinkApiClient>({ - getOrphanVisits: jest.fn(typeof returned === 'function' ? returned : async () => returned), - }); const dispatchMock = jest.fn(); const getState = () => Mock.of<ShlinkState>({ orphanVisits: { cancelLoad: false }, }); - beforeEach(jest.resetAllMocks); - it('dispatches start and error when promise is rejected', async () => { - const ShlinkApiClient = buildApiClientMock(Promise.reject({})); + getOrphanVisitsCall.mockRejectedValue({}); - await getOrphanVisits(() => ShlinkApiClient)()(dispatchMock, getState); + await getOrphanVisits({})(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_ORPHAN_VISITS_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_ORPHAN_VISITS_ERROR }); - expect(ShlinkApiClient.getOrphanVisits).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getOrphanVisits.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getOrphanVisits.rejected.toString(), + })); + expect(getOrphanVisitsCall).toHaveBeenCalledTimes(1); }); it.each([ @@ -156,34 +151,45 @@ describe('orphanVisitsReducer', () => { [{}], ])('dispatches start and success when promise is resolved', async (query) => { const visits = visitsMocks.map((visit) => ({ ...visit, visitedUrl: '' })); - const ShlinkApiClient = buildApiClientMock(Promise.resolve({ + getOrphanVisitsCall.mockResolvedValue({ data: visits, pagination: { currentPage: 1, pagesCount: 1, totalItems: 1, }, - })); + }); - await getOrphanVisits(() => ShlinkApiClient)(query)(dispatchMock, getState); + await getOrphanVisits({ query })(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_ORPHAN_VISITS_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_ORPHAN_VISITS, visits, query: query ?? {} }); - expect(ShlinkApiClient.getOrphanVisits).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getOrphanVisits.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getOrphanVisits.fulfilled.toString(), + payload: { visits, query: query ?? {} }, + })); + expect(getOrphanVisitsCall).toHaveBeenCalledTimes(1); }); it.each([ [ [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 5)) })], - { type: GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last7Days' }, + { type: fallbackToIntervalAction.toString(), payload: 'last7Days' }, + 3, ], [ [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 200)) })], - { type: GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last365Days' }, + { type: fallbackToIntervalAction.toString(), payload: 'last365Days' }, + 3, ], - [[], expect.objectContaining({ type: GET_ORPHAN_VISITS })], - ])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => { + [[], expect.objectContaining({ type: getOrphanVisits.fulfilled.toString() }), 2], + ])('dispatches fallback interval when the list of visits is empty', async ( + lastVisits, + expectedSecondDispatch, + expectedDispatchCalls, + ) => { const buildVisitsResult = (data: Visit[] = []): ShlinkVisits => ({ data, pagination: { @@ -192,22 +198,23 @@ describe('orphanVisitsReducer', () => { totalItems: 1, }, }); - const getShlinkOrphanVisits = jest.fn() + getOrphanVisitsCall .mockResolvedValueOnce(buildVisitsResult()) .mockResolvedValueOnce(buildVisitsResult(lastVisits)); - const ShlinkApiClient = Mock.of<ShlinkApiClient>({ getOrphanVisits: getShlinkOrphanVisits }); - await getOrphanVisits(() => ShlinkApiClient)({}, undefined, true)(dispatchMock, getState); + await getOrphanVisits({ doIntervalFallback: true })(dispatchMock, getState, {}); - expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_ORPHAN_VISITS_START }); + expect(dispatchMock).toHaveBeenCalledTimes(expectedDispatchCalls); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getOrphanVisits.pending.toString(), + })); expect(dispatchMock).toHaveBeenNthCalledWith(2, expectedSecondDispatch); - expect(getShlinkOrphanVisits).toHaveBeenCalledTimes(2); + expect(getOrphanVisitsCall).toHaveBeenCalledTimes(2); }); }); describe('cancelGetOrphanVisits', () => { it('just returns the action with proper type', () => - expect(cancelGetOrphanVisits()).toEqual({ type: GET_ORPHAN_VISITS_CANCEL })); + expect(cancelGetOrphanVisits()).toEqual({ type: cancelGetOrphanVisits.toString() })); }); }); diff --git a/test/visits/reducers/shortUrlVisits.test.ts b/test/visits/reducers/shortUrlVisits.test.ts index 3b7cdbb8..4b65d351 100644 --- a/test/visits/reducers/shortUrlVisits.test.ts +++ b/test/visits/reducers/shortUrlVisits.test.ts @@ -1,57 +1,53 @@ import { Mock } from 'ts-mockery'; import { addDays, formatISO, subDays } from 'date-fns'; -import reducer, { - getShortUrlVisits, - cancelGetShortUrlVisits, - GET_SHORT_URL_VISITS_START, - GET_SHORT_URL_VISITS_ERROR, - GET_SHORT_URL_VISITS, - GET_SHORT_URL_VISITS_LARGE, - GET_SHORT_URL_VISITS_CANCEL, - GET_SHORT_URL_VISITS_PROGRESS_CHANGED, - GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, +import { + getShortUrlVisits as getShortUrlVisitsCreator, + shortUrlVisitsReducerCreator, ShortUrlVisits, } from '../../../src/visits/reducers/shortUrlVisits'; -import { CREATE_VISITS } from '../../../src/visits/reducers/visitCreation'; import { rangeOf } from '../../../src/utils/utils'; import { Visit } from '../../../src/visits/types'; import { ShlinkVisits } from '../../../src/api/types'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { ShlinkState } from '../../../src/container/types'; import { formatIsoDate } from '../../../src/utils/helpers/date'; -import { DateInterval } from '../../../src/utils/dates/types'; +import { DateInterval } from '../../../src/utils/helpers/dateIntervals'; +import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; describe('shortUrlVisitsReducer', () => { const now = new Date(); const visitsMocks = rangeOf(2, () => Mock.all<Visit>()); + const getShortUrlVisitsCall = jest.fn(); + const buildApiClientMock = () => Mock.of<ShlinkApiClient>({ getShortUrlVisits: getShortUrlVisitsCall }); + const creator = getShortUrlVisitsCreator(buildApiClientMock); + const { asyncThunk: getShortUrlVisits, largeAction, progressChangedAction, fallbackToIntervalAction } = creator; + const { reducer, cancelGetVisits: cancelGetShortUrlVisits } = shortUrlVisitsReducerCreator(creator); + + beforeEach(jest.clearAllMocks); describe('reducer', () => { const buildState = (data: Partial<ShortUrlVisits>) => Mock.of<ShortUrlVisits>(data); it('returns loading on GET_SHORT_URL_VISITS_START', () => { - const state = reducer(buildState({ loading: false }), { type: GET_SHORT_URL_VISITS_START } as any); - const { loading } = state; - + const { loading } = reducer(buildState({ loading: false }), { type: getShortUrlVisits.pending.toString() }); expect(loading).toEqual(true); }); it('returns loadingLarge on GET_SHORT_URL_VISITS_LARGE', () => { - const state = reducer(buildState({ loadingLarge: false }), { type: GET_SHORT_URL_VISITS_LARGE } as any); - const { loadingLarge } = state; - + const { loadingLarge } = reducer(buildState({ loadingLarge: false }), { type: largeAction.toString() }); expect(loadingLarge).toEqual(true); }); it('returns cancelLoad on GET_SHORT_URL_VISITS_CANCEL', () => { - const state = reducer(buildState({ cancelLoad: false }), { type: GET_SHORT_URL_VISITS_CANCEL } as any); - const { cancelLoad } = state; - + const { cancelLoad } = reducer(buildState({ cancelLoad: false }), { type: cancelGetShortUrlVisits.toString() }); expect(cancelLoad).toEqual(true); }); it('stops loading and returns error on GET_SHORT_URL_VISITS_ERROR', () => { - const state = reducer(buildState({ loading: true, error: false }), { type: GET_SHORT_URL_VISITS_ERROR } as any); - const { loading, error } = state; + const { loading, error } = reducer( + buildState({ loading: true, error: false }), + { type: getShortUrlVisits.rejected.toString() }, + ); expect(loading).toEqual(false); expect(error).toEqual(true); @@ -59,11 +55,10 @@ describe('shortUrlVisitsReducer', () => { it('return visits on GET_SHORT_URL_VISITS', () => { const actionVisits = [{}, {}]; - const state = reducer( - buildState({ loading: true, error: false }), - { type: GET_SHORT_URL_VISITS, visits: actionVisits } as any, - ); - const { loading, error, visits } = state; + const { loading, error, visits } = reducer(buildState({ loading: true, error: false }), { + type: getShortUrlVisits.fulfilled.toString(), + payload: { visits: actionVisits }, + }); expect(loading).toEqual(false); expect(error).toEqual(false); @@ -126,50 +121,49 @@ describe('shortUrlVisitsReducer', () => { visits: visitsMocks, }); - const { visits } = reducer( - prevState, - { type: CREATE_VISITS, createdVisits: [{ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }] } as any, - ); + const { visits } = reducer(prevState, { + type: createNewVisits.toString(), + payload: { createdVisits: [{ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }] }, + }); expect(visits).toHaveLength(expectedVisits); }); it('returns new progress on GET_SHORT_URL_VISITS_PROGRESS_CHANGED', () => { - const state = reducer(undefined, { type: GET_SHORT_URL_VISITS_PROGRESS_CHANGED, progress: 85 } as any); - + const state = reducer(undefined, { type: progressChangedAction.toString(), payload: 85 }); expect(state).toEqual(expect.objectContaining({ progress: 85 })); }); it('returns fallbackInterval on GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL', () => { const fallbackInterval: DateInterval = 'last30Days'; - const state = reducer(undefined, { type: GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval } as any); + const state = reducer( + undefined, + { type: fallbackToIntervalAction.toString(), payload: fallbackInterval }, + ); expect(state).toEqual(expect.objectContaining({ fallbackInterval })); }); }); describe('getShortUrlVisits', () => { - type GetVisitsReturn = Promise<ShlinkVisits> | ((shortCode: string, query: any) => Promise<ShlinkVisits>); - - const buildApiClientMock = (returned: GetVisitsReturn) => Mock.of<ShlinkApiClient>({ - getShortUrlVisits: jest.fn(typeof returned === 'function' ? returned : async () => returned), - }); const dispatchMock = jest.fn(); const getState = () => Mock.of<ShlinkState>({ shortUrlVisits: Mock.of<ShortUrlVisits>({ cancelLoad: false }), }); - beforeEach(() => dispatchMock.mockReset()); - it('dispatches start and error when promise is rejected', async () => { - const ShlinkApiClient = buildApiClientMock(Promise.reject({})); + getShortUrlVisitsCall.mockRejectedValue({}); - await getShortUrlVisits(() => ShlinkApiClient)('abc123')(dispatchMock, getState); + await getShortUrlVisits({ shortCode: 'abc123' })(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_SHORT_URL_VISITS_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_SHORT_URL_VISITS_ERROR }); - expect(ShlinkApiClient.getShortUrlVisits).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getShortUrlVisits.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getShortUrlVisits.rejected.toString(), + })); + expect(getShortUrlVisitsCall).toHaveBeenCalledTimes(1); }); it.each([ @@ -179,29 +173,31 @@ describe('shortUrlVisitsReducer', () => { ])('dispatches start and success when promise is resolved', async (query, domain) => { const visits = visitsMocks; const shortCode = 'abc123'; - const ShlinkApiClient = buildApiClientMock(Promise.resolve({ + getShortUrlVisitsCall.mockResolvedValue({ data: visitsMocks, pagination: { currentPage: 1, pagesCount: 1, totalItems: 1, }, - })); + }); - await getShortUrlVisits(() => ShlinkApiClient)(shortCode, query)(dispatchMock, getState); + await getShortUrlVisits({ shortCode, query })(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_SHORT_URL_VISITS_START }); - expect(dispatchMock).toHaveBeenNthCalledWith( - 2, - { type: GET_SHORT_URL_VISITS, visits, shortCode, domain, query: query ?? {} }, - ); - expect(ShlinkApiClient.getShortUrlVisits).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getShortUrlVisits.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getShortUrlVisits.fulfilled.toString(), + payload: { visits, shortCode, domain, query: query ?? {} }, + })); + expect(getShortUrlVisitsCall).toHaveBeenCalledTimes(1); }); it('performs multiple API requests when response contains more pages', async () => { const expectedRequests = 3; - const ShlinkApiClient = buildApiClientMock(async (_, { page }) => + getShortUrlVisitsCall.mockImplementation(async (_, { page }) => Promise.resolve({ data: visitsMocks, pagination: { @@ -211,25 +207,33 @@ describe('shortUrlVisitsReducer', () => { }, })); - await getShortUrlVisits(() => ShlinkApiClient)('abc123')(dispatchMock, getState); + await getShortUrlVisits({ shortCode: 'abc123' })(dispatchMock, getState, {}); - expect(ShlinkApiClient.getShortUrlVisits).toHaveBeenCalledTimes(expectedRequests); + expect(getShortUrlVisitsCall).toHaveBeenCalledTimes(expectedRequests); expect(dispatchMock).toHaveBeenNthCalledWith(3, expect.objectContaining({ - visits: [...visitsMocks, ...visitsMocks, ...visitsMocks], + payload: expect.objectContaining({ + visits: [...visitsMocks, ...visitsMocks, ...visitsMocks], + }), })); }); it.each([ [ [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 5)) })], - { type: GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last7Days' }, + { type: fallbackToIntervalAction.toString(), payload: 'last7Days' }, + 3, ], [ [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 200)) })], - { type: GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last365Days' }, + { type: fallbackToIntervalAction.toString(), payload: 'last365Days' }, + 3, ], - [[], expect.objectContaining({ type: GET_SHORT_URL_VISITS })], - ])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => { + [[], expect.objectContaining({ type: getShortUrlVisits.fulfilled.toString() }), 2], + ])('dispatches fallback interval when the list of visits is empty', async ( + lastVisits, + expectedSecondDispatch, + expectedDispatchCalls, + ) => { const buildVisitsResult = (data: Visit[] = []): ShlinkVisits => ({ data, pagination: { @@ -238,22 +242,23 @@ describe('shortUrlVisitsReducer', () => { totalItems: 1, }, }); - const getShlinkShortUrlVisits = jest.fn() + getShortUrlVisitsCall .mockResolvedValueOnce(buildVisitsResult()) .mockResolvedValueOnce(buildVisitsResult(lastVisits)); - const ShlinkApiClient = Mock.of<ShlinkApiClient>({ getShortUrlVisits: getShlinkShortUrlVisits }); - await getShortUrlVisits(() => ShlinkApiClient)('abc123', {}, true)(dispatchMock, getState); + await getShortUrlVisits({ shortCode: 'abc123', doIntervalFallback: true })(dispatchMock, getState, {}); - expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_SHORT_URL_VISITS_START }); + expect(dispatchMock).toHaveBeenCalledTimes(expectedDispatchCalls); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getShortUrlVisits.pending.toString(), + })); expect(dispatchMock).toHaveBeenNthCalledWith(2, expectedSecondDispatch); - expect(getShlinkShortUrlVisits).toHaveBeenCalledTimes(2); + expect(getShortUrlVisitsCall).toHaveBeenCalledTimes(2); }); }); describe('cancelGetShortUrlVisits', () => { it('just returns the action with proper type', () => - expect(cancelGetShortUrlVisits()).toEqual({ type: GET_SHORT_URL_VISITS_CANCEL })); + expect(cancelGetShortUrlVisits()).toEqual({ type: cancelGetShortUrlVisits.toString() })); }); }); diff --git a/test/visits/reducers/tagVisits.test.ts b/test/visits/reducers/tagVisits.test.ts index 5a217d24..fc94e980 100644 --- a/test/visits/reducers/tagVisits.test.ts +++ b/test/visits/reducers/tagVisits.test.ts @@ -1,57 +1,53 @@ import { Mock } from 'ts-mockery'; import { addDays, formatISO, subDays } from 'date-fns'; -import reducer, { - getTagVisits, - cancelGetTagVisits, - GET_TAG_VISITS_START, - GET_TAG_VISITS_ERROR, - GET_TAG_VISITS, - GET_TAG_VISITS_LARGE, - GET_TAG_VISITS_CANCEL, - GET_TAG_VISITS_PROGRESS_CHANGED, - GET_TAG_VISITS_FALLBACK_TO_INTERVAL, +import { + getTagVisits as getTagVisitsCreator, + tagVisitsReducerCreator, TagVisits, } from '../../../src/visits/reducers/tagVisits'; -import { CREATE_VISITS } from '../../../src/visits/reducers/visitCreation'; import { rangeOf } from '../../../src/utils/utils'; import { Visit } from '../../../src/visits/types'; import { ShlinkVisits } from '../../../src/api/types'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { ShlinkState } from '../../../src/container/types'; import { formatIsoDate } from '../../../src/utils/helpers/date'; -import { DateInterval } from '../../../src/utils/dates/types'; +import { DateInterval } from '../../../src/utils/helpers/dateIntervals'; +import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; describe('tagVisitsReducer', () => { const now = new Date(); const visitsMocks = rangeOf(2, () => Mock.all<Visit>()); + const getTagVisitsCall = jest.fn(); + const buildShlinkApiClientMock = () => Mock.of<ShlinkApiClient>({ getTagVisits: getTagVisitsCall }); + const creator = getTagVisitsCreator(buildShlinkApiClientMock); + const { asyncThunk: getTagVisits, fallbackToIntervalAction, largeAction, progressChangedAction } = creator; + const { reducer, cancelGetVisits: cancelGetTagVisits } = tagVisitsReducerCreator(creator); + + beforeEach(jest.clearAllMocks); describe('reducer', () => { const buildState = (data: Partial<TagVisits>) => Mock.of<TagVisits>(data); it('returns loading on GET_TAG_VISITS_START', () => { - const state = reducer(buildState({ loading: false }), { type: GET_TAG_VISITS_START } as any); - const { loading } = state; - + const { loading } = reducer(buildState({ loading: false }), { type: getTagVisits.pending.toString() }); expect(loading).toEqual(true); }); it('returns loadingLarge on GET_TAG_VISITS_LARGE', () => { - const state = reducer(buildState({ loadingLarge: false }), { type: GET_TAG_VISITS_LARGE } as any); - const { loadingLarge } = state; - + const { loadingLarge } = reducer(buildState({ loadingLarge: false }), { type: largeAction.toString() }); expect(loadingLarge).toEqual(true); }); it('returns cancelLoad on GET_TAG_VISITS_CANCEL', () => { - const state = reducer(buildState({ cancelLoad: false }), { type: GET_TAG_VISITS_CANCEL } as any); - const { cancelLoad } = state; - + const { cancelLoad } = reducer(buildState({ cancelLoad: false }), { type: cancelGetTagVisits.toString() }); expect(cancelLoad).toEqual(true); }); it('stops loading and returns error on GET_TAG_VISITS_ERROR', () => { - const state = reducer(buildState({ loading: true, error: false }), { type: GET_TAG_VISITS_ERROR } as any); - const { loading, error } = state; + const { loading, error } = reducer( + buildState({ loading: true, error: false }), + { type: getTagVisits.rejected.toString() }, + ); expect(loading).toEqual(false); expect(error).toEqual(true); @@ -59,11 +55,10 @@ describe('tagVisitsReducer', () => { it('return visits on GET_TAG_VISITS', () => { const actionVisits = [{}, {}]; - const state = reducer( - buildState({ loading: true, error: false }), - { type: GET_TAG_VISITS, visits: actionVisits } as any, - ); - const { loading, error, visits } = state; + const { loading, error, visits } = reducer(buildState({ loading: true, error: false }), { + type: getTagVisits.fulfilled.toString(), + payload: { visits: actionVisits }, + }); expect(loading).toEqual(false); expect(error).toEqual(false); @@ -127,50 +122,46 @@ describe('tagVisitsReducer', () => { }); const { visits } = reducer(prevState, { - type: CREATE_VISITS, - createdVisits: [{ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }], - } as any); + type: createNewVisits.toString(), + payload: { createdVisits: [{ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }] }, + }); expect(visits).toHaveLength(expectedVisits); }); it('returns new progress on GET_TAG_VISITS_PROGRESS_CHANGED', () => { - const state = reducer(undefined, { type: GET_TAG_VISITS_PROGRESS_CHANGED, progress: 85 } as any); - + const state = reducer(undefined, { type: progressChangedAction.toString(), payload: 85 }); expect(state).toEqual(expect.objectContaining({ progress: 85 })); }); it('returns fallbackInterval on GET_TAG_VISITS_FALLBACK_TO_INTERVAL', () => { const fallbackInterval: DateInterval = 'last30Days'; - const state = reducer(undefined, { type: GET_TAG_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval } as any); + const state = reducer(undefined, { type: fallbackToIntervalAction.toString(), payload: fallbackInterval }); expect(state).toEqual(expect.objectContaining({ fallbackInterval })); }); }); describe('getTagVisits', () => { - type GetVisitsReturn = Promise<ShlinkVisits> | ((shortCode: string, query: any) => Promise<ShlinkVisits>); - - const buildApiClientMock = (returned: GetVisitsReturn) => Mock.of<ShlinkApiClient>({ - getTagVisits: jest.fn(typeof returned === 'function' ? returned : async () => returned), - }); const dispatchMock = jest.fn(); const getState = () => Mock.of<ShlinkState>({ tagVisits: { cancelLoad: false }, }); const tag = 'foo'; - beforeEach(jest.clearAllMocks); - it('dispatches start and error when promise is rejected', async () => { - const shlinkApiClient = buildApiClientMock(Promise.reject(new Error())); + getTagVisitsCall.mockRejectedValue(new Error()); - await getTagVisits(() => shlinkApiClient)('foo')(dispatchMock, getState); + await getTagVisits({ tag })(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_TAG_VISITS_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_TAG_VISITS_ERROR }); - expect(shlinkApiClient.getTagVisits).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getTagVisits.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getTagVisits.rejected.toString(), + })); + expect(getTagVisitsCall).toHaveBeenCalledTimes(1); }); it.each([ @@ -178,34 +169,45 @@ describe('tagVisitsReducer', () => { [{}], ])('dispatches start and success when promise is resolved', async (query) => { const visits = visitsMocks; - const shlinkApiClient = buildApiClientMock(Promise.resolve({ + getTagVisitsCall.mockResolvedValue({ data: visitsMocks, pagination: { currentPage: 1, pagesCount: 1, totalItems: 1, }, - })); + }); - await getTagVisits(() => shlinkApiClient)(tag, query)(dispatchMock, getState); + await getTagVisits({ tag, query })(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_TAG_VISITS_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_TAG_VISITS, visits, tag, query: query ?? {} }); - expect(shlinkApiClient.getTagVisits).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getTagVisits.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: getTagVisits.fulfilled.toString(), + payload: { visits, tag, query: query ?? {} }, + })); + expect(getTagVisitsCall).toHaveBeenCalledTimes(1); }); it.each([ [ [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 20)) })], - { type: GET_TAG_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last30Days' }, + { type: fallbackToIntervalAction.toString(), payload: 'last30Days' }, + 3, ], [ [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 100)) })], - { type: GET_TAG_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last180Days' }, + { type: fallbackToIntervalAction.toString(), payload: 'last180Days' }, + 3, ], - [[], expect.objectContaining({ type: GET_TAG_VISITS })], - ])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => { + [[], expect.objectContaining({ type: getTagVisits.fulfilled.toString() }), 2], + ])('dispatches fallback interval when the list of visits is empty', async ( + lastVisits, + expectedSecondDispatch, + expectedDispatchCalls, + ) => { const buildVisitsResult = (data: Visit[] = []): ShlinkVisits => ({ data, pagination: { @@ -214,22 +216,23 @@ describe('tagVisitsReducer', () => { totalItems: 1, }, }); - const getShlinkTagVisits = jest.fn() + getTagVisitsCall .mockResolvedValueOnce(buildVisitsResult()) .mockResolvedValueOnce(buildVisitsResult(lastVisits)); - const ShlinkApiClient = Mock.of<ShlinkApiClient>({ getTagVisits: getShlinkTagVisits }); - await getTagVisits(() => ShlinkApiClient)(tag, {}, true)(dispatchMock, getState); + await getTagVisits({ tag, doIntervalFallback: true })(dispatchMock, getState, {}); - expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_TAG_VISITS_START }); + expect(dispatchMock).toHaveBeenCalledTimes(expectedDispatchCalls); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: getTagVisits.pending.toString(), + })); expect(dispatchMock).toHaveBeenNthCalledWith(2, expectedSecondDispatch); - expect(getShlinkTagVisits).toHaveBeenCalledTimes(2); + expect(getTagVisitsCall).toHaveBeenCalledTimes(2); }); }); describe('cancelGetTagVisits', () => { it('just returns the action with proper type', () => - expect(cancelGetTagVisits()).toEqual({ type: GET_TAG_VISITS_CANCEL })); + expect(cancelGetTagVisits()).toEqual({ type: cancelGetTagVisits.toString() })); }); }); diff --git a/test/visits/reducers/visitCreation.test.ts b/test/visits/reducers/visitCreation.test.ts index c14f8b2e..19e5f899 100644 --- a/test/visits/reducers/visitCreation.test.ts +++ b/test/visits/reducers/visitCreation.test.ts @@ -1,5 +1,5 @@ import { Mock } from 'ts-mockery'; -import { CREATE_VISITS, createNewVisits } from '../../../src/visits/reducers/visitCreation'; +import { createNewVisits } from '../../../src/visits/reducers/visitCreation'; import { ShortUrl } from '../../../src/short-urls/data'; import { Visit } from '../../../src/visits/types'; @@ -9,9 +9,10 @@ describe('visitCreationReducer', () => { const visit = Mock.all<Visit>(); it('just returns the action with proper type', () => { - expect(createNewVisits([{ shortUrl, visit }])).toEqual( - { type: CREATE_VISITS, createdVisits: [{ shortUrl, visit }] }, - ); + expect(createNewVisits([{ shortUrl, visit }])).toEqual({ + type: createNewVisits.toString(), + payload: { createdVisits: [{ shortUrl, visit }] }, + }); }); }); }); diff --git a/test/visits/reducers/visitsOverview.test.ts b/test/visits/reducers/visitsOverview.test.ts index 98ced535..15ce1cf8 100644 --- a/test/visits/reducers/visitsOverview.test.ts +++ b/test/visits/reducers/visitsOverview.test.ts @@ -1,42 +1,53 @@ import { Mock } from 'ts-mockery'; -import reducer, { - GET_OVERVIEW_START, - GET_OVERVIEW_ERROR, - GET_OVERVIEW, +import { GetVisitsOverviewAction, VisitsOverview, - loadVisitsOverview, + loadVisitsOverview as loadVisitsOverviewCreator, + visitsOverviewReducerCreator, } from '../../../src/visits/reducers/visitsOverview'; -import { CREATE_VISITS, CreateVisitsAction } from '../../../src/visits/reducers/visitCreation'; +import { createNewVisits, CreateVisitsAction } from '../../../src/visits/reducers/visitCreation'; import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { ShlinkVisitsOverview } from '../../../src/api/types'; import { ShlinkState } from '../../../src/container/types'; import { CreateVisit, OrphanVisit, Visit } from '../../../src/visits/types'; describe('visitsOverviewReducer', () => { + const getVisitsOverview = jest.fn(); + const buildApiClientMock = () => Mock.of<ShlinkApiClient>({ getVisitsOverview }); + const loadVisitsOverview = loadVisitsOverviewCreator(buildApiClientMock); + const { reducer } = visitsOverviewReducerCreator(loadVisitsOverview); + + beforeEach(jest.clearAllMocks); + describe('reducer', () => { const action = (type: string) => Mock.of<GetVisitsOverviewAction>({ type }) as GetVisitsOverviewAction & CreateVisitsAction; const state = (payload: Partial<VisitsOverview> = {}) => Mock.of<VisitsOverview>(payload); it('returns loading on GET_OVERVIEW_START', () => { - const { loading } = reducer(state({ loading: false, error: false }), action(GET_OVERVIEW_START)); + const { loading } = reducer( + state({ loading: false, error: false }), + action(loadVisitsOverview.pending.toString()), + ); expect(loading).toEqual(true); }); it('stops loading and returns error on GET_OVERVIEW_ERROR', () => { - const { loading, error } = reducer(state({ loading: true, error: false }), action(GET_OVERVIEW_ERROR)); + const { loading, error } = reducer( + state({ loading: true, error: false }), + action(loadVisitsOverview.rejected.toString()), + ); expect(loading).toEqual(false); expect(error).toEqual(true); }); it('return visits overview on GET_OVERVIEW', () => { - const { loading, error, visitsCount } = reducer( - state({ loading: true, error: false }), - { type: GET_OVERVIEW, visitsCount: 100 } as unknown as GetVisitsOverviewAction & CreateVisitsAction, - ); + const { loading, error, visitsCount } = reducer(state({ loading: true, error: false }), { + type: loadVisitsOverview.fulfilled.toString(), + payload: { visitsCount: 100 }, + }); expect(loading).toEqual(false); expect(error).toEqual(false); @@ -51,20 +62,22 @@ describe('visitsOverviewReducer', () => { const { visitsCount, orphanVisitsCount } = reducer( state({ visitsCount: 100, orphanVisitsCount: providedOrphanVisitsCount }), { - type: CREATE_VISITS, - createdVisits: [ - Mock.of<CreateVisit>({ visit: Mock.all<Visit>() }), - Mock.of<CreateVisit>({ visit: Mock.all<Visit>() }), - Mock.of<CreateVisit>({ - visit: Mock.of<OrphanVisit>({ visitedUrl: '' }), - }), - Mock.of<CreateVisit>({ - visit: Mock.of<OrphanVisit>({ visitedUrl: '' }), - }), - Mock.of<CreateVisit>({ - visit: Mock.of<OrphanVisit>({ visitedUrl: '' }), - }), - ], + type: createNewVisits.toString(), + payload: { + createdVisits: [ + Mock.of<CreateVisit>({ visit: Mock.all<Visit>() }), + Mock.of<CreateVisit>({ visit: Mock.all<Visit>() }), + Mock.of<CreateVisit>({ + visit: Mock.of<OrphanVisit>({ visitedUrl: '' }), + }), + Mock.of<CreateVisit>({ + visit: Mock.of<OrphanVisit>({ visitedUrl: '' }), + }), + Mock.of<CreateVisit>({ + visit: Mock.of<OrphanVisit>({ visitedUrl: '' }), + }), + ], + }, } as unknown as GetVisitsOverviewAction & CreateVisitsAction, ); @@ -74,35 +87,41 @@ describe('visitsOverviewReducer', () => { }); describe('loadVisitsOverview', () => { - const buildApiClientMock = (returned: Promise<ShlinkVisitsOverview>) => Mock.of<ShlinkApiClient>({ - getVisitsOverview: jest.fn(async () => returned), - }); const dispatchMock = jest.fn(); const getState = () => Mock.of<ShlinkState>(); beforeEach(() => dispatchMock.mockReset()); it('dispatches start and error when promise is rejected', async () => { - const ShlinkApiClient = buildApiClientMock(Promise.reject()); + getVisitsOverview.mockRejectedValue(undefined); - await loadVisitsOverview(() => ShlinkApiClient)()(dispatchMock, getState); + await loadVisitsOverview()(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_OVERVIEW_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_OVERVIEW_ERROR }); - expect(ShlinkApiClient.getVisitsOverview).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: loadVisitsOverview.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: loadVisitsOverview.rejected.toString(), + })); + expect(getVisitsOverview).toHaveBeenCalledTimes(1); }); it('dispatches start and success when promise is resolved', async () => { const resolvedOverview = Mock.of<ShlinkVisitsOverview>({ visitsCount: 50 }); - const shlinkApiClient = buildApiClientMock(Promise.resolve(resolvedOverview)); + getVisitsOverview.mockResolvedValue(resolvedOverview); - await loadVisitsOverview(() => shlinkApiClient)()(dispatchMock, getState); + await loadVisitsOverview()(dispatchMock, getState, {}); expect(dispatchMock).toHaveBeenCalledTimes(2); - expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_OVERVIEW_START }); - expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_OVERVIEW, visitsCount: 50 }); - expect(shlinkApiClient.getVisitsOverview).toHaveBeenCalledTimes(1); + expect(dispatchMock).toHaveBeenNthCalledWith(1, expect.objectContaining({ + type: loadVisitsOverview.pending.toString(), + })); + expect(dispatchMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ + type: loadVisitsOverview.fulfilled.toString(), + payload: { visitsCount: 50 }, + })); + expect(getVisitsOverview).toHaveBeenCalledTimes(1); }); }); });