diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..1320b9a
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+ "presets": ["@babel/preset-env"]
+}
diff --git a/.browserslistrc b/.browserslistrc
new file mode 100644
index 0000000..4b61082
--- /dev/null
+++ b/.browserslistrc
@@ -0,0 +1,3 @@
+last 2 versions
+not dead
+> 0.5%
\ No newline at end of file
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..db4c6d9
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,2 @@
+dist
+node_modules
\ No newline at end of file
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..b6b5228
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,36 @@
+{
+ "parser": "@typescript-eslint/parser",
+ "plugins": ["@typescript-eslint", "jest", "prettier", "import"],
+ "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended", "prettier"],
+ "parserOptions": {
+ "ecmaVersion": "latest",
+ "sourceType": "module"
+ },
+ "env": {
+ "es6": true,
+ "browser": true,
+ "node": true
+ },
+ "rules": {
+ "no-debugger": "off",
+ "no-console": "off",
+ "object-shorthand": "warn",
+ "array-callback-return": "warn",
+ "prefer-destructuring": "warn",
+ "prefer-arrow-callback": "warn",
+ "no-duplicate-imports": "warn",
+ "import/first": "warn",
+ "eqeqeq": "warn",
+ "no-unneeded-ternary": "warn",
+ "no-else-return": "warn",
+ "spaced-comment": "warn",
+ "@typescript-eslint/no-explicit-any": "error",
+ "@typescript-eslint/no-var-requires": "off",
+ "prettier/prettier": [
+ "error",
+ {
+ "endOfLine": "auto"
+ }
+ ]
+ }
+}
diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template_for_mentor.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template_for_mentor.md
index ba58e9b..10dbd99 100644
--- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template_for_mentor.md
+++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template_for_mentor.md
@@ -1,15 +1,18 @@
1. Task: [link](https://github.com/rolling-scopes-school/tasks/blob/master/tasks/eCommerce-Application/Sprints/Sprint%231.md)
-2. Screenshot:
+2. Screenshot:
3. Deploy: [link]()
4. Done 07.08.2023 / deadline 07.08.2023
5. Score: 110 / 110
+
#### CrossCheck Criteria (55/55):
+
- [x] Example (5/5):
- (+5) Example.
- [x] Example (50/50):
- (+50) Example.
#### Mentor Evaluation Criteria (55/55):
+
- [x] Example (5/5):
- (+5) Example.
- [x] Example (50/50):
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 7c881e4..e732f0c 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,20 +1,21 @@
-__1. Task__
+**1. Task**
_task_title_
-__2. Link in [project](https://github.com/orgs/this-is-this-team/projects/3)__
+**2. Link in [project](https://github.com/orgs/this-is-this-team/projects/3)**
_if multiple issues are combined into a single pull request then insert all links (link-1, link-2, etc.)_
[link](_insert_link_here_)
-__3. Sprint__
+**3. Sprint**
_number_of_sprint_
-__4. Timeline__
+**4. Timeline**
Done 01.08.2023 / Deadline 30.08.2023
-__5. Task description and solution__
+**5. Task description and solution**
_task_description_and_solution_
-__6. Self Check before Merge__
+**6. Self Check before Merge**
+
- [ ] Pull request title should follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary)
- [ ] Reviewers added (elsuppo/MaxLisyanskiy/eugenebalts)
- [ ] All commits in pull request should follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary)
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 0000000..83985be
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,5 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npx lint-staged
+npm run test
\ No newline at end of file
diff --git a/.lintstagedrc b/.lintstagedrc
new file mode 100644
index 0000000..5dcf2f6
--- /dev/null
+++ b/.lintstagedrc
@@ -0,0 +1 @@
+{ "*.{js,ts}": ["npm run lint:check"], "*": ["npm run prettier:check"] }
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..3c41576
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,10 @@
+{
+ "trailingComma": "es5",
+ "tabWidth": 2,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": true,
+ "printWidth": 120,
+ "bracketSameLine": false,
+ "endOfLine": "auto"
+}
diff --git a/README.md b/README.md
index d416b84..0098b50 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,145 @@
-# eCommerce-Application
\ No newline at end of file
+# eCommerce-Application _«this is this.»_
+
+:earth_americas:`this is this.` is a web application for searching and buying travel tours.
+The project is being developed as part of the final task of the course [JavaScript/Front-end (2023Q1)](https://rs.school/js/) from the [RS School](https://rs.school/).
+The [`this-is-this team`](https://github.com/this-is-this-team) is working on the project.
+
+## Commercetools Setup
+
+
+ .env example
+
+
+ CTP_PROJECT_KEY=
+ CTP_CLIENT_SECRET=
+ CTP_CLIENT_ID=
+ CTP_AUTH_URL=
+ CTP_API_URL=
+ CTP_SCOPES=
+
+
+
+
+ necessary scopes
+
+
+
+ - view_products
+ - view_cart_discounts
+ - view_shipping_methods
+ - view_categories
+ - view_discount_codes
+ - view_product_selections
+ - manage_my_shopping_lists
+ - manage_my_payments
+ - manage_my_profile
+ - manage_my_orders
+ - create_anonymous_token
+
+
+
+## Project Purpose
+
+- Develop a Single Page Application (SPA) without using frameworks
+- Teamwork skills
+- Task planning
+- Consolidation of knowledge gained on the course
+
+## Technology Stack
+
+[](#technology-stack)
+
+- **TypeScript** _[docs](https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html)_
+- **Webpack 5** _[docs](https://webpack.js.org/concepts/)_
+- **Jest** _[docs](https://jestjs.io/docs/getting-started)_
+- **SCSS** _[docs](https://sass-lang.com/documentation/)_
+- **CommerceTools API** _[docs](https://docs.commercetools.com/api/general-concepts)_
+- Teamwork tools:
+ - **Prettier** _[docs](https://prettier.io/docs/en/)_
+ - **ESLint** _[docs](https://eslint.org/docs/latest/use/core-concepts)_
+ - **Husky** _[docs](https://typicode.github.io/husky/)_
+ - **lint-staged** _[docs](https://github.com/okonet/lint-staged)_
+
+## Getting Started
+
+To get a local copy of the project perform the following actions:
+
+1. Clone the repo
+
+```
+git clone https://github.com/this-is-this-team/eCommerce-Application.git
+```
+
+2. Install npm packages
+
+```
+npm install
+```
+
+3. Run the project locally
+
+```
+npm run start
+```
+
+## Available scripts
+
+#### Webpack (code building)
+
+- build development version
+
+```
+npm run build:dev
+```
+
+- build production version
+
+```
+npm run build:prod
+```
+
+#### Prettier (code formatting)
+
+- сhecks formatting for all project files
+
+```
+npm run prettier:check
+```
+
+- auto fixes formatting for all project files
+
+```
+npm run prettier:fix
+```
+
+#### ESLint (code linting)
+
+- checks linting for all project files
+
+```
+npm run lint:check
+```
+
+- auto fixes linting error for all project files
+
+```
+npm run lint:fix
+```
+
+#### JEST (code testing)
+
+- run all `*.test.ts` files for test execution
+
+```
+npm run test
+```
+
+
+ ALSO
+
+ Before making a commit an **automated** check is performed for formatting, linting, and code testing using Husky and lint-staged
+ ```
+ npx lint-staged
+ npm run test
+ ```
+
diff --git a/jest.config.json b/jest.config.json
new file mode 100644
index 0000000..48135e5
--- /dev/null
+++ b/jest.config.json
@@ -0,0 +1,9 @@
+{
+ "preset": "ts-jest",
+ "testEnvironment": "jsdom",
+ "moduleFileExtensions": ["ts", "js"],
+ "testMatch": ["**/__tests__/**/*.+(ts|tsx|js)", "**/?(*.)+(spec|test).+(ts|tsx|js)"],
+ "moduleNameMapper": {
+ "^.+\\.(css|less|scss)$": "babel-jest"
+ }
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..fc951e9
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,16175 @@
+{
+ "name": "ecommerce-application",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "ecommerce-application",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "@commercetools/platform-sdk": "^4.11.0",
+ "@commercetools/sdk-client-v2": "^2.2.0",
+ "swiper": "^10.2.0",
+ "toastify-js": "^1.12.0"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.22.9",
+ "@babel/preset-env": "^7.22.9",
+ "@types/jest": "^29.5.3",
+ "@types/node-fetch": "^2.6.4",
+ "@types/toastify-js": "^1.12.0",
+ "@typescript-eslint/eslint-plugin": "^6.2.1",
+ "babel-loader": "^9.1.3",
+ "css-loader": "^6.8.1",
+ "dotenv-webpack": "^8.0.1",
+ "eslint": "^8.46.0",
+ "eslint-config-prettier": "^8.9.0",
+ "eslint-plugin-import": "^2.28.0",
+ "eslint-plugin-jest": "^27.2.3",
+ "eslint-plugin-prettier": "^5.0.0",
+ "eslint-webpack-plugin": "^4.0.1",
+ "html-webpack-plugin": "^5.5.3",
+ "husky": "^8.0.3",
+ "jest": "^29.6.2",
+ "jest-environment-jsdom": "^29.6.2",
+ "lint-staged": "^13.2.3",
+ "mini-css-extract-plugin": "^2.7.6",
+ "postcss": "^8.4.27",
+ "postcss-loader": "^7.3.3",
+ "postcss-preset-env": "^9.1.0",
+ "prettier": "^3.0.0",
+ "sass": "^1.64.2",
+ "sass-loader": "^13.3.2",
+ "style-loader": "^3.3.3",
+ "ts-jest": "^29.1.1",
+ "ts-loader": "^9.4.4",
+ "typescript": "^5.1.6",
+ "webpack": "^5.88.2",
+ "webpack-cli": "^5.1.4",
+ "webpack-dev-server": "^4.15.1"
+ }
+ },
+ "node_modules/@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
+ "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz",
+ "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
+ "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz",
+ "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.9",
+ "@babel/helper-compilation-targets": "^7.22.9",
+ "@babel/helper-module-transforms": "^7.22.9",
+ "@babel/helpers": "^7.22.6",
+ "@babel/parser": "^7.22.7",
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.8",
+ "@babel/types": "^7.22.5",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.2",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@babel/core/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz",
+ "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
+ "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.5.tgz",
+ "integrity": "sha512-m1EP3lVOPptR+2DwD125gziZNcmoNSHGmJROKoy87loWUQyJaVXDgpmruWqDARZSmtYQ+Dl25okU8+qhVzuykw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz",
+ "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-validator-option": "^7.22.5",
+ "browserslist": "^4.21.9",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.9.tgz",
+ "integrity": "sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-member-expression-to-functions": "^7.22.5",
+ "@babel/helper-optimise-call-expression": "^7.22.5",
+ "@babel/helper-replace-supers": "^7.22.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-regexp-features-plugin": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz",
+ "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "regexpu-core": "^5.3.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz",
+ "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.22.6",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+ "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz",
+ "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz",
+ "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz",
+ "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-module-imports": "^7.22.5",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/helper-validator-identifier": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz",
+ "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-remap-async-to-generator": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz",
+ "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-wrap-function": "^7.22.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz",
+ "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-member-expression-to-functions": "^7.22.5",
+ "@babel/helper-optimise-call-expression": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+ "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz",
+ "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
+ "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
+ "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-wrap-function": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.9.tgz",
+ "integrity": "sha512-sZ+QzfauuUEfxSEjKFmi3qDSHgLsTPK/pEpoD/qonZKOtTPTLbf59oabPQ4rKekt9lFcj/hTZaOhWwFYrgjk+Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
+ "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.6",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz",
+ "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.22.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz",
+ "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==",
+ "dev": true,
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz",
+ "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz",
+ "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
+ "@babel/plugin-transform-optional-chaining": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.13.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-property-in-object": {
+ "version": "7.21.0-placeholder-for-preset-env.2",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
+ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
+ "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-export-namespace-from": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-assertions": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz",
+ "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-attributes": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz",
+ "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz",
+ "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz",
+ "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
+ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-arrow-functions": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz",
+ "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-generator-functions": {
+ "version": "7.22.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.7.tgz",
+ "integrity": "sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-remap-async-to-generator": "^7.22.5",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz",
+ "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-remap-async-to-generator": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz",
+ "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoping": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.5.tgz",
+ "integrity": "sha512-EcACl1i5fSQ6bt+YGuU/XGCeZKStLmyVGytWkpyhCLeQVA0eu6Wtiw92V+I1T/hnezUv7j74dA/Ro69gWcU+hg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-class-properties": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz",
+ "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-class-static-block": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz",
+ "integrity": "sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.12.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz",
+ "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-compilation-targets": "^7.22.6",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-optimise-call-expression": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-replace-supers": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-computed-properties": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz",
+ "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/template": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-destructuring": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.5.tgz",
+ "integrity": "sha512-GfqcFuGW8vnEqTUBM7UtPd5A4q797LTvvwKxXTgRsFjoqaJiEg9deBG6kWeQYkVEL569NpnmpC0Pkr/8BLKGnQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-dotall-regex": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz",
+ "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-duplicate-keys": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz",
+ "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-dynamic-import": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz",
+ "integrity": "sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz",
+ "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-export-namespace-from": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz",
+ "integrity": "sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-for-of": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz",
+ "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-function-name": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz",
+ "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-json-strings": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz",
+ "integrity": "sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-json-strings": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-literals": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz",
+ "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-logical-assignment-operators": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz",
+ "integrity": "sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-member-expression-literals": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz",
+ "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-amd": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz",
+ "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz",
+ "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-simple-access": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-systemjs": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz",
+ "integrity": "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-umd": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz",
+ "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz",
+ "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-new-target": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz",
+ "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz",
+ "integrity": "sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-numeric-separator": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz",
+ "integrity": "sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-rest-spread": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz",
+ "integrity": "sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.22.5",
+ "@babel/helper-compilation-targets": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-super": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz",
+ "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-replace-supers": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-optional-catch-binding": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz",
+ "integrity": "sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-optional-chaining": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.6.tgz",
+ "integrity": "sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz",
+ "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-methods": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz",
+ "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-property-in-object": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz",
+ "integrity": "sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-create-class-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-property-literals": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz",
+ "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-regenerator": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz",
+ "integrity": "sha512-rR7KePOE7gfEtNTh9Qw+iO3Q/e4DEsoQ+hdvM6QUDH7JRJ5qxq5AA52ZzBWbI5i9lfNuvySgOGP8ZN7LAmaiPw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "regenerator-transform": "^0.15.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-reserved-words": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz",
+ "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-shorthand-properties": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz",
+ "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-spread": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz",
+ "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-sticky-regex": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz",
+ "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-template-literals": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz",
+ "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typeof-symbol": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz",
+ "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-escapes": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.5.tgz",
+ "integrity": "sha512-biEmVg1IYB/raUO5wT1tgfacCef15Fbzhkx493D3urBI++6hpJ+RFG4SrWMn0NEZLfvilqKf3QDrRVZHo08FYg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-property-regex": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz",
+ "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-regex": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz",
+ "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-sets-regex": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz",
+ "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/preset-env": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.9.tgz",
+ "integrity": "sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-compilation-targets": "^7.22.9",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-validator-option": "^7.22.5",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5",
+ "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
+ "@babel/plugin-syntax-import-assertions": "^7.22.5",
+ "@babel/plugin-syntax-import-attributes": "^7.22.5",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5",
+ "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
+ "@babel/plugin-transform-arrow-functions": "^7.22.5",
+ "@babel/plugin-transform-async-generator-functions": "^7.22.7",
+ "@babel/plugin-transform-async-to-generator": "^7.22.5",
+ "@babel/plugin-transform-block-scoped-functions": "^7.22.5",
+ "@babel/plugin-transform-block-scoping": "^7.22.5",
+ "@babel/plugin-transform-class-properties": "^7.22.5",
+ "@babel/plugin-transform-class-static-block": "^7.22.5",
+ "@babel/plugin-transform-classes": "^7.22.6",
+ "@babel/plugin-transform-computed-properties": "^7.22.5",
+ "@babel/plugin-transform-destructuring": "^7.22.5",
+ "@babel/plugin-transform-dotall-regex": "^7.22.5",
+ "@babel/plugin-transform-duplicate-keys": "^7.22.5",
+ "@babel/plugin-transform-dynamic-import": "^7.22.5",
+ "@babel/plugin-transform-exponentiation-operator": "^7.22.5",
+ "@babel/plugin-transform-export-namespace-from": "^7.22.5",
+ "@babel/plugin-transform-for-of": "^7.22.5",
+ "@babel/plugin-transform-function-name": "^7.22.5",
+ "@babel/plugin-transform-json-strings": "^7.22.5",
+ "@babel/plugin-transform-literals": "^7.22.5",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.22.5",
+ "@babel/plugin-transform-member-expression-literals": "^7.22.5",
+ "@babel/plugin-transform-modules-amd": "^7.22.5",
+ "@babel/plugin-transform-modules-commonjs": "^7.22.5",
+ "@babel/plugin-transform-modules-systemjs": "^7.22.5",
+ "@babel/plugin-transform-modules-umd": "^7.22.5",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
+ "@babel/plugin-transform-new-target": "^7.22.5",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5",
+ "@babel/plugin-transform-numeric-separator": "^7.22.5",
+ "@babel/plugin-transform-object-rest-spread": "^7.22.5",
+ "@babel/plugin-transform-object-super": "^7.22.5",
+ "@babel/plugin-transform-optional-catch-binding": "^7.22.5",
+ "@babel/plugin-transform-optional-chaining": "^7.22.6",
+ "@babel/plugin-transform-parameters": "^7.22.5",
+ "@babel/plugin-transform-private-methods": "^7.22.5",
+ "@babel/plugin-transform-private-property-in-object": "^7.22.5",
+ "@babel/plugin-transform-property-literals": "^7.22.5",
+ "@babel/plugin-transform-regenerator": "^7.22.5",
+ "@babel/plugin-transform-reserved-words": "^7.22.5",
+ "@babel/plugin-transform-shorthand-properties": "^7.22.5",
+ "@babel/plugin-transform-spread": "^7.22.5",
+ "@babel/plugin-transform-sticky-regex": "^7.22.5",
+ "@babel/plugin-transform-template-literals": "^7.22.5",
+ "@babel/plugin-transform-typeof-symbol": "^7.22.5",
+ "@babel/plugin-transform-unicode-escapes": "^7.22.5",
+ "@babel/plugin-transform-unicode-property-regex": "^7.22.5",
+ "@babel/plugin-transform-unicode-regex": "^7.22.5",
+ "@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
+ "@babel/preset-modules": "^0.1.5",
+ "@babel/types": "^7.22.5",
+ "babel-plugin-polyfill-corejs2": "^0.4.4",
+ "babel-plugin-polyfill-corejs3": "^0.8.2",
+ "babel-plugin-polyfill-regenerator": "^0.5.1",
+ "core-js-compat": "^3.31.0",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-modules": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz",
+ "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/@babel/regjsgen": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz",
+ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==",
+ "dev": true
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
+ "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
+ "dev": true,
+ "dependencies": {
+ "regenerator-runtime": "^0.13.11"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
+ "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.22.8",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz",
+ "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.7",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.22.7",
+ "@babel/types": "^7.22.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@babel/types": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz",
+ "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true
+ },
+ "node_modules/@commercetools/platform-sdk": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@commercetools/platform-sdk/-/platform-sdk-4.11.0.tgz",
+ "integrity": "sha512-ftcq6mCxzpIG9wmGpTED6KQCApk4nyURh81J3PRP3d48oCLOrkZSyzDDfvflGoVZQeIcox+YdtyqZoryFrRtmQ==",
+ "dependencies": {
+ "@commercetools/sdk-client-v2": "^2.1.6",
+ "@commercetools/sdk-middleware-auth": "^7.0.0",
+ "@commercetools/sdk-middleware-http": "^7.0.0",
+ "@commercetools/sdk-middleware-logger": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@commercetools/sdk-client-v2": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@commercetools/sdk-client-v2/-/sdk-client-v2-2.2.0.tgz",
+ "integrity": "sha512-/j/hINnuh3gdBeMrHUvuSZo+8nkckCHK3Nu6m3/ZkUqVkamRheU5ve/DlALvYpjs2XS2BdWTs1+Wsyyz1+x6iQ==",
+ "dependencies": {
+ "buffer": "^6.0.3",
+ "node-fetch": "^2.6.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@commercetools/sdk-middleware-auth": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/@commercetools/sdk-middleware-auth/-/sdk-middleware-auth-7.0.1.tgz",
+ "integrity": "sha512-XLRm+o3Yd0mkVoyzsOA98PUu0U0ajQdBHMhZ8N2XMOtL4OY8zsgT8ap5JneXV8zWZNiwIYYAYoUDwBlLZh2lAQ==",
+ "dependencies": {
+ "node-fetch": "^2.6.7"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@commercetools/sdk-middleware-http": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/@commercetools/sdk-middleware-http/-/sdk-middleware-http-7.0.3.tgz",
+ "integrity": "sha512-vCMYMCla8vJsbmIpFyaq0DrjcIgkJpTsW+yOMupXM/ggR6PeJWav0H1iObGX3rZOpn6ZDJZglgGbFQ/Z0kGrJw==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@commercetools/sdk-middleware-logger": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@commercetools/sdk-middleware-logger/-/sdk-middleware-logger-3.0.0.tgz",
+ "integrity": "sha512-DhMXAA2yIch/AaGxy7st85Z1HFmeLtHWGkr9z5rX4xKjan4PHGB/IE5saAR+SNGHhs6+1Lp8vZEHDo3tFqVLmg==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@csstools/cascade-layer-name-parser": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.4.tgz",
+ "integrity": "sha512-zXMGsJetbLoXe+gjEES07MEGjL0Uy3hMxmnGtVBrRpVKr5KV9OgCB09zr/vLrsEtoVQTgJFewxaU8IYSAE4tjg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0"
+ }
+ },
+ "node_modules/@csstools/color-helpers": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-3.0.0.tgz",
+ "integrity": "sha512-rBODd1rY01QcenD34QxbQxLc1g+Uh7z1X/uzTHNQzJUnFCT9/EZYI7KWq+j0YfWMXJsRJ8lVkqBcB0R/qLr+yg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ }
+ },
+ "node_modules/@csstools/css-calc": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-1.1.3.tgz",
+ "integrity": "sha512-7mJZ8gGRtSQfQKBQFi5N0Z+jzNC0q8bIkwojP1W0w+APzEqHu5wJoGVsvKxVnVklu9F8tW1PikbBRseYnAdv+g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0"
+ }
+ },
+ "node_modules/@csstools/css-color-parser": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-1.2.3.tgz",
+ "integrity": "sha512-YaEnCoPTdhE4lPQFH3dU4IEk8S+yCnxS88wMv45JzlnMfZp57hpqA6qf2gX8uv7IJTJ/43u6pTQmhy7hCjlz7g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/color-helpers": "^3.0.0",
+ "@csstools/css-calc": "^1.1.3"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0"
+ }
+ },
+ "node_modules/@csstools/css-parser-algorithms": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.1.tgz",
+ "integrity": "sha512-xrvsmVUtefWMWQsGgFffqWSK03pZ1vfDki4IVIIUxxDKnGBzqNgv0A7SB1oXtVNEkcVO8xi1ZrTL29HhSu5kGA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-tokenizer": "^2.2.0"
+ }
+ },
+ "node_modules/@csstools/css-tokenizer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.0.tgz",
+ "integrity": "sha512-wErmsWCbsmig8sQKkM6pFhr/oPha1bHfvxsUY5CYSQxwyhA9Ulrs8EqCgClhg4Tgg2XapVstGqSVcz0xOYizZA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ }
+ },
+ "node_modules/@csstools/media-query-list-parser": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.3.tgz",
+ "integrity": "sha512-ATul1u+pic4aVpstgueqxEv4MsObEbszAxfTXpx9LHaeD3LAh+wFqdCteyegWmjk0k5rkSCAvIOaJe9U3DD09w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0"
+ }
+ },
+ "node_modules/@csstools/postcss-cascade-layers": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-4.0.0.tgz",
+ "integrity": "sha512-dVPVVqQG0FixjM9CG/+8eHTsCAxRKqmNh6H69IpruolPlnEF1611f2AoLK8TijTSAsqBSclKd4WHs1KUb/LdJw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/selector-specificity": "^3.0.0",
+ "postcss-selector-parser": "^6.0.13"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-color-function": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-3.0.1.tgz",
+ "integrity": "sha512-+vrvCQeUifpMeyd42VQ3JPWGQ8cO19+TnGbtfq1SDSgZzRapCQO4aK9h/jhMOKPnxGzbA57oS0aHgP/12N9gSQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-color-parser": "^1.2.2",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0",
+ "@csstools/postcss-progressive-custom-properties": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-color-mix-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-2.0.1.tgz",
+ "integrity": "sha512-Z5cXkLiccKIVcUTe+fAfjUD7ZUv0j8rq3dSoBpM6I49dcw+50318eYrwUZa3nyb4xNx7ntNNUPmesAc87kPE2Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-color-parser": "^1.2.2",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0",
+ "@csstools/postcss-progressive-custom-properties": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-exponential-functions": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-1.0.0.tgz",
+ "integrity": "sha512-FPndJ/7oGlML7/4EhLi902wGOukO0Nn37PjwOQGc0BhhjQPy3np3By4d3M8s9Cfmp9EHEKgUHRN2DQ5HLT/hTw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-calc": "^1.1.3",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-font-format-keywords": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-3.0.0.tgz",
+ "integrity": "sha512-ntkGj+1uDa/u6lpjPxnkPcjJn7ChO/Kcy08YxctOZI7vwtrdYvFhmE476dq8bj1yna306+jQ9gzXIG/SWfOaRg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-gradients-interpolation-method": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-4.0.1.tgz",
+ "integrity": "sha512-IHeFIcksjI8xKX7PWLzAyigM3UvJdZ4btejeNa7y/wXxqD5dyPPZuY55y8HGTrS6ETVTRqfIznoCPtTzIX7ygQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-color-parser": "^1.2.2",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0",
+ "@csstools/postcss-progressive-custom-properties": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-hwb-function": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-3.0.1.tgz",
+ "integrity": "sha512-FYe2K8EOYlL1BUm2HTXVBo6bWAj0xl4khOk6EFhQHy/C5p3rlr8OcetzQuwMeNQ3v25nB06QTgqUHoOUwoEqhA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-color-parser": "^1.2.2",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-ic-unit": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-3.0.0.tgz",
+ "integrity": "sha512-FH3+zfOfsgtX332IIkRDxiYLmgwyNk49tfltpC6dsZaO4RV2zWY6x9VMIC5cjvmjlDO7DIThpzqaqw2icT8RbQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/postcss-progressive-custom-properties": "^3.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-is-pseudo-class": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-4.0.0.tgz",
+ "integrity": "sha512-0I6siRcDymG3RrkNTSvHDMxTQ6mDyYE8awkcaHNgtYacd43msl+4ZWDfQ1yZQ/viczVWjqJkLmPiRHSgxn5nZA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/selector-specificity": "^3.0.0",
+ "postcss-selector-parser": "^6.0.13"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-logical-float-and-clear": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-2.0.0.tgz",
+ "integrity": "sha512-Wki4vxsF6icRvRz8eF9bPpAvwaAt0RHwhVOyzfoFg52XiIMjb6jcbHkGxwpJXP4DVrnFEwpwmrz5aTRqOW82kg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-logical-resize": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-2.0.0.tgz",
+ "integrity": "sha512-lCQ1aX8c5+WI4t5EoYf3alTzJNNocMqTb+u1J9CINdDhFh1fjovqK+0aHalUHsNstZmzFPNzIkU4Mb3eM9U8SA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-logical-viewport-units": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-2.0.1.tgz",
+ "integrity": "sha512-R5s19SscS7CHoxvdYNMu2Y3WDwG4JjdhsejqjunDB1GqfzhtHSvL7b5XxCkUWqm2KRl35hI6kJ4HEaCDd/3BXg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-tokenizer": "^2.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-media-minmax": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-1.0.6.tgz",
+ "integrity": "sha512-BmwKkqEzzQz6D+5ctoacsiGrq4kVgd1PMEPwkwdR0qFaL2C2nguGsWG87xEw+HIts/2yxhIPTm7Jp3DQq+wn3Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-calc": "^1.1.3",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0",
+ "@csstools/media-query-list-parser": "^2.1.3"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-2.0.1.tgz",
+ "integrity": "sha512-UvMYxXT3R011whbxzRwLx7d7eNGyVsnZo7waAmf10ZGnT34XidY+rsdFnk6OdFwuG6FYqw3/tptQEAZOmUgvLw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0",
+ "@csstools/media-query-list-parser": "^2.1.3"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-nested-calc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-3.0.0.tgz",
+ "integrity": "sha512-HsB66aDWAouOwD/GcfDTS0a7wCuVWaTpXcjl5VKP0XvFxDiU+r0T8FG7xgb6ovZNZ+qzvGIwRM+CLHhDgXrYgQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-normalize-display-values": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-3.0.0.tgz",
+ "integrity": "sha512-6Nw55PRXEKEVqn3bzA8gRRPYxr5tf5PssvcE5DRA/nAxKgKtgNZMCHCSd1uxTCWeyLnkf6h5tYRSB0P1Vh/K/A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-oklab-function": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-3.0.1.tgz",
+ "integrity": "sha512-3TIz+dCPlQPzz4yAEYXchUpfuU2gRYK4u1J+1xatNX85Isg4V+IbLyppblWLV4Vb6npFF8qsHN17rNuxOIy/6w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-color-parser": "^1.2.2",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0",
+ "@csstools/postcss-progressive-custom-properties": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-progressive-custom-properties": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-3.0.0.tgz",
+ "integrity": "sha512-2/D3CCL9DN2xhuUTP8OKvKnaqJ1j4yZUxuGLsCUOQ16wnDAuMLKLkflOmZF5tsPh/02VPeXRmqIN+U595WAulw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-relative-color-syntax": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-2.0.1.tgz",
+ "integrity": "sha512-9B8br/7q0bjD1fV3yE22izjc7Oy5hDbDgwdFEz207cdJHYC9yQneJzP3H+/w3RgC7uyfEVhyyhkGRx5YAfJtmg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-color-parser": "^1.2.2",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0",
+ "@csstools/postcss-progressive-custom-properties": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-scope-pseudo-class": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-3.0.0.tgz",
+ "integrity": "sha512-GFNVsD97OuEcfHmcT0/DAZWAvTM/FFBDQndIOLawNc1Wq8YqpZwBdHa063Lq+Irk7azygTT+Iinyg3Lt76p7rg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.13"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-stepped-value-functions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-3.0.1.tgz",
+ "integrity": "sha512-y1sykToXorFE+5cjtp//xAMWEAEple0kcZn2QhzEFIZDDNvGOCp5JvvmmPGsC3eDlj6yQp70l9uXZNLnimEYfA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-calc": "^1.1.3",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-text-decoration-shorthand": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-3.0.0.tgz",
+ "integrity": "sha512-BAa1MIMJmEZlJ+UkPrkyoz3DC7kLlIl2oDya5yXgvUrelpwxddgz8iMp69qBStdXwuMyfPx46oZcSNx8Z0T2eA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/color-helpers": "^3.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-trigonometric-functions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-3.0.1.tgz",
+ "integrity": "sha512-hW+JPv0MPQfWC1KARgvJI6bisEUFAZWSvUNq/khGCupYV/h6Z9R2ZFz0Xc633LXBst0ezbXpy7NpnPurSx5Klw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-calc": "^1.1.3",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/postcss-unset-value": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-3.0.0.tgz",
+ "integrity": "sha512-P0JD1WHh3avVyKKRKjd0dZIjCEeaBer8t1BbwGMUDtSZaLhXlLNBqZ8KkqHzYWXOJgHleXAny2/sx8LYl6qhEA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/@csstools/selector-specificity": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.0.tgz",
+ "integrity": "sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss-selector-parser": "^6.0.13"
+ }
+ },
+ "node_modules/@discoveryjs/json-ext": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz",
+ "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.1.tgz",
+ "integrity": "sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "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/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.46.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.46.0.tgz",
+ "integrity": "sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
+ "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@humanwhocodes/config-array/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "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",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz",
+ "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/console/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/console/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/console/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/console/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/@jest/console/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/core": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz",
+ "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.6.2",
+ "@jest/reporters": "^29.6.2",
+ "@jest/test-result": "^29.6.2",
+ "@jest/transform": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "@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": "^29.5.0",
+ "jest-config": "^29.6.2",
+ "jest-haste-map": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-regex-util": "^29.4.3",
+ "jest-resolve": "^29.6.2",
+ "jest-resolve-dependencies": "^29.6.2",
+ "jest-runner": "^29.6.2",
+ "jest-runtime": "^29.6.2",
+ "jest-snapshot": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jest-validate": "^29.6.2",
+ "jest-watcher": "^29.6.2",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.6.2",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/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/@jest/core/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/core/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/core/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/@jest/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/@jest/environment": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz",
+ "integrity": "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==",
+ "dev": true,
+ "dependencies": {
+ "@jest/fake-timers": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "jest-mock": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz",
+ "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.6.2",
+ "jest-snapshot": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz",
+ "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==",
+ "dev": true,
+ "dependencies": {
+ "jest-get-type": "^29.4.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz",
+ "integrity": "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.6.2",
+ "jest-mock": "^29.6.2",
+ "jest-util": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz",
+ "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.2",
+ "@jest/expect": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "jest-mock": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz",
+ "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==",
+ "dev": true,
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.6.2",
+ "@jest/test-result": "^29.6.2",
+ "@jest/transform": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^5.1.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jest-worker": "^29.6.2",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/reporters/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/reporters/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/reporters/node_modules/chalk/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/reporters/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/reporters/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/@jest/reporters/node_modules/jest-worker": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz",
+ "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.6.2",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.0",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz",
+ "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==",
+ "dev": true,
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.6.0",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz",
+ "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz",
+ "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz",
+ "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^29.6.2",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.6.2",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz",
+ "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.1",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.6.2",
+ "jest-regex-util": "^29.4.3",
+ "jest-util": "^29.6.2",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform/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/transform/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/transform/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/transform/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/@jest/transform/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true
+ },
+ "node_modules/@jest/transform/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/types": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz",
+ "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.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/types/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/types/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/types/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/types/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/@jest/types/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/@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+ "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "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/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
+ "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+ "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "node_modules/@leichtgewicht/ip-codec": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
+ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
+ "dev": true
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgr/utils": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz",
+ "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "fast-glob": "^3.3.0",
+ "is-glob": "^4.0.3",
+ "open": "^9.1.0",
+ "picocolors": "^1.0.0",
+ "tslib": "^2.6.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/@pkgr/utils/node_modules/define-lazy-prop": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@pkgr/utils/node_modules/open": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz",
+ "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==",
+ "dev": true,
+ "dependencies": {
+ "default-browser": "^4.0.0",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "dev": true
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz",
+ "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==",
+ "dev": true,
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz",
+ "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
+ "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
+ "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz",
+ "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.2",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
+ "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
+ "dev": true,
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/bonjour": {
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz",
+ "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.35",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
+ "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect-history-api-fallback": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz",
+ "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==",
+ "dev": true,
+ "dependencies": {
+ "@types/express-serve-static-core": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/eslint": {
+ "version": "8.44.1",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.1.tgz",
+ "integrity": "sha512-XpNDc4Z5Tb4x+SW1MriMVeIsMoONHCkWFMkR/aPJbzEsxqHy+4Glu/BqTdPrApfDeMaXbtNh6bseNgl5KaWrSg==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/eslint-scope": {
+ "version": "3.7.4",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz",
+ "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint": "*",
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
+ "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==",
+ "dev": true
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.17",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz",
+ "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "4.17.35",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz",
+ "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz",
+ "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/html-minifier-terser": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
+ "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==",
+ "dev": true
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==",
+ "dev": true
+ },
+ "node_modules/@types/http-proxy": {
+ "version": "1.17.11",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz",
+ "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
+ "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==",
+ "dev": true
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz",
+ "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jest": {
+ "version": "29.5.3",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz",
+ "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
+ "node_modules/@types/jsdom": {
+ "version": "20.0.1",
+ "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz",
+ "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "@types/tough-cookie": "*",
+ "parse5": "^7.0.0"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.12",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
+ "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==",
+ "dev": true
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "node_modules/@types/mime": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
+ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "20.4.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.5.tgz",
+ "integrity": "sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg==",
+ "dev": true
+ },
+ "node_modules/@types/node-fetch": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz",
+ "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "form-data": "^3.0.0"
+ }
+ },
+ "node_modules/@types/qs": {
+ "version": "6.9.7",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
+ "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
+ "dev": true
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
+ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
+ "dev": true
+ },
+ "node_modules/@types/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
+ "dev": true
+ },
+ "node_modules/@types/semver": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
+ "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
+ "dev": true
+ },
+ "node_modules/@types/send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==",
+ "dev": true,
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz",
+ "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==",
+ "dev": true,
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/mime": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/sockjs": {
+ "version": "0.3.33",
+ "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz",
+ "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
+ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
+ "dev": true
+ },
+ "node_modules/@types/toastify-js": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/@types/toastify-js/-/toastify-js-1.12.0.tgz",
+ "integrity": "sha512-fqpDHaKhFukN9KRm24bbH0wozvHmSwjvkaLjBUrWcSfSS4zysIwTYqNLG3XbSNhRlsTNRNLGS23tp/VhPwsfHQ==",
+ "dev": true
+ },
+ "node_modules/@types/tough-cookie": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
+ "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==",
+ "dev": true
+ },
+ "node_modules/@types/ws": {
+ "version": "8.5.5",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz",
+ "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.24",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz",
+ "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==",
+ "dev": true,
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.0",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
+ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.2.1.tgz",
+ "integrity": "sha512-iZVM/ALid9kO0+I81pnp1xmYiFyqibAHzrqX4q5YvvVEyJqY+e6rfTXSCsc2jUxGNqJqTfFSSij/NFkZBiBzLw==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.5.1",
+ "@typescript-eslint/scope-manager": "6.2.1",
+ "@typescript-eslint/type-utils": "6.2.1",
+ "@typescript-eslint/utils": "6.2.1",
+ "@typescript-eslint/visitor-keys": "6.2.1",
+ "debug": "^4.3.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.4",
+ "natural-compare": "^1.4.0",
+ "natural-compare-lite": "^1.4.0",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.2.1.tgz",
+ "integrity": "sha512-Ld+uL1kYFU8e6btqBFpsHkwQ35rw30IWpdQxgOqOh4NfxSDH6uCkah1ks8R/RgQqI5hHPXMaLy9fbFseIe+dIg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "6.2.1",
+ "@typescript-eslint/types": "6.2.1",
+ "@typescript-eslint/typescript-estree": "6.2.1",
+ "@typescript-eslint/visitor-keys": "6.2.1",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.2.1.tgz",
+ "integrity": "sha512-UCqBF9WFqv64xNsIEPfBtenbfodPXsJ3nPAr55mGPkQIkiQvgoWNo+astj9ZUfJfVKiYgAZDMnM6dIpsxUMp3Q==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.2.1",
+ "@typescript-eslint/visitor-keys": "6.2.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.2.1.tgz",
+ "integrity": "sha512-fTfCgomBMIgu2Dh2Or3gMYgoNAnQm3RLtRp+jP7A8fY+LJ2+9PNpi5p6QB5C4RSP+U3cjI0vDlI3mspAkpPVbQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "6.2.1",
+ "@typescript-eslint/utils": "6.2.1",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.2.1.tgz",
+ "integrity": "sha512-528bGcoelrpw+sETlyM91k51Arl2ajbNT9L4JwoXE2dvRe1yd8Q64E4OL7vHYw31mlnVsf+BeeLyAZUEQtqahQ==",
+ "dev": true,
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.2.1.tgz",
+ "integrity": "sha512-G+UJeQx9AKBHRQBpmvr8T/3K5bJa485eu+4tQBxFq0KoT22+jJyzo1B50JDT9QdC1DEmWQfdKsa8ybiNWYsi0Q==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.2.1",
+ "@typescript-eslint/visitor-keys": "6.2.1",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.2.1.tgz",
+ "integrity": "sha512-eBIXQeupYmxVB6S7x+B9SdBeB6qIdXKjgQBge2J+Ouv8h9Cxm5dHf/gfAZA6dkMaag+03HdbVInuXMmqFB/lKQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "6.2.1",
+ "@typescript-eslint/types": "6.2.1",
+ "@typescript-eslint/typescript-estree": "6.2.1",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.2.1.tgz",
+ "integrity": "sha512-iTN6w3k2JEZ7cyVdZJTVJx2Lv7t6zFA8DCrJEHD2mwfc16AEvvBWVhbFh34XyG2NORCd0viIgQY1+u7kPI0WpA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.2.1",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@webassemblyjs/ast": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
+ "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/helper-numbers": "1.11.6",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.6"
+ }
+ },
+ "node_modules/@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
+ "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-api-error": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
+ "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-buffer": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
+ "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-numbers": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
+ "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/floating-point-hex-parser": "1.11.6",
+ "@webassemblyjs/helper-api-error": "1.11.6",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
+ "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-wasm-section": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
+ "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.6",
+ "@webassemblyjs/helper-buffer": "1.11.6",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+ "@webassemblyjs/wasm-gen": "1.11.6"
+ }
+ },
+ "node_modules/@webassemblyjs/ieee754": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
+ "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
+ "dev": true,
+ "dependencies": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "node_modules/@webassemblyjs/leb128": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
+ "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
+ "dev": true,
+ "dependencies": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/utf8": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
+ "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/wasm-edit": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
+ "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.6",
+ "@webassemblyjs/helper-buffer": "1.11.6",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+ "@webassemblyjs/helper-wasm-section": "1.11.6",
+ "@webassemblyjs/wasm-gen": "1.11.6",
+ "@webassemblyjs/wasm-opt": "1.11.6",
+ "@webassemblyjs/wasm-parser": "1.11.6",
+ "@webassemblyjs/wast-printer": "1.11.6"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-gen": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
+ "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.6",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+ "@webassemblyjs/ieee754": "1.11.6",
+ "@webassemblyjs/leb128": "1.11.6",
+ "@webassemblyjs/utf8": "1.11.6"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-opt": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
+ "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.6",
+ "@webassemblyjs/helper-buffer": "1.11.6",
+ "@webassemblyjs/wasm-gen": "1.11.6",
+ "@webassemblyjs/wasm-parser": "1.11.6"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-parser": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
+ "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.6",
+ "@webassemblyjs/helper-api-error": "1.11.6",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+ "@webassemblyjs/ieee754": "1.11.6",
+ "@webassemblyjs/leb128": "1.11.6",
+ "@webassemblyjs/utf8": "1.11.6"
+ }
+ },
+ "node_modules/@webassemblyjs/wast-printer": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
+ "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.6",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webpack-cli/configtest": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz",
+ "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x",
+ "webpack-cli": "5.x.x"
+ }
+ },
+ "node_modules/@webpack-cli/info": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz",
+ "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x",
+ "webpack-cli": "5.x.x"
+ }
+ },
+ "node_modules/@webpack-cli/serve": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz",
+ "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x",
+ "webpack-cli": "5.x.x"
+ },
+ "peerDependenciesMeta": {
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+ "dev": true
+ },
+ "node_modules/@xtuc/long": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+ "dev": true
+ },
+ "node_modules/abab": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
+ "dev": true
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "dev": true,
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+ "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "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/acorn-import-assertions": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
+ "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^8"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "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/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/agent-base/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/agent-base/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ajv-formats/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats/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/ajv-keywords": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+ "dev": true,
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-html-community": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
+ "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
+ "dev": true,
+ "engines": [
+ "node >= 0.8.0"
+ ],
+ "bin": {
+ "ansi-html": "bin/ansi-html"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
+ "dev": true
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz",
+ "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "get-intrinsic": "^1.1.3",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz",
+ "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0",
+ "get-intrinsic": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz",
+ "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz",
+ "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz",
+ "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "get-intrinsic": "^1.2.1",
+ "is-array-buffer": "^3.0.2",
+ "is-shared-array-buffer": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.14",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
+ "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ }
+ ],
+ "dependencies": {
+ "browserslist": "^4.21.5",
+ "caniuse-lite": "^1.0.30001464",
+ "fraction.js": "^4.2.0",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz",
+ "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==",
+ "dev": true,
+ "dependencies": {
+ "@jest/transform": "^29.6.2",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.5.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-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/babel-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/babel-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/babel-jest/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/babel-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/babel-loader": {
+ "version": "9.1.3",
+ "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz",
+ "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==",
+ "dev": true,
+ "dependencies": {
+ "find-cache-dir": "^4.0.0",
+ "schema-utils": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.12.0",
+ "webpack": ">=5"
+ }
+ },
+ "node_modules/babel-loader/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/babel-loader/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/babel-loader/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/babel-loader/node_modules/schema-utils": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
+ "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.5.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz",
+ "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz",
+ "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.22.6",
+ "@babel/helper-define-polyfill-provider": "^0.4.2",
+ "semver": "^6.3.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz",
+ "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.4.2",
+ "core-js-compat": "^3.31.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-regenerator": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz",
+ "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.4.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
+ "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.8.3",
+ "@babel/plugin-syntax-import-meta": "^7.8.3",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.8.3",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-top-level-await": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.5.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz",
+ "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==",
+ "dev": true,
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.5.0",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
+ "dev": true
+ },
+ "node_modules/big-integer": {
+ "version": "1.6.51",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
+ "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
+ "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
+ "dev": true,
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.1",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/body-parser/node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/bonjour-service": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz",
+ "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==",
+ "dev": true,
+ "dependencies": {
+ "array-flatten": "^2.1.2",
+ "dns-equal": "^1.0.0",
+ "fast-deep-equal": "^3.1.3",
+ "multicast-dns": "^7.2.5"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "dev": true
+ },
+ "node_modules/bplist-parser": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
+ "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==",
+ "dev": true,
+ "dependencies": {
+ "big-integer": "^1.6.44"
+ },
+ "engines": {
+ "node": ">= 5.10.0"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.21.10",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
+ "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001517",
+ "electron-to-chromium": "^1.4.477",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.11"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "dependencies": {
+ "fast-json-stable-stringify": "2.x"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "dependencies": {
+ "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==",
+ "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.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "node_modules/bundle-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
+ "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
+ "dev": true,
+ "dependencies": {
+ "run-applescript": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind": {
+ "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"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camel-case": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
+ "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
+ "dev": true,
+ "dependencies": {
+ "pascal-case": "^3.1.2",
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001518",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001518.tgz",
+ "integrity": "sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chalk/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chalk/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chrome-trace-event": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
+ "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
+ "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz",
+ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==",
+ "dev": true
+ },
+ "node_modules/clean-css": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz",
+ "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==",
+ "dev": true,
+ "dependencies": {
+ "source-map": "~0.6.0"
+ },
+ "engines": {
+ "node": ">= 10.0"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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/cli-truncate": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz",
+ "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==",
+ "dev": true,
+ "dependencies": {
+ "slice-ansi": "^5.0.0",
+ "string-width": "^5.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-truncate/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/cli-truncate/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/cli-truncate/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/cli-truncate/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "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/clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "dev": true,
+ "dependencies": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
+ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
+ "dev": true
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/colorette": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+ "dev": true
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
+ "node_modules/common-path-prefix": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz",
+ "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==",
+ "dev": true
+ },
+ "node_modules/compressible": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": ">= 1.43.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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/compression/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/connect-history-api-fallback": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
+ "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+ "dev": true
+ },
+ "node_modules/cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "dev": true
+ },
+ "node_modules/core-js-compat": {
+ "version": "3.32.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.0.tgz",
+ "integrity": "sha512-7a9a3D1k4UCVKnLhrgALyFcP7YCsLOQIxPd0dKjf/6GuPcgyiGP70ewWdCGrSK7evyhymi0qO4EqCmSJofDeYw==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.21.9"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "node_modules/cosmiconfig": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz",
+ "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==",
+ "dev": true,
+ "dependencies": {
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/css-blank-pseudo": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-6.0.0.tgz",
+ "integrity": "sha512-VbfLlOWO7sBHBTn6pwDQzc07Z0SDydgDBfNfCE0nvrehdBNv9RKsuupIRa/qal0+fBZhAALyQDPMKz5lnvcchw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.13"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/css-has-pseudo": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-6.0.0.tgz",
+ "integrity": "sha512-X+r+JBuoO37FBOWVNhVJhxtSBUFHgHbrcc0CjFT28JEdOw1qaDwABv/uunyodUuSy2hMPe9j/HjssxSlvUmKjg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/selector-specificity": "^3.0.0",
+ "postcss-selector-parser": "^6.0.13",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/css-loader": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz",
+ "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==",
+ "dev": true,
+ "dependencies": {
+ "icss-utils": "^5.1.0",
+ "postcss": "^8.4.21",
+ "postcss-modules-extract-imports": "^3.0.0",
+ "postcss-modules-local-by-default": "^4.0.3",
+ "postcss-modules-scope": "^3.0.0",
+ "postcss-modules-values": "^4.0.0",
+ "postcss-value-parser": "^4.2.0",
+ "semver": "^7.3.8"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/css-loader/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/css-loader/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/css-loader/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/css-prefers-color-scheme": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-9.0.0.tgz",
+ "integrity": "sha512-03QGAk/FXIRseDdLb7XAiu6gidQ0Nd8945xuM7VFVPpc6goJsG9uIO8xQjTxwbPdPIIV4o4AJoOJyt8gwDl67g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
+ "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.0.1",
+ "domhandler": "^4.3.1",
+ "domutils": "^2.8.0",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/cssdb": {
+ "version": "7.7.0",
+ "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.7.0.tgz",
+ "integrity": "sha512-1hN+I3r4VqSNQ+OmMXxYexnumbOONkSil0TWMebVXHtzYW4tRRPovUNHPHj2d4nrgOuYJ8Vs3XwvywsuwwXNNA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ }
+ ]
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true,
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cssom": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz",
+ "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==",
+ "dev": true
+ },
+ "node_modules/cssstyle": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
+ "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
+ "dev": true,
+ "dependencies": {
+ "cssom": "~0.3.6"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cssstyle/node_modules/cssom": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
+ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
+ "dev": true
+ },
+ "node_modules/data-urls": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz",
+ "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==",
+ "dev": true,
+ "dependencies": {
+ "abab": "^2.0.6",
+ "whatwg-mimetype": "^3.0.0",
+ "whatwg-url": "^11.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/data-urls/node_modules/tr46": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
+ "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/data-urls/node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "engines": {
+ "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/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/decimal.js": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
+ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==",
+ "dev": true
+ },
+ "node_modules/dedent": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz",
+ "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==",
+ "dev": true,
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/default-browser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz",
+ "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==",
+ "dev": true,
+ "dependencies": {
+ "bundle-name": "^3.0.0",
+ "default-browser-id": "^3.0.0",
+ "execa": "^7.1.1",
+ "titleize": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser-id": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz",
+ "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==",
+ "dev": true,
+ "dependencies": {
+ "bplist-parser": "^0.2.0",
+ "untildify": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/execa": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
+ "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/default-browser/node_modules/human-signals": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
+ "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/default-browser/node_modules/is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/npm-run-path": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
+ "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/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,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-gateway": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
+ "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
+ "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
+ "dev": true,
+ "dependencies": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/detect-node": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
+ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
+ "dev": true
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
+ "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dns-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+ "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==",
+ "dev": true
+ },
+ "node_modules/dns-packet": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz",
+ "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==",
+ "dev": true,
+ "dependencies": {
+ "@leichtgewicht/ip-codec": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-converter": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
+ "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
+ "dev": true,
+ "dependencies": {
+ "utila": "~0.4"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
+ "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^4.2.0",
+ "entities": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ]
+ },
+ "node_modules/domexception": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
+ "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==",
+ "dev": true,
+ "dependencies": {
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/domexception/node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/domhandler": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
+ "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.2.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
+ "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
+ "dev": true,
+ "dependencies": {
+ "dom-serializer": "^1.0.1",
+ "domelementtype": "^2.2.0",
+ "domhandler": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dot-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
+ "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
+ "dev": true,
+ "dependencies": {
+ "no-case": "^3.0.4",
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
+ "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/dotenv-defaults": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz",
+ "integrity": "sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==",
+ "dev": true,
+ "dependencies": {
+ "dotenv": "^8.2.0"
+ }
+ },
+ "node_modules/dotenv-webpack": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.0.1.tgz",
+ "integrity": "sha512-CdrgfhZOnx4uB18SgaoP9XHRN2v48BbjuXQsZY5ixs5A8579NxQkmMxRtI7aTwSiSQcM2ao12Fdu+L3ZS3bG4w==",
+ "dev": true,
+ "dependencies": {
+ "dotenv-defaults": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "webpack": "^4 || ^5"
+ }
+ },
+ "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",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "dev": true
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.479",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.479.tgz",
+ "integrity": "sha512-ABv1nHMIR8I5n3O3Een0gr6i0mfM+YcTZqjHy3pAYaOjgFG+BMquuKrSyfYf5CbEkLr9uM05RA3pOk4udNB/aQ==",
+ "dev": true
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.15.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
+ "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/envinfo": {
+ "version": "7.10.0",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz",
+ "integrity": "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==",
+ "dev": true,
+ "bin": {
+ "envinfo": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz",
+ "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "arraybuffer.prototype.slice": "^1.0.1",
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-set-tostringtag": "^2.0.1",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.2.1",
+ "get-symbol-description": "^1.0.0",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
+ "is-callable": "^1.2.7",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.10",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.3",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.5.0",
+ "safe-array-concat": "^1.0.0",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.7",
+ "string.prototype.trimend": "^1.0.6",
+ "string.prototype.trimstart": "^1.0.6",
+ "typed-array-buffer": "^1.0.0",
+ "typed-array-byte-length": "^1.0.0",
+ "typed-array-byte-offset": "^1.0.0",
+ "typed-array-length": "^1.0.4",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz",
+ "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==",
+ "dev": true
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
+ "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3",
+ "has": "^1.0.3",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+ "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "dev": true
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/escodegen": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
+ "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+ "dev": true,
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
+ }
+ },
+ "node_modules/escodegen/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.46.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.46.0.tgz",
+ "integrity": "sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.1",
+ "@eslint/js": "^8.46.0",
+ "@humanwhocodes/config-array": "^0.11.10",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.2",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "8.9.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.9.0.tgz",
+ "integrity": "sha512-+sbni7NfVXnOpnRadUA8S28AUlsZt9GjgFvABIRL9Hkn8KqNzOp+7Lw4QWtrwn20KzU3wqu1QoOj2m+7rKRqkA==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz",
+ "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.11.0",
+ "resolve": "^1.22.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
+ "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.28.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.0.tgz",
+ "integrity": "sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.findlastindex": "^1.2.2",
+ "array.prototype.flat": "^1.3.1",
+ "array.prototype.flatmap": "^1.3.1",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.7",
+ "eslint-module-utils": "^2.8.0",
+ "has": "^1.0.3",
+ "is-core-module": "^2.12.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.6",
+ "object.groupby": "^1.0.0",
+ "object.values": "^1.1.6",
+ "resolve": "^1.22.3",
+ "semver": "^6.3.1",
+ "tsconfig-paths": "^3.14.2"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/eslint-plugin-jest": {
+ "version": "27.2.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz",
+ "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/utils": "^5.10.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0",
+ "eslint": "^7.0.0 || ^8.0.0",
+ "jest": "*"
+ },
+ "peerDependenciesMeta": {
+ "@typescript-eslint/eslint-plugin": {
+ "optional": true
+ },
+ "jest": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
+ "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/visitor-keys": "5.62.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
+ "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
+ "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/visitor-keys": "5.62.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
+ "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.62.0",
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/typescript-estree": "5.62.0",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
+ "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/eslint-plugin-jest/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-jest/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-plugin-jest/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/eslint-plugin-jest/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-plugin-jest/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz",
+ "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.5"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz",
+ "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-webpack-plugin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-4.0.1.tgz",
+ "integrity": "sha512-fUFcXpui/FftGx3NzvWgLZXlLbu+m74sUxGEgxgoxYcUtkIQbS6SdNNZkS99m5ycb23TfoNYrDpp1k/CK5j6Hw==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint": "^8.37.0",
+ "jest-worker": "^29.5.0",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "schema-utils": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "eslint": "^8.0.0",
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/eslint-webpack-plugin/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/eslint-webpack-plugin/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/eslint-webpack-plugin/node_modules/jest-worker": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz",
+ "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.6.2",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/eslint-webpack-plugin/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/eslint-webpack-plugin/node_modules/schema-utils": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
+ "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/eslint/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/eslint/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/eslint/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/eslint/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/eslint/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/eslint/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/eslint/node_modules/globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/eslint/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/eslint/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "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",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/eslint/node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
+ "dev": true
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz",
+ "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/expect-utils": "^29.6.2",
+ "@types/node": "*",
+ "jest-get-type": "^29.4.3",
+ "jest-matcher-utils": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-util": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.18.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
+ "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
+ "dev": true,
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.1",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.5.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.2.0",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.11.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.18.0",
+ "serve-static": "1.15.0",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/express/node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "dev": true
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastest-levenshtein": {
+ "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.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "dev": true,
+ "dependencies": {
+ "websocket-driver": ">=0.5.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/find-cache-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz",
+ "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==",
+ "dev": true,
+ "dependencies": {
+ "common-path-prefix": "^3.0.0",
+ "pkg-dir": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-cache-dir/node_modules/find-up": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
+ "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^7.1.0",
+ "path-exists": "^5.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-cache-dir/node_modules/locate-path": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
+ "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^6.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-cache-dir/node_modules/p-limit": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
+ "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^1.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-cache-dir/node_modules/p-locate": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
+ "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-cache-dir/node_modules/path-exists": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
+ "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ }
+ },
+ "node_modules/find-cache-dir/node_modules/pkg-dir": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz",
+ "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "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.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",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+ "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+ "dev": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fraction.js": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
+ "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://www.patreon.com/infusion"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs-monkey": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz",
+ "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==",
+ "dev": true
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "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
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
+ "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/glob-to-regexp": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+ "dev": true
+ },
+ "node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/handle-thing": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
+ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ }
+ },
+ "node_modules/hpack.js/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/hpack.js/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/hpack.js/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/html-encoding-sniffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
+ "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-encoding": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/html-entities": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz",
+ "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/mdevils"
+ },
+ {
+ "type": "patreon",
+ "url": "https://patreon.com/mdevils"
+ }
+ ]
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true
+ },
+ "node_modules/html-minifier-terser": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
+ "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==",
+ "dev": true,
+ "dependencies": {
+ "camel-case": "^4.1.2",
+ "clean-css": "^5.2.2",
+ "commander": "^8.3.0",
+ "he": "^1.2.0",
+ "param-case": "^3.0.4",
+ "relateurl": "^0.2.7",
+ "terser": "^5.10.0"
+ },
+ "bin": {
+ "html-minifier-terser": "cli.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/html-minifier-terser/node_modules/commander": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/html-webpack-plugin": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz",
+ "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==",
+ "dev": true,
+ "dependencies": {
+ "@types/html-minifier-terser": "^6.0.0",
+ "html-minifier-terser": "^6.0.2",
+ "lodash": "^4.17.21",
+ "pretty-error": "^4.0.0",
+ "tapable": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/html-webpack-plugin"
+ },
+ "peerDependencies": {
+ "webpack": "^5.20.0"
+ }
+ },
+ "node_modules/htmlparser2": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
+ "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
+ "dev": true,
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^4.0.0",
+ "domutils": "^2.5.2",
+ "entities": "^2.0.0"
+ }
+ },
+ "node_modules/http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
+ "dev": true
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dev": true,
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/http-parser-js": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
+ "dev": true
+ },
+ "node_modules/http-proxy": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
+ "dev": true,
+ "dependencies": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+ "dev": true,
+ "dependencies": {
+ "@tootallnate/once": "2",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/http-proxy-middleware": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz",
+ "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==",
+ "dev": true,
+ "dependencies": {
+ "@types/http-proxy": "^1.17.8",
+ "http-proxy": "^1.18.1",
+ "is-glob": "^4.0.1",
+ "is-plain-obj": "^3.0.0",
+ "micromatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "@types/express": "^4.17.13"
+ },
+ "peerDependenciesMeta": {
+ "@types/express": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/husky": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
+ "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
+ "dev": true,
+ "bin": {
+ "husky": "lib/bin.js"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/typicode"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/icss-utils": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
+ "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
+ "dev": true,
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/immutable": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.1.tgz",
+ "integrity": "sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A==",
+ "dev": true
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-fresh/node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+ "dev": true,
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "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/internal-slot": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+ "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/interpret": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz",
+ "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz",
+ "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
+ "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-inside-container/node_modules/is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
+ "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+ "dev": true
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
+ "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
+ "dev": true,
+ "dependencies": {
+ "which-typed-array": "^1.1.11"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "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.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
+ "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report/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/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/istanbul-lib-source-maps/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz",
+ "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==",
+ "dev": true,
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz",
+ "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.6.2"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "29.5.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz",
+ "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "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-changed-files/node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz",
+ "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.2",
+ "@jest/expect": "^29.6.2",
+ "@jest/test-result": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.6.2",
+ "jest-matcher-utils": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-runtime": "^29.6.2",
+ "jest-snapshot": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.6.2",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus/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-circus/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-circus/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-circus/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "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/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-circus/node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz",
+ "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^29.6.2",
+ "@jest/test-result": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jest-validate": "^29.6.2",
+ "prompts": "^2.0.1",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-cli/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-cli/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-cli/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-cli/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-cli/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-config": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz",
+ "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "babel-jest": "^29.6.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": "^29.6.2",
+ "jest-environment-node": "^29.6.2",
+ "jest-get-type": "^29.4.3",
+ "jest-regex-util": "^29.4.3",
+ "jest-resolve": "^29.6.2",
+ "jest-runner": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jest-validate": "^29.6.2",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.6.2",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config/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-config/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-config/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-config/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "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",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz",
+ "integrity": "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.4.3",
+ "jest-get-type": "^29.4.3",
+ "pretty-format": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-diff/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-diff/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-diff/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-diff/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-diff/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-docblock": {
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz",
+ "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==",
+ "dev": true,
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz",
+ "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.4.3",
+ "jest-util": "^29.6.2",
+ "pretty-format": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each/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-each/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-each/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-each/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-each/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-environment-jsdom": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.2.tgz",
+ "integrity": "sha512-7oa/+266AAEgkzae8i1awNEfTfjwawWKLpiw2XesZmaoVVj9u9t8JOYx18cG29rbPNtkUlZ8V4b5Jb36y/VxoQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.2",
+ "@jest/fake-timers": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "@types/jsdom": "^20.0.0",
+ "@types/node": "*",
+ "jest-mock": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jsdom": "^20.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "canvas": "^2.5.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz",
+ "integrity": "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.2",
+ "@jest/fake-timers": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "jest-mock": "^29.6.2",
+ "jest-util": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
+ "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz",
+ "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "@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": "^29.4.3",
+ "jest-util": "^29.6.2",
+ "jest-worker": "^29.6.2",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-haste-map/node_modules/jest-worker": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz",
+ "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.6.2",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz",
+ "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==",
+ "dev": true,
+ "dependencies": {
+ "jest-get-type": "^29.4.3",
+ "pretty-format": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz",
+ "integrity": "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.6.2",
+ "jest-get-type": "^29.4.3",
+ "pretty-format": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils/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-matcher-utils/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-matcher-utils/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-matcher-utils/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-matcher-utils/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-message-util": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz",
+ "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.1",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.6.2",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util/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-message-util/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-message-util/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-message-util/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-message-util/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-mock": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz",
+ "integrity": "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "jest-util": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz",
+ "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz",
+ "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.6.2",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.6.2",
+ "jest-validate": "^29.6.2",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz",
+ "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==",
+ "dev": true,
+ "dependencies": {
+ "jest-regex-util": "^29.4.3",
+ "jest-snapshot": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve/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-resolve/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-resolve/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-resolve/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-resolve/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-runner": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz",
+ "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.6.2",
+ "@jest/environment": "^29.6.2",
+ "@jest/test-result": "^29.6.2",
+ "@jest/transform": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.4.3",
+ "jest-environment-node": "^29.6.2",
+ "jest-haste-map": "^29.6.2",
+ "jest-leak-detector": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-resolve": "^29.6.2",
+ "jest-runtime": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jest-watcher": "^29.6.2",
+ "jest-worker": "^29.6.2",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner/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-runner/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-runner/node_modules/chalk/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-runner/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-runner/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-runner/node_modules/jest-worker": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz",
+ "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.6.2",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "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": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-runner/node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/jest-runner/node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz",
+ "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.2",
+ "@jest/fake-timers": "^29.6.2",
+ "@jest/globals": "^29.6.2",
+ "@jest/source-map": "^29.6.0",
+ "@jest/test-result": "^29.6.2",
+ "@jest/transform": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-mock": "^29.6.2",
+ "jest-regex-util": "^29.4.3",
+ "jest-resolve": "^29.6.2",
+ "jest-snapshot": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime/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-runtime/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-runtime/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-runtime/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-runtime/node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-runtime/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-snapshot": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz",
+ "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==",
+ "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/types": "^7.3.3",
+ "@jest/expect-utils": "^29.6.2",
+ "@jest/transform": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.6.2",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.6.2",
+ "jest-get-type": "^29.4.3",
+ "jest-matcher-utils": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.6.2",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/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-snapshot/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-snapshot/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-snapshot/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-snapshot/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest-snapshot/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-snapshot/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/jest-util": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz",
+ "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "@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-util/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-util/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-util/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-util/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-util/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-validate": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz",
+ "integrity": "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.4.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.6.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/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-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-validate/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-validate/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-validate/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-validate/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": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz",
+ "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^29.6.2",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.6.2",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-watcher/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-watcher/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-watcher/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-watcher/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/jest-watcher/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-worker": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz",
+ "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==",
+ "dev": true,
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsdom": {
+ "version": "20.0.3",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz",
+ "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==",
+ "dev": true,
+ "dependencies": {
+ "abab": "^2.0.6",
+ "acorn": "^8.8.1",
+ "acorn-globals": "^7.0.0",
+ "cssom": "^0.5.0",
+ "cssstyle": "^2.3.0",
+ "data-urls": "^3.0.2",
+ "decimal.js": "^10.4.2",
+ "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.1",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.2",
+ "parse5": "^7.1.1",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^4.1.2",
+ "w3c-xmlserializer": "^4.0.0",
+ "webidl-conversions": "^7.0.0",
+ "whatwg-encoding": "^2.0.0",
+ "whatwg-mimetype": "^3.0.0",
+ "whatwg-url": "^11.0.0",
+ "ws": "^8.11.0",
+ "xml-name-validator": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "canvas": "^2.5.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jsdom/node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dev": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/jsdom/node_modules/tr46": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
+ "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/jsdom/node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/jsdom/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/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "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",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/launch-editor": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz",
+ "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^1.0.0",
+ "shell-quote": "^1.7.3"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
+ "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true
+ },
+ "node_modules/lint-staged": {
+ "version": "13.2.3",
+ "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.3.tgz",
+ "integrity": "sha512-zVVEXLuQIhr1Y7R7YAWx4TZLdvuzk7DnmrsTNL0fax6Z3jrpFcas+vKbzxhhvp6TA55m1SQuWkpzI1qbfDZbAg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "5.2.0",
+ "cli-truncate": "^3.1.0",
+ "commander": "^10.0.0",
+ "debug": "^4.3.4",
+ "execa": "^7.0.0",
+ "lilconfig": "2.1.0",
+ "listr2": "^5.0.7",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "object-inspect": "^1.12.3",
+ "pidtree": "^0.6.0",
+ "string-argv": "^0.3.1",
+ "yaml": "^2.2.2"
+ },
+ "bin": {
+ "lint-staged": "bin/lint-staged.js"
+ },
+ "engines": {
+ "node": "^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/lint-staged"
+ }
+ },
+ "node_modules/lint-staged/node_modules/chalk": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
+ "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/lint-staged/node_modules/commander": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/lint-staged/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/lint-staged/node_modules/execa": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
+ "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/lint-staged/node_modules/human-signals": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
+ "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/lint-staged/node_modules/is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lint-staged/node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lint-staged/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/lint-staged/node_modules/npm-run-path": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
+ "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lint-staged/node_modules/onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lint-staged/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lint-staged/node_modules/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,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/listr2": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz",
+ "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==",
+ "dev": true,
+ "dependencies": {
+ "cli-truncate": "^2.1.0",
+ "colorette": "^2.0.19",
+ "log-update": "^4.0.0",
+ "p-map": "^4.0.0",
+ "rfdc": "^1.3.0",
+ "rxjs": "^7.8.0",
+ "through": "^2.3.8",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": "^14.13.1 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "enquirer": ">= 2.3.0 < 3"
+ },
+ "peerDependenciesMeta": {
+ "enquirer": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/listr2/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/listr2/node_modules/cli-truncate": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+ "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+ "dev": true,
+ "dependencies": {
+ "slice-ansi": "^3.0.0",
+ "string-width": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/listr2/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/listr2/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/listr2/node_modules/slice-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+ "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/loader-runner": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
+ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.11.5"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "dev": true
+ },
+ "node_modules/lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
+ "dev": true
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/log-update": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+ "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-escapes": "^4.3.0",
+ "cli-cursor": "^3.1.0",
+ "slice-ansi": "^4.0.0",
+ "wrap-ansi": "^6.2.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/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-update/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-update/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/log-update/node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lower-case": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
+ "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/make-dir/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/memfs": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz",
+ "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==",
+ "dev": true,
+ "dependencies": {
+ "fs-monkey": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
+ "dev": true
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true,
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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/mini-css-extract-plugin": {
+ "version": "2.7.6",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz",
+ "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==",
+ "dev": true,
+ "dependencies": {
+ "schema-utils": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/mini-css-extract-plugin/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/mini-css-extract-plugin/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/mini-css-extract-plugin/node_modules/schema-utils": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
+ "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "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/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true
+ },
+ "node_modules/multicast-dns": {
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
+ "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==",
+ "dev": true,
+ "dependencies": {
+ "dns-packet": "^5.2.2",
+ "thunky": "^1.0.2"
+ },
+ "bin": {
+ "multicast-dns": "cli.js"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+ "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true
+ },
+ "node_modules/no-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
+ "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
+ "dev": true,
+ "dependencies": {
+ "lower-case": "^2.0.2",
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-forge": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6.13.0"
+ }
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
+ "dev": true
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/nwsapi": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz",
+ "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==",
+ "dev": true
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
+ "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz",
+ "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz",
+ "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.21.2",
+ "get-intrinsic": "^1.2.1"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz",
+ "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+ "dev": true
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "dev": true,
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "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/open": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+ "dev": true,
+ "dependencies": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+ "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+ "dev": true,
+ "dependencies": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-retry": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
+ "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/retry": "0.12.0",
+ "retry": "^0.13.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/param-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
+ "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
+ "dev": true,
+ "dependencies": {
+ "dot-case": "^3.0.4",
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "dev": true,
+ "dependencies": {
+ "entities": "^4.4.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "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",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/pascal-case": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
+ "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
+ "dev": true,
+ "dependencies": {
+ "no-case": "^3.0.4",
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
+ "dev": true
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pidtree": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
+ "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
+ "dev": true,
+ "bin": {
+ "pidtree": "bin/pidtree.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.27",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz",
+ "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-attribute-case-insensitive": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-6.0.2.tgz",
+ "integrity": "sha512-IRuCwwAAQbgaLhxQdQcIIK0dCVXg3XDUnzgKD8iwdiYdwU4rMWRWyl/W9/0nA4ihVpq5pyALiHB2veBJ0292pw==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-clamp": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz",
+ "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=7.6.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.6"
+ }
+ },
+ "node_modules/postcss-color-functional-notation": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-6.0.0.tgz",
+ "integrity": "sha512-kaWTgnhRKFtfMF8H0+NQBFxgr5CGg05WGe07Mc1ld6XHwwRWlqSbHOW0zwf+BtkBQpsdVUu7+gl9dtdvhWMedw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/postcss-progressive-custom-properties": "^3.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-color-hex-alpha": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-9.0.2.tgz",
+ "integrity": "sha512-SfPjgr//VQ/DOCf80STIAsdAs7sbIbxATvVmd+Ec7JvR8onz9pjawhq3BJM3Pie40EE3TyB0P6hft16D33Nlyg==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-color-rebeccapurple": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-9.0.0.tgz",
+ "integrity": "sha512-RmUFL+foS05AKglkEoqfx+KFdKRVmqUAxlHNz4jLqIi7046drIPyerdl4B6j/RA2BSP8FI8gJcHmLRrwJOMnHw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-custom-media": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-10.0.0.tgz",
+ "integrity": "sha512-NxDn7C6GJ7X8TsWOa8MbCdq9rLERRLcPfQSp856k1jzMreL8X9M6iWk35JjPRIb9IfRnVohmxAylDRx7n4Rv4g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/cascade-layer-name-parser": "^1.0.3",
+ "@csstools/css-parser-algorithms": "^2.3.0",
+ "@csstools/css-tokenizer": "^2.1.1",
+ "@csstools/media-query-list-parser": "^2.1.2"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-custom-properties": {
+ "version": "13.3.0",
+ "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.3.0.tgz",
+ "integrity": "sha512-q4VgtIKSy5+KcUvQ0WxTjDy9DZjQ5VCXAZ9+tT9+aPMbA0z6s2t1nMw0QHszru1ib5ElkXl9JUpYYU37VVUs7g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/cascade-layer-name-parser": "^1.0.4",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-custom-selectors": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-7.1.4.tgz",
+ "integrity": "sha512-TU2xyUUBTlpiLnwyE2ZYMUIYB41MKMkBZ8X8ntkqRDQ8sdBLhFFsPgNcOliBd5+/zcK51C9hRnSE7hKUJMxQSw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/cascade-layer-name-parser": "^1.0.3",
+ "@csstools/css-parser-algorithms": "^2.3.0",
+ "@csstools/css-tokenizer": "^2.1.1",
+ "postcss-selector-parser": "^6.0.13"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-dir-pseudo-class": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-8.0.0.tgz",
+ "integrity": "sha512-Oy5BBi0dWPwij/IA+yDYj+/OBMQ9EPqAzTHeSNUYrUWdll/PRJmcbiUj0MNcsBi681I1gcSTLvMERPaXzdbvJg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.13"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-double-position-gradients": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-5.0.0.tgz",
+ "integrity": "sha512-wR8npIkrIVUTicUpCWSSo1f/g7gAEIH70FMqCugY4m4j6TX4E0T2Q5rhfO0gqv00biBZdLyb+HkW8x6as+iJNQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/postcss-progressive-custom-properties": "^3.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-focus-visible": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-9.0.0.tgz",
+ "integrity": "sha512-zA4TbVaIaT8npZBEROhZmlc+GBKE8AELPHXE7i4TmIUEQhw/P/mSJfY9t6tBzpQ1rABeGtEOHYrW4SboQeONMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.13"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-focus-within": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-8.0.0.tgz",
+ "integrity": "sha512-E7+J9nuQzZaA37D/MUZMX1K817RZGDab8qw6pFwzAkDd/QtlWJ9/WTKmzewNiuxzeq6WWY7ATiRePVoDKp+DnA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.13"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-font-variant": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz",
+ "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==",
+ "dev": true,
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-gap-properties": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-5.0.0.tgz",
+ "integrity": "sha512-YjsEEL6890P7MCv6fch6Am1yq0EhQCJMXyT4LBohiu87+4/WqR7y5W3RIv53WdA901hhytgRvjlrAhibhW4qsA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-image-set-function": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-6.0.0.tgz",
+ "integrity": "sha512-bg58QnJexFpPBU4IGPAugAPKV0FuFtX5rHYNSKVaV91TpHN7iwyEzz1bkIPCiSU5+BUN00e+3fV5KFrwIgRocw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-initial": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz",
+ "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==",
+ "dev": true,
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-lab-function": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-6.0.1.tgz",
+ "integrity": "sha512-/Xl6JitDh7jWkcOLxrHcAlEaqkxyaG3g4iDMy5RyhNaiQPJ9Egf2+Mxp1W2qnH5jB2bj59f3RbdKmC6qx1IcXA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/css-color-parser": "^1.2.2",
+ "@csstools/css-parser-algorithms": "^2.3.1",
+ "@csstools/css-tokenizer": "^2.2.0",
+ "@csstools/postcss-progressive-custom-properties": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-loader": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz",
+ "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==",
+ "dev": true,
+ "dependencies": {
+ "cosmiconfig": "^8.2.0",
+ "jiti": "^1.18.2",
+ "semver": "^7.3.8"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "postcss": "^7.0.0 || ^8.0.1",
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/postcss-loader/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/postcss-loader/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/postcss-loader/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/postcss-logical": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-7.0.0.tgz",
+ "integrity": "sha512-zYf3vHkoW82f5UZTEXChTJvH49Yl9X37axTZsJGxrCG2kOUwtaAoz9E7tqYg0lsIoJLybaL8fk/2mOi81zVIUw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-modules-extract-imports": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
+ "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
+ "dev": true,
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-modules-local-by-default": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz",
+ "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==",
+ "dev": true,
+ "dependencies": {
+ "icss-utils": "^5.0.0",
+ "postcss-selector-parser": "^6.0.2",
+ "postcss-value-parser": "^4.1.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-modules-scope": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz",
+ "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.4"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-modules-values": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
+ "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
+ "dev": true,
+ "dependencies": {
+ "icss-utils": "^5.0.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-nesting": {
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.0.0.tgz",
+ "integrity": "sha512-knqwW65kxssmyIFadRSimaiRyLVRd0MdwfabesKw6XvGLwSOCJ+4zfvNQQCOOYij5obwpZzDpODuGRv2PCyiUw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/selector-specificity": "^3.0.0",
+ "postcss-selector-parser": "^6.0.13"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-opacity-percentage": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-2.0.0.tgz",
+ "integrity": "sha512-lyDrCOtntq5Y1JZpBFzIWm2wG9kbEdujpNt4NLannF+J9c8CgFIzPa80YQfdza+Y+yFfzbYj/rfoOsYsooUWTQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "kofi",
+ "url": "https://ko-fi.com/mrcgrtz"
+ },
+ {
+ "type": "liberapay",
+ "url": "https://liberapay.com/mrcgrtz"
+ }
+ ],
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-overflow-shorthand": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-5.0.0.tgz",
+ "integrity": "sha512-2rlxDyeSics/hC2FuMdPnWiP9WUPZ5x7FTuArXLFVpaSQ2woPSfZS4RD59HuEokbZhs/wPUQJ1E3MT6zVv94MQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-page-break": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz",
+ "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==",
+ "dev": true,
+ "peerDependencies": {
+ "postcss": "^8"
+ }
+ },
+ "node_modules/postcss-place": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-9.0.0.tgz",
+ "integrity": "sha512-qLEPD9VPH5opDVemwmRaujODF9nExn24VOC3ghgVLEvfYN7VZLwJHes0q/C9YR5hI2UC3VgBE8Wkdp1TxCXhtg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-preset-env": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-9.1.0.tgz",
+ "integrity": "sha512-G+x9BD7jb9uHBB7o720emXV00CP+VdWeirJsHC5ERSpbTd2e6Xg7vHzT+a6UkxFyddALuV+Q8wJMgeTKaau+Pg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "@csstools/postcss-cascade-layers": "^4.0.0",
+ "@csstools/postcss-color-function": "^3.0.1",
+ "@csstools/postcss-color-mix-function": "^2.0.1",
+ "@csstools/postcss-exponential-functions": "^1.0.0",
+ "@csstools/postcss-font-format-keywords": "^3.0.0",
+ "@csstools/postcss-gradients-interpolation-method": "^4.0.1",
+ "@csstools/postcss-hwb-function": "^3.0.1",
+ "@csstools/postcss-ic-unit": "^3.0.0",
+ "@csstools/postcss-is-pseudo-class": "^4.0.0",
+ "@csstools/postcss-logical-float-and-clear": "^2.0.0",
+ "@csstools/postcss-logical-resize": "^2.0.0",
+ "@csstools/postcss-logical-viewport-units": "^2.0.1",
+ "@csstools/postcss-media-minmax": "^1.0.6",
+ "@csstools/postcss-media-queries-aspect-ratio-number-values": "^2.0.1",
+ "@csstools/postcss-nested-calc": "^3.0.0",
+ "@csstools/postcss-normalize-display-values": "^3.0.0",
+ "@csstools/postcss-oklab-function": "^3.0.1",
+ "@csstools/postcss-progressive-custom-properties": "^3.0.0",
+ "@csstools/postcss-relative-color-syntax": "^2.0.1",
+ "@csstools/postcss-scope-pseudo-class": "^3.0.0",
+ "@csstools/postcss-stepped-value-functions": "^3.0.1",
+ "@csstools/postcss-text-decoration-shorthand": "^3.0.0",
+ "@csstools/postcss-trigonometric-functions": "^3.0.1",
+ "@csstools/postcss-unset-value": "^3.0.0",
+ "autoprefixer": "^10.4.14",
+ "browserslist": "^4.21.9",
+ "css-blank-pseudo": "^6.0.0",
+ "css-has-pseudo": "^6.0.0",
+ "css-prefers-color-scheme": "^9.0.0",
+ "cssdb": "^7.7.0",
+ "postcss-attribute-case-insensitive": "^6.0.2",
+ "postcss-clamp": "^4.1.0",
+ "postcss-color-functional-notation": "^6.0.0",
+ "postcss-color-hex-alpha": "^9.0.2",
+ "postcss-color-rebeccapurple": "^9.0.0",
+ "postcss-custom-media": "^10.0.0",
+ "postcss-custom-properties": "^13.3.0",
+ "postcss-custom-selectors": "^7.1.4",
+ "postcss-dir-pseudo-class": "^8.0.0",
+ "postcss-double-position-gradients": "^5.0.0",
+ "postcss-focus-visible": "^9.0.0",
+ "postcss-focus-within": "^8.0.0",
+ "postcss-font-variant": "^5.0.0",
+ "postcss-gap-properties": "^5.0.0",
+ "postcss-image-set-function": "^6.0.0",
+ "postcss-initial": "^4.0.1",
+ "postcss-lab-function": "^6.0.1",
+ "postcss-logical": "^7.0.0",
+ "postcss-nesting": "^12.0.0",
+ "postcss-opacity-percentage": "^2.0.0",
+ "postcss-overflow-shorthand": "^5.0.0",
+ "postcss-page-break": "^3.0.4",
+ "postcss-place": "^9.0.0",
+ "postcss-pseudo-class-any-link": "^9.0.0",
+ "postcss-replace-overflow-wrap": "^4.0.0",
+ "postcss-selector-not": "^7.0.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-pseudo-class-any-link": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-9.0.0.tgz",
+ "integrity": "sha512-QNCYIL98VKFKY6HGDEJpF6+K/sg9bxcUYnOmNHJxZS5wsFDFaVoPeG68WAuhsqwbIBSo/b9fjEnTwY2mTSD+uA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.13"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-replace-overflow-wrap": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz",
+ "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==",
+ "dev": true,
+ "peerDependencies": {
+ "postcss": "^8.0.3"
+ }
+ },
+ "node_modules/postcss-selector-not": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-7.0.1.tgz",
+ "integrity": "sha512-1zT5C27b/zeJhchN7fP0kBr16Cc61mu7Si9uWWLoA3Px/D9tIJPKchJCkUH3tPO5D0pCFmGeApAv8XpXBQJ8SQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.0.13",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
+ "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
+ "dev": true,
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
+ "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/pretty-error": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
+ "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.20",
+ "renderkid": "^3.0.0"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz",
+ "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.0",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/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/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dev": true,
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-addr/node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/psl": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
+ "dev": true
+ },
+ "node_modules/punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz",
+ "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ]
+ },
+ "node_modules/qs": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "dev": true,
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "dev": true
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "dev": true,
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/raw-body/node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/rechoir": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz",
+ "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==",
+ "dev": true,
+ "dependencies": {
+ "resolve": "^1.20.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/regenerate": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
+ "dev": true
+ },
+ "node_modules/regenerate-unicode-properties": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz",
+ "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==",
+ "dev": true,
+ "dependencies": {
+ "regenerate": "^1.4.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.11",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+ "dev": true
+ },
+ "node_modules/regenerator-transform": {
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz",
+ "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.8.4"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz",
+ "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "functions-have-names": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexpu-core": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz",
+ "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/regjsgen": "^0.8.0",
+ "regenerate": "^1.4.2",
+ "regenerate-unicode-properties": "^10.1.0",
+ "regjsparser": "^0.9.1",
+ "unicode-match-property-ecmascript": "^2.0.0",
+ "unicode-match-property-value-ecmascript": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regjsparser": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz",
+ "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==",
+ "dev": true,
+ "dependencies": {
+ "jsesc": "~0.5.0"
+ },
+ "bin": {
+ "regjsparser": "bin/parser"
+ }
+ },
+ "node_modules/regjsparser/node_modules/jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ }
+ },
+ "node_modules/relateurl": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
+ "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/renderkid": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz",
+ "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==",
+ "dev": true,
+ "dependencies": {
+ "css-select": "^4.1.3",
+ "dom-converter": "^0.2.0",
+ "htmlparser2": "^6.1.0",
+ "lodash": "^4.17.21",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true
+ },
+ "node_modules/resolve": {
+ "version": "1.22.3",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz",
+ "integrity": "sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.12.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
+ "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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/retry": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
+ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
+ "dev": true
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-applescript": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz",
+ "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "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": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz",
+ "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-array-concat/node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+ "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "is-regex": "^1.1.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "node_modules/sass": {
+ "version": "1.64.2",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.64.2.tgz",
+ "integrity": "sha512-TnDlfc+CRnUAgLO9D8cQLFu/GIjJIzJCGkE7o4ekIGQOH7T3GetiRR/PsTWJUHhkzcSPrARkPI+gNWn5alCzDg==",
+ "dev": true,
+ "dependencies": {
+ "chokidar": ">=3.0.0 <4.0.0",
+ "immutable": "^4.0.0",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/sass-loader": {
+ "version": "13.3.2",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz",
+ "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==",
+ "dev": true,
+ "dependencies": {
+ "neo-async": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "fibers": ">= 3.1.0",
+ "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+ "sass": "^1.3.0",
+ "sass-embedded": "*",
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "fibers": {
+ "optional": true
+ },
+ "node-sass": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ }
+ }
+ },
+ "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/schema-utils": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
+ "dev": true
+ },
+ "node_modules/selfsigned": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz",
+ "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==",
+ "dev": true,
+ "dependencies": {
+ "node-forge": "^1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/send": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/serialize-javascript": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
+ "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
+ "dev": true,
+ "dependencies": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/serve-index/node_modules/depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-index/node_modules/http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
+ "dev": true,
+ "dependencies": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-index/node_modules/inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
+ "dev": true
+ },
+ "node_modules/serve-index/node_modules/setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true
+ },
+ "node_modules/serve-index/node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "dev": true,
+ "dependencies": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.18.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "dev": true
+ },
+ "node_modules/shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shell-quote": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
+ "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel": {
+ "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",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true
+ },
+ "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/slice-ansi": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
+ "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^6.0.0",
+ "is-fullwidth-code-point": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
+ "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/sockjs": {
+ "version": "0.3.24",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
+ "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
+ "dev": true,
+ "dependencies": {
+ "faye-websocket": "^0.11.3",
+ "uuid": "^8.3.2",
+ "websocket-driver": "^0.7.4"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/spdy": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
+ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.0",
+ "handle-thing": "^2.0.0",
+ "http-deceiver": "^1.2.7",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/spdy-transport": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
+ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.0",
+ "detect-node": "^2.0.4",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.2",
+ "readable-stream": "^3.0.6",
+ "wbuf": "^1.7.3"
+ }
+ },
+ "node_modules/spdy-transport/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/spdy-transport/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/spdy/node_modules/debug": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/spdy/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/stack-utils/node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-argv": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
+ "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6.19"
+ }
+ },
+ "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/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/string.prototype.trim": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
+ "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
+ "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
+ "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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/style-loader": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz",
+ "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/swiper": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/swiper/-/swiper-10.2.0.tgz",
+ "integrity": "sha512-nktQsOtBInJjr3f5DicxC8eHYGcLXDVIGPSon0QoXRaO6NjKnATCbQ8SZsD3dN1Ph1RH4EhVPwSYCcuDRFWHGQ==",
+ "funding": [
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/swiperjs"
+ },
+ {
+ "type": "open_collective",
+ "url": "http://opencollective.com/swiper"
+ }
+ ],
+ "engines": {
+ "node": ">= 4.7.0"
+ }
+ },
+ "node_modules/symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true
+ },
+ "node_modules/synckit": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
+ "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==",
+ "dev": true,
+ "dependencies": {
+ "@pkgr/utils": "^2.3.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.19.2",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz",
+ "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.8.2",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser-webpack-plugin": {
+ "version": "5.3.9",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
+ "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jest-worker": "^27.4.5",
+ "schema-utils": "^3.1.1",
+ "serialize-javascript": "^6.0.1",
+ "terser": "^5.16.8"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "uglify-js": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+ "dev": true
+ },
+ "node_modules/thunky": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
+ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
+ "dev": true
+ },
+ "node_modules/titleize": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
+ "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toastify-js": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz",
+ "integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ=="
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tough-cookie": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
+ "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
+ "dev": true,
+ "dependencies": {
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
+ "node_modules/ts-api-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz",
+ "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=16.13.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/ts-jest": {
+ "version": "29.1.1",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz",
+ "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==",
+ "dev": true,
+ "dependencies": {
+ "bs-logger": "0.x",
+ "fast-json-stable-stringify": "2.x",
+ "jest-util": "^29.0.0",
+ "json5": "^2.2.3",
+ "lodash.memoize": "4.x",
+ "make-error": "1.x",
+ "semver": "^7.5.3",
+ "yargs-parser": "^21.0.1"
+ },
+ "bin": {
+ "ts-jest": "cli.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": ">=7.0.0-beta.0 <8",
+ "@jest/types": "^29.0.0",
+ "babel-jest": "^29.0.0",
+ "jest": "^29.0.0",
+ "typescript": ">=4.3 <6"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "@jest/types": {
+ "optional": true
+ },
+ "babel-jest": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-jest/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ts-jest/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ts-jest/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/ts-loader": {
+ "version": "9.4.4",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.4.tgz",
+ "integrity": "sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "enhanced-resolve": "^5.0.0",
+ "micromatch": "^4.0.0",
+ "semver": "^7.3.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "typescript": "*",
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/ts-loader/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/ts-loader/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/ts-loader/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/ts-loader/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/ts-loader/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ts-loader/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ts-loader/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/ts-loader/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
+ "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
+ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==",
+ "dev": true
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/tsutils/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "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"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dev": true,
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
+ "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
+ "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+ "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "is-typed-array": "^1.1.9"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
+ "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/unicode-canonical-property-names-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
+ "dev": true,
+ "dependencies": {
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-value-ecmascript": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz",
+ "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-property-aliases-ecmascript": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz",
+ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/universalify": {
+ "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"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
+ "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dev": true,
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/utila": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
+ "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==",
+ "dev": true
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true,
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz",
+ "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/w3c-xmlserializer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
+ "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==",
+ "dev": true,
+ "dependencies": {
+ "xml-name-validator": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/watchpack": {
+ "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",
+ "graceful-fs": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "dev": true,
+ "dependencies": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "node_modules/webpack": {
+ "version": "5.88.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
+ "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint-scope": "^3.7.3",
+ "@types/estree": "^1.0.0",
+ "@webassemblyjs/ast": "^1.11.5",
+ "@webassemblyjs/wasm-edit": "^1.11.5",
+ "@webassemblyjs/wasm-parser": "^1.11.5",
+ "acorn": "^8.7.1",
+ "acorn-import-assertions": "^1.9.0",
+ "browserslist": "^4.14.5",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.15.0",
+ "es-module-lexer": "^1.2.1",
+ "eslint-scope": "5.1.1",
+ "events": "^3.2.0",
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.2.9",
+ "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.2.0",
+ "tapable": "^2.1.1",
+ "terser-webpack-plugin": "^5.3.7",
+ "watchpack": "^2.4.0",
+ "webpack-sources": "^3.2.3"
+ },
+ "bin": {
+ "webpack": "bin/webpack.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependenciesMeta": {
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-cli": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz",
+ "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==",
+ "dev": true,
+ "dependencies": {
+ "@discoveryjs/json-ext": "^0.5.0",
+ "@webpack-cli/configtest": "^2.1.1",
+ "@webpack-cli/info": "^2.0.2",
+ "@webpack-cli/serve": "^2.0.5",
+ "colorette": "^2.0.14",
+ "commander": "^10.0.1",
+ "cross-spawn": "^7.0.3",
+ "envinfo": "^7.7.3",
+ "fastest-levenshtein": "^1.0.12",
+ "import-local": "^3.0.2",
+ "interpret": "^3.1.1",
+ "rechoir": "^0.8.0",
+ "webpack-merge": "^5.7.3"
+ },
+ "bin": {
+ "webpack-cli": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x"
+ },
+ "peerDependenciesMeta": {
+ "@webpack-cli/generators": {
+ "optional": true
+ },
+ "webpack-bundle-analyzer": {
+ "optional": true
+ },
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-cli/node_modules/commander": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/webpack-dev-middleware": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz",
+ "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==",
+ "dev": true,
+ "dependencies": {
+ "colorette": "^2.0.10",
+ "memfs": "^3.4.3",
+ "mime-types": "^2.1.31",
+ "range-parser": "^1.2.1",
+ "schema-utils": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^4.0.0 || ^5.0.0"
+ }
+ },
+ "node_modules/webpack-dev-middleware/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/webpack-dev-middleware/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/webpack-dev-middleware/node_modules/schema-utils": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
+ "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/webpack-dev-server": {
+ "version": "4.15.1",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz",
+ "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==",
+ "dev": true,
+ "dependencies": {
+ "@types/bonjour": "^3.5.9",
+ "@types/connect-history-api-fallback": "^1.3.5",
+ "@types/express": "^4.17.13",
+ "@types/serve-index": "^1.9.1",
+ "@types/serve-static": "^1.13.10",
+ "@types/sockjs": "^0.3.33",
+ "@types/ws": "^8.5.5",
+ "ansi-html-community": "^0.0.8",
+ "bonjour-service": "^1.0.11",
+ "chokidar": "^3.5.3",
+ "colorette": "^2.0.10",
+ "compression": "^1.7.4",
+ "connect-history-api-fallback": "^2.0.0",
+ "default-gateway": "^6.0.3",
+ "express": "^4.17.3",
+ "graceful-fs": "^4.2.6",
+ "html-entities": "^2.3.2",
+ "http-proxy-middleware": "^2.0.3",
+ "ipaddr.js": "^2.0.1",
+ "launch-editor": "^2.6.0",
+ "open": "^8.0.9",
+ "p-retry": "^4.5.0",
+ "rimraf": "^3.0.2",
+ "schema-utils": "^4.0.0",
+ "selfsigned": "^2.1.1",
+ "serve-index": "^1.9.1",
+ "sockjs": "^0.3.24",
+ "spdy": "^4.0.2",
+ "webpack-dev-middleware": "^5.3.1",
+ "ws": "^8.13.0"
+ },
+ "bin": {
+ "webpack-dev-server": "bin/webpack-dev-server.js"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^4.37.0 || ^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "webpack": {
+ "optional": true
+ },
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-dev-server/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/webpack-dev-server/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/webpack-dev-server/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/webpack-dev-server/node_modules/schema-utils": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
+ "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/webpack-merge": {
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz",
+ "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==",
+ "dev": true,
+ "dependencies": {
+ "clone-deep": "^4.0.1",
+ "wildcard": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/webpack-sources": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
+ "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "dev": true,
+ "dependencies": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/whatwg-encoding": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
+ "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
+ "dev": true,
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/whatwg-encoding/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
+ "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
+ "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/wildcard": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
+ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/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/wrap-ansi/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/wrap-ansi/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/write-file-atomic": {
+ "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.0.0"
+ }
+ },
+ "node_modules/ws": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
+ "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xml-name-validator": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+ "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "dev": true
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ },
+ "node_modules/yaml": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz",
+ "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "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"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
+ "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
index 7cfe95f..c1fc635 100644
--- a/package.json
+++ b/package.json
@@ -4,8 +4,58 @@
"description": "this-is-this-team",
"main": "index.js",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "start": "webpack serve",
+ "build:dev": "webpack --node-env=development",
+ "build:prod": "webpack --node-env=production",
+ "lint:check": "eslint .",
+ "lint:fix": "eslint . --fix",
+ "prettier:check": "prettier . --check",
+ "prettier:fix": "prettier . --write",
+ "test": "jest",
+ "prepare": "husky install"
},
"author": "",
- "license": "ISC"
+ "license": "ISC",
+ "devDependencies": {
+ "@babel/core": "^7.22.9",
+ "@babel/preset-env": "^7.22.9",
+ "@types/jest": "^29.5.3",
+ "@types/node-fetch": "^2.6.4",
+ "@types/toastify-js": "^1.12.0",
+ "@typescript-eslint/eslint-plugin": "^6.2.1",
+ "babel-loader": "^9.1.3",
+ "css-loader": "^6.8.1",
+ "dotenv-webpack": "^8.0.1",
+ "eslint": "^8.46.0",
+ "eslint-config-prettier": "^8.9.0",
+ "eslint-plugin-import": "^2.28.0",
+ "eslint-plugin-jest": "^27.2.3",
+ "eslint-plugin-prettier": "^5.0.0",
+ "eslint-webpack-plugin": "^4.0.1",
+ "html-webpack-plugin": "^5.5.3",
+ "husky": "^8.0.3",
+ "jest": "^29.6.2",
+ "jest-environment-jsdom": "^29.6.2",
+ "lint-staged": "^13.2.3",
+ "mini-css-extract-plugin": "^2.7.6",
+ "postcss": "^8.4.27",
+ "postcss-loader": "^7.3.3",
+ "postcss-preset-env": "^9.1.0",
+ "prettier": "^3.0.0",
+ "sass": "^1.64.2",
+ "sass-loader": "^13.3.2",
+ "style-loader": "^3.3.3",
+ "ts-jest": "^29.1.1",
+ "ts-loader": "^9.4.4",
+ "typescript": "^5.1.6",
+ "webpack": "^5.88.2",
+ "webpack-cli": "^5.1.4",
+ "webpack-dev-server": "^4.15.1"
+ },
+ "dependencies": {
+ "@commercetools/platform-sdk": "^4.11.0",
+ "@commercetools/sdk-client-v2": "^2.2.0",
+ "swiper": "^10.2.0",
+ "toastify-js": "^1.12.0"
+ }
}
diff --git a/src/assets/favicon.png b/src/assets/favicon.png
new file mode 100644
index 0000000..45074d5
Binary files /dev/null and b/src/assets/favicon.png differ
diff --git a/src/assets/icons/account-icon.svg b/src/assets/icons/account-icon.svg
new file mode 100644
index 0000000..aec8ebb
--- /dev/null
+++ b/src/assets/icons/account-icon.svg
@@ -0,0 +1,8 @@
+
diff --git a/src/assets/icons/bag-icon.svg b/src/assets/icons/bag-icon.svg
new file mode 100644
index 0000000..67a5261
--- /dev/null
+++ b/src/assets/icons/bag-icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/icons/cart-icon.svg b/src/assets/icons/cart-icon.svg
new file mode 100644
index 0000000..e1223e7
--- /dev/null
+++ b/src/assets/icons/cart-icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icons/cart-trash-icon.svg b/src/assets/icons/cart-trash-icon.svg
new file mode 100644
index 0000000..8e9c782
--- /dev/null
+++ b/src/assets/icons/cart-trash-icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/icons/change-password-icon.svg b/src/assets/icons/change-password-icon.svg
new file mode 100644
index 0000000..8ba5d88
--- /dev/null
+++ b/src/assets/icons/change-password-icon.svg
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/src/assets/icons/check.svg b/src/assets/icons/check.svg
new file mode 100644
index 0000000..6f86b8d
--- /dev/null
+++ b/src/assets/icons/check.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/assets/icons/chevron-up.svg b/src/assets/icons/chevron-up.svg
new file mode 100644
index 0000000..1acd021
--- /dev/null
+++ b/src/assets/icons/chevron-up.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/icons/create-account-icon.svg b/src/assets/icons/create-account-icon.svg
new file mode 100644
index 0000000..20c5927
--- /dev/null
+++ b/src/assets/icons/create-account-icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icons/empty-addresses-book.svg b/src/assets/icons/empty-addresses-book.svg
new file mode 100644
index 0000000..2b25c72
--- /dev/null
+++ b/src/assets/icons/empty-addresses-book.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/icons/github-profile-icon.svg b/src/assets/icons/github-profile-icon.svg
new file mode 100644
index 0000000..35b02e5
--- /dev/null
+++ b/src/assets/icons/github-profile-icon.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/link-arrow.svg b/src/assets/icons/link-arrow.svg
new file mode 100644
index 0000000..e056de3
--- /dev/null
+++ b/src/assets/icons/link-arrow.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icons/logout-icon.svg b/src/assets/icons/logout-icon.svg
new file mode 100644
index 0000000..8112b50
--- /dev/null
+++ b/src/assets/icons/logout-icon.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/popup-close-icon.svg b/src/assets/icons/popup-close-icon.svg
new file mode 100644
index 0000000..f4242aa
--- /dev/null
+++ b/src/assets/icons/popup-close-icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icons/quote-icon.svg b/src/assets/icons/quote-icon.svg
new file mode 100644
index 0000000..71c7a9b
--- /dev/null
+++ b/src/assets/icons/quote-icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icons/rsschool-icon-active.svg b/src/assets/icons/rsschool-icon-active.svg
new file mode 100644
index 0000000..ff5edc6
--- /dev/null
+++ b/src/assets/icons/rsschool-icon-active.svg
@@ -0,0 +1,12 @@
+
diff --git a/src/assets/icons/rsschool-icon.svg b/src/assets/icons/rsschool-icon.svg
new file mode 100644
index 0000000..ef8175f
--- /dev/null
+++ b/src/assets/icons/rsschool-icon.svg
@@ -0,0 +1,12 @@
+
diff --git a/src/assets/icons/spinner-icon.svg b/src/assets/icons/spinner-icon.svg
new file mode 100644
index 0000000..94ef831
--- /dev/null
+++ b/src/assets/icons/spinner-icon.svg
@@ -0,0 +1,12 @@
+
diff --git a/src/assets/icons/star-icon.svg b/src/assets/icons/star-icon.svg
new file mode 100644
index 0000000..6a62140
--- /dev/null
+++ b/src/assets/icons/star-icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icons/star.svg b/src/assets/icons/star.svg
new file mode 100644
index 0000000..1ea437e
--- /dev/null
+++ b/src/assets/icons/star.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/icons/success-icon.svg b/src/assets/icons/success-icon.svg
new file mode 100644
index 0000000..ea65186
--- /dev/null
+++ b/src/assets/icons/success-icon.svg
@@ -0,0 +1,8 @@
+
diff --git a/src/assets/icons/visibility-off.svg b/src/assets/icons/visibility-off.svg
new file mode 100644
index 0000000..62be473
--- /dev/null
+++ b/src/assets/icons/visibility-off.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/visibility.svg b/src/assets/icons/visibility.svg
new file mode 100644
index 0000000..28d3a2e
--- /dev/null
+++ b/src/assets/icons/visibility.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/img/banner_discover-world.jpg b/src/assets/img/banner_discover-world.jpg
new file mode 100644
index 0000000..054361a
Binary files /dev/null and b/src/assets/img/banner_discover-world.jpg differ
diff --git a/src/assets/img/main_hero-image.jpg b/src/assets/img/main_hero-image.jpg
new file mode 100644
index 0000000..a61b86c
Binary files /dev/null and b/src/assets/img/main_hero-image.jpg differ
diff --git a/src/assets/img/placeholder-image.svg b/src/assets/img/placeholder-image.svg
new file mode 100644
index 0000000..d2e692d
--- /dev/null
+++ b/src/assets/img/placeholder-image.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/img/promo-codes/CRUISE100.jpg b/src/assets/img/promo-codes/CRUISE100.jpg
new file mode 100644
index 0000000..d5ae2e6
Binary files /dev/null and b/src/assets/img/promo-codes/CRUISE100.jpg differ
diff --git a/src/assets/img/promo-codes/FAMILYFUN.jpg b/src/assets/img/promo-codes/FAMILYFUN.jpg
new file mode 100644
index 0000000..abd464e
Binary files /dev/null and b/src/assets/img/promo-codes/FAMILYFUN.jpg differ
diff --git a/src/assets/img/promo-codes/GROUP24.jpg b/src/assets/img/promo-codes/GROUP24.jpg
new file mode 100644
index 0000000..d94c4ae
Binary files /dev/null and b/src/assets/img/promo-codes/GROUP24.jpg differ
diff --git a/src/assets/img/promo-codes/LASTCHANCE.jpg b/src/assets/img/promo-codes/LASTCHANCE.jpg
new file mode 100644
index 0000000..c8f028f
Binary files /dev/null and b/src/assets/img/promo-codes/LASTCHANCE.jpg differ
diff --git a/src/assets/img/shop_hero-image.jpg b/src/assets/img/shop_hero-image.jpg
new file mode 100644
index 0000000..8f7f0d5
Binary files /dev/null and b/src/assets/img/shop_hero-image.jpg differ
diff --git a/src/assets/img/shop_hero-image_africa.jpg b/src/assets/img/shop_hero-image_africa.jpg
new file mode 100644
index 0000000..c805c68
Binary files /dev/null and b/src/assets/img/shop_hero-image_africa.jpg differ
diff --git a/src/assets/img/shop_hero-image_america.jpg b/src/assets/img/shop_hero-image_america.jpg
new file mode 100644
index 0000000..035dbb1
Binary files /dev/null and b/src/assets/img/shop_hero-image_america.jpg differ
diff --git a/src/assets/img/shop_hero-image_asia.jpg b/src/assets/img/shop_hero-image_asia.jpg
new file mode 100644
index 0000000..bdf16ac
Binary files /dev/null and b/src/assets/img/shop_hero-image_asia.jpg differ
diff --git a/src/assets/img/shop_hero-image_europe.jpg b/src/assets/img/shop_hero-image_europe.jpg
new file mode 100644
index 0000000..2af8a06
Binary files /dev/null and b/src/assets/img/shop_hero-image_europe.jpg differ
diff --git a/src/assets/img/shop_hero-image_hiking.jpg b/src/assets/img/shop_hero-image_hiking.jpg
new file mode 100644
index 0000000..5b406cb
Binary files /dev/null and b/src/assets/img/shop_hero-image_hiking.jpg differ
diff --git a/src/assets/img/shop_hero-image_sailing.jpg b/src/assets/img/shop_hero-image_sailing.jpg
new file mode 100644
index 0000000..e8f08dd
Binary files /dev/null and b/src/assets/img/shop_hero-image_sailing.jpg differ
diff --git a/src/assets/img/team-members/andrew.jfif b/src/assets/img/team-members/andrew.jfif
new file mode 100644
index 0000000..6ea3134
Binary files /dev/null and b/src/assets/img/team-members/andrew.jfif differ
diff --git a/src/assets/img/team-members/maksim.png b/src/assets/img/team-members/maksim.png
new file mode 100644
index 0000000..5cee598
Binary files /dev/null and b/src/assets/img/team-members/maksim.png differ
diff --git a/src/assets/img/team-members/yauheni.jfif b/src/assets/img/team-members/yauheni.jfif
new file mode 100644
index 0000000..81e3310
Binary files /dev/null and b/src/assets/img/team-members/yauheni.jfif differ
diff --git a/src/components/about-us/about-us-collaboration.ts b/src/components/about-us/about-us-collaboration.ts
new file mode 100644
index 0000000..878085b
--- /dev/null
+++ b/src/components/about-us/about-us-collaboration.ts
@@ -0,0 +1,51 @@
+import BaseComponent from '../base-component';
+import aboutUsMethods from '../../constants/aboutUsMethods';
+import './about-us.scss';
+
+export default class AboutUsCollaboration extends BaseComponent<'section'> {
+ constructor() {
+ super('section', ['about-us-collaboration']);
+ this.renderAboutUsCollaboration();
+ }
+
+ private renderAboutUsCollaboration = (): void => {
+ const title = new BaseComponent('h2', ['about-us-collaboration__title'], 'Collaboration').getElement();
+ const blockquote = new BaseComponent('blockquote', ['about-us-collaboration__blockquote']).getElement();
+ blockquote.insertAdjacentHTML(
+ 'afterbegin',
+ `
+
Great things in business are never done alone, they’re done by a team.
+
+ `
+ );
+
+ const methods = new BaseComponent('div', ['about-us-methods']).getElement();
+ const methodsTitle = new BaseComponent(
+ 'h4',
+ ['about-us-methods__title'],
+ 'Our effective collaboration methods:'
+ ).getElement();
+ const methodsWrapp = new BaseComponent('ul', ['about-us-methods__list']).getElement();
+
+ aboutUsMethods.forEach((obj, index) => {
+ const methodsItem = new BaseComponent('li', ['about-us-methods-item']).getElement();
+ const methodsItemIndex = new BaseComponent(
+ 'span',
+ ['about-us-methods-item__index'],
+ String(index + 1)
+ ).getElement();
+ const methodsItemTextWrapp = new BaseComponent('div', ['about-us-methods-item-wrapp']).getElement();
+ const methodsItemTitle = new BaseComponent('p', ['about-us-methods-item__title'], obj.title).getElement();
+ const methodsItemDescr = new BaseComponent('p', ['about-us-methods-item__descr'], obj.description).getElement();
+
+ methodsItemTextWrapp.append(methodsItemTitle, methodsItemDescr);
+ methodsItem.append(methodsItemIndex, methodsItemTextWrapp);
+
+ methodsWrapp.append(methodsItem);
+ });
+
+ methods.append(methodsTitle, methodsWrapp);
+
+ this.node.append(title, blockquote, methods);
+ };
+}
diff --git a/src/components/about-us/about-us-list.ts b/src/components/about-us/about-us-list.ts
new file mode 100644
index 0000000..40eb171
--- /dev/null
+++ b/src/components/about-us/about-us-list.ts
@@ -0,0 +1,15 @@
+import aboutUsMembers from '../../constants/aboutUsMembers';
+import BaseComponent from '../base-component';
+import AboutUsMember from './about-us-member';
+import './about-us.scss';
+
+export default class AboutUsList extends BaseComponent<'section'> {
+ constructor() {
+ super('section', ['about-us-list']);
+ this.renderAboutUsList();
+ }
+
+ private renderAboutUsList = (): void => {
+ aboutUsMembers.forEach((obj) => this.node.append(new AboutUsMember(obj).getElement()));
+ };
+}
diff --git a/src/components/about-us/about-us-member.ts b/src/components/about-us/about-us-member.ts
new file mode 100644
index 0000000..06a37ba
--- /dev/null
+++ b/src/components/about-us/about-us-member.ts
@@ -0,0 +1,43 @@
+import BaseComponent from '../base-component';
+import { IAboutUsMember } from '../../types/interfaces';
+import './about-us.scss';
+
+export default class AboutUsMember extends BaseComponent<'div'> {
+ constructor(member: IAboutUsMember) {
+ super('div', ['about-us-member']);
+ this.renderAboutUsMember(member);
+ }
+
+ private renderAboutUsMember = (member: IAboutUsMember): void => {
+ const memberHeader = new BaseComponent('div', ['about-us-member__header']).getElement();
+ const memberHeaderImg = new BaseComponent('div', ['about-us-member__img', member.imgClass]).getElement();
+ const memberHeaderWrapp = new BaseComponent('div', ['about-us-member__header-wrapp']).getElement();
+ const memberHeaderName = new BaseComponent('h3', ['about-us-member__title'], member.name).getElement();
+ const memberHeaderRole = new BaseComponent('p', ['about-us-member__role'], member.role).getElement();
+ memberHeaderWrapp.append(memberHeaderName, memberHeaderRole);
+ memberHeader.append(memberHeaderImg, memberHeaderWrapp);
+
+ const memberAbout = new BaseComponent('div', ['about-us-member__about']).getElement();
+ const memberAboutLabel = new BaseComponent('span', ['about-us-member__label'], 'About').getElement();
+ const memberAboutText = new BaseComponent('p', ['about-us-member__text'], member.about).getElement();
+ memberAbout.append(memberAboutLabel, memberAboutText);
+
+ const memberContributions = new BaseComponent('div', ['about-us-member__contributions']).getElement();
+ const memberContributionsLabel = new BaseComponent(
+ 'span',
+ ['about-us-member__label'],
+ 'Contributions'
+ ).getElement();
+ const memberContributionsList = new BaseComponent('ul', ['about-us-member__contributions-list']).getElement();
+ member.contributions.forEach((contribution) => {
+ memberContributionsList.append(new BaseComponent('li', [], contribution).getElement());
+ });
+ memberContributions.append(memberContributionsLabel, memberContributionsList);
+
+ const memberGithubLink = new BaseComponent('a', ['about-us-member__link'], 'GitHub Profile').getElement();
+ memberGithubLink.href = member.link;
+ memberGithubLink.target = '_blank';
+
+ this.node.append(memberHeader, memberAbout, memberContributions, memberGithubLink);
+ };
+}
diff --git a/src/components/about-us/about-us-rsschool-link.ts b/src/components/about-us/about-us-rsschool-link.ts
new file mode 100644
index 0000000..7446570
--- /dev/null
+++ b/src/components/about-us/about-us-rsschool-link.ts
@@ -0,0 +1,23 @@
+import BaseComponent from '../base-component';
+import './about-us.scss';
+
+export default class AboutUsRSSchool extends BaseComponent<'div'> {
+ constructor() {
+ super('div', ['about-us-rsschool']);
+ this.renderAboutUsRsschool();
+ }
+
+ private renderAboutUsRsschool(): void {
+ const rsschoolLink = new BaseComponent('a', ['about-us-rsschool__link']).getElement();
+ rsschoolLink.href = 'https://rs.school/js/';
+ rsschoolLink.target = '_blank';
+
+ const rsschoolText = new BaseComponent(
+ 'h4',
+ ['about-us-rsschool__text'],
+ 'The project is being developed as part of the final task of the course JavaScript/Front-end (2023Q1) from the RS School.'
+ ).getElement();
+
+ this.node.append(rsschoolLink, rsschoolText);
+ }
+}
diff --git a/src/components/about-us/about-us.scss b/src/components/about-us/about-us.scss
new file mode 100644
index 0000000..ee93f1a
--- /dev/null
+++ b/src/components/about-us/about-us.scss
@@ -0,0 +1,318 @@
+.about-us {
+ &-list {
+ margin: 48px 0 104px 0;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-gap: 24px;
+ gap: 24px;
+
+ @include pre-tablet {
+ grid-template-columns: repeat(1, 1fr);
+ }
+
+ @include mobile {
+ margin: 30px 0 60px 0;
+ }
+ }
+
+ &-member {
+ padding: 32px;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ //justify-content: space-between;
+ gap: 32px;
+ border-radius: 8px;
+ background: $color-bg-light;
+
+ @include pre-tablet {
+ gap: 24px;
+ }
+
+ @include small-mobile {
+ padding: 16px;
+ gap: 16px;
+ }
+
+ &__header {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ gap: 20px;
+ padding-bottom: 32px;
+ border-bottom: 2px solid rgba($color-primary, 0.08);
+
+ @include pre-tablet {
+ padding-bottom: 24px;
+ }
+
+ @include small-mobile {
+ padding-bottom: 16px;
+ }
+ }
+
+ &__img {
+ min-width: 96px;
+ height: 96px;
+ border-radius: 100%;
+ background-color: #fff;
+ background-image: url('../../assets/img/placeholder-image.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ overflow: hidden;
+
+ @include small-mobile {
+ min-width: 60px;
+ height: 60px;
+ }
+
+ &.andrew {
+ background-image: url('../../assets/img/team-members/andrew.jfif');
+ }
+ &.yauheni {
+ background-image: url('../../assets/img/team-members/yauheni.jfif');
+ }
+ &.maksim {
+ background-image: url('../../assets/img/team-members/maksim.png');
+ }
+ }
+
+ &__header-wrapp {
+ display: flex;
+ flex-direction: column;
+ }
+
+ &__title {
+ @include font-h4;
+ }
+
+ &__role {
+ font: $font-label;
+
+ @include small-mobile {
+ font-size: 12px;
+ }
+ }
+
+ &__label {
+ display: inline-block;
+ margin-bottom: 12px;
+ font: $font-about-label;
+ letter-spacing: 1.1px;
+ text-transform: uppercase;
+
+ @include small-mobile {
+ margin-bottom: 8px;
+ }
+ }
+
+ &__text {
+ @include small-mobile {
+ font-size: 14px;
+ }
+ }
+
+ &__link {
+ margin-top: auto;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ position: relative;
+ font: $font-button;
+ color: $color-button;
+ transition: all 0.3s ease-in-out;
+
+ &::after {
+ content: '';
+ width: 20px;
+ height: 20px;
+ background-image: url('../../assets/icons/github-profile-icon.svg');
+ }
+
+ &::before {
+ content: '';
+ position: absolute;
+ width: 0;
+ height: 1px;
+ background: $color-button;
+ left: 0;
+ bottom: -4px;
+ transition: width 0.2s ease-in-out;
+ }
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ &::before {
+ width: 100%;
+ }
+ }
+ }
+
+ &__contributions-list {
+ margin-left: 16px;
+
+ & li {
+ list-style: disc;
+ margin-bottom: 8px;
+
+ @include small-mobile {
+ font-size: 14px;
+ margin-bottom: 4px;
+ }
+ }
+ }
+ }
+
+ &-collaboration {
+ padding: 104px 0;
+ border-top: 1px solid $color-border;
+ border-bottom: 1px solid $color-border;
+
+ @include mobile {
+ padding-top: 60px;
+ margin-bottom: 60px;
+ }
+
+ &__title {
+ @include font-h1;
+ }
+
+ &__blockquote {
+ margin-top: 48px;
+ width: fit-content;
+ padding: 64px;
+ background: $color-bg-light;
+ border-radius: 8px;
+ position: relative;
+
+ @include tablet {
+ padding: 40px;
+ }
+
+ & p {
+ @include font-h2;
+ }
+
+ & footer {
+ margin-top: 40px;
+ font: $font-button;
+
+ @include tablet {
+ margin-top: 20px;
+ }
+ }
+
+ &::before {
+ content: '';
+ display: block;
+ width: 36px;
+ height: 32px;
+ background-image: url('../../assets/icons/quote-icon.svg');
+ background-position: center;
+ background-size: cover;
+ margin-bottom: 20px;
+
+ @include tablet {
+ width: 27px;
+ height: 24px;
+ }
+ }
+ }
+ }
+
+ &-methods {
+ margin-top: 48px;
+
+ &__title {
+ @include font-h2;
+ }
+
+ &__list {
+ margin-top: 48px;
+ }
+
+ &-item {
+ display: flex;
+ margin-bottom: 40px;
+
+ &__index {
+ margin-right: 20px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 40px;
+ height: 40px;
+ border-radius: 100%;
+ background: $color-button;
+ color: $color-white;
+ }
+
+ &__title {
+ @include font-h4;
+ margin-bottom: 10px;
+ }
+
+ &__descr {
+ max-width: 1000px;
+ @include small-mobile {
+ font-size: 14px;
+ }
+ }
+ }
+ }
+
+ &-rsschool {
+ padding: 104px 0;
+ display: flex;
+ align-items: center;
+
+ @include pre-tablet {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+
+ @include mobile {
+ padding: 40px 32px;
+ margin-bottom: 60px;
+ }
+
+ &__link {
+ display: block;
+ min-width: 220px;
+ height: 80px;
+ background-image: url('../../assets/icons/rsschool-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ transition: all 0.3s ease;
+
+ &:hover {
+ background-image: url('../../assets/icons/rsschool-icon-active.svg');
+ }
+
+ @include pre-tablet {
+ margin-bottom: 40px;
+ }
+
+ @include small-mobile {
+ min-width: 135px;
+ height: 50px;
+ }
+ }
+
+ &__text {
+ max-width: 1300px;
+ margin: 0 0 0 40px;
+ padding: 0 0 0 40px;
+ @include font-h2;
+ border-left: 1.5px solid rgba($color-primary, 0.12);
+
+ @include pre-tablet {
+ margin: 0;
+ padding: 0;
+ border: none;
+ }
+ }
+ }
+}
diff --git a/src/components/account/account-addresses/account-addresses.scss b/src/components/account/account-addresses/account-addresses.scss
new file mode 100644
index 0000000..0ee25a9
--- /dev/null
+++ b/src/components/account/account-addresses/account-addresses.scss
@@ -0,0 +1,68 @@
+.account-addresses {
+ &__title {
+ @include font-h3;
+ }
+
+ &__wrapp {
+ margin-top: 24px;
+ padding: 32px;
+ display: flex;
+ flex-direction: column;
+ background: $color-bg-card;
+ border-radius: 8px;
+
+ @include tablet {
+ margin-top: 8px;
+ }
+
+ @include small-mobile {
+ padding: 24px;
+ }
+
+ &.centered {
+ align-items: center;
+ }
+ }
+
+ &__view-btn {
+ margin-top: 32px;
+ max-width: fit-content;
+ }
+
+ &__add-btn {
+ margin-top: 24px;
+ max-width: fit-content;
+ }
+
+ &__item {
+ margin-top: 10px;
+
+ &:first-child {
+ margin-top: 0;
+ }
+ }
+
+ &-empty {
+ &__img {
+ width: 40px;
+ height: 40px;
+ background-image: url('../../../assets/icons/empty-addresses-book.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+
+ &__title {
+ margin-top: 16px;
+ text-align: center;
+ @include font-h4;
+ }
+
+ &__descr {
+ margin-top: 8px;
+ max-width: 338px;
+ text-align: center;
+ font-size: 15px;
+ }
+ }
+}
diff --git a/src/components/account/account-addresses/account-addresses.ts b/src/components/account/account-addresses/account-addresses.ts
new file mode 100644
index 0000000..5a2c0a1
--- /dev/null
+++ b/src/components/account/account-addresses/account-addresses.ts
@@ -0,0 +1,75 @@
+import BaseComponent from '../../base-component';
+import userStore from '../../../store/user-store';
+import Button from '../../button/button';
+import { changeUrlEvent } from '../../../utils/change-url-event';
+import './account-addresses.scss';
+import { AppRoutesPath } from '../../../router/types';
+import Sup from '../../sup/sup';
+
+export default class AccountAddresses extends BaseComponent<'div'> {
+ private detailsTitle: HTMLElement;
+
+ constructor() {
+ super('div', ['account-addresses']);
+
+ this.detailsTitle = new BaseComponent('h3', ['account-addresses__title'], 'Address Book').getElement();
+
+ this.node.append(this.detailsTitle, this.addressBookInfo());
+ }
+
+ private addressBookInfo(): HTMLElement {
+ const { customer } = userStore.getState();
+
+ const defaultBillingAddressId = customer?.defaultBillingAddressId;
+ const defaultShippingAddressId = customer?.defaultShippingAddressId;
+
+ const addressesWrapp = new BaseComponent('div', ['account-addresses__wrapp']).getElement();
+
+ if (customer && customer?.addresses.length > 0) {
+ customer?.addresses.forEach((address) => {
+ const addressElementText = `${address.streetName}, ${address.city}, ${address.postalCode} ${address.country}`;
+ const addressElement = new BaseComponent('p', ['account-addresses__item'], addressElementText).getElement();
+
+ if (address.id === defaultBillingAddressId) {
+ addressElement.append(new Sup('Default Billing').getElement());
+ }
+ if (address.id === defaultShippingAddressId) {
+ addressElement.append(new Sup('Default Shipping').getElement());
+ }
+
+ addressesWrapp.append(addressElement);
+ });
+
+ const viewAddressesBtn = new Button(
+ 'button',
+ `View Addresses (${customer.addresses.length})`,
+ ['account-addresses__view-btn'],
+ false,
+ () => changeUrlEvent(AppRoutesPath.ACCOUNT_ADDRESSES)
+ ).getElement();
+
+ addressesWrapp.append(viewAddressesBtn);
+ } else {
+ const addressEmptyImg = new BaseComponent('span', ['account-addresses-empty__img']).getElement();
+ const addressEmptyTitle = new BaseComponent(
+ 'h4',
+ ['account-addresses-empty__title'],
+ 'Your Address Book is Empty'
+ ).getElement();
+ const addressEmptyDescr = new BaseComponent(
+ 'p',
+ ['account-addresses-empty__descr'],
+ 'Investor focus research & development value proposition graphical user interface investor. '
+ ).getElement();
+
+ const addAddressesBtn = new Button('button', `Add Address`, ['account-addresses__add-btn'], false, () =>
+ changeUrlEvent(AppRoutesPath.ACCOUNT_ADDRESSES)
+ ).getElement();
+
+ addressesWrapp.classList.add('centered');
+ addressesWrapp.append(addressEmptyImg, addressEmptyTitle, addressEmptyDescr, addAddressesBtn);
+ }
+
+ return addressesWrapp;
+ }
+}
diff --git a/src/components/account/account-details/account-details.scss b/src/components/account/account-details/account-details.scss
new file mode 100644
index 0000000..5562f0c
--- /dev/null
+++ b/src/components/account/account-details/account-details.scss
@@ -0,0 +1,27 @@
+.account-details {
+ &__title {
+ @include font-h3;
+ }
+
+ &__wrapp {
+ margin-top: 24px;
+ padding: 32px;
+ display: flex;
+ flex-direction: column;
+ background: $color-bg-card;
+ border-radius: 8px;
+
+ @include tablet {
+ margin-top: 8px;
+ }
+
+ @include small-mobile {
+ padding: 24px;
+ }
+ }
+
+ &__edit-btn {
+ margin-top: 32px;
+ max-width: fit-content;
+ }
+}
diff --git a/src/components/account/account-details/account-details.ts b/src/components/account/account-details/account-details.ts
new file mode 100644
index 0000000..4024148
--- /dev/null
+++ b/src/components/account/account-details/account-details.ts
@@ -0,0 +1,54 @@
+import BaseComponent from '../../base-component';
+import Button from '../../button/button';
+import List from '../../list/list';
+import DetailsForm from '../../form/details-form';
+import userStore from '../../../store/user-store';
+import { ListDataType } from '../../../types/types';
+import { AccountInfoMode } from '../../../types/enums';
+import './account-details.scss';
+
+export default class AccountDetails extends BaseComponent<'div'> {
+ private mode: AccountInfoMode;
+ private detailsTitle: HTMLElement;
+ private detailsWrapp: HTMLElement;
+
+ constructor(mode: AccountInfoMode, onChange: () => void = () => {}) {
+ super('div', ['account-details']);
+
+ this.mode = mode;
+ this.detailsTitle = new BaseComponent('h3', ['account-details__title'], 'Account Details').getElement();
+ this.detailsWrapp = new BaseComponent('div', ['account-details__wrapp']).getElement();
+
+ this.createDetailsList(onChange);
+
+ this.node.append(this.detailsTitle, this.detailsWrapp);
+ }
+
+ private createDetailsList(onChange: () => void = () => {}): void {
+ const { customer } = userStore.getState();
+
+ if (this.mode === AccountInfoMode.SHOW) {
+ const buttonEdit = new Button(
+ 'button',
+ 'Edit account details',
+ ['account-details__edit-btn'],
+ false,
+ onChange
+ ).getElement();
+
+ const listObj: ListDataType = {
+ 'First Name': customer?.firstName || '',
+ 'Last Name': customer?.lastName || '',
+ 'Birth Date': customer?.dateOfBirth || '',
+ 'Email ': customer?.email || '',
+ 'Password ': `● ● ● ● ● ● ●`,
+ };
+
+ const listOfLiElements = customer ? new List(listObj).getElement() : '';
+
+ this.detailsWrapp.append(listOfLiElements, buttonEdit);
+ } else {
+ this.detailsWrapp.append(new DetailsForm(onChange).getElement());
+ }
+ }
+}
diff --git a/src/components/address/address.scss b/src/components/address/address.scss
new file mode 100644
index 0000000..8376dcb
--- /dev/null
+++ b/src/components/address/address.scss
@@ -0,0 +1,28 @@
+.address {
+ max-width: 828px;
+ margin-top: 24px;
+ padding: 32px;
+ display: flex;
+ flex-direction: column;
+ border-radius: 8px;
+ background: $color-bg-card;
+
+ @include small-mobile {
+ padding: 24px;
+ }
+
+ &__sups {
+ margin: 0 0 16px -3px;
+ }
+
+ &__actions {
+ margin-top: 32px;
+ display: flex;
+ align-items: center;
+ gap: 24px;
+
+ @include mobile {
+ flex-direction: column;
+ }
+ }
+}
diff --git a/src/components/address/address.ts b/src/components/address/address.ts
new file mode 100644
index 0000000..6b0035a
--- /dev/null
+++ b/src/components/address/address.ts
@@ -0,0 +1,94 @@
+import BaseComponent from '../base-component';
+import List from '../list/list';
+import Button from '../button/button';
+import Sup from '../sup/sup';
+import AddressForm from '../form/address-form';
+import { AddressesMode } from '../../types/enums';
+import { IAddressData } from '../../types/interfaces';
+import './address.scss';
+
+export default class Address extends BaseComponent<'div'> {
+ private mode: AddressesMode;
+ private addressData: IAddressData | null;
+ private firstBtnAction: (type: AddressesMode) => void;
+ private secondBtnAction: (id: string) => void;
+
+ constructor(
+ mode: AddressesMode,
+ addressData: IAddressData | null,
+ firstCallback: (type: AddressesMode) => void,
+ secondCallback: (id: string) => void
+ ) {
+ super('div', ['address']);
+
+ this.mode = mode;
+ this.addressData = addressData;
+ this.firstBtnAction = firstCallback;
+ this.secondBtnAction = secondCallback;
+
+ if (mode === AddressesMode.NEW) {
+ this.renderNewAddress();
+ } else {
+ this.renderAddress();
+ }
+ }
+
+ private renderNewAddress = (): void => {
+ const form = new AddressForm(this.firstBtnAction, this.secondBtnAction).getElement();
+ this.node.append(form);
+ };
+
+ private renderAddress = (): void => {
+ const data = this.addressData;
+
+ this.node.innerHTML = '';
+
+ if (this.mode === AddressesMode.SHOW) {
+ const defaultsWrapp = new BaseComponent('div', ['address__sups']).getElement();
+
+ if (data?.defaultBillingAddressId || data?.defaultShippingAddressId) {
+ const defaultBilling =
+ data?.defaultBillingAddressId === data?.address.id ? new Sup('Default Billing').getElement() : '';
+ const defaultShipping =
+ data?.defaultShippingAddressId === data?.address.id ? new Sup('Default Shipping').getElement() : '';
+
+ defaultsWrapp.append(defaultBilling, defaultShipping);
+ }
+
+ const type: string[] = [];
+
+ if (data?.billingAddressIds?.includes(data?.address.id || '')) type.push('Billing');
+ if (data?.shippingAddressIds?.includes(data?.address.id || '')) type.push('Shipping');
+
+ const listObj = {
+ 'Type ': `${type.join(', ')}`,
+ 'Street ': data?.address?.streetName || '',
+ 'City ': data?.address?.city || '',
+ 'Postcode ': data?.address?.postalCode || '',
+ 'Country ': data?.address?.country || '',
+ };
+
+ const list = new List(listObj).getElement();
+
+ const buttonWrapp = new BaseComponent('div', ['address__actions']).getElement();
+ const buttonSubmit = new Button('submit', 'Edit Address', [], false, this.changeMode).getElement();
+ const buttonCancel = new Button('button', 'Remove Address', ['button--cancel'], false, () =>
+ this.secondBtnAction(data?.address?.id || '')
+ ).getElement();
+
+ buttonWrapp.append(buttonSubmit, buttonCancel);
+
+ if (defaultsWrapp.childElementCount > 0) this.node.append(defaultsWrapp);
+
+ this.node.append(list, buttonWrapp);
+ } else {
+ this.node.append(new AddressForm(this.firstBtnAction, this.changeMode, this.addressData).getElement());
+ }
+ };
+
+ private changeMode = (): void => {
+ this.mode = this.mode === AddressesMode.SHOW ? AddressesMode.EDIT : AddressesMode.SHOW;
+ this.firstBtnAction(this.mode);
+ this.renderAddress();
+ };
+}
diff --git a/src/components/banner/banner.scss b/src/components/banner/banner.scss
new file mode 100644
index 0000000..d2e7031
--- /dev/null
+++ b/src/components/banner/banner.scss
@@ -0,0 +1,66 @@
+.banner {
+ width: 100%;
+ height: 680px;
+ color: $color-white;
+ background-image: url('../../assets/img/banner_discover-world.jpg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+
+ @include tablet {
+ height: 540px;
+ }
+
+ &--main-page {
+ height: calc(100dvh - 80px);
+ background-image: url('../../assets/img/main_hero-image.jpg');
+ }
+
+ &__container {
+ @include container;
+ height: 100%;
+ }
+
+ &__content {
+ max-width: 840px;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ padding-top: 250px;
+
+ @include tablet {
+ padding-top: 200px;
+ }
+
+ @include mobile {
+ padding-top: 120px;
+ }
+
+ .banner--main-page & {
+ justify-content: flex-end;
+ padding: 120px 0;
+
+ @include tablet {
+ padding: 80px 0;
+ }
+
+ @include mobile {
+ padding: 40px 0;
+ }
+ }
+ }
+
+ &__title {
+ @include font-h1;
+ margin-bottom: 24px;
+ }
+
+ &__text {
+ font: $font-subtitle;
+ margin-bottom: 32px;
+
+ @include tablet {
+ font-size: 16px;
+ }
+ }
+}
diff --git a/src/components/banner/banner.test.ts b/src/components/banner/banner.test.ts
new file mode 100644
index 0000000..3ca4baa
--- /dev/null
+++ b/src/components/banner/banner.test.ts
@@ -0,0 +1,44 @@
+import Banner from './banner';
+
+describe('Banner', () => {
+ it('should render banner with correct title and text', () => {
+ const title = 'Test Title';
+ const text = 'Test Text';
+
+ const banner = new Banner(title, text).getElement();
+ const bannerTitle: HTMLElement | null = banner.querySelector('.banner__title');
+ const bannerText: HTMLElement | null = banner.querySelector('.banner__text');
+
+ expect(bannerTitle?.textContent).toBe(title);
+ expect(bannerText?.textContent).toBe(text);
+ });
+
+ it('should have the correct class names', () => {
+ const banner = new Banner('Title', 'Text', ['test-class']).getElement();
+
+ expect(banner.classList.contains('test-class')).toBe(true);
+ });
+
+ it('should create a banner with no additional class if none provided', () => {
+ const banner = new Banner('Title', 'Text').getElement();
+
+ expect(banner.classList.length).toBe(1);
+ });
+
+ it('should call the button click handler when clicked', () => {
+ const banner = new Banner('Title', 'Text').getElement();
+ const bannerButton: HTMLButtonElement | null = banner.querySelector('.button--white');
+ const buttonClickSpy = jest.spyOn(bannerButton!, 'click');
+
+ bannerButton?.click();
+
+ expect(buttonClickSpy).toHaveBeenCalled();
+ });
+
+ it('should not throw error when button is clicked with no click handler', () => {
+ const banner = new Banner('Title', 'Text').getElement();
+ const bannerButton: HTMLButtonElement | null = banner.querySelector('.button--white');
+
+ expect(() => bannerButton?.click()).not.toThrow();
+ });
+});
diff --git a/src/components/banner/banner.ts b/src/components/banner/banner.ts
new file mode 100644
index 0000000..5c3377d
--- /dev/null
+++ b/src/components/banner/banner.ts
@@ -0,0 +1,29 @@
+import BaseComponent from '../../components/base-component';
+import { AppRoutesPath } from '../../router/types';
+import { changeUrlEvent } from '../../utils/change-url-event';
+import Button from '../button/button';
+import './banner.scss';
+
+export default class Banner extends BaseComponent<'section'> {
+ constructor(title: string, text: string, classes: string[] = []) {
+ super('section', ['banner', ...classes]);
+
+ this.createMarkup(title, text);
+ }
+
+ private createMarkup(title: string, text: string): void {
+ const container: HTMLDivElement = new BaseComponent('div', ['banner__container']).getElement();
+ const bannerContent: HTMLDivElement = new BaseComponent('div', ['banner__content']).getElement();
+ const bannerTitle: HTMLHeadingElement = new BaseComponent('h1', ['banner__title'], title).getElement();
+ const bannerText: HTMLParagraphElement = new BaseComponent('p', ['banner__text'], text).getElement();
+ const bannerButton: HTMLButtonElement = new Button('button', 'Shop All', ['button--white'], false, () =>
+ changeUrlEvent(AppRoutesPath.SHOP)
+ ).getElement();
+
+ bannerContent.append(bannerTitle, bannerText, bannerButton);
+
+ container.append(bannerContent);
+
+ this.node.append(container);
+ }
+}
diff --git a/src/components/base-component.ts b/src/components/base-component.ts
new file mode 100644
index 0000000..0f4eb50
--- /dev/null
+++ b/src/components/base-component.ts
@@ -0,0 +1,13 @@
+export default class BaseComponent {
+ protected node: HTMLElementTagNameMap[K];
+
+ constructor(tagName: K, classNames: Array = [], textContent: string = '') {
+ this.node = document.createElement(tagName);
+ this.node.classList.add(...classNames);
+ this.node.textContent = textContent;
+ }
+
+ public getElement(): HTMLElementTagNameMap[K] {
+ return this.node;
+ }
+}
diff --git a/src/components/basket-empty/basket-empty.scss b/src/components/basket-empty/basket-empty.scss
new file mode 100644
index 0000000..bb34119
--- /dev/null
+++ b/src/components/basket-empty/basket-empty.scss
@@ -0,0 +1,33 @@
+.basket-empty {
+ margin-bottom: 80px;
+
+ &__container {
+ @include container;
+ }
+
+ &__content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 12px;
+ padding: 80px 20px;
+ text-align: center;
+ background-color: $color-bg-light;
+ border-radius: 8px;
+ }
+
+ &__icon {
+ width: 40px;
+ height: 40px;
+ background: url('../../assets/icons/bag-icon.svg') center/cover;
+ }
+
+ &__title {
+ @include font-h4;
+ }
+
+ &__subtitle {
+ margin-bottom: 20px;
+ }
+}
diff --git a/src/components/basket-empty/basket-empty.ts b/src/components/basket-empty/basket-empty.ts
new file mode 100644
index 0000000..368c4ec
--- /dev/null
+++ b/src/components/basket-empty/basket-empty.ts
@@ -0,0 +1,34 @@
+import { AppRoutesPath } from '../../router/types';
+import { changeUrlEvent } from '../../utils/change-url-event';
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import './basket-empty.scss';
+
+export default class BasketEmpty extends BaseComponent<'section'> {
+ constructor() {
+ super('section', ['basket-empty']);
+
+ this.renderBasketContent();
+ }
+
+ private renderBasketContent(): void {
+ const basketEmptyContainer = new BaseComponent('div', ['basket-empty__container']).getElement();
+ const basketEmptyContent = new BaseComponent('div', ['basket-empty__content']).getElement();
+ const basketIcon = new BaseComponent('div', ['basket-empty__icon']).getElement();
+ const contentTitle = new BaseComponent('h4', ['basket-empty__title'], 'Your Shopping Cart is Empty').getElement();
+
+ const basketSubtitle = new BaseComponent(
+ 'p',
+ ['basket-empty__subtitle'],
+ 'Looks like you haven’t added anything yet, let’s get you started!'
+ ).getElement();
+
+ const basketBtn = new Button('button', 'Start Shopping', ['basket-empty__button'], false, () =>
+ changeUrlEvent(AppRoutesPath.SHOP)
+ ).getElement();
+
+ basketEmptyContent.append(basketIcon, contentTitle, basketSubtitle, basketBtn);
+ basketEmptyContainer.append(basketEmptyContent);
+ this.node.append(basketEmptyContainer);
+ }
+}
diff --git a/src/components/basket-items/basket-items.scss b/src/components/basket-items/basket-items.scss
new file mode 100644
index 0000000..8430dde
--- /dev/null
+++ b/src/components/basket-items/basket-items.scss
@@ -0,0 +1,263 @@
+.basket-items {
+ margin-bottom: 60px;
+
+ &__container {
+ @include container;
+ }
+
+ &__table {
+ width: 100%;
+ border-collapse: collapse;
+ margin-bottom: 24px;
+
+ &-head {
+ text-align: left;
+ font-size: 11px;
+ font-weight: 700;
+ line-height: 120%;
+ letter-spacing: 1.1px;
+ text-transform: uppercase;
+
+ @include tablet {
+ display: none;
+ }
+ }
+
+ &-body {
+ font: $font-label;
+ text-transform: capitalize;
+ }
+
+ &-row {
+ @include tablet {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ flex-wrap: wrap;
+ border-bottom: 1px solid $color-border;
+ }
+ }
+
+ &-th {
+ padding: 27.5px 0;
+ border-bottom: 1px solid $color-border;
+ }
+
+ &-td {
+ padding: 24px 16px 24px 0;
+ border-bottom: 1px solid $color-border;
+
+ &--price,
+ &--total-price {
+ min-width: 100px;
+
+ @include mobile {
+ width: 100%;
+ }
+ }
+
+ &--price {
+ @include mobile {
+ &::before {
+ content: 'Price ';
+ }
+ }
+ }
+
+ &--total-price {
+ @include mobile {
+ &::before {
+ content: 'Total ';
+ }
+ }
+ }
+
+ &--quantity {
+ @include mobile {
+ width: 100%;
+ }
+ }
+
+ &--remove {
+ padding-right: 0;
+ width: 80px;
+
+ @include tablet {
+ order: -1;
+ margin-left: auto;
+ }
+
+ @include mobile {
+ width: 24px;
+ }
+ }
+
+ @include tablet {
+ border: none;
+ }
+
+ @include mobile {
+ padding: 12px 0;
+ }
+ }
+
+ &-row:last-child .basket-items__table-td {
+ border: none;
+ }
+ }
+
+ &__product {
+ display: flex;
+ align-items: center;
+ gap: 20px;
+
+ @include tablet {
+ width: 85%;
+ order: -2;
+ }
+
+ @include mobile {
+ width: 70%;
+ }
+ }
+
+ &__image {
+ &-wrapper {
+ width: 132px;
+ height: 83px;
+ background: $color-bg-secondary;
+ border-radius: 8px;
+ overflow: hidden;
+
+ @include mobile {
+ height: auto;
+ }
+ }
+
+ img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ object-position: center;
+ }
+
+ &--placeholder {
+ background-image: url('../../assets/img/placeholder-image.svg');
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+ }
+
+ &__prices {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ flex-wrap: wrap;
+
+ @include mobile {
+ display: inline-flex;
+ }
+ }
+
+ &__price {
+ color: $color-primary;
+
+ &--old {
+ text-decoration: line-through;
+ color: $color-secondary-40;
+ }
+
+ &--new {
+ color: $color-error;
+ }
+ }
+
+ &__quantity {
+ width: 107px;
+ height: 43px;
+ border-radius: 6px;
+ background: $color-bg-light;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font: $font-button;
+
+ @include mobile {
+ width: 100%;
+ }
+
+ &--disabled {
+ pointer-events: none;
+ opacity: 0.5;
+ }
+ }
+
+ &__remove {
+ background: transparent;
+ color: $color-primary;
+ position: relative;
+ display: flex;
+ align-items: center;
+ gap: 2px;
+ opacity: 0.6;
+ padding: 0;
+ width: 80px;
+
+ &_all {
+ width: unset;
+ }
+
+ @include mobile {
+ width: 24px;
+
+ &_all {
+ width: unset;
+ }
+ }
+
+ &-icon {
+ width: 15px;
+ height: 15px;
+ background-image: url('../../assets/icons/popup-close-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+
+ @include mobile {
+ width: 24px;
+ height: 24px;
+ }
+ }
+
+ span {
+ @include mobile {
+ display: none;
+ }
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ width: 100%;
+ height: 1px;
+ background: $color-secondary-60;
+ left: 0;
+ bottom: -4px;
+ transition: width 0.2s ease-in-out;
+
+ @include mobile {
+ display: none;
+ }
+ }
+
+ &:hover,
+ &:active {
+ background: transparent !important;
+
+ &::after {
+ width: 0;
+ }
+ }
+ }
+}
diff --git a/src/components/basket-items/basket-items.ts b/src/components/basket-items/basket-items.ts
new file mode 100644
index 0000000..c14af17
--- /dev/null
+++ b/src/components/basket-items/basket-items.ts
@@ -0,0 +1,320 @@
+import { LineItem } from '@commercetools/platform-sdk';
+import BaseComponent from '../../components/base-component';
+import Button from '../button/button';
+import formatPrice from '../../utils/formatPrice';
+import Notification from '../notification/notification';
+import cartStore from '../../store/cart-store';
+import removeProductFromCart from '../../services/basket/removeProductFromCart';
+import './basket-items.scss';
+import changeCartItemQuantity from '../../services/basket/changeCartItemQuantity';
+import removeCart from '../../services/basket/removeCart';
+
+enum BasketItemQuantityAction {
+ DEC = 'decrement',
+ INC = 'increment',
+}
+
+export default class BasketItems extends BaseComponent<'section'> {
+ private tableElements: HTMLTableRowElement[];
+ private lineTotalElements: Record;
+ private quantityElements: Record;
+ private clearAllBtn: HTMLButtonElement = new Button(
+ 'button',
+ 'Clear All',
+ ['basket-items__remove', 'basket-items__remove_all'],
+ false,
+ () => this.onRemoveCart()
+ ).getElement();
+
+ constructor(items: LineItem[]) {
+ super('section', ['basket-items']);
+
+ this.tableElements = [];
+ this.quantityElements = {};
+ this.lineTotalElements = {};
+
+ this.renderBasketItems(items);
+ this.addSubscribtion();
+ }
+
+ private renderBasketItems(items: LineItem[]): void {
+ const basketItemsContainer = new BaseComponent('div', ['basket-items__container']).getElement();
+ const table: HTMLTableElement = this.renderTable(items);
+
+ basketItemsContainer.append(table, this.clearAllBtn);
+
+ this.node.append(basketItemsContainer);
+ }
+
+ private async onRemoveCart(): Promise {
+ try {
+ const response = await removeCart();
+
+ cartStore.dispatch({ type: 'UPDATE_CART', cart: response });
+
+ this.clearAllBtn.disabled = false;
+ } catch (err) {
+ if (err instanceof Error) new Notification('error', err.message);
+
+ this.clearAllBtn.disabled = false;
+ }
+ }
+
+ private renderTable(items: LineItem[]): HTMLTableElement {
+ const table: HTMLTableElement = new BaseComponent('table', ['basket-items__table']).getElement();
+ const tableHead: HTMLTableSectionElement = this.renderTableHead();
+ const tableBody: HTMLTableSectionElement = this.renderTableBody(items);
+
+ table.append(tableHead, tableBody);
+
+ return table;
+ }
+
+ private renderTableHead(): HTMLTableSectionElement {
+ const headers: string[] = ['Product', 'Price', 'Quantity', 'Total', ''];
+ const tableHead: HTMLTableSectionElement = new BaseComponent('thead', ['basket-items__table-head']).getElement();
+ const tableHeadRow: HTMLTableRowElement = new BaseComponent('tr', ['basket-items__table-row']).getElement();
+
+ headers.forEach((headerText) => {
+ const th: HTMLTableCellElement = new BaseComponent('th', ['basket-items__table-th']).getElement();
+ th.textContent = headerText;
+ tableHeadRow.append(th);
+ });
+
+ tableHead.append(tableHeadRow);
+
+ return tableHead;
+ }
+
+ private renderTableBody(items: LineItem[]): HTMLTableSectionElement {
+ const tableBody: HTMLTableSectionElement = new BaseComponent('tbody', ['basket-items__table-body']).getElement();
+
+ items.forEach((item) => {
+ const row: HTMLTableRowElement = new BaseComponent('tr', ['basket-items__table-row']).getElement();
+
+ const infoCell = this.renderInfo(item);
+ const priceCell = this.renderPrice(item);
+ const quantityCell = this.renderQuantityField(item);
+ const totalPriceCell = this.renderTotalPrice(item);
+ const removeCell = this.renderRemoveBtn(item);
+
+ row.append(infoCell, priceCell, quantityCell, totalPriceCell, removeCell);
+ tableBody.append(row);
+
+ row.id = item.id;
+ this.tableElements.push(row);
+ });
+
+ return tableBody;
+ }
+
+ private renderInfo(item: LineItem): HTMLTableCellElement {
+ const infoElement: HTMLTableCellElement = new BaseComponent('td', [
+ 'basket-items__table-td',
+ 'basket-items__product',
+ ]).getElement();
+ const titleElement: HTMLSpanElement = new BaseComponent('span', ['basket-items__title'], item.name.en).getElement();
+ const imageWrapper: HTMLDivElement = new BaseComponent('div', ['basket-items__image-wrapper']).getElement();
+ const imageElement: HTMLImageElement = new BaseComponent('img', ['basket-items__image']).getElement();
+
+ if (item.variant.images?.[0]?.url) {
+ imageElement.src = item.variant.images?.[0]?.url;
+ imageElement.alt = 'tour-image';
+ imageWrapper.append(imageElement);
+ } else {
+ imageWrapper.classList.add('basket-items__image--placeholder');
+ }
+
+ infoElement.append(imageWrapper, titleElement);
+
+ return infoElement;
+ }
+
+ private renderPrice(item: LineItem): HTMLTableCellElement {
+ const priceField: HTMLTableCellElement = new BaseComponent('td', [
+ 'basket-items__table-td',
+ 'basket-items__table-td--price',
+ ]).getElement();
+ const pricesElement: HTMLDivElement = new BaseComponent('div', ['basket-items__prices']).getElement();
+ const priceStandard: HTMLSpanElement = new BaseComponent('span', ['basket-items__price']).getElement();
+ const priceDisc: HTMLSpanElement = new BaseComponent('span', [
+ 'basket-items__price',
+ 'basket-items__price--new',
+ ]).getElement();
+
+ if (item.price.value) {
+ priceStandard.textContent = formatPrice(
+ item.price.value.currencyCode,
+ item.price.value.centAmount,
+ item.price.value.fractionDigits
+ );
+ pricesElement.append(priceStandard);
+ }
+
+ if (item.price.discounted) {
+ priceDisc.textContent = formatPrice(
+ item.price.discounted.value.currencyCode,
+ item.price.discounted.value.centAmount,
+ item.price.discounted.value.fractionDigits
+ );
+ priceStandard.classList.add('basket-items__price--old');
+ pricesElement.append(priceDisc);
+ }
+
+ priceField.append(pricesElement);
+
+ return priceField;
+ }
+
+ private renderQuantityField(item: LineItem): HTMLTableCellElement {
+ const maxQuantity: number = Number(item.variant.attributes?.[3].value);
+
+ const quantityElement: HTMLTableCellElement = new BaseComponent('td', [
+ 'basket-items__table-td',
+ 'basket-items__table-td--quantity',
+ ]).getElement();
+
+ const quantityField: HTMLDivElement = new BaseComponent('div', ['basket-items__quantity']).getElement();
+ const quantityFieldDec: HTMLButtonElement = new Button('button', '-', ['button--quantity'], false, () =>
+ this.handleChangeItemQuantity(item, BasketItemQuantityAction.DEC)
+ ).getElement();
+ const quantityFieldNumber: HTMLSpanElement = new BaseComponent('span', [], `${item.quantity}`).getElement();
+ const quantityFieldInc: HTMLButtonElement = new Button(
+ 'button',
+ '+',
+ ['button--quantity'],
+ maxQuantity === item.quantity,
+ () => this.handleChangeItemQuantity(item, BasketItemQuantityAction.INC)
+ ).getElement();
+
+ this.quantityElements[item.id] = [quantityField, quantityFieldNumber, quantityFieldInc];
+
+ quantityField.append(quantityFieldDec, quantityFieldNumber, quantityFieldInc);
+
+ quantityElement.append(quantityField);
+ return quantityElement;
+ }
+
+ private renderTotalPrice(item: LineItem): HTMLTableCellElement {
+ const priceElement: HTMLTableCellElement = new BaseComponent('td', [
+ 'basket-items__table-td',
+ 'basket-items__table-td--total-price',
+ ]).getElement();
+ const price: HTMLSpanElement = new BaseComponent('span', ['basket-items__price']).getElement();
+
+ if (item.totalPrice.centAmount) {
+ price.textContent = formatPrice(
+ item.totalPrice.currencyCode,
+ item.totalPrice.centAmount,
+ item.totalPrice.fractionDigits
+ );
+ this.lineTotalElements[item.id] = price;
+ priceElement.append(price);
+ }
+
+ return priceElement;
+ }
+
+ private renderRemoveBtn(item: LineItem): HTMLTableCellElement {
+ const removeField: HTMLTableCellElement = new BaseComponent('td', [
+ 'basket-items__table-td',
+ 'basket-items__table-td--remove',
+ ]).getElement();
+ const removeBtn: HTMLButtonElement = new Button('button', '', ['basket-items__remove']).getElement();
+ const iconRemoveBtn: HTMLDivElement = new BaseComponent('div', ['basket-items__remove-icon']).getElement();
+ const textRemoveBtn: HTMLSpanElement = new BaseComponent('span', [], 'Remove').getElement();
+
+ removeBtn.addEventListener('click', (event) => this.onRemoveFromCart(event, item.productId));
+
+ removeBtn.append(iconRemoveBtn, textRemoveBtn);
+ removeField.append(removeBtn);
+
+ return removeField;
+ }
+
+ private handleChangeItemQuantity(item: LineItem, action: BasketItemQuantityAction): void {
+ if (action === BasketItemQuantityAction.DEC) {
+ const newQuantity = Number(this.quantityElements[item.id][1].textContent) - 1;
+ this.onChangeQuantity(item.id, newQuantity);
+ } else {
+ const newQuantity = Number(this.quantityElements[item.id][1].textContent) + 1;
+ this.onChangeQuantity(item.id, newQuantity);
+ }
+ }
+
+ private onChangeQuantity = async (lineItemId: string, quantity: number): Promise => {
+ try {
+ this.quantityElements[lineItemId][0].classList.add('basket-items__quantity--disabled');
+ const cart = await changeCartItemQuantity(lineItemId, quantity);
+ cartStore.dispatch({ type: 'UPDATE_CART', cart });
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ if (error.message === 'invalid_token') {
+ localStorage.removeItem('tokenAnon');
+ localStorage.removeItem('token');
+ }
+ } else {
+ console.error(error);
+ }
+ } finally {
+ this.quantityElements[lineItemId][0].classList.remove('basket-items__quantity--disabled');
+ }
+ };
+
+ private async onRemoveFromCart(event: MouseEvent, productId: string): Promise {
+ try {
+ if (event.currentTarget instanceof HTMLButtonElement) event.currentTarget.disabled = true;
+
+ const updatedCart = await removeProductFromCart(productId);
+ cartStore.dispatch({ type: 'UPDATE_CART', cart: updatedCart });
+ new Notification('success', 'Tour has been successfully removed from cart!').showNotification();
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+
+ if (event.currentTarget instanceof HTMLButtonElement) event.currentTarget.disabled = false;
+ }
+ }
+
+ private addSubscribtion(): void {
+ cartStore.subscribe((state) => {
+ const cartItemIds = state.cart?.lineItems.map((item) => item.id).flat();
+
+ this.tableElements.forEach((itemHtml) => {
+ if (!cartItemIds?.includes(itemHtml.id)) {
+ itemHtml.remove();
+ }
+
+ if (cartItemIds?.includes(itemHtml.id)) {
+ const lineItem: LineItem | undefined = state.cart?.lineItems.find((item) => item.id === itemHtml.id);
+
+ if (lineItem) {
+ this.lineTotalElements[itemHtml.id].textContent = formatPrice(
+ lineItem.totalPrice.currencyCode,
+ lineItem.totalPrice.centAmount,
+ lineItem.totalPrice.fractionDigits
+ );
+
+ const currentDisplayQuantity: string | null = this.quantityElements[itemHtml.id][1].textContent;
+ const currentActualQuantity: number | undefined = lineItem.quantity;
+ const maxQuantity: number = Number(lineItem.variant.attributes?.[3].value);
+
+ if (Number(currentDisplayQuantity) !== currentActualQuantity) {
+ this.quantityElements[itemHtml.id][1].textContent = String(currentActualQuantity);
+ }
+
+ if (maxQuantity === currentActualQuantity) {
+ this.quantityElements[itemHtml.id][2].disabled = true;
+ } else {
+ this.quantityElements[itemHtml.id][2].disabled = false;
+ }
+ }
+ }
+ });
+ });
+ }
+}
diff --git a/src/components/basket-total/basket-total.scss b/src/components/basket-total/basket-total.scss
new file mode 100644
index 0000000..d0ff27a
--- /dev/null
+++ b/src/components/basket-total/basket-total.scss
@@ -0,0 +1,66 @@
+.basket-total {
+ margin-bottom: 80px;
+
+ &__container {
+ @include container;
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ align-items: flex-end;
+ }
+
+ &__content {
+ display: flex;
+ flex-direction: column;
+ width: 480px;
+ padding: 32px;
+ background-color: $color-bg-light;
+ border-radius: 8px;
+
+ @include mobile {
+ width: 100%;
+ }
+ }
+
+ &__button {
+ width: 480px;
+
+ @include mobile {
+ width: 100%;
+ }
+ }
+
+ &__promo {
+ display: flex;
+ align-items: flex-end;
+ gap: 8px;
+ margin-bottom: 24px;
+
+ &-input {
+ flex-grow: 1;
+ }
+
+ &-button {
+ height: 48px;
+ padding: 12px 32px;
+ }
+ }
+
+ &__total {
+ padding: 20px 0;
+ border-top: 1px solid $color-border;
+ font: $font-label;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ &-price {
+ font: $font-button;
+
+ &.discount {
+ font-size: 16px;
+ color: $color-success;
+ }
+ }
+ }
+}
diff --git a/src/components/basket-total/basket-total.ts b/src/components/basket-total/basket-total.ts
new file mode 100644
index 0000000..2a61765
--- /dev/null
+++ b/src/components/basket-total/basket-total.ts
@@ -0,0 +1,153 @@
+import { Cart } from '@commercetools/platform-sdk';
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import InputField from '../input/input';
+import cartStore from '../../store/cart-store';
+import addDiscountToCart from '../../services/basket/addDiscountToCart';
+import Notification from '../notification/notification';
+import createBasketTotal from '../../utils/createBasketTotal';
+import createBasketDiscountTotal from '../../utils/createBasketDiscountTotal';
+import getDiscountCode from '../../services/getDiscountCode';
+import removeDiscountCart from '../../services/basket/removeDiscountCart';
+import './basket-total.scss';
+
+export default class BasketTotal extends BaseComponent<'section'> {
+ private totalBox: HTMLDivElement | null = null;
+ private inputPromo: InputField | null = null;
+ private buttonClearDiscount: HTMLButtonElement | null = null;
+ private currentPromoCode: string = '';
+
+ constructor(cart: Cart) {
+ super('section', ['basket-total']);
+
+ this.renderSection(cart);
+ this.addSubscribtion();
+ }
+
+ private renderSection(cart: Cart): void {
+ const container: HTMLDivElement = new BaseComponent('div', ['basket-total__container']).getElement();
+ const content: HTMLDivElement = new BaseComponent('div', ['basket-total__content']).getElement();
+ const button: HTMLButtonElement = new Button(
+ 'button',
+ 'Proceed to Checkout',
+ ['basket-total__button'],
+ true
+ ).getElement();
+
+ const promoBox = this.renderPromoForm();
+ this.totalBox = new BaseComponent('div', ['basket-total__prices']).getElement();
+
+ if (cart.discountCodes.length > 0) {
+ this.renderTotalWithDiscount(cart);
+ } else {
+ this.renderTotal(cart);
+ }
+
+ content.append(promoBox, this.totalBox);
+ container.append(content, button);
+
+ this.node.append(container);
+ }
+
+ private renderPromoForm(): HTMLFormElement {
+ const promoForm: HTMLFormElement = new BaseComponent('form', ['basket-total__promo']).getElement();
+ this.inputPromo = new InputField('text', 'promo', 'TRAVEL2023', 'Enter Promo Code', ['basket-total__promo-input']);
+ const buttonApply: HTMLButtonElement = new Button('button', 'Apply', ['basket-total__promo-button']).getElement();
+ this.buttonClearDiscount = new Button(
+ 'button',
+ '',
+ ['button--trash-cart', 'basket-total__delete-promo'],
+ false,
+ this.onRemoveDiscount
+ ).getElement();
+
+ const onClick = () => {
+ const promoFormData: FormData = new FormData(promoForm);
+ const promoCode: string | undefined = promoFormData.get('promo')?.toString();
+
+ if (promoCode) this.addPromoCodeToBasket(promoCode);
+ };
+
+ buttonApply.addEventListener('click', onClick);
+
+ promoForm.append(this.inputPromo.getElement(), buttonApply, this.buttonClearDiscount);
+
+ return promoForm;
+ }
+
+ private renderTotal(cart: Cart): void {
+ (this.totalBox as HTMLDivElement).innerHTML = '';
+ this.totalBox?.append(...createBasketTotal(cart));
+ this.buttonClearDiscount?.classList.add('hidden');
+ }
+
+ private async renderTotalWithDiscount(cart: Cart): Promise {
+ (this.totalBox as HTMLDivElement).innerHTML = '';
+ this.totalBox?.append(...createBasketDiscountTotal(cart));
+ const discount = await getDiscountCode();
+ this.inputPromo?.setValue(discount?.code || '');
+ this.currentPromoCode = discount?.code || '';
+ this.buttonClearDiscount?.classList.remove('hidden');
+ }
+
+ private async addPromoCodeToBasket(promoCode: string): Promise {
+ if (this.currentPromoCode !== promoCode) {
+ try {
+ const cart = await addDiscountToCart(promoCode);
+ this.currentPromoCode = promoCode;
+
+ cartStore.dispatch({ type: 'UPDATE_CART', cart });
+
+ this.renderTotalWithDiscount(cart as Cart);
+ new Notification('success', 'Promo Code is successfully applied!').showNotification();
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ if (error.message === 'invalid_token') {
+ localStorage.removeItem('tokenAnon');
+ localStorage.removeItem('token');
+ }
+ } else {
+ console.error(error);
+ }
+ }
+ } else {
+ new Notification('warning', 'This promo code has already been entered!').showNotification();
+ }
+ }
+
+ private onRemoveDiscount = async (): Promise => {
+ try {
+ const cart = await removeDiscountCart();
+ this.renderTotal(cart as Cart);
+ this.inputPromo?.setValue('');
+ this.currentPromoCode = '';
+
+ cartStore.dispatch({ type: 'UPDATE_CART', cart });
+
+ new Notification('success', 'Promo Code is successfully deleted!').showNotification();
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ if (error.message === 'invalid_token') {
+ localStorage.removeItem('tokenAnon');
+ localStorage.removeItem('token');
+ }
+ } else {
+ console.error(error);
+ }
+ }
+ };
+
+ private addSubscribtion(): void {
+ cartStore.subscribe((state) => {
+ (this.totalBox as HTMLDivElement).innerHTML = '';
+
+ if (this.currentPromoCode) {
+ this.renderTotalWithDiscount(state.cart as Cart);
+ } else {
+ this.renderTotal(state.cart as Cart);
+ }
+ });
+ }
+}
diff --git a/src/components/breadcrumbs/breadcrumbs.scss b/src/components/breadcrumbs/breadcrumbs.scss
new file mode 100644
index 0000000..2c73a2c
--- /dev/null
+++ b/src/components/breadcrumbs/breadcrumbs.scss
@@ -0,0 +1,21 @@
+.breadcrumbs {
+ &__container {
+ @include container;
+ display: flex;
+ justify-content: space-between;
+ }
+
+ &__links {
+ padding: 32px 0;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ flex-wrap: wrap;
+ }
+
+ &__current {
+ font: $font-xs;
+ color: $color-primary;
+ white-space: nowrap;
+ }
+}
diff --git a/src/components/breadcrumbs/breadcrumbs.test.ts b/src/components/breadcrumbs/breadcrumbs.test.ts
new file mode 100644
index 0000000..c3757cb
--- /dev/null
+++ b/src/components/breadcrumbs/breadcrumbs.test.ts
@@ -0,0 +1,31 @@
+import Breadcrumbs from './breadcrumbs';
+import { IBreadcrumbLink } from '../../types/interfaces';
+import { AppRoutesPath } from '../../router/types';
+
+describe('Breadcrumbs component', () => {
+ const breadcrumbLinks: IBreadcrumbLink[] = [
+ { pageName: 'Home', pageHref: AppRoutesPath.MAIN },
+ { pageName: 'Login', pageHref: AppRoutesPath.LOGIN },
+ ];
+
+ const breadcrumbs: HTMLDivElement = new Breadcrumbs(breadcrumbLinks, 'Test').getElement();
+
+ it('should render correct html', () => {
+ const expectedHTML =
+ '';
+
+ expect(breadcrumbs.outerHTML).toContain(expectedHTML);
+ });
+
+ it('should render correct links amount', () => {
+ const linksElement: HTMLDivElement | null = breadcrumbs.querySelector('.breadcrumbs__links');
+
+ expect(linksElement?.childNodes.length).toEqual(breadcrumbLinks.length + 1);
+ });
+
+ it('should render correct currentPage', () => {
+ const currentPage: HTMLParagraphElement | null = breadcrumbs.querySelector('.breadcrumbs__current');
+
+ expect(currentPage?.textContent).toBe('Test');
+ });
+});
diff --git a/src/components/breadcrumbs/breadcrumbs.ts b/src/components/breadcrumbs/breadcrumbs.ts
new file mode 100644
index 0000000..e12fec3
--- /dev/null
+++ b/src/components/breadcrumbs/breadcrumbs.ts
@@ -0,0 +1,44 @@
+import BaseComponent from '../base-component';
+import Link from '../link/link';
+import Button from '../button/button';
+import userLogout from '../../services/userLogout';
+import Notification from '../../components/notification/notification';
+import { IBreadcrumbLink } from '../../types/interfaces';
+import { changeUrlEvent } from '../../utils/change-url-event';
+import { AppRoutesPath } from '../../router/types';
+import './breadcrumbs.scss';
+
+export default class Breadcrumbs extends BaseComponent<'div'> {
+ constructor(links: IBreadcrumbLink[], currentPage: string, showLogoutBtn: boolean = false) {
+ super('div', ['breadcrumbs']);
+
+ this.renderBreadcrumbs(links, currentPage, showLogoutBtn);
+ }
+
+ renderBreadcrumbs(links: IBreadcrumbLink[], currentPage: string, showLogoutBtn: boolean = false): void {
+ const container: HTMLDivElement = new BaseComponent('div', ['breadcrumbs__container']).getElement();
+ const linksElement: HTMLDivElement = new BaseComponent('div', ['breadcrumbs__links']).getElement();
+ const activeLinksElements: HTMLAnchorElement[] = links.map((link) =>
+ new Link(link.pageName, ['link--breadcrumbs'], link.pageHref).getElement()
+ );
+ const currentPageElement: HTMLParagraphElement = new BaseComponent(
+ 'p',
+ ['breadcrumbs__current'],
+ currentPage
+ ).getElement();
+
+ linksElement.append(...activeLinksElements, currentPageElement);
+
+ const logoutBtn = new Button('button', 'Log Out', ['button--logout'], false, () => {
+ userLogout();
+ changeUrlEvent(AppRoutesPath.MAIN);
+ new Notification('success', 'You have successfully logged out!').showNotification();
+ });
+
+ container.append(linksElement);
+
+ if (showLogoutBtn) container.append(logoutBtn.getElement());
+
+ this.node.append(container);
+ }
+}
diff --git a/src/components/button/button.scss b/src/components/button/button.scss
new file mode 100644
index 0000000..4d33dde
--- /dev/null
+++ b/src/components/button/button.scss
@@ -0,0 +1,302 @@
+.button {
+ background: $color-button;
+ border-radius: 6px;
+ padding: 16px 32px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ color: $color-white;
+ font: $font-button;
+ cursor: pointer;
+ transition: background 0.3s ease-in-out;
+
+ &:disabled {
+ opacity: 0.5;
+ cursor: default;
+ }
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ background: $color-button-hover;
+ }
+
+ &--white {
+ width: 124px;
+ background: $color-white;
+ color: $color-primary;
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ background: $color-gray;
+ }
+ }
+
+ &--loading {
+ position: relative;
+ color: transparent;
+
+ &::after {
+ content: '';
+ position: absolute;
+ width: 20px;
+ height: 20px;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background-image: url('../../assets/icons/spinner-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+ }
+
+ &--success {
+ position: relative;
+ color: transparent;
+
+ &::after {
+ content: '';
+ position: absolute;
+ width: 20px;
+ height: 20px;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background-image: url('../../assets/icons/success-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+ }
+
+ &--cart {
+ padding: 0;
+ width: 48px;
+ height: 48px;
+ position: relative;
+
+ &::after {
+ content: '';
+ position: absolute;
+ width: 20px;
+ height: 20px;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background-image: url('../../assets/icons/cart-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+ }
+
+ &--logout {
+ position: relative;
+ background: none;
+ border-radius: 0;
+ padding: 0;
+ color: $color-secondary-40;
+ transition: transform 0.3s ease-in-out;
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ background: none;
+ transform: scale(1.06);
+ }
+
+ &::before {
+ content: '';
+ position: absolute;
+ width: 20px;
+ height: 20px;
+ top: 50%;
+ left: -22px;
+ transform: translate(0, -50%);
+ background-image: url('../../assets/icons/logout-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ width: 81px;
+ height: 1px;
+ top: 67%;
+ left: -21px;
+ transform: translate(0, -50%);
+ background-color: $color-secondary-40;
+ }
+ }
+
+ &--cancel {
+ position: relative;
+ background: none;
+ border-radius: 0;
+ padding: 0;
+ color: $color-secondary-40;
+ transition: color 0.3s ease-in-out;
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ background: none;
+ color: $color-secondary-60;
+
+ &::after {
+ background: $color-secondary-60;
+ width: 0;
+ }
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ width: 100%;
+ height: 1px;
+ left: 0;
+ bottom: 0px;
+ background-color: $color-secondary-40;
+ transition: all 0.3s ease-in-out;
+ }
+ }
+
+ &--change-password {
+ position: relative;
+ background: none;
+ width: fit-content;
+ border-radius: 0;
+ padding: 0;
+ margin-left: 30px;
+ color: $color-button-hover;
+ transition: transform 0.3s ease-in-out;
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ background: none;
+ transform: scale(1.03);
+ }
+
+ &::before {
+ content: '';
+ position: absolute;
+ width: 26px;
+ height: 25px;
+ top: 50%;
+ left: -30px;
+ transform: translate(0, -50%);
+ background-image: url('../../assets/icons/change-password-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+ }
+
+ &--reset {
+ background: transparent;
+ padding: 0;
+ color: $color-button;
+ position: relative;
+
+ &::before {
+ content: '';
+ position: absolute;
+ width: 100%;
+ height: 1px;
+ background: $color-button;
+ left: 0;
+ bottom: -4px;
+ transition: width 0.2s ease-in-out;
+ }
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ background: transparent;
+
+ &::before {
+ width: 0;
+ }
+ }
+ }
+
+ &--add-address {
+ position: relative;
+ background: none;
+ border-radius: 0;
+ padding: 0;
+ color: $color-button;
+ transition: all 0.3s ease-in-out;
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ background: none;
+ color: $color-button-hover;
+
+ &::after {
+ background: $color-button-hover;
+ width: 0;
+ }
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ width: 100%;
+ height: 1px;
+ left: 0;
+ bottom: 0px;
+ background: $color-button;
+ transition: all 0.3s ease-in-out;
+ }
+ }
+
+ &--trash-cart {
+ position: relative;
+ display: block;
+ background-color: $color-error;
+ overflow: hidden;
+ height: 48px;
+
+ &.hidden {
+ display: none;
+ }
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ background-color: rgba($color-error, 0.8);
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ width: 25px;
+ height: 25px;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ background-image: url('../../assets/icons/cart-trash-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+ }
+
+ &--quantity {
+ background: none;
+ border-radius: 6px;
+ padding: 8px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ color: $color-black;
+ font: $font-button;
+ font-size: 20px;
+ cursor: pointer;
+ transition: all 0.3s ease-in-out;
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ color: $color-white;
+ }
+ }
+}
diff --git a/src/components/button/button.test.ts b/src/components/button/button.test.ts
new file mode 100644
index 0000000..89307b0
--- /dev/null
+++ b/src/components/button/button.test.ts
@@ -0,0 +1,31 @@
+import Button from './button';
+
+describe('Button', () => {
+ const button: Button = new Button('button', 'Test Button', ['btn-test-class'], true, () => {
+ console.log('Button is clicked!');
+ });
+
+ it('should render correct html-element', () => {
+ expect(button.getElement().outerHTML).toBe(
+ ''
+ );
+ });
+ it('should render correct textContent', () => {
+ expect(button.getElement().textContent).toBe('Test Button');
+ });
+ it('should render correct classList', () => {
+ expect(button.getElement().classList.contains('btn-test-class')).toBe(true);
+ });
+ it('should button is disabled', () => {
+ const mockCallBack: jest.Mock = jest.fn();
+ button.getElement().click();
+ expect(mockCallBack.mock.calls.length).not.toEqual(1);
+ });
+ test('Console log should have been called', () => {
+ const logSpy: jest.SpyInstance = jest.spyOn(global.console, 'log');
+ button.getElement().disabled = false;
+ button.getElement().click();
+ expect(logSpy).toHaveBeenCalled();
+ expect(logSpy).toHaveBeenCalledWith('Button is clicked!');
+ });
+});
diff --git a/src/components/button/button.ts b/src/components/button/button.ts
new file mode 100644
index 0000000..941ebab
--- /dev/null
+++ b/src/components/button/button.ts
@@ -0,0 +1,17 @@
+import BaseComponent from '../base-component';
+import './button.scss';
+
+export default class Button extends BaseComponent<'button'> {
+ constructor(
+ type: 'submit' | 'reset' | 'button' = 'button',
+ text: string,
+ classes: string[] = [],
+ disabled: boolean = false,
+ onClick: () => void = () => {}
+ ) {
+ super('button', ['button', ...classes], text);
+ this.node.type = type;
+ disabled && this.node.setAttribute('disabled', 'true');
+ this.node.addEventListener('click', onClick);
+ }
+}
diff --git a/src/components/category-list/category-list.scss b/src/components/category-list/category-list.scss
new file mode 100644
index 0000000..a8beacd
--- /dev/null
+++ b/src/components/category-list/category-list.scss
@@ -0,0 +1,54 @@
+.category-list {
+ margin-top: 48px;
+
+ &__container {
+ @include container;
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ }
+
+ &__title {
+ @include font-h4;
+ }
+
+ &__list {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 16px;
+ }
+
+ &__link {
+ color: $color-secondary-60;
+ transition: color 0.3s ease-in-out;
+ position: relative;
+
+ &::before {
+ content: '';
+ position: absolute;
+ width: 0;
+ height: 1px;
+ background: $color-primary;
+ left: 0;
+ bottom: -4px;
+ transition: width 0.2s ease-in-out;
+ }
+
+ &:hover {
+ color: $color-primary;
+
+ &::before {
+ width: 100%;
+ }
+ }
+
+ &--active {
+ color: $color-primary;
+
+ &::before {
+ width: 100%;
+ }
+ }
+ }
+}
diff --git a/src/components/category-list/category-list.ts b/src/components/category-list/category-list.ts
new file mode 100644
index 0000000..6da464a
--- /dev/null
+++ b/src/components/category-list/category-list.ts
@@ -0,0 +1,27 @@
+import { ICategory } from '../../types/types';
+import BaseComponent from '../base-component';
+import Link from '../link/link';
+import './category-list.scss';
+
+export default class CategoryList extends BaseComponent<'div'> {
+ constructor(title: string, categories: ICategory[], currentSlug: string) {
+ super('div', ['category-list']);
+
+ this.drawList(title, categories, currentSlug);
+ }
+
+ private drawList(title: string, items: ICategory[], currentSlug: string): void {
+ const container: HTMLDivElement = new BaseComponent('div', ['category-list__container']).getElement();
+ const titleElelemt: HTMLHeadingElement = new BaseComponent('h4', ['category-list__title'], title).getElement();
+ const categoryList: HTMLDivElement = new BaseComponent('div', ['category-list__list']).getElement();
+ const categoryElements = items.map((item) => {
+ const classes: string[] =
+ currentSlug === item.slug ? ['category-list__link', 'category-list__link--active'] : ['category-list__link'];
+ return new Link(item.label, ['link', ...classes], item.url).getElement();
+ });
+ categoryList.append(...categoryElements);
+ container.append(titleElelemt, categoryList);
+
+ this.node.append(container);
+ }
+}
diff --git a/src/components/footer/footer.scss b/src/components/footer/footer.scss
new file mode 100644
index 0000000..d75dee9
--- /dev/null
+++ b/src/components/footer/footer.scss
@@ -0,0 +1,102 @@
+.footer {
+ background-color: $color-primary;
+
+ &__container {
+ @include container;
+ padding: 80px 120px;
+ display: flex;
+ justify-content: space-between;
+
+ @include tablet {
+ padding: 40px 60px;
+ }
+
+ @include mobile {
+ flex-direction: column;
+ justify-content: flex-start;
+ gap: 40px;
+ padding: 20px;
+ }
+ }
+
+ &__information {
+ display: flex;
+ flex-direction: column;
+ align-self: flex-start;
+ gap: 16px;
+ max-width: 400px;
+
+ @include mobile {
+ order: 2;
+ max-width: unset;
+ }
+
+ @include tablet {
+ max-width: 300px;
+ }
+ }
+
+ &__subtitle {
+ color: $color-white;
+ }
+
+ &__post-subtitle {
+ color: $color-white;
+ font-size: 14px;
+ opacity: 0.5;
+
+ @include mobile {
+ font-size: 12px;
+ }
+ }
+
+ &__nav {
+ display: flex;
+ gap: 64px;
+
+ @include tablet {
+ gap: 30px;
+ }
+
+ @include mobile {
+ order: 1;
+ justify-content: flex-start;
+ flex-wrap: wrap;
+ gap: 40px;
+ }
+ }
+
+ &__menu {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+
+ @include mobile {
+ gap: 5px;
+ }
+
+ .menu {
+ &__title > a {
+ color: $color-white;
+
+ @include tablet {
+ display: block;
+ }
+ }
+
+ &__item:not(.menu__title) > a {
+ color: $color-gray;
+ opacity: 0.5;
+ transition: all 0.2s ease;
+
+ @include tablet {
+ display: block;
+ }
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/footer/footer.test.ts b/src/components/footer/footer.test.ts
new file mode 100644
index 0000000..51bf940
--- /dev/null
+++ b/src/components/footer/footer.test.ts
@@ -0,0 +1,33 @@
+import Footer from './footer';
+
+describe('Footer', () => {
+ const footer = new Footer().getElement();
+
+ it('renders without crashing', () => {
+ expect(footer).toBeDefined();
+ });
+
+ it('contains footer information', () => {
+ const footerInformation: HTMLElement | null = footer.querySelector('.footer__information');
+
+ expect(footerInformation).toBeTruthy();
+ });
+
+ it('contains a link to the login page', () => {
+ const loginLink: HTMLElement | null = footer.querySelector('.menu__link[href="/login"]');
+
+ expect(loginLink).toBeTruthy();
+ });
+
+ it('contains a link to the signUp page', () => {
+ const registrationLink: HTMLElement | null = footer.querySelector('.menu__link[href="/registration"]');
+
+ expect(registrationLink).toBeTruthy();
+ });
+
+ it('renders correct number of menu items', () => {
+ const menuItems = footer.querySelectorAll('.menu__item');
+
+ expect(menuItems.length).toBe(15);
+ });
+});
diff --git a/src/components/footer/footer.ts b/src/components/footer/footer.ts
new file mode 100644
index 0000000..98f103e
--- /dev/null
+++ b/src/components/footer/footer.ts
@@ -0,0 +1,95 @@
+import BaseComponent from '../base-component';
+import Logo from '../logo/logo';
+import menuItems from '../header/header-nav/menu-items';
+import Link from '../link/link';
+import { AppRoutesPath } from '../../router/types';
+import { IMenuItems } from '../../types/types';
+import './footer.scss';
+
+export default class Footer extends BaseComponent<'footer'> {
+ private container: HTMLDivElement;
+
+ constructor() {
+ super('footer', ['footer']);
+
+ this.container = this.createMarkup();
+
+ this.node.append(this.container);
+ }
+
+ private createMarkup(): HTMLDivElement {
+ const container: HTMLDivElement = new BaseComponent<'div'>('div', ['footer__container']).getElement();
+ const footerInfo: HTMLDivElement = this.drawFooterInfo();
+ const footerNavigation: HTMLElement = this.drawNavigation();
+
+ container.append(footerInfo, footerNavigation);
+
+ return container;
+ }
+
+ private drawFooterInfo(): HTMLDivElement {
+ const footerInfo: HTMLDivElement = new BaseComponent<'div'>('div', ['footer__information']).getElement();
+ const footerLogo: HTMLHeadingElement = new Logo().getElement();
+ const footerSubtitle: HTMLParagraphElement = new BaseComponent<'p'>(
+ 'p',
+ ['footer__subtitle'],
+ 'From hidden gems to iconic landmarks, our journeys are designed to ignite your sense of wonder.'
+ ).getElement();
+
+ const footerPostSubtitle: HTMLParagraphElement = new BaseComponent<'p'>(
+ 'p',
+ ['footer__post-subtitle'],
+ 'The project is made for noncommercial purposes.'
+ ).getElement();
+
+ footerInfo.append(footerLogo, footerSubtitle, footerPostSubtitle);
+
+ return footerInfo;
+ }
+
+ private drawNavigation(): HTMLElement {
+ const navigation: HTMLElement = new BaseComponent<'nav'>('nav', ['footer__nav']).getElement();
+
+ menuItems.forEach((item: IMenuItems) => {
+ if (item.innerItems) {
+ const menu: HTMLUListElement = new BaseComponent<'ul'>('ul', ['footer__menu']).getElement();
+
+ const menuTitle: HTMLLIElement = this.createListItem(item.title, ['menu__item', 'menu__title'], item.href);
+
+ menu.append(menuTitle);
+
+ item.innerItems.forEach((innerItem) => {
+ const menuItem: HTMLLIElement = this.createListItem(innerItem.title, ['menu__item'], innerItem.href);
+
+ menu.append(menuItem);
+ });
+
+ navigation.append(menu);
+ }
+ });
+
+ const pagesMenu: HTMLUListElement = new BaseComponent<'ul'>('ul', ['footer__menu']).getElement();
+
+ const pagesItem: HTMLLIElement = this.createListItem('Pages', ['menu__item', 'menu__title'], AppRoutesPath.ANCHOR);
+ const signupItem: HTMLLIElement = this.createListItem('Create Account', ['menu__item'], AppRoutesPath.SIGN_UP);
+ const loginItem: HTMLLIElement = this.createListItem('Log In', ['menu__item'], AppRoutesPath.LOGIN);
+ const aboutUsItem: HTMLLIElement = this.createListItem('About Us', ['menu__item'], AppRoutesPath.ABOUT_US);
+ const accountItem: HTMLLIElement = this.createListItem('Account', ['menu__item'], AppRoutesPath.ACCOUNT);
+ const shoppingCartItem: HTMLLIElement = this.createListItem('Shopping Cart', ['menu__item'], AppRoutesPath.BASKET);
+
+ pagesMenu.append(pagesItem, signupItem, loginItem, aboutUsItem, accountItem, shoppingCartItem);
+
+ navigation.append(pagesMenu);
+
+ return navigation;
+ }
+
+ private createListItem(name: string, classNames: string[], href: AppRoutesPath | string): HTMLLIElement {
+ const listItem: HTMLLIElement = new BaseComponent<'li'>('li', [...classNames]).getElement();
+ const itemLink: HTMLAnchorElement = new Link(name, ['menu__link'], href).getElement();
+
+ listItem.append(itemLink);
+
+ return listItem;
+ }
+}
diff --git a/src/components/form/address-form.ts b/src/components/form/address-form.ts
new file mode 100644
index 0000000..667aa75
--- /dev/null
+++ b/src/components/form/address-form.ts
@@ -0,0 +1,211 @@
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import InputField from '../input/input';
+import SelectTypeField from '../select/select-type';
+import Notification from '../notification/notification';
+import addAddress from '../../services/addresses/addAddress';
+import setDefaultTypeAddress from '../../services/addresses/setDefaultTypeAddress';
+import addTypeAddressID from '../../services/addresses/addTypeAddressID';
+import changeAddress from '../../services/addresses/changeAddress';
+import removeTypeAddressID from '../../services/addresses/removeTypeAddressID';
+import { AddressInputs } from '../../constants/addressInputs';
+import { IAddressData, IAddressFormData, InputFilds } from '../../types/interfaces';
+import { AddressesMode } from '../../types/enums';
+import './form.scss';
+
+export default class AddressForm extends BaseComponent<'form'> {
+ private inputs: InputFilds;
+ private selectType: SelectTypeField;
+ private isDefaultBilling: boolean = false;
+ private isDefaultShipping: boolean = false;
+ private buttonSubmit: HTMLButtonElement;
+ private buttonCancel: HTMLButtonElement;
+ private firstBtnAction: (type: AddressesMode) => void;
+ private secondBtnAction: (id: string) => void;
+ private addressData: IAddressData | null;
+
+ constructor(
+ firstCallback: (type: AddressesMode) => void,
+ secondCallback: (id: string) => void,
+ addressData: IAddressData | null = null
+ ) {
+ super('form', ['form__form']);
+ this.inputs = {};
+ this.selectType = new SelectTypeField();
+ this.addressData = addressData;
+ if (addressData) {
+ this.isDefaultBilling = addressData?.defaultBillingAddressId === addressData?.address.id;
+ this.isDefaultShipping = addressData?.defaultShippingAddressId === addressData?.address.id;
+ }
+ this.firstBtnAction = firstCallback;
+ this.secondBtnAction = secondCallback;
+ this.node.addEventListener('submit', (event) => this.onSubmit(event));
+ this.buttonSubmit = new Button('submit', this.addressData ? 'Save Address' : 'Add Address', []).getElement();
+ this.buttonCancel = new Button('button', 'Cancel', ['button--cancel'], false, () =>
+ this.secondBtnAction('new')
+ ).getElement();
+ this.createMarkup();
+ }
+
+ private createMarkup(): void {
+ const actionField: HTMLDivElement = new BaseComponent('div', ['form__action']).getElement();
+ actionField.append(this.buttonSubmit, this.buttonCancel);
+
+ const formContent: HTMLDivElement = new BaseComponent('div', ['form__content']).getElement();
+
+ const addressMainInputs = AddressInputs['main'].map(({ type, name, placeholder, label }) => {
+ const inputField = new InputField(type, name, placeholder, label);
+
+ if (name === 'streetName') {
+ inputField.setValue(this.addressData?.address.streetName || '');
+ } else if (name === 'city') {
+ inputField.setValue(this.addressData?.address.city || '');
+ } else if (name === 'postalCode') {
+ inputField.setValue(this.addressData?.address.postalCode || '');
+ }
+
+ this.inputs[name] = inputField;
+
+ return inputField.getElement();
+ });
+
+ const addressCheckboxesInputs = AddressInputs['checkboxes'].map(({ type, name, placeholder, label }) => {
+ const inputField = new InputField(type, name, placeholder, label);
+
+ if (name === 'checkboxDefaultShipping') {
+ inputField.getElement().addEventListener('change', () => {
+ this.isDefaultShipping = !this.isDefaultShipping;
+ });
+
+ if (this.addressData) {
+ inputField.setChecked(this.addressData?.defaultShippingAddressId === this.addressData?.address.id);
+ }
+ }
+
+ if (name === 'checkboxDefaultBilling') {
+ inputField.getElement().addEventListener('change', () => {
+ this.isDefaultBilling = !this.isDefaultBilling;
+ });
+
+ if (this.addressData) {
+ inputField.setChecked(this.addressData?.defaultBillingAddressId === this.addressData?.address.id);
+ }
+ }
+
+ this.inputs[name] = inputField;
+
+ return inputField.getElement();
+ });
+
+ const chackboxesWrapp = new BaseComponent('div', []).getElement();
+ chackboxesWrapp.append(...addressCheckboxesInputs);
+
+ if (this.addressData)
+ this.selectType.setValue(
+ this.addressData?.billingAddressIds?.includes(this.addressData?.address.id || ''),
+ this.addressData?.shippingAddressIds?.includes(this.addressData?.address.id || '')
+ );
+
+ formContent.append(this.selectType.getElement(), ...addressMainInputs, chackboxesWrapp);
+
+ this.node.append(formContent, actionField);
+ }
+
+ private getSignupData(): IAddressFormData | undefined {
+ const type: string | undefined = this.selectType.getValue();
+ const streetName: string | undefined = this.inputs['streetName'].getValue('streetBilling');
+ const city: string | undefined = this.inputs['city'].getValue('cityBilling');
+ const postalCode: string | undefined = this.inputs['postalCode'].getValue('postcodeBilling');
+ const country = 'US';
+
+ if (!(type && streetName && city && postalCode && country)) {
+ return;
+ }
+
+ return {
+ type,
+ streetName,
+ city,
+ postalCode,
+ country,
+ };
+ }
+
+ private async onSubmit(event: SubmitEvent): Promise {
+ event.preventDefault();
+
+ this.buttonSubmit.disabled = true;
+ this.buttonSubmit.classList.add('button--loading');
+
+ const values = this.getSignupData();
+
+ if (!values) {
+ this.buttonSubmit.disabled = false;
+ this.buttonSubmit.classList.remove('button--loading');
+ return;
+ }
+ let addressId: string;
+
+ try {
+ if (this.addressData) {
+ await changeAddress(this.addressData.address.id || '', values);
+ addressId = this.addressData.address.id || '';
+ } else {
+ const { addresses } = await addAddress(values);
+ addressId = addresses[addresses.length - 1].id || '';
+ }
+
+ if (values.type === 'Billing') {
+ await addTypeAddressID('Billing', addressId);
+ if (this.addressData?.shippingAddressIds?.includes(addressId)) await removeTypeAddressID('Shipping', addressId);
+ } else if (values.type === 'Shipping') {
+ await addTypeAddressID('Shipping', addressId);
+ if (this.addressData?.billingAddressIds?.includes(addressId)) await removeTypeAddressID('Billing', addressId);
+ } else {
+ await addTypeAddressID('Billing', addressId);
+ await addTypeAddressID('Shipping', addressId);
+ }
+
+ if (this.isDefaultBilling && this.isDefaultShipping) {
+ await setDefaultTypeAddress('Billing', addressId);
+ await setDefaultTypeAddress('Shhipping', addressId);
+ } else if (this.isDefaultBilling) {
+ await setDefaultTypeAddress('Billing', addressId);
+ if (this.addressData?.defaultBillingAddressId === this.addressData?.address.id) {
+ await setDefaultTypeAddress('Shipping', '');
+ }
+ } else if (this.isDefaultShipping) {
+ await setDefaultTypeAddress('Shipping', addressId);
+ if (this.addressData?.defaultShippingAddressId === this.addressData?.address.id) {
+ await setDefaultTypeAddress('Billing', '');
+ }
+ } else {
+ await setDefaultTypeAddress('Billing', '');
+ await setDefaultTypeAddress('Shipping', '');
+ }
+
+ if (this.addressData?.address.id) {
+ new Notification('success', 'The selected address has been successfully updated!').showNotification();
+ } else {
+ new Notification('success', 'Your Address is successfully added!').showNotification();
+ }
+
+ this.buttonSubmit.classList.remove('button--loading');
+ this.buttonSubmit.classList.add('button--success');
+
+ setTimeout(() => {
+ this.firstBtnAction(this.addressData?.address.id ? AddressesMode.SHOW : AddressesMode.NEW);
+ }, 500);
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+
+ this.buttonSubmit.disabled = false;
+ this.buttonSubmit.classList.remove('button--loading');
+ this.buttonSubmit.classList.remove('button--success');
+ }
+ }
+}
diff --git a/src/components/form/details-form.ts b/src/components/form/details-form.ts
new file mode 100644
index 0000000..ffdef20
--- /dev/null
+++ b/src/components/form/details-form.ts
@@ -0,0 +1,143 @@
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import InputField from '../input/input';
+import Notification from '../notification/notification';
+import PopupPassword from '../popup/popup-password';
+import updateUser from '../../services/updateUser';
+import userStore from '../../store/user-store';
+import { MyCustomerUpdateAction } from '@commercetools/platform-sdk';
+import { detailsEditInputs } from '../../constants/detailsEditInputs';
+import { IDetailsData, InputFilds } from '../../types/interfaces';
+import { removePopupFromBody } from '../../utils/remove-popup';
+import './form.scss';
+
+export default class DetailsForm extends BaseComponent<'form'> {
+ private inputs: InputFilds;
+ private buttonWrapp: HTMLDivElement;
+ private buttonChangePassword: HTMLButtonElement;
+ private buttonSubmit: HTMLButtonElement;
+ private buttonCancel: HTMLButtonElement;
+ private onChangeModeCallback: () => void;
+
+ constructor(onChange: () => void = () => {}) {
+ super('form', ['form__form']);
+ this.inputs = {};
+ this.buttonWrapp = new BaseComponent('div', ['form__action']).getElement();
+ this.buttonSubmit = new Button('submit', 'Save account details', []).getElement();
+ this.buttonCancel = new Button('button', 'Cancel', ['button--cancel'], false, onChange).getElement();
+ this.buttonChangePassword = new Button('button', 'Change password?', ['button--change-password'], false, () => {
+ document.body.append(new PopupPassword(() => removePopupFromBody('.popup-password')).getElement());
+ }).getElement();
+
+ this.buttonWrapp.append(this.buttonSubmit, this.buttonCancel);
+
+ this.createDetailsForm();
+
+ this.onChangeModeCallback = onChange;
+
+ this.node.append(this.buttonChangePassword, this.buttonWrapp);
+ this.node.addEventListener('submit', (event) => this.onSubmit(event));
+ }
+
+ private createDetailsForm(): void {
+ const { customer } = userStore.getState();
+
+ const formContent: HTMLDivElement = new BaseComponent('div', [
+ 'form__content',
+ 'form--details__content',
+ ]).getElement();
+
+ const infoInputs = detailsEditInputs.main.map(({ type, name, placeholder, label }) => {
+ const inputField: InputField = new InputField(type, name, placeholder, label);
+ if (name === 'firstName') {
+ inputField.setValue(customer?.firstName || '');
+ } else if (name === 'lastName') {
+ inputField.setValue(customer?.lastName || '');
+ } else if (name === 'dateOfBirth') {
+ inputField.setValue(customer?.dateOfBirth || '');
+ } else if (name === 'email') {
+ inputField.setValue(customer?.email || '');
+ }
+ this.inputs[name] = inputField;
+ return inputField.getElement();
+ });
+
+ formContent.append(...infoInputs);
+ this.node.append(formContent);
+ }
+
+ private getDetailsData(): IDetailsData | undefined {
+ const firstName: string | undefined = this.inputs['firstName'].getValue('firstName');
+ const lastName: string | undefined = this.inputs['lastName'].getValue('lastName');
+ const email: string | undefined = this.inputs['email'].getValue('email');
+ const dateOfBirth: string | undefined = this.inputs['dateOfBirth'].getValue('birthDate');
+
+ if (!(firstName && lastName && email && dateOfBirth)) {
+ return;
+ }
+
+ return {
+ firstName,
+ lastName,
+ email,
+ dateOfBirth,
+ };
+ }
+
+ private async onSubmit(event: SubmitEvent): Promise {
+ event.preventDefault();
+
+ this.buttonSubmit.disabled = true;
+ this.buttonSubmit.classList.add('button--loading');
+
+ const values: IDetailsData | undefined = this.getDetailsData();
+
+ if (!values) {
+ this.buttonSubmit.disabled = false;
+ this.buttonSubmit.classList.remove('button--loading');
+
+ return;
+ }
+
+ try {
+ const body: MyCustomerUpdateAction[] = [
+ {
+ action: 'setFirstName',
+ firstName: values.firstName,
+ },
+ {
+ action: 'setLastName',
+ lastName: values.lastName,
+ },
+ {
+ action: 'changeEmail',
+ email: values.email,
+ },
+ {
+ action: 'setDateOfBirth',
+ dateOfBirth: values.dateOfBirth,
+ },
+ ];
+ await updateUser(body);
+
+ new Notification('success', 'Account details is successfully updated!').showNotification();
+
+ this.buttonSubmit.classList.remove('button--loading');
+ this.buttonSubmit.classList.add('button--success');
+
+ setTimeout(() => {
+ this.onChangeModeCallback();
+ }, 500);
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+
+ this.buttonSubmit.disabled = false;
+ this.buttonSubmit.classList.remove('button--loading');
+ this.buttonSubmit.classList.remove('button--success');
+ }
+ }
+}
diff --git a/src/components/form/form.scss b/src/components/form/form.scss
new file mode 100644
index 0000000..b671eb2
--- /dev/null
+++ b/src/components/form/form.scss
@@ -0,0 +1,84 @@
+.form {
+ background: $color-bg-card;
+ border-radius: 8px;
+ padding: 64px;
+ display: flex;
+ flex-direction: column;
+
+ @include mobile {
+ padding: 32px;
+ }
+
+ @include small-mobile {
+ padding: 24px;
+ }
+
+ &__title {
+ @include font-h2;
+ margin-bottom: 12px;
+ }
+
+ &__subtitle {
+ color: $color-secondary-60;
+ margin-bottom: 32px;
+ }
+
+ &__form {
+ display: flex;
+ flex-direction: column;
+ gap: 32px;
+
+ &-block {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ }
+ }
+
+ &__content {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 32px;
+
+ @include tablet {
+ grid-template-columns: 1fr;
+ gap: 16px;
+ }
+ }
+
+ &__action {
+ display: flex;
+ align-items: center;
+ gap: 24px;
+
+ @include mobile {
+ flex-direction: column;
+ }
+ }
+
+ &--login {
+ width: min(544px, 100%);
+ }
+
+ &--details {
+ &__content {
+ @media (max-width: 1430px) {
+ grid-template-columns: 1fr;
+ }
+ }
+ }
+
+ &--password {
+ margin-top: 20px;
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 20px;
+ padding: 20px;
+ border-radius: 8px;
+ background-color: $color-bg-card;
+
+ @include mobile {
+ padding: 14px 8px;
+ }
+ }
+}
diff --git a/src/components/form/login-form.ts b/src/components/form/login-form.ts
new file mode 100644
index 0000000..b18bd57
--- /dev/null
+++ b/src/components/form/login-form.ts
@@ -0,0 +1,108 @@
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import InputField from '../input/input';
+import Link from '../link/link';
+import { ISigninData } from '../../types/interfaces';
+import { AppRoutesPath } from '../../router/types';
+import './form.scss';
+import signinUser from '../../services/signinUser';
+import Notification from '../notification/notification';
+import { changeUrlEvent } from '../../utils/change-url-event';
+import userStore from '../../store/user-store';
+
+export default class LoginForm extends BaseComponent<'div'> {
+ private formElement: HTMLFormElement;
+ private emailField: InputField;
+ private passwordField: InputField;
+ private buttonSubmit: HTMLButtonElement;
+
+ constructor() {
+ super('div', ['form', 'form--login']);
+
+ this.formElement = new BaseComponent('form', ['form__form']).getElement();
+ this.formElement.addEventListener('submit', (event) => this.onSubmit(event));
+
+ this.emailField = new InputField('email', 'email', 'Email', 'Email');
+ this.passwordField = new InputField('password', 'password', 'Password', 'Password');
+ this.buttonSubmit = new Button('submit', 'Log in').getElement();
+
+ this.createMarkup();
+ }
+
+ private createMarkup(): void {
+ const title = 'Welcome Back!';
+ const subTitle = 'Log In to access your account.';
+ const formTitle: HTMLHeadElement = new BaseComponent('h2', ['form__title'], title).getElement();
+ const formSubtitle: HTMLParagraphElement = new BaseComponent('p', ['form__subtitle'], subTitle).getElement();
+
+ const actionField: HTMLDivElement = new BaseComponent('div', ['form__action']).getElement();
+ const linkOnLogin: HTMLAnchorElement = new Link(
+ 'Create Account',
+ ['link--arrow'],
+ AppRoutesPath.SIGN_UP
+ ).getElement();
+
+ actionField.append(this.buttonSubmit, linkOnLogin);
+
+ const inputsBlock: HTMLDivElement = new BaseComponent('div', ['form__form-block']).getElement();
+
+ inputsBlock.append(this.emailField.getElement(), this.passwordField.getElement());
+
+ this.formElement.append(inputsBlock, actionField);
+
+ this.node.append(formTitle, formSubtitle, this.formElement);
+ }
+
+ private getLoginData(): ISigninData | undefined {
+ const email: string | undefined = this.emailField.getValue('email');
+ const password: string | undefined = this.passwordField.getValue('password');
+
+ if (!(email && password)) {
+ return;
+ }
+
+ return {
+ email,
+ password,
+ };
+ }
+
+ private async onSubmit(event: SubmitEvent): Promise {
+ event.preventDefault();
+
+ this.buttonSubmit.disabled = true;
+ this.buttonSubmit.classList.add('button--loading');
+
+ const values: ISigninData | undefined = this.getLoginData();
+
+ if (!values) {
+ this.buttonSubmit.disabled = false;
+ this.buttonSubmit.classList.remove('button--loading');
+
+ return;
+ }
+
+ try {
+ await signinUser(values);
+
+ const { customer } = userStore.getState();
+ const userFullName = `${customer?.firstName} ${customer?.lastName}`;
+ new Notification('success', `Hello, ${userFullName}!`).showNotification();
+
+ this.buttonSubmit.classList.remove('button--loading');
+ this.buttonSubmit.classList.add('button--success');
+
+ changeUrlEvent(AppRoutesPath.MAIN);
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+
+ this.buttonSubmit.disabled = false;
+ this.buttonSubmit.classList.remove('button--loading');
+ this.buttonSubmit.classList.remove('button--success');
+ }
+ }
+}
diff --git a/src/components/form/signup-form.ts b/src/components/form/signup-form.ts
new file mode 100644
index 0000000..46eb981
--- /dev/null
+++ b/src/components/form/signup-form.ts
@@ -0,0 +1,197 @@
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import InputField from '../input/input';
+import Link from '../link/link';
+import signupUser from '../../services/signupUser';
+import Notification from '../notification/notification';
+import { signupInputs } from '../../constants/signupInputs';
+import { IAddress, InputFilds, ISignupData } from '../../types/interfaces';
+import { AppRoutesPath } from '../../router/types';
+import { changeUrlEvent } from '../../utils/change-url-event';
+import './form.scss';
+
+export default class SignupForm extends BaseComponent<'div'> {
+ private formElement: HTMLFormElement;
+ private inputs: InputFilds;
+ private checkboxAddress: boolean;
+ private isDefaultShipping: boolean;
+ private isDefaultBilling: boolean;
+ private buttonSubmit: HTMLButtonElement;
+
+ constructor() {
+ super('div', ['form']);
+ this.formElement = new BaseComponent('form', ['form__form']).getElement();
+ this.inputs = {};
+ this.checkboxAddress = false;
+ this.isDefaultShipping = false;
+ this.isDefaultBilling = false;
+ this.formElement.addEventListener('submit', (event) => this.onSubmit(event));
+ this.buttonSubmit = new Button('submit', 'Create Account').getElement();
+ this.createMarkup();
+ }
+
+ private createMarkup(): void {
+ const title = 'Create Account';
+ const subTitle = 'Create a new account & experience our services.';
+ const formTitle: HTMLHeadElement = new BaseComponent('h2', ['form__title'], title).getElement();
+ const formSubtitle: HTMLParagraphElement = new BaseComponent('p', ['form__subtitle'], subTitle).getElement();
+
+ const actionField: HTMLDivElement = new BaseComponent('div', ['form__action']).getElement();
+ const linkOnLogin: HTMLAnchorElement = new Link('Log In', ['link--arrow'], AppRoutesPath.LOGIN).getElement();
+ actionField.append(this.buttonSubmit, linkOnLogin);
+
+ const formContent: HTMLDivElement = new BaseComponent('div', ['form__content']).getElement();
+ const infoInputsBlock: HTMLDivElement = new BaseComponent('div', ['form__form-block']).getElement();
+ const addressesBlock: HTMLDivElement = new BaseComponent('div', ['form__form-block']).getElement();
+
+ const infoInputs = signupInputs['infoInputs'].map(({ type, name, placeholder, label }) => {
+ const inputField: InputField = new InputField(type, name, placeholder, label);
+ this.inputs[name] = inputField;
+ return inputField.getElement();
+ });
+
+ const addressInputs = signupInputs['addressInputs'].map(({ type, name, placeholder, label }) => {
+ const inputField = new InputField(type, name, placeholder, label);
+
+ if (name === 'checkboxAddress') {
+ inputField.getElement().addEventListener('change', () => this.toggleBillingAddress());
+ }
+
+ if (name === 'checkboxDefaultShipping') {
+ inputField.getElement().addEventListener('change', () => {
+ this.isDefaultShipping = !this.isDefaultShipping;
+ });
+ }
+
+ if (name === 'checkboxDefaultBilling') {
+ inputField.getElement().addEventListener('change', () => {
+ this.isDefaultBilling = !this.isDefaultBilling;
+ });
+ }
+
+ this.inputs[name] = inputField;
+
+ return inputField.getElement();
+ });
+
+ infoInputsBlock.append(...infoInputs);
+ addressesBlock.append(...addressInputs);
+ formContent.append(infoInputsBlock, addressesBlock);
+
+ this.formElement.append(formContent, actionField);
+ this.node.append(formTitle, formSubtitle, this.formElement);
+ }
+
+ private toggleBillingAddress(): void {
+ this.inputs['streetBilling'].getElement().classList.toggle('form-field--hidden');
+ this.inputs['cityBilling'].getElement().classList.toggle('form-field--hidden');
+ this.inputs['postcodeBilling'].getElement().classList.toggle('form-field--hidden');
+
+ this.checkboxAddress = !this.checkboxAddress;
+ }
+
+ private getShippingAddress(): IAddress | undefined {
+ const streetShipping: string | undefined = this.inputs['streetShipping'].getValue('streetShipping');
+ const cityShipping: string | undefined = this.inputs['cityShipping'].getValue('cityShipping');
+ const postcodeShipping: string | undefined = this.inputs['postcodeShipping'].getValue('postcodeShipping');
+
+ if (!(streetShipping && cityShipping && postcodeShipping)) {
+ return;
+ }
+
+ return {
+ key: 'shipping',
+ country: 'US',
+ streetName: streetShipping,
+ city: cityShipping,
+ postalCode: postcodeShipping,
+ };
+ }
+
+ private getBillingAddress(): IAddress | undefined {
+ const streetBilling: string | undefined = this.inputs['streetBilling'].getValue('streetBilling');
+ const cityBilling: string | undefined = this.inputs['cityBilling'].getValue('cityBilling');
+ const postcodeBilling: string | undefined = this.inputs['postcodeBilling'].getValue('postcodeBilling');
+
+ if (!(streetBilling && cityBilling && postcodeBilling && !this.checkboxAddress)) {
+ return;
+ }
+
+ return {
+ key: 'billing',
+ country: 'US',
+ streetName: streetBilling,
+ city: cityBilling,
+ postalCode: postcodeBilling,
+ };
+ }
+
+ private getSignupData(): ISignupData | undefined {
+ const firstName: string | undefined = this.inputs['firstName'].getValue('firstName');
+ const lastName: string | undefined = this.inputs['lastName'].getValue('lastName');
+ const email: string | undefined = this.inputs['email'].getValue('email');
+ const password: string | undefined = this.inputs['password'].getValue('password');
+ const dateOfBirth: string | undefined = this.inputs['birthDate'].getValue('birthDate');
+ const shippingAddress: IAddress | undefined = this.getShippingAddress();
+ const billingAddress: IAddress | undefined = this.getBillingAddress();
+
+ if (!(firstName && lastName && email && password && dateOfBirth && shippingAddress)) {
+ return;
+ }
+
+ const addresses: IAddress[] = [shippingAddress];
+
+ if (!this.checkboxAddress) {
+ if (!billingAddress) return;
+ addresses.push(billingAddress);
+ }
+
+ return {
+ firstName,
+ lastName,
+ email,
+ password,
+ dateOfBirth,
+ addresses,
+ shippingAddresses: [0],
+ billingAddresses: [billingAddress ? 1 : 0],
+ ...(this.isDefaultShipping ? { defaultShippingAddress: 0 } : {}),
+ ...(this.isDefaultBilling ? { defaultBillingAddress: billingAddress ? 1 : 0 } : {}),
+ };
+ }
+
+ private async onSubmit(event: SubmitEvent): Promise {
+ event.preventDefault();
+ this.buttonSubmit.disabled = true;
+ this.buttonSubmit.classList.add('button--loading');
+
+ const values: ISignupData | undefined = this.getSignupData();
+
+ if (!values) {
+ this.buttonSubmit.disabled = false;
+ this.buttonSubmit.classList.remove('button--loading');
+ return;
+ }
+
+ try {
+ await signupUser(values);
+
+ new Notification('success', 'Registration completed successfully').showNotification();
+
+ this.buttonSubmit.classList.remove('button--loading');
+ this.buttonSubmit.classList.add('button--success');
+
+ changeUrlEvent(AppRoutesPath.MAIN);
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+
+ this.buttonSubmit.disabled = false;
+ this.buttonSubmit.classList.remove('button--loading');
+ this.buttonSubmit.classList.remove('button--success');
+ }
+ }
+}
diff --git a/src/components/header/burger-menu/burger-menu.scss b/src/components/header/burger-menu/burger-menu.scss
new file mode 100644
index 0000000..c74564c
--- /dev/null
+++ b/src/components/header/burger-menu/burger-menu.scss
@@ -0,0 +1,53 @@
+.burger-menu {
+ display: none;
+ flex-direction: column;
+ justify-content: space-between;
+ width: 20px;
+ height: 15px;
+ transition: all 0.2 ease;
+ z-index: 100;
+
+ & div {
+ width: 100%;
+ height: 2px;
+ background-color: $color-primary;
+ transition: all 0.3s ease;
+ }
+
+ &_opened {
+ & > div {
+ background-color: $color-logo;
+ }
+
+ & > div:nth-child(2) {
+ opacity: 0;
+ }
+
+ & > div:nth-child(1) {
+ transform: translateY(6.5px) rotate(-45deg);
+ }
+
+ & > div:nth-child(3) {
+ transform: translateY(-6.5px) rotate(45deg);
+ }
+ }
+
+ @include tablet {
+ display: flex;
+ }
+}
+
+body {
+ & .blur {
+ position: absolute;
+ content: '';
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ display: block;
+ background-color: rgba(0, 0, 0, 0.4);
+ z-index: 10;
+ overflow: hidden;
+ }
+}
diff --git a/src/components/header/burger-menu/burger-menu.ts b/src/components/header/burger-menu/burger-menu.ts
new file mode 100644
index 0000000..6fff06a
--- /dev/null
+++ b/src/components/header/burger-menu/burger-menu.ts
@@ -0,0 +1,48 @@
+import './burger-menu.scss';
+import BaseComponent from '../../base-component';
+
+export default class BurgerMenu extends BaseComponent<'div'> {
+ private isOpenMenu: boolean;
+ private blur: HTMLDivElement;
+ private headerMenu: HTMLElement;
+
+ constructor(headerMenu: HTMLElement) {
+ super('div', ['burger-menu']);
+
+ this.blur = new BaseComponent<'div'>('div', ['blur']).getElement();
+ this.drawBurgerMenu();
+ this.headerMenu = headerMenu;
+ this.isOpenMenu = false;
+
+ this.node.onclick = () => {
+ this.toggleBurgerMenu();
+ };
+
+ this.blur.onclick = () => {
+ this.toggleBurgerMenu();
+ };
+ }
+
+ private drawBurgerMenu(): void {
+ for (let i = 0; i < 3; i++) {
+ const line = new BaseComponent<'div'>('div', ['burger-menu__line']).getElement();
+ this.node.append(line);
+ }
+ }
+
+ private toggleBurgerMenu(): void {
+ this.isOpenMenu = !this.isOpenMenu;
+
+ if (this.isOpenMenu) {
+ document.body.append(this.blur);
+ document.body.classList.add('hidden');
+ this.headerMenu.classList.add('header__menu_opened');
+ this.node.classList.add('burger-menu_opened');
+ } else {
+ this.blur.remove();
+ document.body.removeAttribute('class');
+ this.headerMenu.classList.remove('header__menu_opened');
+ this.node.classList.remove('burger-menu_opened');
+ }
+ }
+}
diff --git a/src/components/header/header-nav/header-nav.scss b/src/components/header/header-nav/header-nav.scss
new file mode 100644
index 0000000..4e59ad5
--- /dev/null
+++ b/src/components/header/header-nav/header-nav.scss
@@ -0,0 +1,124 @@
+.header {
+ @include tablet {
+ position: relative;
+ }
+
+ &__menu {
+ background-color: white;
+
+ @include tablet {
+ & {
+ position: fixed;
+ top: 0;
+ right: -400px;
+ width: 320px;
+ height: 100vh;
+ z-index: 20;
+ transition: right 0.3s ease;
+ }
+
+ &_opened {
+ position: absolute;
+ right: 0;
+ }
+ }
+ }
+
+ &__list {
+ position: relative;
+ display: flex;
+ gap: 54px;
+
+ @include tablet {
+ top: 80px;
+ width: 100%;
+ flex-direction: column;
+ gap: 0;
+ background-color: white;
+ width: 320px;
+ z-index: 20;
+ }
+ }
+
+ &__item {
+ position: relative;
+ display: inline-block;
+ transition: all 0.2s ease;
+
+ & > a,
+ &:after {
+ @include tablet {
+ display: block;
+ padding: 5px 50px;
+ font-size: 20px;
+ }
+ }
+
+ &:hover {
+ &:after,
+ & > a {
+ opacity: 0.6;
+ }
+ }
+
+ &_with-submenu {
+ &:after {
+ @include chevron;
+ top: calc(50% - 10px);
+ right: -20px;
+ cursor: pointer;
+ transform: rotate(180deg);
+
+ @include tablet {
+ display: none;
+ }
+ }
+
+ &:hover {
+ &:after {
+ transform: rotate(0);
+ }
+ }
+ }
+
+ & .dropdown-menu {
+ padding: 12px 0;
+ width: 140px;
+
+ @include tablet {
+ position: static;
+ width: 100%;
+ padding: 0;
+ box-shadow: none;
+ opacity: 0.5;
+
+ &_closed {
+ display: block;
+ }
+ }
+
+ & .header__link {
+ display: inline-block;
+ width: 100%;
+ padding: 12px 20px;
+
+ &:hover {
+ background-color: $color-gray;
+ }
+
+ @include tablet {
+ padding: 0;
+ width: 100%;
+ padding: 5px 70px;
+ }
+ }
+ }
+ }
+
+ &__bridge {
+ @include tablet {
+ display: block;
+ right: 0;
+ }
+ }
+}
diff --git a/src/components/header/header-nav/header-nav.ts b/src/components/header/header-nav/header-nav.ts
new file mode 100644
index 0000000..ab16ed0
--- /dev/null
+++ b/src/components/header/header-nav/header-nav.ts
@@ -0,0 +1,91 @@
+import './header-nav.scss';
+import BaseComponent from '../../base-component';
+import menuItems from './menu-items';
+import { IMenuItems } from '../../../types/types';
+import Link from '../../link/link';
+
+export default class HeaderNav extends BaseComponent<'nav'> {
+ private list: HTMLUListElement;
+
+ constructor() {
+ super('nav', ['header__menu']);
+
+ this.list = this.createHeaderList(menuItems);
+
+ this.node.append(this.list);
+ }
+
+ private createHeaderList(menuItems: IMenuItems[] = []): HTMLUListElement {
+ const headerList: HTMLUListElement = new BaseComponent<'ul'>('ul', ['header__list']).getElement();
+
+ menuItems.forEach((item) => {
+ const headerItem: HTMLLIElement = this.createListItem(item, [
+ 'header__item',
+ item['innerItems'] ? 'header__item_with-submenu' : 'header__item_empty',
+ ]);
+
+ const { innerItems }: IMenuItems = item;
+
+ if (innerItems) {
+ const bridge: HTMLDivElement = new BaseComponent<'div'>('div', ['header__bridge']).getElement();
+ const dropdownMenu: HTMLUListElement = new BaseComponent<'ul'>('ul', [
+ 'dropdown-menu',
+ 'dropdown-menu_closed',
+ ]).getElement();
+
+ innerItems.forEach((innerItem) => {
+ const innerListItem: HTMLLIElement = this.createListItem(innerItem, ['item__inner-item']);
+
+ dropdownMenu.append(innerListItem);
+
+ headerItem.append(bridge);
+
+ headerItem.append(dropdownMenu);
+
+ headerItem.onmouseenter = (event) => {
+ if (event.target instanceof HTMLElement) this.showInnerList(event.target);
+ };
+
+ headerItem.onmouseleave = (event) => {
+ if (event.target instanceof HTMLElement) this.hideInnerList(event.target);
+ };
+ });
+ }
+
+ headerList.append(headerItem);
+ });
+
+ return headerList;
+ }
+
+ private createListItem(menuItem: IMenuItems, classNames: string[]): HTMLLIElement {
+ const listItem: HTMLLIElement = new BaseComponent<'li'>('li', [...classNames]).getElement();
+ const itemLink: HTMLAnchorElement = new Link(menuItem.title, ['header__link'], menuItem.href).getElement();
+
+ listItem.append(itemLink);
+
+ return listItem;
+ }
+
+ private showInnerList(element: HTMLElement): void {
+ const classClosed = 'dropdown-menu_closed';
+ const classOpened = 'dropdown-menu_opened';
+ const dropdownMenu = element.querySelector(`.${classClosed}`);
+
+ if (dropdownMenu) {
+ dropdownMenu.classList.remove(classClosed);
+ dropdownMenu.classList.add(classOpened);
+ }
+ }
+
+ private hideInnerList(element: HTMLElement): void {
+ const classClosed = 'dropdown-menu_closed';
+ const classOpened = 'dropdown-menu_opened';
+ const dropdownMenu = element.querySelector(`.${classOpened}`);
+
+ if (dropdownMenu) {
+ dropdownMenu.classList.remove(classOpened);
+ dropdownMenu.classList.add(classClosed);
+ }
+ }
+}
diff --git a/src/components/header/header-nav/menu-items.ts b/src/components/header/header-nav/menu-items.ts
new file mode 100644
index 0000000..241f7dd
--- /dev/null
+++ b/src/components/header/header-nav/menu-items.ts
@@ -0,0 +1,51 @@
+import { AppRoutesPath } from '../../../router/types';
+import { IMenuItems } from '../../../types/types';
+
+const menuItems: IMenuItems[] = [
+ {
+ title: 'Shop',
+ href: AppRoutesPath.SHOP,
+ innerItems: [
+ {
+ title: 'Shop All',
+ href: AppRoutesPath.SHOP,
+ },
+ {
+ title: 'Best Sellers',
+ href: AppRoutesPath.SHOP,
+ },
+ {
+ title: 'New Tours',
+ href: AppRoutesPath.SHOP,
+ },
+ ],
+ },
+ {
+ title: 'Categories',
+ href: AppRoutesPath.SHOP,
+ innerItems: [
+ {
+ title: 'Europe',
+ href: '/shop/europe',
+ },
+ {
+ title: 'Asia',
+ href: '/shop/asia',
+ },
+ {
+ title: 'America',
+ href: '/shop/america',
+ },
+ {
+ title: 'Africa',
+ href: '/shop/africa',
+ },
+ ],
+ },
+ {
+ title: 'About Us',
+ href: AppRoutesPath.ABOUT_US,
+ },
+];
+
+export default menuItems;
diff --git a/src/components/header/header-user/header-user.scss b/src/components/header/header-user/header-user.scss
new file mode 100644
index 0000000..c5fe444
--- /dev/null
+++ b/src/components/header/header-user/header-user.scss
@@ -0,0 +1,122 @@
+.header {
+ &__user {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ margin-left: auto;
+ }
+
+ &__user-account {
+ position: relative;
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ height: 100%;
+ transition: all 0.2s ease;
+ cursor: pointer;
+
+ &:hover > .user-account__title {
+ opacity: 0.6;
+ }
+
+ .user-account {
+ &__title {
+ opacity: 1;
+ user-select: none;
+ cursor: unset;
+ max-width: 150px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ transition: opacity 0.2s ease;
+
+ @include tablet {
+ display: none;
+ }
+
+ @include mobile {
+ display: none;
+ }
+ }
+
+ &__icon {
+ @include account-icon;
+
+ &_authorized {
+ width: 1.5rem;
+ height: 1.5rem;
+ background: salmon;
+ border-radius: 100%;
+ }
+ }
+ }
+
+ .dropdown-menu {
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 16px;
+ padding: 12px 20px 24px;
+
+ @include tablet {
+ top: 35px;
+ right: 0;
+ }
+
+ &_opened {
+ display: flex;
+ }
+
+ &__button {
+ padding: 16px 40px;
+ white-space: nowrap;
+ }
+
+ &__link {
+ white-space: nowrap;
+ }
+ }
+ }
+
+ &__user-cart {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding-left: 16px;
+ border-left: 2px solid $color-border;
+ gap: 4px;
+ height: 100%;
+ padding-left: 16px;
+
+ .user-cart {
+ &__icon {
+ @include cart-icon;
+ }
+
+ &__counter {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 25px;
+ width: 25px;
+ background-color: $color-gray;
+ color: $color-primary;
+ border-radius: 100%;
+ pointer-events: none;
+
+ @include mobile {
+ position: absolute;
+ transform: scale(0.7);
+ top: -10px;
+ right: -10px;
+ }
+ }
+ }
+
+ @include mobile {
+ padding: 0;
+ border: 0;
+ }
+ }
+}
diff --git a/src/components/header/header-user/header-user.ts b/src/components/header/header-user/header-user.ts
new file mode 100644
index 0000000..65c7921
--- /dev/null
+++ b/src/components/header/header-user/header-user.ts
@@ -0,0 +1,132 @@
+import BaseComponent from '../../base-component';
+import Button from '../../button/button';
+import Link from '../../link/link';
+import { AppRoutesPath } from '../../../router/types';
+import { changeUrlEvent } from '../../../utils/change-url-event';
+import userStore from '../../../store/user-store';
+import userLogout from '../../../services/userLogout';
+import './header-user.scss';
+import cartStore from '../../../store/cart-store';
+
+export default class HeaderUser extends BaseComponent<'div'> {
+ private account: HTMLDivElement;
+ private dropdownMenu: HTMLDivElement;
+ private cart: HTMLAnchorElement;
+ private accountIcon: HTMLSpanElement;
+ private accountTitle: HTMLParagraphElement;
+ private loginBtn: HTMLButtonElement;
+ private createAccountBtn: HTMLAnchorElement;
+ private logoutBtn: HTMLButtonElement;
+ private profileBtn: HTMLAnchorElement;
+ private bridge: HTMLDivElement;
+ private cartCounter: HTMLDivElement;
+
+ constructor() {
+ super('div', ['header__user']);
+
+ this.account = new BaseComponent<'div'>('div', ['header__user-account']).getElement();
+ this.accountIcon = new BaseComponent<'span'>('span', ['user-account__icon']).getElement();
+ this.accountTitle = new BaseComponent<'p'>('p', ['user-account__title'], 'Account').getElement();
+ this.dropdownMenu = new BaseComponent<'div'>('div', ['dropdown-menu', 'dropdown-menu_closed']).getElement();
+ this.profileBtn = new Link(
+ 'My profile',
+ ['link--unset', 'dropdown-menu__link'],
+ AppRoutesPath.ACCOUNT
+ ).getElement();
+ this.loginBtn = new Button('button', 'Log In', ['dropdown-menu__button'], false, () =>
+ changeUrlEvent(AppRoutesPath.LOGIN)
+ ).getElement();
+ this.createAccountBtn = new Link(
+ 'Create Account',
+ ['link--arrow', 'dropdown-menu__link'],
+ AppRoutesPath.SIGN_UP
+ ).getElement();
+
+ this.logoutBtn = new Button('button', 'Log Out', ['dropdown-menu__button'], false, () => {
+ userLogout();
+ changeUrlEvent(AppRoutesPath.MAIN);
+ }).getElement();
+
+ this.bridge = new BaseComponent('div', ['header__bridge']).getElement();
+
+ this.drawAccount(userStore.getState().isAuth);
+
+ this.cartCounter = new BaseComponent<'div'>('div', ['user-cart__counter'], '0').getElement();
+ this.cart = this.drawCart();
+
+ this.node.append(this.account, this.cart);
+
+ this.setListeners();
+ this.addSubscribtion();
+ }
+
+ private drawAccount(isAuth: boolean): void {
+ if (isAuth) {
+ const userName = `${userStore.getState().customer?.firstName}`;
+
+ this.accountIcon.classList.add('user-account__icon_authorized');
+ this.accountIcon.textContent = `${userName[0]}`;
+ this.accountTitle.textContent = userName;
+
+ this.dropdownMenu.innerHTML = '';
+ this.dropdownMenu.append(this.profileBtn, this.logoutBtn);
+ } else {
+ this.accountIcon.classList.remove('user-account__icon_authorized');
+ this.accountIcon.textContent = '';
+ this.accountTitle.textContent = 'Account';
+
+ this.dropdownMenu.innerHTML = '';
+ this.dropdownMenu.append(this.loginBtn, this.createAccountBtn);
+ }
+
+ this.account.innerHTML = '';
+ this.account.append(this.accountIcon, this.accountTitle, this.bridge, this.dropdownMenu);
+ }
+
+ private setListeners(): void {
+ this.account.addEventListener('click', () => this.onOpenDropdownMenu());
+ this.account.addEventListener('mouseenter', () => this.onOpenDropdownMenu());
+ this.account.addEventListener('mouseleave', () => this.onCloseDropdownMenu());
+ }
+
+ private closeDropdownOnMobile(event: TouchEvent): void {
+ if (this.dropdownMenu.classList.contains('dropdown-menu_opened')) {
+ if (event.target instanceof HTMLElement) {
+ if (this.account && event.target !== this.account && !event.target.closest('.header__user-account')) {
+ this.onCloseDropdownMenu();
+ }
+ }
+ }
+ }
+
+ private onOpenDropdownMenu(): void {
+ this.dropdownMenu.classList.remove('dropdown-menu_closed');
+ this.dropdownMenu.classList.add('dropdown-menu_opened');
+
+ document.body?.addEventListener('touchstart', (event) => this.closeDropdownOnMobile(event));
+ }
+
+ private onCloseDropdownMenu(): void {
+ this.dropdownMenu.classList.remove('dropdown-menu_opened');
+ this.dropdownMenu.classList.add('dropdown-menu_closed');
+
+ document.body?.removeEventListener('touchstart', (event) => this.closeDropdownOnMobile(event));
+ }
+
+ private drawCart(): HTMLAnchorElement {
+ const cart: HTMLAnchorElement = new Link('', ['header__user-cart'], AppRoutesPath.BASKET).getElement();
+ const cartIcon: HTMLDivElement = new BaseComponent<'div'>('div', ['user-cart__icon']).getElement();
+
+ cart.append(cartIcon, this.cartCounter);
+
+ return cart;
+ }
+
+ private addSubscribtion(): void {
+ userStore.subscribe((state) => this.drawAccount(state.isAuth));
+
+ cartStore.subscribe((state) => {
+ this.cartCounter.textContent = state.cart?.totalLineItemQuantity ? String(state.cart.totalLineItemQuantity) : '0';
+ });
+ }
+}
diff --git a/src/components/header/header.scss b/src/components/header/header.scss
new file mode 100644
index 0000000..f127b8f
--- /dev/null
+++ b/src/components/header/header.scss
@@ -0,0 +1,55 @@
+.header {
+ height: 80px;
+ border-bottom: 1px solid rgba(0, 19, 41, 0.12);
+
+ &__container {
+ @include container;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ gap: 64px;
+ height: 100%;
+
+ @include tablet {
+ justify-content: space-between;
+ gap: 20px;
+ }
+ }
+
+ &__link {
+ color: $color-primary;
+ transition: all 0.2s ease;
+ }
+
+ &__bridge {
+ position: absolute;
+ top: 20px;
+ width: calc(100% + 20px);
+ height: 15px;
+ z-index: 0;
+
+ @include tablet {
+ display: none;
+ }
+ }
+
+ .dropdown-menu {
+ position: absolute;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ top: 35px;
+ border-radius: 8px;
+ background: $color-white;
+ box-shadow: 0px 0px 40px 0px rgba(0, 0, 0, 0.08);
+ z-index: 2;
+
+ &_closed {
+ display: none;
+ }
+
+ &_opened {
+ display: block;
+ }
+ }
+}
diff --git a/src/components/header/header.ts b/src/components/header/header.ts
new file mode 100644
index 0000000..a8ebe51
--- /dev/null
+++ b/src/components/header/header.ts
@@ -0,0 +1,30 @@
+import './header.scss';
+import BaseComponent from '../base-component';
+import HeaderNav from './header-nav/header-nav';
+import HeaderUser from './header-user/header-user';
+import Logo from '../logo/logo';
+import BurgerMenu from './burger-menu/burger-menu';
+
+export default class Header extends BaseComponent<'header'> {
+ private container: HTMLDivElement;
+
+ constructor() {
+ super('header', ['header']);
+
+ this.container = this.createMarkup();
+
+ this.node.append(this.container);
+ }
+
+ private createMarkup(): HTMLDivElement {
+ const container: HTMLDivElement = new BaseComponent<'div'>('div', ['header__container']).getElement();
+ const headerLogo: HTMLHeadingElement = new Logo().getElement();
+ const navigation: HTMLElement = new HeaderNav().getElement();
+ const userWrapper: HTMLDivElement = new HeaderUser().getElement();
+ const burgerMenu: HTMLDivElement = new BurgerMenu(navigation).getElement();
+
+ container.append(headerLogo, navigation, userWrapper, burgerMenu);
+
+ return container;
+ }
+}
diff --git a/src/components/input/input.scss b/src/components/input/input.scss
new file mode 100644
index 0000000..284712b
--- /dev/null
+++ b/src/components/input/input.scss
@@ -0,0 +1,109 @@
+.form-field {
+ display: flex;
+ flex-direction: column;
+
+ &__label {
+ font: $font-label;
+ color: $color-primary;
+ margin-bottom: 8px;
+ }
+
+ &__input {
+ padding: 10px 24px;
+ height: 48px;
+ width: 100%;
+ font: $font-main;
+ color: $color-primary;
+ background: $color-white;
+ border: 1px solid $color-white;
+ border-radius: 6px;
+ transition:
+ color 0.3s ease-in-out,
+ border 0.3s ease-in-out;
+
+ &:focus,
+ &:hover {
+ border: 1px solid $color-border;
+ }
+
+ &.valid-error {
+ border: 1px solid $color-error;
+ color: $color-error;
+ }
+
+ &::placeholder {
+ opacity: 0.4;
+ }
+
+ &:disabled {
+ opacity: 0.6;
+ border: 1px solid $color-white;
+ }
+
+ @include small-mobile {
+ padding: 10px 14px;
+ }
+ }
+
+ &-password {
+ position: relative;
+
+ .form-field__input {
+ padding-right: 46px;
+ }
+ }
+
+ &__check {
+ position: absolute;
+ right: 24px;
+ top: 44.5px;
+ width: 20px;
+ height: 20px;
+ background-image: url('../../assets/icons/visibility.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ cursor: pointer;
+
+ @include small-mobile {
+ right: 14px;
+ }
+
+ &.password-visible {
+ background-image: url('../../assets/icons/visibility-off.svg');
+ }
+ }
+
+ &__error {
+ margin-top: 4px;
+ font-size: 14px;
+ color: $color-error;
+ }
+
+ &-checkbox {
+ flex-direction: row-reverse;
+ align-items: center;
+ justify-content: flex-end;
+
+ input {
+ cursor: pointer;
+ width: auto;
+ }
+
+ .form-field__label {
+ margin: 0 0 0 8px;
+ }
+ }
+
+ &-country {
+ &::after {
+ content: '* currently, the shop only operates in the USA';
+ color: $color-secondary-60;
+ margin-top: 8px;
+ }
+ }
+
+ &--hidden {
+ display: none;
+ }
+}
diff --git a/src/components/input/input.test.ts b/src/components/input/input.test.ts
new file mode 100644
index 0000000..779394f
--- /dev/null
+++ b/src/components/input/input.test.ts
@@ -0,0 +1,29 @@
+import Input from './input';
+
+describe('Input', () => {
+ const inputComponent: Input = new Input('password', 'Test Input', 'Test Placeholder', 'Test Label', [
+ 'input-test-class',
+ ]);
+
+ it('should render correct html', () => {
+ const expectedHTML: string =
+ '';
+
+ expect(inputComponent.getElement().outerHTML).toContain(expectedHTML);
+ });
+
+ it('should render correct textContent', () => {
+ const label: HTMLElement | null = inputComponent.getElement().querySelector('.form-field__label');
+ expect(label?.textContent).toBe('Test Label');
+ });
+
+ it('should render correct textContent', () => {
+ const input: HTMLInputElement | null = inputComponent.getElement().querySelector('input');
+ expect(input?.getAttribute('type')).toBe('password');
+ });
+
+ it('should render correct textContent', () => {
+ const input: HTMLInputElement | null = inputComponent.getElement().querySelector('input');
+ expect(input?.getAttribute('placeholder')).toBe('Test Placeholder');
+ });
+});
diff --git a/src/components/input/input.ts b/src/components/input/input.ts
new file mode 100644
index 0000000..67518a8
--- /dev/null
+++ b/src/components/input/input.ts
@@ -0,0 +1,116 @@
+import BaseComponent from '../base-component';
+import formValidationRules from '../../constants/formValidationRules';
+import './input.scss';
+
+export default class InputField extends BaseComponent<'div'> {
+ private labelElement: HTMLLabelElement;
+ private inputElement: HTMLInputElement;
+ private errorElement: HTMLSpanElement;
+
+ constructor(
+ type: string = 'text',
+ name: string = '',
+ placeholder: string = '',
+ label: string = '',
+ classes: string[] = []
+ ) {
+ super('div', ['form-field', ...classes]);
+
+ this.labelElement = new BaseComponent('label', ['form-field__label'], label).getElement();
+ this.inputElement = new BaseComponent('input', ['form-field__input']).getElement();
+ this.errorElement = new BaseComponent('span', ['form-field__error']).getElement();
+
+ this.setAttributes(type, name, placeholder);
+
+ if (type === 'date') this.addMinMaxForInputDate();
+ if (type === 'password') this.createPasswordCheckbox();
+ if (type === 'checkbox') this.node.classList.add('form-field-checkbox');
+ if (name === 'country') this.createCountryField();
+
+ this.node.append(this.labelElement, this.inputElement);
+ }
+
+ public getValue(inputName: keyof typeof formValidationRules, comparisonValues?: string): string | undefined {
+ const regex: RegExp = formValidationRules[inputName]?.rule;
+
+ if (regex && !regex.test(this.inputElement.value.trim())) {
+ this.showError(inputName);
+ this.inputElement.addEventListener('input', () => this.clearError());
+
+ return;
+ }
+
+ if (inputName === 'newPassword' && this.inputElement.value === comparisonValues) {
+ this.showError(inputName, true);
+ this.inputElement.addEventListener('input', () => this.clearError());
+
+ return;
+ }
+
+ this.inputElement.removeEventListener('input', () => this.clearError());
+
+ return this.inputElement.value.trim();
+ }
+
+ public setChecked(isChecked: boolean = false): void {
+ this.inputElement.checked = isChecked;
+ }
+
+ public setValue(value: string): void {
+ this.inputElement.value = value;
+ }
+
+ public setAttribute(name: string, value: string): void {
+ this.inputElement.setAttribute(name, value);
+ }
+
+ private setAttributes(type: string = 'text', name: string = '', placeholder: string = ''): void {
+ this.inputElement.type = type;
+ this.inputElement.name = name;
+ this.inputElement.id = name;
+ this.inputElement.placeholder = placeholder;
+ this.labelElement.setAttribute('for', name);
+ }
+
+ private createCountryField(): void {
+ this.node.classList.add('form-field-country');
+ this.inputElement.value = 'US';
+ this.inputElement.disabled = true;
+ }
+
+ private addMinMaxForInputDate(): void {
+ this.inputElement.min = '1900-01-01';
+ const thirteenYearsAgo: Date = new Date(new Date().setFullYear(new Date().getFullYear() - 13));
+ const formattedDate: string = `${thirteenYearsAgo.getFullYear()}-${(thirteenYearsAgo.getMonth() + 1)
+ .toString()
+ .padStart(2, '0')}-${thirteenYearsAgo.getDate().toString().padStart(2, '0')}`;
+ this.inputElement.max = formattedDate;
+ }
+
+ private showError(inputName: keyof typeof formValidationRules, isConfirm: boolean = false): void {
+ this.inputElement.classList.add('valid-error');
+ this.errorElement.textContent = isConfirm
+ ? formValidationRules[inputName].secondErrorText || ''
+ : formValidationRules[inputName].errorText;
+ this.node.append(this.errorElement);
+ }
+
+ private clearError(): void {
+ this.inputElement.classList.remove('valid-error');
+ this.errorElement.textContent = '';
+ this.errorElement.remove();
+ }
+
+ private createPasswordCheckbox(): void {
+ this.node.classList.add('form-field-password');
+
+ const checkboxBlock: HTMLDivElement = new BaseComponent('div', ['form-field__check']).getElement();
+
+ checkboxBlock.addEventListener('click', () => {
+ this.inputElement.type = this.inputElement.type === 'password' ? 'text' : 'password';
+ checkboxBlock.classList.toggle('password-visible');
+ });
+
+ this.node.append(checkboxBlock);
+ }
+}
diff --git a/src/components/link/link.scss b/src/components/link/link.scss
new file mode 100644
index 0000000..1547a49
--- /dev/null
+++ b/src/components/link/link.scss
@@ -0,0 +1,109 @@
+.link {
+ &--breadcrumbs {
+ font: $font-xs;
+ color: $color-secondary-40;
+ transition: color 0.3s ease-in-out;
+ white-space: nowrap;
+
+ &::after {
+ content: '/';
+ margin-left: 6px;
+ }
+
+ &:hover {
+ color: $color-secondary-60;
+ }
+ }
+
+ &--arrow,
+ &--unset {
+ font: $font-button;
+ display: flex;
+ align-items: center;
+ position: relative;
+ transition:
+ border 0.3s ease-in-out,
+ color 0.3s ease-in-out,
+ opacity 0.3s ease-in-out;
+
+ &::after {
+ content: '';
+ display: inline-block;
+ margin-left: 6px;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ transition: transform 0.3s ease-in-out;
+ }
+ }
+
+ &--arrow {
+ color: $color-button;
+ &::after {
+ width: 8px;
+ height: 8px;
+ background-image: url('../../assets/icons/link-arrow.svg');
+ }
+
+ &::before {
+ content: '';
+ position: absolute;
+ width: 100%;
+ height: 1px;
+ background: $color-button;
+ left: 0;
+ bottom: -4px;
+ transition: width 0.2s ease-in-out;
+ }
+
+ &:hover,
+ &:active {
+ color: $color-button-hover;
+
+ &::after {
+ transform: rotate(45deg);
+ }
+
+ &::before {
+ width: 0;
+ }
+ }
+ }
+
+ &--unset {
+ color: unset;
+ opacity: 0.5;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+
+ &--return {
+ position: relative;
+ font: $font-button;
+ color: $color-secondary-40;
+ transition: all 0.3s ease-in-out;
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ color: $color-secondary-60;
+
+ &::after {
+ background: $color-secondary-60;
+ width: 0;
+ }
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ width: 100%;
+ height: 1px;
+ left: 0;
+ bottom: -1px;
+ background: $color-secondary-40;
+ transition: all 0.3s ease-in-out;
+ }
+ }
+}
diff --git a/src/components/link/link.test.ts b/src/components/link/link.test.ts
new file mode 100644
index 0000000..5ed1fd9
--- /dev/null
+++ b/src/components/link/link.test.ts
@@ -0,0 +1,28 @@
+import Link from './link';
+import { AppRoutesPath } from '../../router/types';
+
+describe('Link', () => {
+ const link: Link = new Link('Hello', ['link-test-class'], AppRoutesPath.LOGIN);
+
+ it('should render correct html-element', () => {
+ expect(link.getElement().outerHTML).toBe('Hello');
+ });
+ it('should render correct textContent', () => {
+ expect(link.getElement().textContent).toBe('Hello');
+ });
+ it('should render correct classList', () => {
+ expect(link.getElement().classList.contains('link-test-class')).toBe(true);
+ });
+ it('should render correct href', () => {
+ expect(link.getElement().href).toBe('http://localhost/login');
+ });
+ it('should change url', () => {
+ link.getElement().click();
+ expect(window.location.pathname).toBe('/login');
+ });
+ it('should trigger a new custom event', () => {
+ const dispatchEventSpy: jest.SpyInstance = jest.spyOn(window, 'dispatchEvent');
+ link.getElement().click();
+ expect(dispatchEventSpy.mock.calls[0][0].bubbles).toEqual(true);
+ });
+});
diff --git a/src/components/link/link.ts b/src/components/link/link.ts
new file mode 100644
index 0000000..fc6ed48
--- /dev/null
+++ b/src/components/link/link.ts
@@ -0,0 +1,16 @@
+import BaseComponent from '../base-component';
+import { AppRoutesPath } from '../../router/types';
+import { changeUrlEvent } from '../../utils/change-url-event';
+import './link.scss';
+
+export default class Link extends BaseComponent<'a'> {
+ constructor(text: string, classes: string[] = [], href: AppRoutesPath | string) {
+ super('a', ['link', ...classes], text);
+ this.node.href = href;
+
+ this.node.addEventListener('click', (e) => {
+ e.preventDefault();
+ changeUrlEvent(href);
+ });
+ }
+}
diff --git a/src/components/list/list.scss b/src/components/list/list.scss
new file mode 100644
index 0000000..fd6d3a0
--- /dev/null
+++ b/src/components/list/list.scss
@@ -0,0 +1,27 @@
+.list {
+ &-item {
+ display: flex;
+ padding: 16px 0;
+ border-bottom: 1px solid rgba($color-primary, 0.08);
+
+ &:first-child {
+ padding-top: 0;
+ }
+
+ &__key {
+ min-width: 140px;
+ font: $font-button;
+
+ @include mobile {
+ min-width: 100px;
+ }
+ }
+
+ &__value {
+ font-size: 15px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+ }
+}
diff --git a/src/components/list/list.test.ts b/src/components/list/list.test.ts
new file mode 100644
index 0000000..3b00bcc
--- /dev/null
+++ b/src/components/list/list.test.ts
@@ -0,0 +1,28 @@
+import { ListDataType } from '../../types/types';
+import List from './list';
+
+describe('List', () => {
+ const mockObj: ListDataType = {
+ name: 'John',
+ lastName: 'Deer',
+ country: 'US',
+ };
+
+ const list = new List(mockObj).getElement();
+
+ it('should be defined', () => {
+ expect(list).toBeDefined();
+ });
+
+ it('should root-element have the correct tagName', () => {
+ expect(list.tagName).toBe('UL');
+ });
+
+ it('should child-element have the correct tagName', () => {
+ expect(list.children[0].tagName).toBe('LI');
+ });
+
+ it('should have the correct presence of children nodes', () => {
+ expect(list.childNodes.length).toBe(3);
+ });
+});
diff --git a/src/components/list/list.ts b/src/components/list/list.ts
new file mode 100644
index 0000000..39bb457
--- /dev/null
+++ b/src/components/list/list.ts
@@ -0,0 +1,26 @@
+import BaseComponent from '../base-component';
+import { ListDataType } from '../../types/types';
+import './list.scss';
+
+export default class List extends BaseComponent<'ul'> {
+ constructor(data: ListDataType) {
+ super('ul', ['list']);
+ this.node.append(...this.createList(data));
+ }
+
+ private createList(data: ListDataType): HTMLElement[] {
+ const listOfElements: HTMLElement[] = [];
+
+ for (const key in data) {
+ const newElement = new BaseComponent('li', ['list-item']).getElement();
+ const newElementKey = new BaseComponent('p', ['list-item__key'], key).getElement();
+ const newElementValue = new BaseComponent('p', ['list-item__value'], data[key]).getElement();
+
+ newElement.append(newElementKey, newElementValue);
+
+ listOfElements.push(newElement);
+ }
+
+ return listOfElements;
+ }
+}
diff --git a/src/components/logo/logo.scss b/src/components/logo/logo.scss
new file mode 100644
index 0000000..10bf88c
--- /dev/null
+++ b/src/components/logo/logo.scss
@@ -0,0 +1,17 @@
+.logo {
+ display: inline-block;
+ font: $font-logo;
+
+ &__link {
+ color: $color-logo;
+ white-space: nowrap;
+ }
+
+ @include tablet {
+ font-size: 24px;
+ }
+
+ @include mobile {
+ font-size: 22px;
+ }
+}
diff --git a/src/components/logo/logo.test.ts b/src/components/logo/logo.test.ts
new file mode 100644
index 0000000..c988bf9
--- /dev/null
+++ b/src/components/logo/logo.test.ts
@@ -0,0 +1,21 @@
+import Logo from './logo';
+
+describe('Logo', () => {
+ const logo: HTMLElement = new Logo().getElement();
+
+ it('should be defined', () => {
+ expect(logo).toBeDefined();
+ });
+
+ it('should have the correct tagName', () => {
+ expect(logo.tagName).toBe('H1');
+ });
+
+ it('should child-element have the correct tagName', () => {
+ expect(logo.children[0].tagName).toBe('A');
+ });
+
+ it('should have the "logo" class', () => {
+ expect(logo.classList.contains('logo')).toBe(true);
+ });
+});
diff --git a/src/components/logo/logo.ts b/src/components/logo/logo.ts
new file mode 100644
index 0000000..1ca91ea
--- /dev/null
+++ b/src/components/logo/logo.ts
@@ -0,0 +1,14 @@
+import BaseComponent from '../base-component';
+import Link from '../link/link';
+import { AppRoutesPath } from '../../router/types';
+import './logo.scss';
+
+export default class Logo extends BaseComponent<'h1'> {
+ constructor() {
+ super('h1', ['logo']);
+
+ const logoLink = new Link('this is this.', ['logo__link'], AppRoutesPath.MAIN).getElement();
+
+ this.node.append(logoLink);
+ }
+}
diff --git a/src/components/notification/notification.scss b/src/components/notification/notification.scss
new file mode 100644
index 0000000..b3505f4
--- /dev/null
+++ b/src/components/notification/notification.scss
@@ -0,0 +1,33 @@
+.custom-toast {
+ display: flex;
+ align-items: flex-start;
+ gap: 8px;
+ color: $color-white;
+ padding: 20px 24px;
+ border-radius: 8px;
+ transition: all 0.2s ease;
+
+ &:hover {
+ opacity: 0.9;
+ }
+
+ .toast-close {
+ transition: all 0.2s ease;
+
+ &:hover {
+ opacity: 0.7;
+ }
+ }
+
+ &_success {
+ background: $color-success;
+ }
+
+ &_error {
+ background: $color-error;
+ }
+
+ &_warning {
+ background: $color-logo;
+ }
+}
diff --git a/src/components/notification/notification.test.ts b/src/components/notification/notification.test.ts
new file mode 100644
index 0000000..6cd3c92
--- /dev/null
+++ b/src/components/notification/notification.test.ts
@@ -0,0 +1,19 @@
+import Notification from './notification';
+
+const TEST_DURATION: number = 1000;
+
+describe('Notification', () => {
+ const notification: Notification = new Notification('success', 'Test Notification Text', TEST_DURATION);
+
+ it('should have correct type propeprty', () => {
+ expect(notification).toHaveProperty('type', 'success');
+ });
+
+ it('should have correct message propeprty', () => {
+ expect(notification).toHaveProperty('message', 'Test Notification Text');
+ });
+
+ it('should have correct duration propeprty', () => {
+ expect(notification).toHaveProperty('duration', TEST_DURATION);
+ });
+});
diff --git a/src/components/notification/notification.ts b/src/components/notification/notification.ts
new file mode 100644
index 0000000..1e5723e
--- /dev/null
+++ b/src/components/notification/notification.ts
@@ -0,0 +1,27 @@
+import Toastify from 'toastify-js';
+import 'toastify-js/src/toastify.css';
+import './notification.scss';
+
+const BASE_DURATION: number = 5000;
+
+export default class Notification {
+ private message: string;
+ private type: 'error' | 'success' | 'warning';
+ private duration: number;
+
+ constructor(type: 'error' | 'success' | 'warning', message: string, duration: number = BASE_DURATION) {
+ this.message = message;
+ this.type = type;
+ this.duration = duration;
+ }
+
+ public showNotification(): void {
+ Toastify({
+ className: `custom-toast custom-toast_${this.type}`,
+ text: this.message,
+ duration: this.duration,
+ gravity: 'bottom',
+ close: true,
+ }).showToast();
+ }
+}
diff --git a/src/components/popup/popup-password.ts b/src/components/popup/popup-password.ts
new file mode 100644
index 0000000..d2bf3e3
--- /dev/null
+++ b/src/components/popup/popup-password.ts
@@ -0,0 +1,122 @@
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import InputField from '../input/input';
+import Notification from '../notification/notification';
+import changePassword from '../../services/changePassword';
+import signinUser from '../../services/signinUser';
+import userStore from '../../store/user-store';
+import { detailsEditInputs } from '../../constants/detailsEditInputs';
+import { IDetailsPasswordData, InputFilds } from '../../types/interfaces';
+import './popup.scss';
+
+export default class PopupPassword extends BaseComponent<'div'> {
+ private inputs: InputFilds = {};
+ private formElement: HTMLFormElement;
+ private buttonWrapp: HTMLDivElement;
+ private buttonSubmit: HTMLButtonElement;
+ private buttonCancel: HTMLButtonElement;
+ private onCloseCallback: () => void;
+
+ constructor(onClose: () => void = () => {}) {
+ super('div', ['popup', 'open', 'popup-password']);
+ this.formElement = new BaseComponent('form', ['form__form']).getElement();
+ this.formElement.addEventListener('submit', (event) => this.onSubmit(event));
+ this.buttonWrapp = new BaseComponent('div', ['form__action']).getElement();
+ this.buttonSubmit = new Button('submit', 'Save password', []).getElement();
+ this.buttonCancel = new Button('button', 'Cancel', ['button--cancel'], false, this.closePopup).getElement();
+ this.buttonWrapp.append(this.buttonSubmit, this.buttonCancel);
+ this.formElement.append(this.buttonWrapp);
+
+ const popupWrapp = new BaseComponent('div', ['popup__content']).getElement();
+ const popupCloseIcon = new BaseComponent('div', ['popup__close']).getElement();
+ popupCloseIcon.addEventListener('click', this.closePopup);
+ const popupCloseTitle = new BaseComponent('h2', ['popup__title'], 'Create new password').getElement();
+ popupWrapp.append(popupCloseIcon, popupCloseTitle, this.formElement);
+
+ this.createPasswordForm();
+
+ this.onCloseCallback = onClose;
+
+ this.node.append(popupWrapp);
+ this.node.addEventListener('click', this.closeOnBackDropClick);
+ }
+
+ private closePopup = (): void => {
+ this.node.classList.remove('open');
+ this.onCloseCallback();
+ };
+
+ private closeOnBackDropClick = (e: MouseEvent): void => {
+ const dialogElement = e.currentTarget;
+ const isClickedOnBackDrop = e.target === dialogElement;
+ if (isClickedOnBackDrop) {
+ this.closePopup();
+ }
+ };
+
+ private createPasswordForm(): void {
+ const formContent: HTMLDivElement = new BaseComponent('div', ['form--password']).getElement();
+ const infoInputs = detailsEditInputs.passwords.map(({ type, name, placeholder, label }) => {
+ const inputField: InputField = new InputField(type, name, placeholder, label);
+ this.inputs[name] = inputField;
+ return inputField.getElement();
+ });
+ formContent.append(...infoInputs);
+ this.formElement.prepend(formContent);
+ }
+
+ private getDetailsData(): IDetailsPasswordData | undefined {
+ const currentPassword: string | undefined = this.inputs['currentPassword'].getValue('password');
+ const newPassword: string | undefined = this.inputs['newPassword'].getValue('newPassword', currentPassword);
+
+ if (!(currentPassword && newPassword)) {
+ return;
+ }
+
+ return {
+ currentPassword,
+ newPassword,
+ };
+ }
+
+ private async onSubmit(event: SubmitEvent): Promise {
+ event.preventDefault();
+
+ this.buttonSubmit.disabled = true;
+ this.buttonSubmit.classList.add('button--loading');
+
+ const values: IDetailsPasswordData | undefined = this.getDetailsData();
+
+ if (!values) {
+ this.buttonSubmit.disabled = false;
+ this.buttonSubmit.classList.remove('button--loading');
+ return;
+ }
+
+ try {
+ const { customer } = userStore.getState();
+
+ await changePassword(values.currentPassword, values.newPassword);
+
+ await signinUser({ email: customer?.email || '', password: values.newPassword });
+
+ this.buttonSubmit.classList.remove('button--loading');
+ this.buttonSubmit.classList.add('button--success');
+ new Notification('success', 'New password successfully updated!').showNotification();
+
+ setTimeout(() => {
+ this.closePopup();
+ }, 500);
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+
+ this.buttonSubmit.disabled = false;
+ this.buttonSubmit.classList.remove('button--loading');
+ this.buttonSubmit.classList.remove('button--success');
+ }
+ }
+}
diff --git a/src/components/popup/popup.scss b/src/components/popup/popup.scss
new file mode 100644
index 0000000..6e4d035
--- /dev/null
+++ b/src/components/popup/popup.scss
@@ -0,0 +1,78 @@
+.popup {
+ display: none;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba($color-black, 0.6);
+ padding: 0 60px;
+ z-index: 100;
+
+ @include mobile {
+ padding: 0 10px;
+ }
+
+ &.open {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ animation: popup-fade 0.5s ease forwards;
+ }
+
+ &__content {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ max-width: 560px;
+ height: auto;
+ padding: 32px;
+ border-radius: 9px;
+ background: $color-white;
+ overflow: hidden;
+ transition: all 0.3s ease;
+
+ @include mobile {
+ padding: 24px 12px;
+ }
+ }
+
+ &__title {
+ @include font-h4;
+ }
+
+ &__close {
+ position: absolute;
+ top: 24px;
+ right: 24px;
+ width: 20px;
+ height: 20px;
+ background-image: url('../../assets/icons/popup-close-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ cursor: pointer;
+ transition: transform 0.3s ease-in-out;
+
+ @include mobile {
+ top: 12px;
+ right: 12px;
+ }
+
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
+ transform: scale(1.15);
+ }
+ }
+}
+
+@keyframes popup-fade {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
diff --git a/src/components/popup/popup.test.ts b/src/components/popup/popup.test.ts
new file mode 100644
index 0000000..d76b390
--- /dev/null
+++ b/src/components/popup/popup.test.ts
@@ -0,0 +1,25 @@
+import PopupPassword from './popup-password';
+
+const popupHTML = ``;
+
+describe('Popup', () => {
+ const popup: HTMLElement = new PopupPassword().getElement();
+
+ it('should render correct html-element', () => {
+ expect(popup.outerHTML).toBe(popupHTML);
+ });
+
+ it('should active popup', () => {
+ document.body.append(popup);
+ const isPopup = document.querySelector('.popup') as HTMLElement;
+ expect(isPopup.classList.contains('open')).toBe(true);
+ });
+
+ it('should close popup', () => {
+ document.body.append(popup);
+ const closeBtn = document.querySelector('.popup__close') as HTMLElement;
+ closeBtn.click();
+ const isPopup = document.querySelector('.popup') as HTMLElement;
+ expect(isPopup.classList.contains('open')).toBe(false);
+ });
+});
diff --git a/src/components/product-card/product-card.scss b/src/components/product-card/product-card.scss
new file mode 100644
index 0000000..5704f5e
--- /dev/null
+++ b/src/components/product-card/product-card.scss
@@ -0,0 +1,173 @@
+.product-card {
+ border-radius: 8px;
+ box-shadow: 0px 0px 40px 0px rgba(0, 0, 0, 0.08);
+ position: relative;
+ display: flex;
+ flex-direction: column;
+
+ &__media {
+ height: 252px;
+ background: $color-bg-secondary;
+ border-radius: 8px;
+ overflow: hidden;
+ cursor: pointer;
+
+ img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ object-position: center;
+ transition: scale 0.3s ease-in-out;
+ }
+
+ &--placeholder {
+ background-image: url('../../assets/img/placeholder-image.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+
+ &:hover {
+ img {
+ scale: 1.2;
+ }
+ }
+ }
+
+ &__content {
+ padding: 32px;
+ height: calc(100% - 252px);
+ display: flex;
+ flex-direction: column;
+ position: relative;
+ }
+
+ &__middle {
+ display: flex;
+ align-items: center;
+
+ &-divider {
+ color: $color-primary;
+ opacity: 0.2;
+ margin: 0 12px;
+ }
+ }
+
+ &__price {
+ color: $color-price;
+ font: $font-button;
+
+ &--old {
+ text-decoration: line-through;
+ color: $color-secondary-40;
+ }
+
+ &--new {
+ color: $color-error;
+ margin-left: 6px;
+ }
+ }
+
+ &__days {
+ font: $font-label;
+ }
+
+ &__bottom {
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+ margin-top: auto;
+ }
+
+ &__reviews {
+ background: $color-bg-light;
+ padding: 4px 12px;
+ color: $color-secondary-60;
+ font: $font-xs;
+ border-radius: 100px;
+ }
+
+ &__button {
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s ease-in-out;
+
+ @include pre-tablet {
+ opacity: 1;
+ pointer-events: all;
+ }
+
+ &--added {
+ opacity: 1;
+ pointer-events: all;
+ background: $color-price !important;
+ }
+ }
+
+ &__title {
+ @include font-h4;
+ margin-bottom: 10px;
+ }
+
+ &__description {
+ margin-bottom: 16px;
+ }
+
+ &__rating {
+ position: absolute;
+ top: -236px;
+ left: 16px;
+ padding: 6px 8px;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ background: $color-white;
+ border-radius: 100px;
+ font: $font-xs;
+ font-weight: 700;
+
+ &::before {
+ content: '';
+ width: 14px;
+ height: 14px;
+ background-image: url('../../assets/icons/star-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+ }
+
+ &:hover {
+ .product-card__button:not(.product-card__button--added) {
+ opacity: 1;
+ pointer-events: all;
+ }
+ }
+
+ &.card-overlay-enabled {
+ &::before {
+ content: '';
+ display: block;
+ position: absolute;
+ inset: 0;
+ z-index: 2;
+ background: $color-white;
+ opacity: 0.5;
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ z-index: 3;
+ width: 100px;
+ height: 100px;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background-image: url('../../assets/icons/spinner-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ }
+ }
+}
diff --git a/src/components/product-card/product-card.test.ts b/src/components/product-card/product-card.test.ts
new file mode 100644
index 0000000..ad550b8
--- /dev/null
+++ b/src/components/product-card/product-card.test.ts
@@ -0,0 +1,118 @@
+import { ProductProjection } from '@commercetools/platform-sdk';
+import ProductCard from './product-card';
+
+describe('ProductCard', () => {
+ const mockProduct: ProductProjection = {
+ id: '440872b3-7de4-4d35-992f-80221313c0ce',
+ version: 13,
+ productType: {
+ typeId: 'product-type',
+ id: '31b96cba-837c-4f7b-be29-45fb85dbea58',
+ },
+ name: {
+ en: 'Wildlife of the Rockies',
+ },
+ categories: [
+ {
+ typeId: 'category',
+ id: '818991f4-c138-4839-ad69-09809dda6beb',
+ },
+ ],
+ categoryOrderHints: {},
+ slug: {
+ en: 'america---safari-am---Wildlife-of-the-Rockies',
+ },
+ metaTitle: {
+ en: 'Wildlife of the Rockies',
+ },
+ metaDescription: {
+ en: "Experience North America's diverse wildlife in the Rocky Mountains.",
+ },
+ variants: [],
+ masterVariant: {
+ attributes: [
+ {
+ name: 'rating',
+ value: '4.6',
+ },
+ {
+ name: 'reviews',
+ value: '70',
+ },
+ {
+ name: 'days',
+ value: '6',
+ },
+ {
+ name: 'inStock',
+ value: '19',
+ },
+ {
+ name: 'location',
+ value: 'Banff, Jasper National Parks, Canada',
+ },
+ {
+ name: 'shortDescription',
+ value: "Experience North America's diverse wildlife in the Rocky Mountains.",
+ },
+ {
+ name: 'adventureStyle',
+ value: 'Safari',
+ },
+ {
+ name: 'aboutTour',
+ value:
+ "Route: Depart from Denver, USA, and venture into the Rocky Mountains to observe North America's diverse wildlife. Group Size: Intimate group of 6-8 wildlife enthusiasts. Activities: Wildlife tracking, guided hikes, observing bighorn sheep and elk, learning about Rocky Mountain ecosystems.",
+ },
+ ],
+ assets: [],
+ images: [
+ {
+ url: 'https://firebasestorage.googleapis.com/v0/b/aillery.appspot.com/o/images%2F43%2Fphoto-1682685796002-e05458d61f07.jpg?alt=media&token=18a7f29d-e9be-4694-bc3e-a56f31e70a77',
+ dimensions: {
+ w: 2071,
+ h: 1381,
+ },
+ },
+ ],
+ prices: [
+ {
+ id: '3ce8271a-a18c-4850-aebd-20ae95525ead',
+ value: {
+ type: 'centPrecision',
+ currencyCode: 'USD',
+ centAmount: 165000,
+ fractionDigits: 2,
+ },
+ country: 'US',
+ },
+ ],
+ key: 'tour43',
+ sku: 'tour-43',
+ id: 1,
+ },
+ searchKeywords: {},
+ hasStagedChanges: false,
+ published: true,
+ taxCategory: {
+ typeId: 'tax-category',
+ id: 'ed35c239-a7a5-45c8-a820-3f464a87aa8d',
+ },
+ priceMode: 'Embedded',
+ createdAt: '2023-08-30T12:42:27.667Z',
+ lastModifiedAt: '2023-09-08T19:38:26.588Z',
+ };
+ const productCard = new ProductCard(mockProduct).getElement();
+
+ it('should be defined', () => {
+ expect(productCard).toBeDefined();
+ });
+ it('should have the correct title text', () => {
+ const titleElement = productCard.querySelector('.product-card__title');
+ expect(titleElement?.textContent).toBe('Wildlife of the Rockies');
+ });
+ it('should have a button with the correct class', () => {
+ const buttonElement = productCard.querySelector('.product-card__button');
+ expect(buttonElement?.classList.contains('button--cart')).toBe(true);
+ });
+});
diff --git a/src/components/product-card/product-card.ts b/src/components/product-card/product-card.ts
new file mode 100644
index 0000000..bf679a4
--- /dev/null
+++ b/src/components/product-card/product-card.ts
@@ -0,0 +1,156 @@
+import { TypedMoney, type ProductProjection } from '@commercetools/platform-sdk';
+import { ICategory } from '../../types/types';
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import Link from '../link/link';
+import categories from '../../constants/categories';
+import subcategories from '../../constants/subcategories';
+import formatPrice from '../../utils/formatPrice';
+import addToCart from '../../services/basket/addToCart';
+import Notification from '../notification/notification';
+import cartStore from '../../store/cart-store';
+import './product-card.scss';
+
+export default class ProductCard extends BaseComponent<'div'> {
+ private cartButton: HTMLButtonElement;
+ private productId: string;
+
+ constructor(product: ProductProjection) {
+ super('div', ['product-card']);
+
+ this.productId = product.id;
+
+ this.cartButton = this.createButtonCart();
+
+ this.createMarkup(product);
+ this.addSubscribtion();
+ }
+
+ private createButtonCart(): HTMLButtonElement {
+ const classes = this.isProductInCart()
+ ? ['product-card__button', 'product-card__button--added', 'button--cart']
+ : ['product-card__button', 'button--cart'];
+ const isDisabled = this.isProductInCart();
+ const button = new Button('button', '', classes, isDisabled, () => this.onAddToCart(this.productId)).getElement();
+
+ return button;
+ }
+
+ private createMarkup(product: ProductProjection): void {
+ const title: string = product.name.en;
+ const description: string = product.metaDescription?.en || '';
+ const image: string = product.masterVariant.images?.[0]?.url || '';
+ const reviews: string = product.masterVariant.attributes?.[1]?.value || '0';
+ const standardPrice: TypedMoney | undefined = product.masterVariant.prices?.[0]?.value;
+ const discountedPrice: TypedMoney | undefined = product.masterVariant.prices?.[0]?.discounted?.value;
+ const days: string = product.masterVariant.attributes?.[2]?.value || '';
+ const rating: string = product.masterVariant.attributes?.[0]?.value || '';
+
+ const linkToProduct = this.createLinkToProduct(product.slug.en, this.productId);
+
+ const cardMedia = new Link('', ['product-card__media'], linkToProduct).getElement();
+ const cardImage: HTMLImageElement = new BaseComponent('img', ['product-card__image']).getElement();
+ const cardRating = new BaseComponent('div', ['product-card__rating'], rating).getElement();
+ if (image) {
+ cardImage.src = image;
+ cardMedia.append(cardImage);
+ } else {
+ cardMedia.classList.add('product-card__media--placeholder');
+ }
+
+ const cardContent = new BaseComponent('div', ['product-card__content']).getElement();
+ const cardTitle = new BaseComponent('h4', ['product-card__title'], title).getElement();
+ const cardDescription = new BaseComponent('p', ['product-card__description'], description).getElement();
+
+ const cardMiddle = new BaseComponent('div', ['product-card__middle']).getElement();
+ const cardPrice = new BaseComponent('span', ['product-card__price']).getElement();
+ const cardPriceDisc = new BaseComponent('span', ['product-card__price', 'product-card__price--new']).getElement();
+
+ if (standardPrice) {
+ cardPrice.textContent = formatPrice(
+ standardPrice.currencyCode,
+ standardPrice.centAmount,
+ standardPrice.fractionDigits
+ );
+ cardMiddle.append(cardPrice);
+ }
+
+ if (discountedPrice) {
+ cardPriceDisc.textContent = formatPrice(
+ discountedPrice.currencyCode,
+ discountedPrice.centAmount,
+ discountedPrice.fractionDigits
+ );
+ cardPrice.classList.add('product-card__price--old');
+ cardMiddle.append(cardPriceDisc);
+ }
+
+ const cardMiddleDivider = new BaseComponent('div', ['product-card__middle-divider'], '|').getElement();
+ const cardDays = new BaseComponent('span', ['product-card__days'], `${days} days`).getElement();
+ cardMiddle.append(cardMiddleDivider, cardDays);
+
+ const cardBottom = new BaseComponent('div', ['product-card__bottom']).getElement();
+ const cardReviews = new BaseComponent('p', ['product-card__reviews'], `${reviews}+ Reviews`).getElement();
+
+ cardBottom.append(cardReviews, this.cartButton);
+
+ cardContent.append(cardRating, cardTitle, cardDescription, cardMiddle, cardBottom);
+
+ this.node.append(cardMedia, cardContent);
+ }
+
+ private createLinkToProduct(slug: string, id: string): string {
+ const parts: string[] = slug.split('---');
+
+ const [categorySlug, subcategorySlug] = parts;
+
+ const currentCategory: ICategory | undefined = categories.find((item) => item.slug === categorySlug);
+ const currentsubCategory: ICategory | undefined = subcategories[categorySlug]?.find(
+ (item) => item.slug === subcategorySlug
+ );
+
+ if (currentCategory && !currentsubCategory) return `/shop/${categorySlug}/${id}`;
+ if (!currentCategory && !currentsubCategory) return `/shop/${id}`;
+ if (!currentCategory) return `/shop/${id}`;
+
+ return `/shop/${categorySlug}/${subcategorySlug}/${id}`;
+ }
+
+ private async onAddToCart(id: string): Promise {
+ try {
+ this.cartButton.disabled = true;
+ this.node.classList.add('card-overlay-enabled');
+
+ const cart = await addToCart(id);
+ cartStore.dispatch({ type: 'UPDATE_CART', cart });
+ new Notification('success', 'Tour has been successfully added to cart!').showNotification();
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+
+ this.cartButton.disabled = false;
+ } finally {
+ this.node.classList.remove('card-overlay-enabled');
+ }
+ }
+
+ private isProductInCart(): boolean {
+ const { cart } = cartStore.getState();
+ return !!cart?.lineItems.find((item) => item.productId === this.productId);
+ }
+
+ private addSubscribtion(): void {
+ cartStore.subscribe((state) => {
+ if (state.cart?.lineItems.find((item) => item.productId === this.productId)) {
+ this.cartButton.classList.add('product-card__button--added');
+ this.cartButton.disabled = true;
+ } else {
+ this.cartButton.classList.remove('product-card__button--added');
+ this.cartButton.disabled = false;
+ }
+ });
+ }
+}
diff --git a/src/components/product-list/product-list.scss b/src/components/product-list/product-list.scss
new file mode 100644
index 0000000..452142d
--- /dev/null
+++ b/src/components/product-list/product-list.scss
@@ -0,0 +1,37 @@
+.product-list {
+ padding: 48px 0;
+
+ &__container {
+ @include container;
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 24px;
+ position: relative;
+
+ @include laptop {
+ grid-template-columns: repeat(3, 1fr);
+ }
+
+ @include pre-tablet {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ @include mobile {
+ grid-template-columns: 1fr;
+ }
+
+ &--loading {
+ &::after {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ transform: translateY(-50%);
+ content: 'Loading';
+ }
+ }
+ }
+
+ &__empty {
+ @include font-h4;
+ }
+}
diff --git a/src/components/product-list/product-list.ts b/src/components/product-list/product-list.ts
new file mode 100644
index 0000000..5dc3676
--- /dev/null
+++ b/src/components/product-list/product-list.ts
@@ -0,0 +1,38 @@
+import { type ProductProjection } from '@commercetools/platform-sdk';
+import BaseComponent from '../base-component';
+import ProductCard from '../product-card/product-card';
+import './product-list.scss';
+
+export default class ProductList extends BaseComponent<'section'> {
+ private items: ProductProjection[];
+ private cards: HTMLDivElement[];
+ private container: HTMLDivElement;
+
+ constructor(items: ProductProjection[]) {
+ super('section', ['product-list']);
+
+ this.items = items;
+ this.cards = [];
+ this.container = new BaseComponent('div', ['product-list__container']).getElement();
+
+ this.createMarkup();
+ }
+
+ private async createMarkup(): Promise {
+ if (this.items.length) {
+ this.cards = this.items.map((item) => {
+ return new ProductCard(item).getElement();
+ });
+ this.container.append(...this.cards);
+ } else {
+ const emptyListText = new BaseComponent('div', ['product-list__empty'], 'No tours found').getElement();
+ this.container.append(emptyListText);
+ }
+
+ this.node.append(this.container);
+ }
+
+ public addNewProducts(cards: HTMLElement[]): void {
+ this.container.append(...cards);
+ }
+}
diff --git a/src/components/product/product.scss b/src/components/product/product.scss
new file mode 100644
index 0000000..8f630ed
--- /dev/null
+++ b/src/components/product/product.scss
@@ -0,0 +1,129 @@
+.product {
+ display: flex;
+ flex-direction: column;
+ gap: 40px;
+ width: calc(50% - 12px);
+ padding: 64px;
+ background-color: $color-bg-card;
+ border-radius: 8px;
+
+ @include tablet {
+ gap: 20px;
+ padding: 32px;
+ }
+
+ @include laptop {
+ width: 80%;
+ }
+
+ @include mobile {
+ width: 100%;
+ }
+
+ &__routes {
+ font-size: 11px;
+ font-weight: 700;
+ text-transform: uppercase;
+ opacity: 0.5;
+ }
+
+ &__info {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+
+ @include tablet {
+ gap: 8px;
+ }
+ }
+
+ &__title {
+ @include font-h2;
+ }
+
+ &__opinion {
+ display: flex;
+ gap: 10px;
+ align-items: center;
+ color: $color-secondary-40;
+ }
+
+ &__rating {
+ position: relative;
+ display: flex;
+ align-items: center;
+ padding: 4px 8px 4px 28px;
+ font-weight: 700;
+ font-size: 14px;
+ color: $color-primary;
+ background-color: white;
+ border-radius: 30px;
+
+ &::before {
+ position: absolute;
+ display: block;
+ content: '';
+ left: 8px;
+ width: 16px;
+ height: 16px;
+ background: url('../../assets/icons/star.svg') center/cover no-repeat;
+ }
+ }
+
+ &__stock {
+ display: flex;
+ align-items: center;
+ padding-left: 22px;
+ position: relative;
+ font-weight: 700;
+
+ &::before {
+ position: absolute;
+ display: block;
+ content: '';
+ left: 0;
+ width: 18px;
+ height: 18px;
+ background: url('../../assets/icons/check.svg') center/cover no-repeat;
+ }
+ }
+
+ &__add-to-cart {
+ & button {
+ width: 100%;
+ box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.08);
+ }
+ }
+
+ &__about {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+
+ @include tablet {
+ gap: 8px;
+ }
+
+ &-item {
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+ padding-bottom: 16px;
+ border-bottom: 1px solid rgba(0, 19, 41, 0.12);
+
+ @include tablet {
+ padding-bottom: 8px;
+ }
+
+ &:nth-last-child(1) {
+ padding-bottom: 0;
+ border: none;
+ }
+
+ & p {
+ font-size: 14px;
+ margin-left: 5px;
+ }
+ }
+ }
+}
diff --git a/src/components/product/product.ts b/src/components/product/product.ts
new file mode 100644
index 0000000..b8408c7
--- /dev/null
+++ b/src/components/product/product.ts
@@ -0,0 +1,219 @@
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import { Price, ProductData, TypedMoney } from '@commercetools/platform-sdk';
+import formatPrice from '../../utils/formatPrice';
+import Notification from '../notification/notification';
+import addToCart from '../../services/basket/addToCart';
+import removeProductFromCart from '../../services/basket/removeProductFromCart';
+import cartStore from '../../store/cart-store';
+import './product.scss';
+
+interface ProductAttributes {
+ [name: string]: string;
+}
+
+export default class Product extends BaseComponent<'div'> {
+ private productForm: HTMLDivElement = new BaseComponent('div').getElement();
+ private cartButton: HTMLButtonElement = new Button('button', 'Cart').getElement();
+ private productData: ProductData | null = null;
+ private productAttributes: ProductAttributes = {
+ rating: '-',
+ reviews: '0',
+ days: 'Please ask about tour duration by writing to us at this.is.this@gmail.com',
+ inStock: 'Please check availability by writing to us at this.is.this@gmail.com',
+ location: 'Paradise',
+ shortDescription: 'No information about this tour',
+ adventureStyle: 'Relax',
+ aboutTour: 'No information about this tour',
+ };
+ private productId: string;
+ private removeFromCartBtn = new Button('button', 'Remove From Cart', ['button--white'], false, () =>
+ this.onRemoveFromCart()
+ ).getElement();
+ private addToCartBtn = new Button('button', 'Add To Cart', [], false, () => this.onAddToCart()).getElement();
+
+ constructor(productId: string, productData: ProductData) {
+ super('div', ['product']);
+
+ this.productData = productData;
+ this.productId = productId;
+
+ this.createMarkup();
+ }
+
+ private createMarkup(): void {
+ this.getProductAttributes();
+
+ const productInfo = this.drawProductInfo();
+ this.productForm = this.drawProductForm();
+ const productAbout = this.drawProductAbout();
+
+ this.node.append(productInfo, this.productForm, productAbout);
+ }
+
+ private drawProductPrice(): HTMLDivElement {
+ const productPrices = new BaseComponent('div', ['product__prices']).getElement();
+
+ const prices: Price[] | undefined = this.productData?.masterVariant.prices;
+
+ if (prices?.length) {
+ const standardPrice: TypedMoney = prices[0].value;
+ const discountedPrice: TypedMoney | undefined = prices[0].discounted?.value;
+
+ const productPrice = new BaseComponent(
+ 'span',
+ ['product-card__price'],
+ formatPrice(standardPrice.currencyCode, standardPrice.centAmount, standardPrice.fractionDigits)
+ ).getElement();
+
+ productPrices.append(productPrice);
+
+ if (discountedPrice) {
+ const productDiscountedPrice = new BaseComponent(
+ 'span',
+ ['product-card__price', 'product-card__price--new'],
+ formatPrice(discountedPrice.currencyCode, discountedPrice.centAmount, discountedPrice.fractionDigits)
+ ).getElement();
+
+ productPrice.classList.add('product-card__price--old');
+ productPrices.append(productDiscountedPrice);
+ }
+ }
+
+ return productPrices;
+ }
+
+ private drawProductInfo(): HTMLDivElement {
+ const title = this.productData?.name.en || 'Unnamed tour';
+ const { rating, reviews, inStock, shortDescription, adventureStyle } = this.productAttributes;
+
+ const productRoutes = new BaseComponent('p', ['product__routes'], adventureStyle).getElement();
+ const productInfo = new BaseComponent('div', ['product__info']).getElement();
+ const productOpinion = new BaseComponent('div', ['product__opinion']).getElement();
+ const productTitle = new BaseComponent('h2', ['product__title'], title).getElement();
+ const productPrice = this.drawProductPrice();
+ const productRating = new BaseComponent('p', ['product__rating'], rating).getElement();
+ const productReviews = new BaseComponent('p', ['product__reviews'], `${reviews}+ Reviews`).getElement();
+ const productDescription = new BaseComponent('p', ['product__description'], shortDescription).getElement();
+ const productStock = new BaseComponent('p', ['product__stock'], `${inStock} In Stock`).getElement();
+
+ productOpinion.append(productRating, productReviews);
+ productInfo.append(productRoutes, productTitle, productPrice, productOpinion, productDescription, productStock);
+
+ return productInfo;
+ }
+
+ private getProductAttributes(): void {
+ const attributes = this.productData?.masterVariant.attributes;
+
+ if (attributes) {
+ for (const key of attributes) {
+ if (key.name in this.productAttributes) {
+ this.productAttributes[key.name] = key.value;
+ }
+ }
+ }
+ }
+
+ private drawProductForm(): HTMLDivElement {
+ const productForm = new BaseComponent('div', ['product__add-to-cart']).getElement();
+
+ this.drawButton();
+
+ productForm.append(this.cartButton);
+
+ return productForm;
+ }
+
+ private drawButton(): void {
+ if (this.isProductInCart()) {
+ this.cartButton = this.removeFromCartBtn;
+ } else {
+ this.cartButton = this.addToCartBtn;
+ }
+ }
+
+ private drawProductAbout(): HTMLUListElement {
+ const { aboutTour, location } = this.productAttributes;
+
+ const productAbout = new BaseComponent('ul', ['product__about']).getElement();
+ const productAboutItem = new BaseComponent('li', ['product__about-item'], 'About Tour').getElement();
+ const productLocationItem = new BaseComponent('li', ['product__about-item'], 'Location').getElement();
+
+ aboutTour
+ .slice(0, -1)
+ .split('.')
+ .forEach((sentence) => {
+ const aboutTourSentence = new BaseComponent('p', ['product__description'], `${sentence}.`).getElement();
+
+ productAboutItem.append(aboutTourSentence);
+ });
+
+ const productLocation = new BaseComponent('p', ['product__description'], location).getElement();
+
+ productLocationItem.append(productLocation);
+ productAbout.append(productAboutItem, productLocationItem);
+
+ return productAbout;
+ }
+
+ private async onAddToCart(): Promise {
+ try {
+ this.cartButton.disabled = true;
+ this.node.classList.add('card-overlay-enabled');
+
+ const updatedCart = await addToCart(this.productId);
+ cartStore.dispatch({ type: 'UPDATE_CART', cart: updatedCart });
+ new Notification('success', 'Tour has been successfully added to cart!').showNotification();
+
+ this.cartButton = this.removeFromCartBtn;
+
+ this.productForm.innerHTML = '';
+ this.productForm.append(this.cartButton);
+
+ this.cartButton.disabled = false;
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+ } finally {
+ this.cartButton.disabled = false;
+ this.node.classList.remove('card-overlay-enabled');
+ }
+ }
+
+ private async onRemoveFromCart(): Promise {
+ try {
+ this.cartButton.disabled = true;
+ this.node.classList.add('card-overlay-enabled');
+
+ const updatedCart = await removeProductFromCart(this.productId);
+
+ cartStore.dispatch({ type: 'UPDATE_CART', cart: updatedCart });
+ new Notification('success', 'Tour has been successfully removed from cart!').showNotification();
+
+ this.cartButton = this.addToCartBtn;
+
+ this.productForm.innerHTML = '';
+ this.productForm.append(this.cartButton);
+
+ this.cartButton.disabled = false;
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+ } finally {
+ this.cartButton.disabled = false;
+ this.node.classList.remove('card-overlay-enabled');
+ }
+ }
+
+ private isProductInCart(): boolean {
+ const { cart } = cartStore.getState();
+ return !!cart?.lineItems.find((item) => item.productId === this.productId);
+ }
+}
diff --git a/src/components/promo-codes/promo-codes-list.test.ts b/src/components/promo-codes/promo-codes-list.test.ts
new file mode 100644
index 0000000..c03524e
--- /dev/null
+++ b/src/components/promo-codes/promo-codes-list.test.ts
@@ -0,0 +1,38 @@
+import PromoCodesList from './promo-codes-list';
+
+describe('PromoCodesList Component', () => {
+ const promoCodesList = new PromoCodesList().getElement();
+
+ it('should render without errors', () => {
+ expect(promoCodesList).toBeDefined();
+ });
+
+ it('should have the correct tag name', () => {
+ expect(promoCodesList.tagName).toBe('UL');
+ });
+
+ it('should have the "promo-codes-list" class', () => {
+ expect(promoCodesList.classList.contains('promo-codes-list')).toBe(true);
+ });
+
+ it('should render promo code items', () => {
+ const promoCodeItems = promoCodesList.querySelectorAll('.promo-codes-item');
+ expect(promoCodeItems.length).toBeGreaterThan(0);
+ });
+
+ it('should handle copy promo code', () => {
+ const clipboardMock = {
+ writeText: jest.fn(),
+ };
+ Object.defineProperty(global.navigator, 'clipboard', {
+ value: clipboardMock,
+ });
+
+ const promoCodeItem = promoCodesList.querySelector('.promo-codes-item')!;
+ const copyButton: HTMLButtonElement | null = promoCodeItem.querySelector('.promo-codes-item__button');
+
+ copyButton!.click();
+
+ expect(clipboardMock.writeText).toHaveBeenCalled();
+ });
+});
diff --git a/src/components/promo-codes/promo-codes-list.ts b/src/components/promo-codes/promo-codes-list.ts
new file mode 100644
index 0000000..285f112
--- /dev/null
+++ b/src/components/promo-codes/promo-codes-list.ts
@@ -0,0 +1,53 @@
+import promoCodes from '../../constants/promoCodes';
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import InputField from '../input/input';
+import Notification from '../notification/notification';
+import './promo-codes.scss';
+
+export default class PromoCodesList extends BaseComponent<'ul'> {
+ constructor() {
+ super('ul', ['promo-codes-list']);
+ this.renderPromoCodesList();
+ }
+
+ private handleCopyPromoCode(code: string): void {
+ navigator.clipboard.writeText(code);
+ new Notification('success', 'This Promo Code is successfully saved to clipboard!').showNotification();
+ }
+
+ private renderPromoCodesList(): void {
+ promoCodes.forEach((obj) => {
+ const item = new BaseComponent('li', ['promo-codes-item']).getElement();
+
+ const firstWrapp = new BaseComponent('div', ['promo-codes-item__wrapp']).getElement();
+ const itemImg = new BaseComponent('span', ['promo-codes-item__img', obj.code]).getElement();
+ const itemTitle = new BaseComponent('h4', ['promo-codes-item__title'], obj.title).getElement();
+ const itemDescr = new BaseComponent('h4', ['promo-codes-item__descr'], obj.descr).getElement();
+ firstWrapp.append(itemImg, itemTitle, itemDescr);
+
+ const secondWrapp = new BaseComponent('div', ['promo-codes-item__wrapp']).getElement();
+ const itemActions = new BaseComponent('div', ['promo-codes-item__actions']).getElement();
+ const itemInput = new InputField('text', '', '', '', ['promo-codes-item__input']);
+ itemInput.setValue(obj.code);
+ itemInput.setAttribute('readonly', 'readonly');
+ const inputBtn = new Button('button', 'Copy', ['promo-codes-item__button'], false, () =>
+ this.handleCopyPromoCode(obj.code)
+ ).getElement();
+
+ itemActions.append(itemInput.getElement(), inputBtn);
+
+ const itemDateText = new BaseComponent(
+ 'p',
+ ['promo-codes-item__date'],
+ `Promo Code valid until ${obj.expirationDate}`
+ ).getElement();
+
+ secondWrapp.append(itemActions, itemDateText);
+
+ item.append(firstWrapp, secondWrapp);
+
+ this.node.append(item);
+ });
+ }
+}
diff --git a/src/components/promo-codes/promo-codes.scss b/src/components/promo-codes/promo-codes.scss
new file mode 100644
index 0000000..bc7c48d
--- /dev/null
+++ b/src/components/promo-codes/promo-codes.scss
@@ -0,0 +1,139 @@
+.promo-codes {
+ padding: 104px 0;
+ background-color: $color-bg-light;
+
+ @include mobile {
+ padding: 60px 0;
+ }
+
+ &__container {
+ @include container;
+ }
+
+ &__title {
+ @include font-h2;
+ margin-bottom: 48px;
+ }
+
+ &-list {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ grid-gap: 24px;
+ gap: 24px;
+
+ @include laptop {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ @include mobile {
+ grid-template-columns: repeat(1, 1fr);
+ }
+ }
+
+ &-item {
+ padding: 32px;
+ background: $color-white;
+ border-radius: 8px;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+
+ &__img {
+ margin-bottom: 24px;
+ display: block;
+ width: 116px;
+ height: 116px;
+ border-radius: 8px;
+ background-color: #fff;
+ background-image: url('../../assets/img/placeholder-image.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ overflow: hidden;
+
+ &.FAMILYFUN {
+ background-image: url('../../assets/img/promo-codes/FAMILYFUN.jpg');
+ }
+ &.LASTCHANCE {
+ background-image: url('../../assets/img/promo-codes/LASTCHANCE.jpg');
+ }
+ &.CRUISE100 {
+ background-image: url('../../assets/img/promo-codes/CRUISE100.jpg');
+ }
+ &.GROUP24 {
+ background-image: url('../../assets/img/promo-codes/GROUP24.jpg');
+ }
+ }
+
+ &__title {
+ @include font-h4;
+ margin-bottom: 12px;
+ }
+
+ &__descr {
+ margin-bottom: 67px;
+
+ @include small-mobile {
+ margin-bottom: 30px;
+ }
+ }
+
+ &__actions {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 16px;
+
+ @media (max-width: 1600px) {
+ flex-direction: column;
+ }
+
+ @include laptop {
+ flex-direction: row;
+ }
+
+ @include small-mobile {
+ flex-direction: column;
+ }
+ }
+
+ &__input {
+ width: 100%;
+
+ & label {
+ margin-bottom: 0;
+ }
+
+ & input {
+ height: 55px;
+ font: $font-label;
+ background: $color-bg-light;
+ border: 1px solid $color-bg-light;
+ }
+ }
+
+ &__button {
+ margin: 0 0 0 8px;
+
+ @media (max-width: 1600px) {
+ margin: 12px 0 0 0;
+ width: 100%;
+ }
+
+ @include laptop {
+ margin: 0 0 0 8px;
+ width: auto;
+ }
+
+ @include small-mobile {
+ margin: 12px 0 0 0;
+ width: 100%;
+ }
+ }
+
+ &__date {
+ font: $font-xs;
+ opacity: 0.5;
+ }
+ }
+}
diff --git a/src/components/promo-codes/promo-codes.test.ts b/src/components/promo-codes/promo-codes.test.ts
new file mode 100644
index 0000000..552f532
--- /dev/null
+++ b/src/components/promo-codes/promo-codes.test.ts
@@ -0,0 +1,28 @@
+import PromoCodes from './promo-codes';
+
+describe('PromoCodes', () => {
+ const promoCodes = new PromoCodes().getElement();
+
+ it('should render without errors', () => {
+ expect(promoCodes).toBeDefined();
+ });
+
+ it('should have the correct tag name', () => {
+ expect(promoCodes.tagName).toBe('SECTION');
+ });
+
+ it('should have the "promo-codes" class', () => {
+ expect(promoCodes.classList.contains('promo-codes')).toBe(true);
+ });
+
+ it('should render a title', () => {
+ const title = promoCodes.querySelector('.promo-codes__title');
+ expect(title).toBeDefined();
+ expect(title?.textContent).toBe('Your Passport to Savings: Travel Promo Deals');
+ });
+
+ it('should render a PromoCodesList', () => {
+ const promoCodesList = promoCodes.querySelector('.promo-codes__container .promo-codes-list');
+ expect(promoCodesList).toBeDefined();
+ });
+});
diff --git a/src/components/promo-codes/promo-codes.ts b/src/components/promo-codes/promo-codes.ts
new file mode 100644
index 0000000..78367eb
--- /dev/null
+++ b/src/components/promo-codes/promo-codes.ts
@@ -0,0 +1,24 @@
+import BaseComponent from '../base-component';
+import PromoCodesList from './promo-codes-list';
+import './promo-codes.scss';
+
+export default class PromoCodes extends BaseComponent<'section'> {
+ constructor() {
+ super('section', ['promo-codes']);
+ this.renderPromoCodes();
+ }
+
+ private renderPromoCodes(): void {
+ const container = new BaseComponent('div', ['promo-codes__container']).getElement();
+ const title = new BaseComponent(
+ 'h2',
+ ['promo-codes__title'],
+ 'Your Passport to Savings: Travel Promo Deals'
+ ).getElement();
+ const list = new PromoCodesList().getElement();
+
+ container.append(title, list);
+
+ this.node.append(container);
+ }
+}
diff --git a/src/components/select/select-type.ts b/src/components/select/select-type.ts
new file mode 100644
index 0000000..1d46457
--- /dev/null
+++ b/src/components/select/select-type.ts
@@ -0,0 +1,50 @@
+import BaseComponent from '../base-component';
+import './select.scss';
+
+export default class SelectTypeField extends BaseComponent<'div'> {
+ private labelElement: HTMLLabelElement;
+ private selectElement: HTMLSelectElement;
+
+ constructor(name: string = '', classes: string[] = []) {
+ super('div', ['form-field', ...classes]);
+
+ this.labelElement = new BaseComponent('label', ['form-field__label'], 'Type').getElement();
+ this.selectElement = new BaseComponent('select', ['form-field__input']).getElement();
+
+ this.setAttributes(name);
+
+ this.createSelectField();
+
+ this.node.append(this.labelElement, this.selectElement);
+ }
+
+ public getValue(): string | undefined {
+ return this.selectElement.value.trim();
+ }
+
+ public setValue(firstValue: boolean | undefined, secondValue: boolean | undefined): void {
+ if (firstValue && secondValue) {
+ this.selectElement.value = 'Billing, Shipping';
+ } else if (firstValue) {
+ this.selectElement.value = 'Billing';
+ } else {
+ this.selectElement.value = 'Shipping';
+ }
+ }
+
+ private setAttributes(name: string = ''): void {
+ this.selectElement.name = name;
+ this.selectElement.id = name;
+ this.labelElement.setAttribute('for', name);
+ }
+
+ private createSelectField(): void {
+ const types = ['Billing', 'Shipping', 'Billing, Shipping'];
+ types.forEach((type) => {
+ const option = new BaseComponent('option', ['form-field__input']).getElement();
+ option.value = type;
+ option.text = type;
+ this.selectElement.appendChild(option);
+ });
+ }
+}
diff --git a/src/components/select/select.scss b/src/components/select/select.scss
new file mode 100644
index 0000000..6784618
--- /dev/null
+++ b/src/components/select/select.scss
@@ -0,0 +1,50 @@
+.select-field {
+ position: relative;
+ display: flex;
+ border-radius: 6px;
+ overflow: hidden;
+
+ &__select {
+ appearance: none;
+ outline: none;
+ border: 0;
+ box-shadow: none;
+ flex: 1;
+ padding: 16px 24px;
+ width: 260px;
+ font: $font-main;
+ color: $color-primary;
+ background-color: rgba($color-primary, 0.03);
+ background-image: none;
+ cursor: pointer;
+ }
+
+ &__select::-ms-expand {
+ display: none;
+ }
+
+ &::after {
+ position: absolute;
+ top: 50%;
+ right: 24px;
+ display: block;
+ content: '';
+ width: 20px;
+ height: 20px;
+ background-image: url('../../assets/icons/chevron-up.svg');
+ transform: translateY(-50%) rotate(180deg);
+ background-position: center;
+ background-size: cover;
+ pointer-events: none;
+ }
+
+ &__option {
+ &[value=''] {
+ display: none;
+
+ .select--sort & {
+ display: block;
+ }
+ }
+ }
+}
diff --git a/src/components/select/select.ts b/src/components/select/select.ts
new file mode 100644
index 0000000..e6f3f42
--- /dev/null
+++ b/src/components/select/select.ts
@@ -0,0 +1,60 @@
+import shopStore from '../../store/shop-store';
+import BaseComponent from '../base-component';
+import './select.scss';
+
+interface IOption {
+ label: string;
+ value: string;
+}
+
+export default class SelectField extends BaseComponent<'div'> {
+ private selectElement: HTMLSelectElement;
+
+ constructor(name: string = '', options: IOption[], classes: string[] = []) {
+ super('div', ['select-field', ...classes]);
+
+ this.selectElement = new BaseComponent('select', ['select-field__select']).getElement();
+
+ this.renderSelect(name, options);
+ this.setListener();
+ }
+
+ private renderSelect(name: string, options: IOption[]): void {
+ this.selectElement.id = name;
+ this.selectElement.name = name;
+
+ const optionsElements = options.map((option): HTMLOptionElement => {
+ const optionEl = new BaseComponent('option', ['select-field__option'], option.label).getElement();
+ optionEl.value = option.value;
+ if (name === 'price' && shopStore.getState().filterPrice === option.value) {
+ optionEl.selected = true;
+ }
+ if (name === 'days' && shopStore.getState().filterDays === option.value) {
+ optionEl.selected = true;
+ }
+ if (name === 'sort' && shopStore.getState().sortValue === option.value) {
+ optionEl.selected = true;
+ }
+ return optionEl;
+ });
+
+ this.selectElement.append(...optionsElements);
+
+ this.node.append(this.selectElement);
+ }
+
+ private setListener(): void {
+ this.selectElement.addEventListener('change', (event) => {
+ event.preventDefault();
+ if (event.currentTarget instanceof HTMLSelectElement && event.currentTarget.id === 'price') {
+ shopStore.dispatch({ type: 'SET_FILTER_PRICE', newFilterPrice: event.currentTarget.value });
+ }
+ if (event.currentTarget instanceof HTMLSelectElement && event.currentTarget.id === 'days') {
+ shopStore.dispatch({ type: 'SET_FILTER_DAYS', newFilterDays: event.currentTarget.value });
+ }
+ if (event.currentTarget instanceof HTMLSelectElement && event.currentTarget.id === 'sort') {
+ shopStore.dispatch({ type: 'SET_SORT_VALUE', newSortValue: event.currentTarget.value });
+ }
+ });
+ }
+}
diff --git a/src/components/shop-flters/shop-filters.scss b/src/components/shop-flters/shop-filters.scss
new file mode 100644
index 0000000..19b1980
--- /dev/null
+++ b/src/components/shop-flters/shop-filters.scss
@@ -0,0 +1,8 @@
+.shop-filters {
+ &__form {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 24px;
+ }
+}
diff --git a/src/components/shop-flters/shop-filters.ts b/src/components/shop-flters/shop-filters.ts
new file mode 100644
index 0000000..3d22c60
--- /dev/null
+++ b/src/components/shop-flters/shop-filters.ts
@@ -0,0 +1,51 @@
+import daysFilterOptions from '../../constants/daysFilterOptions';
+import priceFilterOptions from '../../constants/priceFilterOptions';
+import shopStore from '../../store/shop-store';
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import Select from '../select/select';
+import './shop-filters.scss';
+
+export default class ShopFilters extends BaseComponent<'div'> {
+ private formFilter: HTMLFormElement;
+ private resetButton: HTMLButtonElement;
+
+ constructor() {
+ super('div', ['shop-filters']);
+
+ this.formFilter = new BaseComponent('form', ['shop-filters__form']).getElement();
+ this.resetButton = new Button('reset', 'Reset', ['button--reset'], this.checkDisableBtn(), () => {
+ this.formFilter.reset();
+ shopStore.dispatch({ type: 'RESET_ALL_FILTERS' });
+ }).getElement();
+
+ this.renderFilters();
+ this.addSubscribtion();
+ }
+
+ private checkDisableBtn(): boolean {
+ const { filterPrice, filterDays } = shopStore.getState();
+ if (filterPrice || filterDays) {
+ return false;
+ }
+ return true;
+ }
+
+ private renderFilters(): void {
+ const selectPrice: HTMLDivElement = new Select('price', priceFilterOptions).getElement();
+ const selectDays: HTMLDivElement = new Select('days', daysFilterOptions).getElement();
+
+ this.formFilter.append(selectPrice, selectDays, this.resetButton);
+ this.node.append(this.formFilter);
+ }
+
+ private addSubscribtion(): void {
+ shopStore.subscribe((state) => {
+ if (state.filterPrice || state.filterDays) {
+ this.resetButton.disabled = false;
+ } else {
+ this.resetButton.disabled = true;
+ }
+ });
+ }
+}
diff --git a/src/components/shop-hero/shop-hero.scss b/src/components/shop-hero/shop-hero.scss
new file mode 100644
index 0000000..69ce863
--- /dev/null
+++ b/src/components/shop-hero/shop-hero.scss
@@ -0,0 +1,69 @@
+.shop-hero {
+ &__container {
+ @include container;
+ }
+
+ &__wrapper {
+ display: flex;
+ gap: 72px;
+ width: 100%;
+ padding-bottom: 104px;
+ border-bottom: 1px solid $color-border;
+ }
+
+ &__content {
+ display: flex;
+ flex-direction: column;
+ max-width: 500px;
+ align-self: flex-end;
+ }
+
+ &__title {
+ @include font-h2;
+ margin-bottom: 24px;
+ }
+
+ &__text {
+ font-size: 18px;
+ line-height: 150%;
+ }
+
+ &__image {
+ width: 100%;
+ height: 300px;
+ border-radius: 8px;
+ overflow: hidden;
+ background-image: url('../../assets/img/shop_hero-image.jpg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+
+ @include tablet {
+ display: none;
+ }
+
+ &--europe {
+ background-image: url('../../assets/img/shop_hero-image_europe.jpg');
+ }
+
+ &--asia {
+ background-image: url('../../assets/img/shop_hero-image_asia.jpg');
+ }
+
+ &--africa {
+ background-image: url('../../assets/img/shop_hero-image_africa.jpg');
+ }
+
+ &--america {
+ background-image: url('../../assets/img/shop_hero-image_america.jpg');
+ }
+
+ &--hiking {
+ background-image: url('../../assets/img/shop_hero-image_hiking.jpg');
+ }
+
+ &--sailing {
+ background-image: url('../../assets/img/shop_hero-image_sailing.jpg');
+ }
+ }
+}
diff --git a/src/components/shop-hero/shop-hero.test.ts b/src/components/shop-hero/shop-hero.test.ts
new file mode 100644
index 0000000..542457e
--- /dev/null
+++ b/src/components/shop-hero/shop-hero.test.ts
@@ -0,0 +1,17 @@
+import ShopHero from './shop-hero';
+
+describe('ShopHero', () => {
+ const shopHero: HTMLElement = new ShopHero('Europe').getElement();
+
+ it('should be defined', () => {
+ expect(shopHero).toBeDefined();
+ });
+ it('should have the correct title text', () => {
+ const titleElement = shopHero.querySelector('.shop-hero__title');
+ expect(titleElement?.textContent).toBe('Europe');
+ });
+ it('should have the correct image class', () => {
+ const imageBlock = shopHero.querySelector('.shop-hero__image');
+ expect(imageBlock?.classList.contains('shop-hero__image--europe')).toBe(true);
+ });
+});
diff --git a/src/components/shop-hero/shop-hero.ts b/src/components/shop-hero/shop-hero.ts
new file mode 100644
index 0000000..60511aa
--- /dev/null
+++ b/src/components/shop-hero/shop-hero.ts
@@ -0,0 +1,44 @@
+import BaseComponent from '../base-component';
+import './shop-hero.scss';
+
+export default class ShopHero extends BaseComponent<'section'> {
+ constructor(titleText: string) {
+ super('section', ['shop-hero']);
+
+ this.drawSection(titleText);
+ }
+
+ private drawSection(titleText: string): void {
+ const container: HTMLDivElement = new BaseComponent('div', ['shop-hero__container']).getElement();
+ const wrapper: HTMLDivElement = new BaseComponent('div', ['shop-hero__wrapper']).getElement();
+ const content: HTMLDivElement = new BaseComponent('div', ['shop-hero__content']).getElement();
+ const title: HTMLHeadingElement = new BaseComponent('h2', ['shop-hero__title'], titleText).getElement();
+ const text: HTMLParagraphElement = new BaseComponent(
+ 'p',
+ ['shop-hero__text'],
+ 'Satisfy your wanderlust with our collection of exclusive tours tailored to quench your thirst for exploration.'
+ ).getElement();
+ const imageBlock = new BaseComponent('div', ['shop-hero__image']).getElement();
+
+ if (titleText === 'Europe') {
+ imageBlock.classList.add('shop-hero__image--europe');
+ } else if (titleText === 'Asia') {
+ imageBlock.classList.add('shop-hero__image--asia');
+ } else if (titleText === 'Africa') {
+ imageBlock.classList.add('shop-hero__image--africa');
+ } else if (titleText === 'America') {
+ imageBlock.classList.add('shop-hero__image--america');
+ } else if (titleText === 'Hiking & Trekking') {
+ imageBlock.classList.add('shop-hero__image--hiking');
+ } else if (titleText === 'Sailing') {
+ imageBlock.classList.add('shop-hero__image--sailing');
+ } else if (titleText === 'Safari') {
+ imageBlock.classList.add('shop-hero__image--africa');
+ }
+
+ content.append(title, text);
+ wrapper.append(content, imageBlock);
+ container.append(wrapper);
+ this.node.append(container);
+ }
+}
diff --git a/src/components/shop-search/shop-search.scss b/src/components/shop-search/shop-search.scss
new file mode 100644
index 0000000..c8dcca2
--- /dev/null
+++ b/src/components/shop-search/shop-search.scss
@@ -0,0 +1,66 @@
+.shop-search {
+ margin-top: 48px;
+
+ &__container {
+ @include container;
+ }
+
+ &__form {
+ display: flex;
+ align-items: center;
+ gap: 24px;
+ }
+
+ &__input-field {
+ width: 544px;
+ position: relative;
+
+ @include mobile {
+ width: auto;
+ min-width: 0;
+ }
+ }
+
+ &__input {
+ width: 100%;
+ height: 56px;
+ border: solid 1px $color-border;
+ transition: border 0.3s ease-in-out;
+
+ &:focus,
+ &:active,
+ &:hover {
+ border: 1px solid $color-secondary-60;
+ }
+ }
+
+ &__button {
+ height: 56px;
+
+ @include mobile {
+ padding: 16px;
+ }
+ }
+
+ &__reset {
+ position: absolute;
+ top: 50%;
+ right: 10px;
+ transform: translateY(-50%);
+ width: 15px;
+ height: 15px;
+ background-image: url('../../assets/icons/popup-close-icon.svg');
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ cursor: pointer;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s ease-in-out;
+
+ &--visible {
+ opacity: 1;
+ pointer-events: all;
+ }
+ }
+}
diff --git a/src/components/shop-search/shop-search.ts b/src/components/shop-search/shop-search.ts
new file mode 100644
index 0000000..cf46eca
--- /dev/null
+++ b/src/components/shop-search/shop-search.ts
@@ -0,0 +1,81 @@
+import shopStore from '../../store/shop-store';
+import BaseComponent from '../base-component';
+import Button from '../button/button';
+import './shop-search.scss';
+import '../input/input.scss';
+
+export default class ShopSearch extends BaseComponent<'div'> {
+ private formSearch: HTMLFormElement;
+ private searchInput: HTMLInputElement;
+ private searchButton: HTMLButtonElement;
+ private resetButton: HTMLDivElement;
+
+ constructor(initialValue?: string) {
+ super('div', ['shop-search']);
+
+ this.formSearch = new BaseComponent('form', ['shop-search__form']).getElement();
+ this.searchInput = new BaseComponent('input', ['form-field__input', 'shop-search__input']).getElement();
+ this.searchButton = new Button('submit', 'Search', ['shop-search__button'], true).getElement();
+ this.resetButton = new BaseComponent('div', ['shop-search__reset']).getElement();
+
+ this.searchInput.id = 'search';
+ this.searchInput.name = 'search';
+ this.searchInput.placeholder = 'Search';
+
+ if (initialValue) {
+ this.searchInput.value = initialValue;
+ this.searchButton.disabled = false;
+ this.resetButton.classList.add('shop-search__reset--visible');
+ }
+
+ this.renderSearchPanel();
+ this.setListeners();
+ }
+
+ private renderSearchPanel(): void {
+ const container: HTMLDivElement = new BaseComponent('div', ['shop-search__container']).getElement();
+ const inputWrapper: HTMLDivElement = new BaseComponent('div', ['shop-search__input-field']).getElement();
+
+ inputWrapper.append(this.searchInput, this.resetButton);
+ this.formSearch.append(inputWrapper, this.searchButton);
+ container.append(this.formSearch);
+ this.node.append(container);
+ }
+
+ private getSearchValue(): string | undefined {
+ return new FormData(this.formSearch).get('search')?.toString();
+ }
+
+ private onSubmit(event: SubmitEvent): void {
+ event.preventDefault();
+
+ const searchValue = this.getSearchValue();
+
+ if (searchValue !== undefined && searchValue !== shopStore.getState().searchValue) {
+ shopStore.dispatch({ type: 'SET_SEARCH_VALUE', newSearchValue: searchValue });
+ }
+ }
+
+ private resetSearch(): void {
+ this.formSearch.reset();
+ this.resetButton.classList.remove('shop-search__reset--visible');
+ this.searchButton.disabled = true;
+
+ if (shopStore.getState().searchValue !== '') {
+ shopStore.dispatch({ type: 'SET_SEARCH_VALUE', newSearchValue: '' });
+ }
+ }
+
+ private setListeners(): void {
+ this.searchInput.addEventListener('input', (event) => {
+ if (event.currentTarget instanceof HTMLInputElement && event.currentTarget.value) {
+ this.searchButton.disabled = false;
+ this.resetButton.classList.add('shop-search__reset--visible');
+ } else {
+ this.resetSearch();
+ }
+ });
+ this.formSearch.addEventListener('submit', (event) => this.onSubmit(event));
+ this.resetButton.addEventListener('click', () => this.resetSearch());
+ }
+}
diff --git a/src/components/shop-sort/shop-sort.scss b/src/components/shop-sort/shop-sort.scss
new file mode 100644
index 0000000..ecbb6a1
--- /dev/null
+++ b/src/components/shop-sort/shop-sort.scss
@@ -0,0 +1,9 @@
+.shop-sort {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+
+ @include mobile {
+ flex-wrap: wrap;
+ }
+}
diff --git a/src/components/shop-sort/shop-sort.ts b/src/components/shop-sort/shop-sort.ts
new file mode 100644
index 0000000..d7c8dcf
--- /dev/null
+++ b/src/components/shop-sort/shop-sort.ts
@@ -0,0 +1,19 @@
+import sortShopOptions from '../../constants/sortShopOptions';
+import BaseComponent from '../base-component';
+import Select from '../select/select';
+import './shop-sort.scss';
+
+export default class ShopSort extends BaseComponent<'div'> {
+ constructor() {
+ super('div', ['shop-sort']);
+
+ this.renderSort();
+ }
+
+ private renderSort(): void {
+ const selectSortLabel: HTMLSpanElement = new BaseComponent('span', [], 'Sort By:').getElement();
+ const selectSort: HTMLDivElement = new Select('sort', sortShopOptions, ['select--sort']).getElement();
+
+ this.node.append(selectSortLabel, selectSort);
+ }
+}
diff --git a/src/components/slider/slider.scss b/src/components/slider/slider.scss
new file mode 100644
index 0000000..8caf519
--- /dev/null
+++ b/src/components/slider/slider.scss
@@ -0,0 +1,101 @@
+.product__slider {
+ display: flex;
+ flex-direction: column;
+ width: calc(50% - 12px);
+ gap: 24px;
+ user-select: none;
+
+ @include laptop {
+ width: 80%;
+ }
+
+ @include mobile {
+ width: 100%;
+ }
+
+ .swiper {
+ width: 100%;
+
+ &-list {
+ display: flex;
+
+ .swiper-slide {
+ width: 25%;
+ aspect-ratio: 3/2;
+ opacity: 0.4;
+
+ &-thumb-active {
+ opacity: 1;
+ }
+ }
+ }
+
+ &-view {
+ display: flex;
+
+ .swiper-slide {
+ width: 100%;
+ aspect-ratio: 3/2;
+
+ &-active {
+ cursor: zoom-in;
+ }
+ }
+ }
+
+ &-wrapper {
+ width: 100%;
+ display: flex;
+ }
+
+ &-slide img {
+ display: block;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ border-radius: 8px;
+ }
+ }
+
+ &_modal {
+ display: flex;
+ justify-content: center;
+ max-width: 100%;
+ max-height: 80vh;
+ user-select: none;
+ z-index: 20;
+
+ .swiper-view {
+ max-height: 100%;
+ width: 100%;
+ }
+
+ .swiper-slide {
+ display: flex;
+ justify-content: center;
+ width: 100%;
+ }
+
+ & img {
+ display: block;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ border-radius: 8px;
+ }
+ }
+}
+
+.swiper-button {
+ &-next,
+ &-prev {
+ opacity: 0.6;
+ color: #ffffff;
+ cursor: pointer;
+ transition: opacity 0.3s ease;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+}
diff --git a/src/components/slider/slider.ts b/src/components/slider/slider.ts
new file mode 100644
index 0000000..64139ce
--- /dev/null
+++ b/src/components/slider/slider.ts
@@ -0,0 +1,170 @@
+import Swiper from 'swiper';
+import BaseComponent from '../base-component';
+import { Image } from '@commercetools/platform-sdk';
+import { Navigation, Thumbs } from 'swiper/modules';
+import 'swiper/css/navigation';
+import 'swiper/css';
+import './slider.scss';
+
+interface IMainComponents {
+ sliderView: HTMLDivElement;
+ sliderBtnNext: HTMLDivElement;
+ sliderBtnPrev: HTMLDivElement;
+ sliderList: HTMLDivElement;
+}
+
+export default class ProductSlider extends BaseComponent<'div'> {
+ private images: Image[];
+ private sliderView: HTMLElement;
+ private sliderList: HTMLElement;
+ private sliderBtnNext: HTMLElement;
+ private sliderBtnPrev: HTMLElement;
+ private modalWindow: HTMLElement;
+
+ constructor(images: Image[]) {
+ super('div', ['product__slider']);
+ this.images = images;
+
+ const mainComponents = this.initMainComponents();
+ this.sliderView = mainComponents.sliderView;
+ this.sliderList = mainComponents.sliderList;
+ this.sliderBtnNext = mainComponents.sliderBtnNext;
+ this.sliderBtnPrev = mainComponents.sliderBtnPrev;
+ this.modalWindow = new BaseComponent('div', ['popup', 'open']).getElement();
+ this.modalWindow.addEventListener('click', this.onBackdropClick.bind(this));
+
+ this.createMarkup();
+ }
+
+ private initMainComponents(): IMainComponents {
+ const sliderView = new BaseComponent('div', ['swiper', 'swiper-view']).getElement();
+ const sliderBtnNext = new BaseComponent('div', ['swiper-button-next']).getElement();
+ const sliderBtnPrev = new BaseComponent('div', ['swiper-button-prev']).getElement();
+ const sliderList = new BaseComponent('div', ['swiper', 'swiper-list']).getElement();
+
+ return {
+ sliderView,
+ sliderBtnNext,
+ sliderBtnPrev,
+ sliderList,
+ };
+ }
+
+ private createMarkup(): void {
+ const swiperViewWrapper = new BaseComponent('div', ['swiper-wrapper']).getElement();
+ this.setOpenListener(swiperViewWrapper);
+
+ const swiperListWrapper = new BaseComponent('div', ['swiper-wrapper']).getElement();
+
+ for (let i = 0; i < this.images.length; i++) {
+ const imageViewContainer = new BaseComponent('div', ['swiper-slide']).getElement();
+ const imageView = new BaseComponent('img').getElement();
+ imageView.src = this.images[i].url;
+
+ const imageListContainer = new BaseComponent('div', ['swiper-slide']).getElement();
+ const imageList = new BaseComponent('img').getElement();
+ imageList.src = this.images[i].url;
+
+ imageViewContainer.append(imageView);
+ imageListContainer.append(imageList);
+
+ swiperViewWrapper.append(imageViewContainer);
+ swiperListWrapper.append(imageListContainer);
+ }
+
+ this.sliderView.append(swiperViewWrapper, this.sliderBtnNext, this.sliderBtnPrev);
+ this.sliderList.append(swiperListWrapper);
+
+ this.node.append(this.sliderView, this.sliderList);
+
+ this.initSwiper();
+ }
+
+ private initSwiper(): void {
+ const swiperList = new Swiper(this.sliderList, {
+ loop: true,
+ spaceBetween: 10,
+ slidesPerView: 4,
+ freeMode: true,
+ watchSlidesProgress: true,
+ });
+
+ new Swiper(this.sliderView, {
+ loop: true,
+ spaceBetween: 24,
+ modules: [Navigation, Thumbs],
+ navigation: {
+ nextEl: this.sliderBtnNext,
+ prevEl: this.sliderBtnPrev,
+ },
+ thumbs: {
+ swiper: swiperList,
+ },
+ });
+ }
+
+ private setOpenListener(element: HTMLElement): void {
+ element.addEventListener('click', (event) => {
+ event.preventDefault();
+
+ if (event.target instanceof HTMLElement) {
+ const firstSlide: HTMLElement | null = event.target.closest('.swiper-slide-active');
+ const imageIndex = Number(firstSlide?.getAttribute('data-swiper-slide-index') || 0);
+
+ this.openModal(imageIndex);
+ }
+ });
+ }
+
+ private openModal(index: number): void {
+ const modalContainer = new BaseComponent('div', ['product__slider_modal']).getElement();
+ const modalView = this.sliderView.cloneNode(true);
+
+ modalView.innerHTML = '';
+
+ const modalViewWrapper = new BaseComponent('div', ['swiper-wrapper']).getElement();
+ const modalBtnNext = this.sliderBtnNext.cloneNode(true);
+ const modalBtnPrev = this.sliderBtnPrev.cloneNode(true);
+
+ for (let i = 0; i < this.images.length; i++) {
+ const imageViewContainer = new BaseComponent('div', ['swiper-slide']).getElement();
+ const imageView = new BaseComponent('img').getElement();
+ imageView.src = this.images[i].url;
+
+ imageViewContainer.append(imageView);
+
+ modalViewWrapper.append(imageViewContainer);
+ }
+
+ modalView.append(modalViewWrapper, modalBtnNext, modalBtnPrev);
+
+ modalContainer.append(modalView);
+ this.modalWindow.append(modalContainer);
+
+ document.body.append(this.modalWindow);
+
+ new Swiper(modalView, {
+ loop: true,
+ spaceBetween: 24,
+ modules: [Navigation],
+ navigation: {
+ nextEl: modalBtnNext,
+ prevEl: modalBtnPrev,
+ },
+ initialSlide: index,
+ });
+ }
+
+ onBackdropClick(event: MouseEvent): void {
+ event.preventDefault();
+
+ if (event.target instanceof HTMLElement) {
+ if (event.target.classList.contains('popup')) this.removeModalWindow();
+ }
+ }
+
+ private removeModalWindow(): void {
+ this.modalWindow.innerHTML = '';
+ this.modalWindow.remove();
+ }
+}
diff --git a/src/components/sup/sup.scss b/src/components/sup/sup.scss
new file mode 100644
index 0000000..4d7f9b5
--- /dev/null
+++ b/src/components/sup/sup.scss
@@ -0,0 +1,10 @@
+.sup {
+ margin: 0 3px;
+ padding: 2px 6px 3px;
+ font-size: 10px;
+ font-weight: 700;
+ text-align: center;
+ white-space: nowrap;
+ border-radius: 8px;
+ background: rgba(#ff8a00, 0.5);
+}
diff --git a/src/components/sup/sup.test.ts b/src/components/sup/sup.test.ts
new file mode 100644
index 0000000..3986601
--- /dev/null
+++ b/src/components/sup/sup.test.ts
@@ -0,0 +1,15 @@
+import Sup from './sup';
+
+describe('Sup', () => {
+ const sup: HTMLElement = new Sup('Sub text', ['sup-test-class']).getElement();
+
+ it('should render correct html-element', () => {
+ expect(sup.outerHTML).toBe('Sub text');
+ });
+ it('should render correct textContent', () => {
+ expect(sup.textContent).toBe('Sub text');
+ });
+ it('should render correct classList', () => {
+ expect(sup.classList.contains('sup-test-class')).toBe(true);
+ });
+});
diff --git a/src/components/sup/sup.ts b/src/components/sup/sup.ts
new file mode 100644
index 0000000..e8a40d5
--- /dev/null
+++ b/src/components/sup/sup.ts
@@ -0,0 +1,8 @@
+import BaseComponent from '../base-component';
+import './sup.scss';
+
+export default class Sup extends BaseComponent<'sup'> {
+ constructor(text: string, classes: string[] = []) {
+ super('sup', ['sup', ...classes], text);
+ }
+}
diff --git a/src/constants/aboutUsMembers.ts b/src/constants/aboutUsMembers.ts
new file mode 100644
index 0000000..ad84641
--- /dev/null
+++ b/src/constants/aboutUsMembers.ts
@@ -0,0 +1,36 @@
+import { IAboutUsMember } from '../types/interfaces';
+
+const aboutUsMembers: IAboutUsMember[] = [
+ {
+ name: 'Andrew Suponev',
+ role: 'Team Lead, Front-End Developer',
+ imgClass: 'andrew',
+ about: `Since childhood I loved to stay up late and create websites using basic HTML and CSS. But, unfortunately, after graduation, my life path and IT missed each other. Now I'm 29 years old, I dream be a web developer and contribute to society by doing what I love.`,
+ contributions: [
+ 'Configured project setup',
+ 'Implemented interaction with commercetools',
+ 'Create Signup Page',
+ 'Created Catalog page',
+ ],
+ link: 'https://github.com/elsuppo',
+ },
+ {
+ name: 'Yauheni Baltsevich',
+ role: 'Front-End Developer',
+ imgClass: 'yauheni',
+ about:
+ 'My main goal is to become a Software Engeener. Currently, I live for permanent residence in Poland, it was here that I firmly decided that I would become a Software Engeneer, since this is a profession in which I definitely see myself.',
+ contributions: ['Сonfigured Jest', 'Configured TypeScript', 'Created Signin Page', 'Created Detailed Product page'],
+ link: 'https://github.com/eugenebalts',
+ },
+ {
+ name: 'Maksim Lisianskii',
+ role: 'Front-End Developer',
+ imgClass: 'maksim',
+ about: `I'm middle Front-end Developer living in Saint-Petersburg. I'm currently learning TypeScript and React and I enjoy making beautiful web sites on HTML,CSS and JavaScript.`,
+ contributions: ['Configured Bundler', 'Implemented Routing', 'Created Account Page', 'Created Adresses Page'],
+ link: 'https://github.com/MaxLisyanskiy',
+ },
+];
+
+export default aboutUsMembers;
diff --git a/src/constants/aboutUsMethods.ts b/src/constants/aboutUsMethods.ts
new file mode 100644
index 0000000..a76f75a
--- /dev/null
+++ b/src/constants/aboutUsMethods.ts
@@ -0,0 +1,29 @@
+interface IAboutUsMethods {
+ title: string;
+ description: string;
+}
+
+const aboutUsMethods: IAboutUsMethods[] = [
+ {
+ title: 'Correct team formation and distribution of roles',
+ description:
+ 'This is the initial stage of project team development, where all involved participants get to know each other. The leader of the project establishes favorable relationships and interactions within the work group. The team studies the main goals and objectives, begins to develop common norms and agree on values, as well as the distribution of roles in the team.',
+ },
+ {
+ title: 'Apply project management methodologies',
+ description:
+ 'Methodologies help to record the completion time of different types of tasks and correct weak points in time. We used Kanban and Scrum methodologies.',
+ },
+ {
+ title: 'Set up team communication',
+ description:
+ 'Decide on a fixed daily time, "sunday retrospectives" - meetings where they discuss the past week and decide what processes can be improved, chat and a Discord channel - necessary things that we have implemented for convenient communication in the team!',
+ },
+ {
+ title: 'Provide team members with regular feedback and task reviews',
+ description:
+ 'Feedback from each team member helps our team understand how we are doing the job - what we are already doing well and what skills need to be improved. Also, a code-review before merging is a way to look at the code from a different perspective and identify errors that might have been missed, suggest or recommend good practices, and it also improves the reviewer’s ability to see other people’s code.',
+ },
+];
+
+export default aboutUsMethods;
diff --git a/src/constants/addressInputs.ts b/src/constants/addressInputs.ts
new file mode 100644
index 0000000..9485af6
--- /dev/null
+++ b/src/constants/addressInputs.ts
@@ -0,0 +1,42 @@
+export const AddressInputs = {
+ main: [
+ {
+ type: 'text',
+ name: 'streetName',
+ label: 'Street',
+ placeholder: 'Street',
+ },
+ {
+ type: 'text',
+ name: 'city',
+ label: 'City',
+ placeholder: 'City',
+ },
+ {
+ type: 'text',
+ name: 'postalCode',
+ label: 'Postcode',
+ placeholder: 'Postcode',
+ },
+ {
+ type: 'text',
+ name: 'country',
+ label: 'Country',
+ placeholder: 'Country',
+ },
+ ],
+ checkboxes: [
+ {
+ type: 'checkbox',
+ name: 'checkboxDefaultBilling',
+ label: 'Set Billing address as default',
+ placeholder: '',
+ },
+ {
+ type: 'checkbox',
+ name: 'checkboxDefaultShipping',
+ label: 'Set Shipping address as default',
+ placeholder: '',
+ },
+ ],
+};
diff --git a/src/constants/categories.ts b/src/constants/categories.ts
new file mode 100644
index 0000000..9f2c88c
--- /dev/null
+++ b/src/constants/categories.ts
@@ -0,0 +1,26 @@
+import { ICategory } from '../types/types';
+
+const categories: ICategory[] = [
+ {
+ slug: 'europe',
+ label: 'Europe',
+ url: '/shop/europe',
+ },
+ {
+ slug: 'asia',
+ label: 'Asia',
+ url: '/shop/asia',
+ },
+ {
+ slug: 'america',
+ label: 'America',
+ url: '/shop/america',
+ },
+ {
+ slug: 'africa',
+ label: 'Africa',
+ url: '/shop/africa',
+ },
+];
+
+export default categories;
diff --git a/src/constants/daysFilterOptions.ts b/src/constants/daysFilterOptions.ts
new file mode 100644
index 0000000..e4b8624
--- /dev/null
+++ b/src/constants/daysFilterOptions.ts
@@ -0,0 +1,28 @@
+const daysFilterOptions = [
+ {
+ label: 'Days',
+ value: '',
+ },
+ {
+ label: '0 - 5 days',
+ value: '"0","1","2","3","4","5"',
+ },
+ {
+ label: '6 - 10 days',
+ value: '"6","7","8","9","10"',
+ },
+ {
+ label: '11 - 15 days',
+ value: '"11","12","13","14","15"',
+ },
+ {
+ label: '16 - 20 days',
+ value: '"16","17","18","19","20"',
+ },
+ {
+ label: 'over 20 days',
+ value: '"21","22","23","24","25"',
+ },
+];
+
+export default daysFilterOptions;
diff --git a/src/constants/detailsEditInputs.ts b/src/constants/detailsEditInputs.ts
new file mode 100644
index 0000000..d5d2a0d
--- /dev/null
+++ b/src/constants/detailsEditInputs.ts
@@ -0,0 +1,43 @@
+export const detailsEditInputs = {
+ main: [
+ {
+ type: 'text',
+ name: 'firstName',
+ label: 'First Name',
+ placeholder: 'First Name',
+ },
+ {
+ type: 'text',
+ name: 'lastName',
+ label: 'Last Name',
+ placeholder: 'Last Name',
+ },
+ {
+ type: 'date',
+ name: 'dateOfBirth',
+ label: 'Date of birth',
+ placeholder: 'Date of birth',
+ },
+ {
+ type: 'email',
+ name: 'email',
+ label: 'Email',
+ placeholder: 'Email',
+ },
+ ],
+ passwords: [
+ {
+ type: 'password',
+ name: 'currentPassword',
+ label: 'Current Password',
+ placeholder: 'Current Password',
+ },
+
+ {
+ type: 'password',
+ name: 'newPassword',
+ label: 'New password',
+ placeholder: 'New password',
+ },
+ ],
+};
diff --git a/src/constants/formValidationRules.ts b/src/constants/formValidationRules.ts
new file mode 100644
index 0000000..8464d26
--- /dev/null
+++ b/src/constants/formValidationRules.ts
@@ -0,0 +1,74 @@
+interface IValidationRule {
+ rule: RegExp;
+ errorText: string;
+ secondErrorText?: string;
+}
+
+interface IValidationRules {
+ password: IValidationRule;
+ newPassword: IValidationRule;
+ firstName: IValidationRule;
+ lastName: IValidationRule;
+ email: IValidationRule;
+ birthDate: IValidationRule;
+ streetShipping: IValidationRule;
+ cityShipping: IValidationRule;
+ postcodeShipping: IValidationRule;
+ streetBilling: IValidationRule;
+ cityBilling: IValidationRule;
+ postcodeBilling: IValidationRule;
+}
+
+const formValidationRules: IValidationRules = {
+ password: {
+ rule: /^(?=.*\p{Lu})(?=.*\p{Ll})(?=.*\d).{8,}$/u,
+ errorText: 'Requires minimum 8 characters, 1 uppercase, 1 lowercase and 1 number',
+ },
+ newPassword: {
+ rule: /^(?=.*\p{Lu})(?=.*\p{Ll})(?=.*\d).{8,}$/u,
+ errorText: 'Requires minimum 8 characters, 1 uppercase, 1 lowercase and 1 number',
+ secondErrorText: 'The new password must be different from the current password',
+ },
+ firstName: {
+ rule: /^[^\d!@#$%^&*()_+[\]{};':"\\|,.<>/?]+$/,
+ errorText: 'Requires at least one letter, no special characters or numbers',
+ },
+ lastName: {
+ rule: /^[^\d!@#$%^&*()_+[\]{};':"\\|,.<>/?]+$/,
+ errorText: 'Requires at least one letter, no special characters or numbers',
+ },
+ email: {
+ rule: /^\S+@\S+\.\S+$/,
+ errorText: 'Requires a valid email address (e.g., example@email.com)',
+ },
+ birthDate: {
+ rule: /^\d{4}-\d{2}-\d{2}$/,
+ errorText: 'Please enter your date of birth in the format "dd.mm.yyyy"',
+ },
+ streetShipping: {
+ rule: /^.+$/,
+ errorText: 'Requires at least one letter',
+ },
+ cityShipping: {
+ rule: /^[^\d!@#$%^&*()_+[\]{};':"\\|,.<>/?]+$/,
+ errorText: 'Requires at least one letter, no special characters or numbers',
+ },
+ postcodeShipping: {
+ rule: /^\d{5}$/,
+ errorText: 'Requires exactly 5 digits, follow the format for the country (e.g., 12345 for the U.S)',
+ },
+ streetBilling: {
+ rule: /^.+$/,
+ errorText: 'Requires at least one letter',
+ },
+ cityBilling: {
+ rule: /^[^\d!@#$%^&*()_+[\]{};':"\\|,.<>/?]+$/,
+ errorText: 'Requires at least one letter, no special characters or numbers',
+ },
+ postcodeBilling: {
+ rule: /^\d{5}$/,
+ errorText: 'Requires exactly 5 digits, follow the format for the country (e.g., 12345 for the U.S)',
+ },
+};
+
+export default formValidationRules;
diff --git a/src/constants/priceFilterOptions.ts b/src/constants/priceFilterOptions.ts
new file mode 100644
index 0000000..46be987
--- /dev/null
+++ b/src/constants/priceFilterOptions.ts
@@ -0,0 +1,28 @@
+const priceFilterOptions = [
+ {
+ label: 'Price',
+ value: '',
+ },
+ {
+ label: 'under $1,500',
+ value: 'range (* to 150000)',
+ },
+ {
+ label: '$1,500 - $2,000',
+ value: 'range (150000 to 200000)',
+ },
+ {
+ label: '$2,000 - $2,500',
+ value: 'range (200000 to 250000)',
+ },
+ {
+ label: '$2,500 - $3,000',
+ value: 'range (250000 to 300000)',
+ },
+ {
+ label: 'over $3,000',
+ value: 'range (300000 to *)',
+ },
+];
+
+export default priceFilterOptions;
diff --git a/src/constants/productsOptions.ts b/src/constants/productsOptions.ts
new file mode 100644
index 0000000..04b3514
--- /dev/null
+++ b/src/constants/productsOptions.ts
@@ -0,0 +1,2 @@
+export const BASE_PRODUCT_OFFSET: number = 0;
+export const BASE_PRODUCT_LIMIT: number = 12;
diff --git a/src/constants/promoCodes.ts b/src/constants/promoCodes.ts
new file mode 100644
index 0000000..bfdb943
--- /dev/null
+++ b/src/constants/promoCodes.ts
@@ -0,0 +1,30 @@
+import { IPromoCodes } from '../types/interfaces';
+
+const promoCodes: IPromoCodes[] = [
+ {
+ title: 'Family Getaway Deal: Kids Stay Free',
+ descr: 'Have an unforgettable family getaway where kids stay for free with promo code FAMILYFUN.',
+ code: 'FAMILYFUN',
+ expirationDate: '09/25/2023, 11:59 PM',
+ },
+ {
+ title: 'Last-Minute Wanderlust: 10% Off Any Booking',
+ descr: 'Embrace your last-minute wanderlust and enjoy 10% off any booking with promo code LASTCHANCE.',
+ code: 'LASTCHANCE',
+ expirationDate: '10/01/2023, 11:59 PM',
+ },
+ {
+ title: 'Cruise in Style: $100 Off Ocean View Cabins',
+ descr: 'Cruise in style! Get $100 off ocean view cabins with promo code CRUISE100.',
+ code: 'CRUISE100',
+ expirationDate: '10/08/2023, 11:59 PM',
+ },
+ {
+ title: 'Group Adventure: 25% Off for Parties of 4 or More',
+ descr: 'Plan a group adventure and enjoy a 25% discount for parties of 4 or more with promo code GROUP24.',
+ code: 'GROUP24',
+ expirationDate: '12/25/2023, 11:59 PM',
+ },
+];
+
+export default promoCodes;
diff --git a/src/constants/signupInputs.ts b/src/constants/signupInputs.ts
new file mode 100644
index 0000000..53559b1
--- /dev/null
+++ b/src/constants/signupInputs.ts
@@ -0,0 +1,96 @@
+export const signupInputs = {
+ infoInputs: [
+ {
+ type: 'text',
+ name: 'firstName',
+ label: 'First Name',
+ placeholder: 'First Name',
+ },
+ {
+ type: 'text',
+ name: 'lastName',
+ label: 'Last Name',
+ placeholder: 'Last Name',
+ },
+ {
+ type: 'email',
+ name: 'email',
+ label: 'Email',
+ placeholder: 'Email',
+ },
+ {
+ type: 'password',
+ name: 'password',
+ label: 'Password',
+ placeholder: 'Password',
+ },
+ {
+ type: 'date',
+ name: 'birthDate',
+ label: 'Date of birth',
+ placeholder: 'Date of birth',
+ },
+ {
+ type: 'text',
+ name: 'country',
+ label: 'Country',
+ placeholder: 'Country',
+ },
+ ],
+ addressInputs: [
+ {
+ type: 'text',
+ name: 'streetShipping',
+ label: 'Shipping address (street)',
+ placeholder: 'Street',
+ },
+ {
+ type: 'text',
+ name: 'cityShipping',
+ label: 'Shipping address (city)',
+ placeholder: 'City',
+ },
+ {
+ type: 'text',
+ name: 'postcodeShipping',
+ label: 'Shipping address (postcode)',
+ placeholder: 'Postcode',
+ },
+ {
+ type: 'checkbox',
+ name: 'checkboxAddress',
+ label: 'The shipping address matches the billing address',
+ placeholder: '',
+ },
+ {
+ type: 'text',
+ name: 'streetBilling',
+ label: 'Billing address (street)',
+ placeholder: 'Street',
+ },
+ {
+ type: 'text',
+ name: 'cityBilling',
+ label: 'Billing address (city)',
+ placeholder: 'City',
+ },
+ {
+ type: 'text',
+ name: 'postcodeBilling',
+ label: 'Billing address (postcode)',
+ placeholder: 'Postcode',
+ },
+ {
+ type: 'checkbox',
+ name: 'checkboxDefaultShipping',
+ label: 'Set Shipping address as default',
+ placeholder: '',
+ },
+ {
+ type: 'checkbox',
+ name: 'checkboxDefaultBilling',
+ label: 'Set Billing address as default',
+ placeholder: '',
+ },
+ ],
+};
diff --git a/src/constants/sortShopOptions.ts b/src/constants/sortShopOptions.ts
new file mode 100644
index 0000000..d14c3d6
--- /dev/null
+++ b/src/constants/sortShopOptions.ts
@@ -0,0 +1,24 @@
+const sortShopOptions = [
+ {
+ label: 'Default',
+ value: '',
+ },
+ {
+ label: 'By price (ascending)',
+ value: 'price asc',
+ },
+ {
+ label: 'By price (descending)',
+ value: 'price desc',
+ },
+ {
+ label: 'By title (A - Z)',
+ value: 'name.en asc',
+ },
+ {
+ label: 'By title (Z - A)',
+ value: 'name.en desc',
+ },
+];
+
+export default sortShopOptions;
diff --git a/src/constants/subcategories.ts b/src/constants/subcategories.ts
new file mode 100644
index 0000000..81c2171
--- /dev/null
+++ b/src/constants/subcategories.ts
@@ -0,0 +1,134 @@
+import { ICategory } from '../types/types';
+
+const subcategories: { [key: string]: ICategory[] } = {
+ europe: [
+ {
+ slug: '',
+ label: 'All Tours',
+ url: '/shop',
+ },
+ {
+ slug: 'europe',
+ label: 'All in Europe',
+ url: '/shop/europe',
+ },
+ {
+ slug: 'hiking-trekking-eu',
+ label: 'Hiking & Trekking',
+ url: '/shop/europe/hiking-trekking-eu',
+ },
+ {
+ slug: 'explorer-eu',
+ label: 'Explorer',
+ url: '/shop/europe/explorer-eu',
+ },
+ {
+ slug: 'safari-eu',
+ label: 'Safari',
+ url: '/shop/europe/safari-eu',
+ },
+ {
+ slug: 'sailing-eu',
+ label: 'Sailing',
+ url: '/shop/europe/sailing-eu',
+ },
+ ],
+ asia: [
+ {
+ slug: '',
+ label: 'All Tours',
+ url: '/shop',
+ },
+ {
+ slug: 'asia',
+ label: 'All in Asia',
+ url: '/shop/asia',
+ },
+ {
+ slug: 'hiking-trekking-as',
+ label: 'Hiking & Trekking',
+ url: '/shop/asia/hiking-trekking-as',
+ },
+ {
+ slug: 'explorer-as',
+ label: 'Explorer',
+ url: '/shop/asia/explorer-as',
+ },
+ {
+ slug: 'safari-as',
+ label: 'Safari',
+ url: '/shop/asia/safari-as',
+ },
+ {
+ slug: 'sailing-as',
+ label: 'Sailing',
+ url: '/shop/asia/sailing-as',
+ },
+ ],
+ america: [
+ {
+ slug: '',
+ label: 'All Tours',
+ url: '/shop',
+ },
+ {
+ slug: 'america',
+ label: 'All in America',
+ url: '/shop/america',
+ },
+ {
+ slug: 'hiking-trekking-am',
+ label: 'Hiking & Trekking',
+ url: '/shop/america/hiking-trekking-am',
+ },
+ {
+ slug: 'explorer-am',
+ label: 'Explorer',
+ url: '/shop/america/explorer-am',
+ },
+ {
+ slug: 'safari-am',
+ label: 'Safari',
+ url: '/shop/america/safari-am',
+ },
+ {
+ slug: 'sailing-am',
+ label: 'Sailing',
+ url: '/shop/america/sailing-am',
+ },
+ ],
+ africa: [
+ {
+ slug: '',
+ label: 'All Tours',
+ url: '/shop',
+ },
+ {
+ slug: 'africa',
+ label: 'All in Africa',
+ url: '/shop/africa',
+ },
+ {
+ slug: 'hiking-trekking-af',
+ label: 'Hiking & Trekking',
+ url: '/shop/africa/hiking-trekking-af',
+ },
+ {
+ slug: 'explorer-af',
+ label: 'Explorer',
+ url: '/shop/africa/explorer-af',
+ },
+ {
+ slug: 'safari-af',
+ label: 'Safari',
+ url: '/shop/africa/safari-af',
+ },
+ {
+ slug: 'sailing-af',
+ label: 'Sailing',
+ url: '/shop/africa/sailing-af',
+ },
+ ],
+};
+
+export default subcategories;
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 0000000..bb197ca
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,9 @@
+
+
+
+
+
+ <%= htmlWebpackPlugin.options.title %>
+
+
+
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..fecdbfb
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,43 @@
+import { createRouter } from './router';
+import Header from './components/header/header';
+import Footer from './components/footer/footer';
+import getUser from './services/getUser';
+import userStore from './store/user-store';
+import Notification from './components/notification/notification';
+import getCart from './services/basket/getCart';
+import cartStore from './store/cart-store';
+import './styles/index.scss';
+
+class App {
+ public async start() {
+ const header = new Header().getElement();
+ const main = document.createElement('main');
+ const footer = new Footer().getElement();
+
+ document.body.append(header, main, footer);
+
+ try {
+ const token = localStorage.getItem('token');
+ if (token) {
+ const customer = await getUser(token);
+ userStore.dispatch({ type: 'SET_IS_AUTH', isAuth: true });
+ userStore.dispatch({ type: 'ADD_CUSTOMER', customer });
+ }
+ const cart = await getCart();
+ cartStore.dispatch({ type: 'UPDATE_CART', cart });
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+ localStorage.removeItem('token');
+ }
+
+ createRouter(main);
+ }
+}
+
+const app: App = new App();
+
+app.start();
diff --git a/src/pages/about-us-page/about-us-page.scss b/src/pages/about-us-page/about-us-page.scss
new file mode 100644
index 0000000..a9bb5c5
--- /dev/null
+++ b/src/pages/about-us-page/about-us-page.scss
@@ -0,0 +1,14 @@
+.about-us-page {
+ &__container {
+ @include container;
+ }
+
+ &__title {
+ @include font-h1;
+ max-width: 1025px;
+
+ & span {
+ color: $color-logo;
+ }
+ }
+}
diff --git a/src/pages/about-us-page/about-us-page.ts b/src/pages/about-us-page/about-us-page.ts
new file mode 100644
index 0000000..5876f94
--- /dev/null
+++ b/src/pages/about-us-page/about-us-page.ts
@@ -0,0 +1,46 @@
+import BaseComponent from '../../components/base-component';
+import Breadcrumbs from '../../components/breadcrumbs/breadcrumbs';
+import { IBreadcrumbLink } from '../../types/interfaces';
+import { AppRoutesPath } from '../../router/types';
+import AboutUsList from '../../components/about-us/about-us-list';
+import AboutUsCollaboration from '../../components/about-us/about-us-collaboration';
+import AboutUsRSSchool from '../../components/about-us/about-us-rsschool-link';
+import './about-us-page.scss';
+
+const breadcrumbsLinks: IBreadcrumbLink[] = [
+ {
+ pageName: 'Home',
+ pageHref: AppRoutesPath.MAIN,
+ },
+];
+
+export default class AboutUsPage extends BaseComponent<'div'> {
+ private breadcrumbs: HTMLElement;
+ private aboutUsContainer: HTMLElement;
+
+ constructor() {
+ super('div', ['about-us-page']);
+
+ this.breadcrumbs = new Breadcrumbs(breadcrumbsLinks, 'About Us').getElement();
+
+ this.aboutUsContainer = new BaseComponent('div', ['about-us-page__container']).getElement();
+ this.renderAboutUsSection();
+
+ this.node.append(this.breadcrumbs, this.aboutUsContainer);
+ }
+
+ private renderAboutUsSection(): void {
+ const sectionTitle = new BaseComponent(
+ 'h1',
+ ['about-us-page__title'],
+ 'Discover Our Team: Meet the Faces Behind'
+ ).getElement();
+ sectionTitle.insertAdjacentHTML('beforeend', ' this is this.');
+
+ const aboutUsList = new AboutUsList().getElement();
+ const aboutUsCollaboration = new AboutUsCollaboration().getElement();
+ const aboutUsRSSchool = new AboutUsRSSchool().getElement();
+
+ this.aboutUsContainer.append(sectionTitle, aboutUsList, aboutUsCollaboration, aboutUsRSSchool);
+ }
+}
diff --git a/src/pages/account-page/account-page.scss b/src/pages/account-page/account-page.scss
new file mode 100644
index 0000000..da86be3
--- /dev/null
+++ b/src/pages/account-page/account-page.scss
@@ -0,0 +1,29 @@
+.account-page {
+ padding-bottom: 50px;
+
+ &__container {
+ @include container;
+ display: flex;
+
+ @include tablet {
+ flex-direction: column;
+ }
+ }
+
+ &__details {
+ width: 50%;
+ margin-right: 24px;
+ @include tablet {
+ width: 100%;
+ margin-right: 0;
+ }
+ }
+
+ &__addresses {
+ width: 50%;
+ @include tablet {
+ margin-top: 30px;
+ width: 100%;
+ }
+ }
+}
diff --git a/src/pages/account-page/account-page.ts b/src/pages/account-page/account-page.ts
new file mode 100644
index 0000000..c384292
--- /dev/null
+++ b/src/pages/account-page/account-page.ts
@@ -0,0 +1,45 @@
+import BaseComponent from '../../components/base-component';
+import Breadcrumbs from '../../components/breadcrumbs/breadcrumbs';
+import AccountDetails from '../../components/account/account-details/account-details';
+import AccountAddresses from '../../components/account/account-addresses/account-addresses';
+import { IBreadcrumbLink } from '../../types/interfaces';
+import { AccountInfoMode } from '../../types/enums';
+import { AppRoutesPath } from '../../router/types';
+import './account-page.scss';
+
+const breadcrumbsLinks: IBreadcrumbLink[] = [
+ {
+ pageName: 'Home',
+ pageHref: AppRoutesPath.MAIN,
+ },
+];
+
+export default class AccountPage extends BaseComponent<'div'> {
+ private breadcrumbs: HTMLElement;
+ private container: HTMLElement;
+ private detailsSection: HTMLElement;
+ private addressesSection: HTMLElement;
+ private userProfileMode: AccountInfoMode = AccountInfoMode.SHOW;
+
+ constructor() {
+ super('div', ['account-page']);
+
+ this.breadcrumbs = new Breadcrumbs(breadcrumbsLinks, 'Account', true).getElement();
+ this.container = new BaseComponent('div', ['account-page__container']).getElement();
+ this.detailsSection = new BaseComponent('section', ['account-page__details']).getElement();
+ this.addressesSection = new BaseComponent('section', ['account-page__addresses']).getElement();
+
+ this.detailsSection.append(new AccountDetails(this.userProfileMode, this.changeUserProfileMode).getElement());
+ this.addressesSection.append(new AccountAddresses().getElement());
+
+ this.container.append(this.detailsSection, this.addressesSection);
+
+ this.node.append(this.breadcrumbs, this.container);
+ }
+
+ private changeUserProfileMode = (): void => {
+ this.detailsSection.innerHTML = '';
+ this.userProfileMode = this.userProfileMode === AccountInfoMode.SHOW ? AccountInfoMode.EDIT : AccountInfoMode.SHOW;
+ this.detailsSection.append(new AccountDetails(this.userProfileMode, this.changeUserProfileMode).getElement());
+ };
+}
diff --git a/src/pages/addresses-page/addresses-page.scss b/src/pages/addresses-page/addresses-page.scss
new file mode 100644
index 0000000..90b1478
--- /dev/null
+++ b/src/pages/addresses-page/addresses-page.scss
@@ -0,0 +1,24 @@
+.addresses-page {
+ padding-bottom: 50px;
+
+ &__container {
+ @include container;
+ }
+
+ &__title-wrapp {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ &__title {
+ @include font-h3;
+ }
+
+ &__add-btn {
+ margin-top: 32px;
+ &.hidden {
+ display: none;
+ }
+ }
+}
diff --git a/src/pages/addresses-page/addresses-page.ts b/src/pages/addresses-page/addresses-page.ts
new file mode 100644
index 0000000..ef26965
--- /dev/null
+++ b/src/pages/addresses-page/addresses-page.ts
@@ -0,0 +1,138 @@
+import BaseComponent from '../../components/base-component';
+import Breadcrumbs from '../../components/breadcrumbs/breadcrumbs';
+import Link from '../../components/link/link';
+import Button from '../../components/button/button';
+import Address from '../../components/address/address';
+import Notification from '../../components/notification/notification';
+import userStore from '../../store/user-store';
+import removeAddress from '../../services/addresses/removeAddress';
+import changeVisibleAddressesBtns from '../../utils/change-visible-addresses-btns';
+import { IAddressData, IBreadcrumbLink } from '../../types/interfaces';
+import { AppRoutesPath } from '../../router/types';
+import { AddressesMode } from '../../types/enums';
+import './addresses-page.scss';
+
+const breadcrumbsLinks: IBreadcrumbLink[] = [
+ {
+ pageName: 'Home',
+ pageHref: AppRoutesPath.MAIN,
+ },
+ {
+ pageName: 'Account',
+ pageHref: AppRoutesPath.ACCOUNT,
+ },
+];
+
+export default class AddressesPage extends BaseComponent<'div'> {
+ private breadcrumbs: HTMLElement;
+ private container: HTMLElement;
+ private addressesSection: HTMLElement;
+ private addressesListWrapp: HTMLElement;
+ private addresses: HTMLDivElement[] = [];
+ private addNewAddressBtn: HTMLButtonElement | null = null;
+
+ constructor() {
+ super('div', ['addresses-page']);
+
+ this.breadcrumbs = new Breadcrumbs(breadcrumbsLinks, 'Addresses').getElement();
+ this.container = new BaseComponent('div', ['addresses-page__container']).getElement();
+ this.addressesSection = new BaseComponent('section', ['addresses-page__section']).getElement();
+ this.addressesListWrapp = new BaseComponent('div', ['addresses-page__list']).getElement();
+ this.addressesSection.append(this.addressesListWrapp);
+
+ this.container.append(this.addressesSection);
+
+ this.renderAddressesSection();
+ this.renderAddressesList();
+
+ this.node.append(this.breadcrumbs, this.container);
+ }
+
+ private renderAddressesSection = (): void => {
+ const titleWrapp = new BaseComponent('div', ['addresses-page__title-wrapp']).getElement();
+ const sectionTitle = new BaseComponent('h1', ['addresses-page__title'], 'Addresses').getElement();
+ const returnToAccountLink = new Link('Return To Account', ['link--return'], AppRoutesPath.ACCOUNT).getElement();
+ this.addNewAddressBtn = new Button(
+ 'button',
+ '+ Add New Address',
+ ['button--add-address', 'addresses-page__add-btn'],
+ false,
+ this.renderNewAddressForm
+ ).getElement();
+
+ titleWrapp.append(sectionTitle, returnToAccountLink);
+
+ this.addressesSection.prepend(titleWrapp, this.addNewAddressBtn);
+ };
+
+ private renderAddressesList = (): void => {
+ const { customer } = userStore.getState();
+
+ this.addressesListWrapp.innerHTML = '';
+
+ if (customer && customer?.addresses.length > 0) {
+ customer?.addresses.forEach((item) => {
+ const obj: IAddressData = {
+ address: item,
+ billingAddressIds: customer.billingAddressIds,
+ shippingAddressIds: customer.shippingAddressIds,
+ defaultBillingAddressId: customer.defaultBillingAddressId,
+ defaultShippingAddressId: customer.defaultShippingAddressId,
+ };
+
+ const address = new Address(
+ AddressesMode.SHOW,
+ obj,
+ (type: AddressesMode) => this.onChangeForm(type),
+ (id: string) => this.onDeleteAddress(id)
+ ).getElement();
+ this.addressesListWrapp.append(address);
+ this.addresses.push(address);
+ });
+ }
+ };
+
+ private renderNewAddressForm = (): void => {
+ const newAddress = new Address(AddressesMode.NEW, null, this.onSubmitNewForm, (id: string) =>
+ this.onCancelNewForm(id)
+ ).getElement();
+ this.addressesListWrapp.prepend(newAddress);
+ this.addNewAddressBtn?.classList.add('hidden');
+
+ changeVisibleAddressesBtns(this.addresses, true);
+ };
+
+ private onChangeForm = (type: AddressesMode): void => {
+ this.addNewAddressBtn?.classList.toggle('hidden', type === AddressesMode.EDIT);
+ changeVisibleAddressesBtns(this.addresses, type === AddressesMode.EDIT);
+ if (type === AddressesMode.SHOW) this.renderAddressesList();
+ };
+
+ private onSubmitNewForm = (): void => {
+ this.onCancelNewForm('new');
+ this.renderAddressesList();
+ };
+
+ private onCancelNewForm = (id: string): void => {
+ if (id === 'new') {
+ this.addNewAddressBtn?.classList.remove('hidden');
+ this.addressesListWrapp?.firstChild?.remove();
+ changeVisibleAddressesBtns(this.addresses, false);
+ }
+ };
+
+ private onDeleteAddress = async (id: string): Promise => {
+ try {
+ await removeAddress(id);
+
+ new Notification('success', 'The selected address was successfully deleted!').showNotification();
+ this.renderAddressesList();
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ } else {
+ console.error(error);
+ }
+ }
+ };
+}
diff --git a/src/pages/basket-page/basket-page.scss b/src/pages/basket-page/basket-page.scss
new file mode 100644
index 0000000..34c404f
--- /dev/null
+++ b/src/pages/basket-page/basket-page.scss
@@ -0,0 +1,19 @@
+.basket-page {
+ &__section {
+ @include container;
+ }
+
+ &__title {
+ @include font-h3;
+ margin-bottom: 24px;
+ }
+
+ &__loading {
+ @include container;
+ @include font-h4;
+ margin: 48px 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+}
diff --git a/src/pages/basket-page/basket-page.ts b/src/pages/basket-page/basket-page.ts
new file mode 100644
index 0000000..4c3904a
--- /dev/null
+++ b/src/pages/basket-page/basket-page.ts
@@ -0,0 +1,96 @@
+import { Cart } from '@commercetools/platform-sdk';
+import BaseComponent from '../../components/base-component';
+import Breadcrumbs from '../../components/breadcrumbs/breadcrumbs';
+import { IBreadcrumbLink } from '../../types/interfaces';
+import { AppRoutesPath } from '../../router/types';
+import BasketEmpty from '../../components/basket-empty/basket-empty';
+import Notification from '../../components/notification/notification';
+import BasketItems from '../../components/basket-items/basket-items';
+import BasketTotal from '../../components/basket-total/basket-total';
+import getCart from '../../services/basket/getCart';
+import cartStore from '../../store/cart-store';
+import './basket-page.scss';
+
+const breadcrumbsLinks: IBreadcrumbLink[] = [
+ {
+ pageName: 'Home',
+ pageHref: AppRoutesPath.MAIN,
+ },
+];
+
+export default class BasketPage extends BaseComponent<'div'> {
+ private cart: Cart | undefined;
+ private basketMainSection: HTMLElement | undefined;
+ private basketTotalSection: HTMLElement | undefined;
+
+ constructor() {
+ super('div', ['basket-page']);
+
+ this.cart = undefined;
+
+ this.renderBreadcrumbs();
+ this.renderTitle();
+ this.renderMainContent();
+ this.addSubscribtion();
+ }
+
+ private renderBreadcrumbs(): void {
+ const breadcrumbs = new Breadcrumbs(breadcrumbsLinks, 'Basket').getElement();
+
+ this.node.append(breadcrumbs);
+ }
+
+ private renderTitle(): void {
+ const basketTitleSection = new BaseComponent('section', ['basket-page__section']).getElement();
+ const basketPageTitle = new BaseComponent('h3', ['basket-page__title'], 'Shopping Cart').getElement();
+
+ basketTitleSection.append(basketPageTitle);
+
+ this.node.append(basketTitleSection);
+ }
+
+ private async renderMainContent(): Promise {
+ const loadingElement = new BaseComponent('div', ['basket-page__loading'], 'Loading...').getElement();
+
+ try {
+ this.node.append(loadingElement);
+
+ this.cart = await getCart();
+ cartStore.dispatch({ type: 'UPDATE_CART', cart: this.cart });
+
+ if (this.cart && this.cart.lineItems.length > 0) {
+ this.basketMainSection = new BasketItems(this.cart.lineItems).getElement();
+ this.basketTotalSection = new BasketTotal(this.cart).getElement();
+ this.node.append(this.basketMainSection, this.basketTotalSection);
+ } else {
+ this.basketMainSection = new BasketEmpty().getElement();
+ this.node.append(this.basketMainSection);
+ }
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification('error', error.message).showNotification();
+ if (error.message === 'invalid_token') {
+ localStorage.removeItem('tokenAnon');
+ localStorage.removeItem('token');
+ }
+ } else {
+ console.error(error);
+ }
+
+ this.basketMainSection = new BasketEmpty().getElement();
+ this.node.append(this.basketMainSection);
+ } finally {
+ loadingElement.remove();
+ }
+ }
+
+ private addSubscribtion(): void {
+ cartStore.subscribe((state) => {
+ if (state.cart?.lineItems.length === 0 && this.basketMainSection) {
+ this.basketMainSection.innerHTML = '';
+ this.basketTotalSection?.remove();
+ this.basketMainSection.append(new BasketEmpty().getElement());
+ }
+ });
+ }
+}
diff --git a/src/pages/catalog-page/catalog-page.scss b/src/pages/catalog-page/catalog-page.scss
new file mode 100644
index 0000000..2f55253
--- /dev/null
+++ b/src/pages/catalog-page/catalog-page.scss
@@ -0,0 +1,27 @@
+.catalog-page {
+ &__loading {
+ @include container;
+ @include font-h4;
+ margin: 48px 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+}
+
+.shop-controls {
+ margin-top: 48px;
+
+ &__container {
+ @include container;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-wrap: wrap;
+ gap: 16px;
+
+ @include mobile {
+ gap: 60px;
+ }
+ }
+}
diff --git a/src/pages/catalog-page/catalog-page.ts b/src/pages/catalog-page/catalog-page.ts
new file mode 100644
index 0000000..b217d54
--- /dev/null
+++ b/src/pages/catalog-page/catalog-page.ts
@@ -0,0 +1,235 @@
+import { type ProductProjection } from '@commercetools/platform-sdk';
+import BaseComponent from '../../components/base-component';
+import Breadcrumbs from '../../components/breadcrumbs/breadcrumbs';
+import { IBreadcrumbLink } from '../../types/interfaces';
+import { AppRoutesPath } from '../../router/types';
+import { ICategory } from '../../types/types';
+import ProductList from '../../components/product-list/product-list';
+import CategoryList from '../../components/category-list/category-list';
+import getProducts from '../../services/getProducts';
+import subcategories from '../../constants/subcategories';
+import categories from '../../constants/categories';
+import ShopHero from '../../components/shop-hero/shop-hero';
+import { changeUrlEvent } from '../../utils/change-url-event';
+import ShopFilters from '../../components/shop-flters/shop-filters';
+import shopStore from '../../store/shop-store';
+import ShopSort from '../../components/shop-sort/shop-sort';
+import ShopSearch from '../../components/shop-search/shop-search';
+import { BASE_PRODUCT_LIMIT, BASE_PRODUCT_OFFSET } from '../../constants/productsOptions';
+import ProductCard from '../../components/product-card/product-card';
+import './catalog-page.scss';
+
+export default class CatalogPage extends BaseComponent<'div'> {
+ private products: ProductProjection[];
+ private categorySlug: string;
+ private subcategorySlug: string;
+ private breadcrumbsLinks: IBreadcrumbLink[];
+ private currentPage: string;
+ private heroTitleText: string;
+ private catalogSection: ProductList;
+
+ private productsOffset: number = BASE_PRODUCT_OFFSET;
+ private productsTotal: number = BASE_PRODUCT_LIMIT;
+ private isLoading: boolean = false;
+ private shouldLoad: boolean = false;
+
+ constructor() {
+ super('div', ['catalog-page']);
+
+ this.products = [];
+ this.categorySlug = '';
+ this.subcategorySlug = '';
+ this.breadcrumbsLinks = [{ pageName: 'Home', pageHref: AppRoutesPath.MAIN }];
+ this.currentPage = 'Shop';
+ this.heroTitleText = 'Shop All';
+ this.catalogSection = new ProductList(this.products);
+
+ shopStore.unsubscribe();
+ this.renderPage();
+ this.addSubscribtion();
+ }
+
+ private renderPage(): void {
+ const isPage = this.parseUrl();
+
+ if (!isPage) {
+ changeUrlEvent(AppRoutesPath.NOT_FOUND);
+ } else {
+ this.renderBreadcrumbs();
+ this.renderHeroSection();
+ this.renderCategoryList();
+ this.renderSearchPanel();
+ this.renderControls();
+ this.renderProductList();
+ }
+ }
+
+ private parseUrl(): boolean {
+ const url: string = window.location.pathname;
+ const parts: string[] = url.split('/').filter((part) => part !== '');
+
+ if (parts.length === 3) {
+ this.categorySlug = parts[parts.length - 2];
+ this.subcategorySlug = parts[parts.length - 1];
+
+ const currentCategory: ICategory | undefined = categories.find((item) => item.slug === this.categorySlug);
+ const currentsubCategory: ICategory | undefined = subcategories[this.categorySlug]?.find(
+ (item) => item.slug === this.subcategorySlug
+ );
+
+ if (!currentCategory || !currentsubCategory) return false;
+
+ this.breadcrumbsLinks = [
+ { pageName: 'Home', pageHref: AppRoutesPath.MAIN },
+ { pageName: 'Shop', pageHref: AppRoutesPath.SHOP },
+ { pageName: currentCategory.label, pageHref: `/shop/${this.categorySlug}` },
+ ];
+ this.currentPage = currentsubCategory.label;
+ this.heroTitleText = this.currentPage;
+
+ return true;
+ }
+
+ if (parts.length === 2) {
+ this.categorySlug = parts[parts.length - 1];
+
+ const currentCategory: ICategory | undefined = categories.find((item) => item.slug === this.categorySlug);
+
+ if (!currentCategory) return false;
+
+ this.breadcrumbsLinks = [
+ { pageName: 'Home', pageHref: AppRoutesPath.MAIN },
+ { pageName: 'Shop', pageHref: AppRoutesPath.SHOP },
+ ];
+ this.currentPage = currentCategory.label;
+ this.heroTitleText = this.currentPage;
+
+ return true;
+ }
+
+ return true;
+ }
+
+ private renderBreadcrumbs(): void {
+ const breadcrumbs: HTMLDivElement = new Breadcrumbs(this.breadcrumbsLinks, this.currentPage).getElement();
+ this.node.append(breadcrumbs);
+ }
+
+ private renderHeroSection(): void {
+ const heroSection: HTMLElement = new ShopHero(this.heroTitleText).getElement();
+ this.node.append(heroSection);
+ }
+
+ private renderControls(): void {
+ const shopControls: HTMLDivElement = new BaseComponent('div', ['shop-controls']).getElement();
+ const container: HTMLDivElement = new BaseComponent('div', ['shop-controls__container']).getElement();
+ const filtersElement: HTMLElement = new ShopFilters().getElement();
+ const sortElement: HTMLElement = new ShopSort().getElement();
+
+ container.append(filtersElement, sortElement);
+ shopControls.append(container);
+
+ this.node.append(shopControls);
+ }
+
+ private renderCategoryList(): void {
+ let categoryList: ICategory[] = [];
+ let titleCategoryEl: string = 'Categories';
+
+ if (this.categorySlug) {
+ categoryList = subcategories[this.categorySlug];
+ titleCategoryEl = 'Subcategories';
+ } else {
+ categoryList = categories;
+ }
+
+ const categoryListElement: HTMLDivElement = new CategoryList(
+ titleCategoryEl,
+ categoryList,
+ this.subcategorySlug ? this.subcategorySlug : this.categorySlug
+ ).getElement();
+
+ this.node.append(categoryListElement);
+ }
+
+ private renderSearchPanel(): void {
+ const { searchValue } = shopStore.getState();
+
+ const searchPanel = new ShopSearch(searchValue).getElement();
+
+ this.node.append(searchPanel);
+ }
+
+ private handleGettingProducts = async (isFirstRender: boolean): Promise => {
+ const { filterPrice, filterDays, sortValue, searchValue } = shopStore.getState();
+
+ const response = await getProducts(
+ this.categorySlug,
+ this.subcategorySlug,
+ filterPrice,
+ filterDays,
+ sortValue,
+ searchValue,
+ (this.productsOffset = isFirstRender ? BASE_PRODUCT_OFFSET : this.productsOffset + BASE_PRODUCT_LIMIT)
+ );
+
+ this.products = response?.products || [];
+ this.productsOffset = response?.offset || BASE_PRODUCT_OFFSET;
+ this.productsTotal = response?.total || BASE_PRODUCT_LIMIT;
+
+ if (response?.total && response?.total > BASE_PRODUCT_LIMIT) {
+ this.shouldLoad = true;
+ } else {
+ this.shouldLoad = false;
+ }
+ };
+
+ private infiniteLoading = async (): Promise => {
+ const footer = document.querySelector('footer');
+
+ if (this.isLoading || !this.shouldLoad) return;
+
+ if (window.scrollY + window.innerHeight >= document.documentElement.scrollHeight - footer.clientHeight) {
+ if (this.productsOffset < this.productsTotal - 10) {
+ this.isLoading = true;
+
+ const loadingElement = new BaseComponent('div', ['catalog-page__loading'], 'Loading...').getElement();
+ this.node.append(loadingElement);
+
+ await this.handleGettingProducts(false);
+
+ const newProducts: HTMLElement[] = [];
+ this.products.forEach((item) => newProducts.push(new ProductCard(item).getElement()));
+
+ loadingElement.remove();
+
+ this.catalogSection.addNewProducts(newProducts);
+
+ this.isLoading = false;
+ }
+ }
+ };
+
+ private renderProductList = async (): Promise => {
+ this.catalogSection.getElement().remove();
+
+ const loadingElement = new BaseComponent('div', ['catalog-page__loading'], 'Loading...').getElement();
+ this.node.append(loadingElement);
+
+ await this.handleGettingProducts(true);
+
+ this.catalogSection = new ProductList(this.products);
+ loadingElement.remove();
+
+ this.node.append(this.catalogSection.getElement());
+
+ window.addEventListener('scroll', this.infiniteLoading);
+ window.addEventListener('resize', this.infiniteLoading);
+ };
+
+ private addSubscribtion(): void {
+ shopStore.subscribe(() => {
+ this.renderProductList();
+ });
+ }
+}
diff --git a/src/pages/login-page/login-page.scss b/src/pages/login-page/login-page.scss
new file mode 100644
index 0000000..4f7aada
--- /dev/null
+++ b/src/pages/login-page/login-page.scss
@@ -0,0 +1,18 @@
+.login-page {
+ display: flex;
+ flex-direction: column;
+}
+
+.login-section {
+ margin-bottom: 104px;
+
+ @include mobile {
+ margin-bottom: 80px;
+ }
+
+ &__container {
+ @include container;
+ display: flex;
+ justify-content: center;
+ }
+}
diff --git a/src/pages/login-page/login-page.ts b/src/pages/login-page/login-page.ts
new file mode 100644
index 0000000..d540f69
--- /dev/null
+++ b/src/pages/login-page/login-page.ts
@@ -0,0 +1,48 @@
+import BaseComponent from '../../components/base-component';
+import Breadcrumbs from '../../components/breadcrumbs/breadcrumbs';
+import LoginForm from '../../components/form/login-form';
+import Banner from '../../components/banner/banner';
+import { IBannerContent, IBreadcrumbLink } from '../../types/interfaces';
+import { AppRoutesPath } from '../../router/types';
+import './login-page.scss';
+
+const breadcrumbsLinks: IBreadcrumbLink[] = [
+ {
+ pageName: 'Home',
+ pageHref: AppRoutesPath.MAIN,
+ },
+];
+
+const bannerContent: IBannerContent = {
+ title: 'Discover the World: Book Unforgettable Journeys Today!',
+ text: 'Our expertly crafted itineraries take you beyond the ordinary, unveiling the hidden gems of captivating destinations across the globe.',
+};
+
+export default class LoginPage extends BaseComponent<'div'> {
+ private breadcrumbs: HTMLElement;
+ private loginSection: HTMLElement;
+ private bannerSection: HTMLElement;
+
+ constructor() {
+ super('div', ['login-page']);
+
+ this.breadcrumbs = new Breadcrumbs(breadcrumbsLinks, 'Log In').getElement();
+
+ this.loginSection = new BaseComponent('section', ['login-section']).getElement();
+ this.renderSignupSection();
+
+ this.bannerSection = new Banner(bannerContent.title, bannerContent.text).getElement();
+
+ this.node.append(this.breadcrumbs, this.loginSection, this.bannerSection);
+ }
+
+ private renderSignupSection(): void {
+ const container: HTMLElement = new BaseComponent('div', ['login-section__container']).getElement();
+
+ const signupForm: HTMLDivElement = new LoginForm().getElement();
+
+ container.append(signupForm);
+
+ this.loginSection.append(container);
+ }
+}
diff --git a/src/pages/main-page/main-page.scss b/src/pages/main-page/main-page.scss
new file mode 100644
index 0000000..000d9d2
--- /dev/null
+++ b/src/pages/main-page/main-page.scss
@@ -0,0 +1,7 @@
+.temporary-section {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100dvh;
+ @include font-h1;
+}
diff --git a/src/pages/main-page/main-page.ts b/src/pages/main-page/main-page.ts
new file mode 100644
index 0000000..33a6ae0
--- /dev/null
+++ b/src/pages/main-page/main-page.ts
@@ -0,0 +1,24 @@
+import BaseComponent from '../../components/base-component';
+import Banner from '../../components/banner/banner';
+import { IBannerContent } from '../../types/interfaces';
+import PromoCodes from '../../components/promo-codes/promo-codes';
+import './main-page.scss';
+
+const bannerContent: IBannerContent = {
+ title: 'Wanderlust Dreams: Unveil the World with Exclusive Tours',
+ text: 'Satisfy your wanderlust with our collection of exclusive tours tailored to quench your thirst for exploration.',
+};
+
+export default class MainPage extends BaseComponent<'div'> {
+ private bannerSection: HTMLElement;
+ private promoCodesSection: HTMLElement;
+
+ constructor() {
+ super('div', ['main-page']);
+
+ this.bannerSection = new Banner(bannerContent.title, bannerContent.text, ['banner--main-page']).getElement();
+ this.promoCodesSection = new PromoCodes().getElement();
+
+ this.node.append(this.bannerSection, this.promoCodesSection);
+ }
+}
diff --git a/src/pages/not-found-page/not-found-page.scss b/src/pages/not-found-page/not-found-page.scss
new file mode 100644
index 0000000..b5648f4
--- /dev/null
+++ b/src/pages/not-found-page/not-found-page.scss
@@ -0,0 +1,34 @@
+.not-found-page {
+ display: flex;
+ flex-direction: column;
+}
+
+.not-found-section {
+ margin: 275px 0;
+
+ @include mobile {
+ margin: 80px 0;
+ }
+
+ &__container {
+ @include container;
+ }
+
+ &__wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ &__title {
+ @include font-h1;
+ text-align: center;
+ margin-bottom: 24px;
+ }
+
+ &__descr {
+ font: $font-subtitle;
+ text-align: center;
+ margin-bottom: 32px;
+ }
+}
diff --git a/src/pages/not-found-page/not-found-page.ts b/src/pages/not-found-page/not-found-page.ts
new file mode 100644
index 0000000..763d181
--- /dev/null
+++ b/src/pages/not-found-page/not-found-page.ts
@@ -0,0 +1,55 @@
+import BaseComponent from '../../components/base-component';
+import Banner from '../../components/banner/banner';
+import Button from '../../components/button/button';
+import { changeUrlEvent } from '../../utils/change-url-event';
+import { AppRoutesPath } from '../../router/types';
+import { IBannerContent } from '../../types/interfaces';
+import './not-found-page.scss';
+
+interface ISectionContent {
+ title: string;
+ descr: string;
+}
+
+const bannerContent: IBannerContent = {
+ title: 'Wanderlust Dreams: Unveil the World with Exclusive Tours',
+ text: 'Satisfy your wanderlust with our collection of exclusive tours tailored to quench your thirst for exploration.',
+};
+
+const sectionContent: ISectionContent = {
+ title: '404: Destination Not Found',
+ descr: `Looks like this path hasn't been explored yet. Let's navigate you back to familiar terrain.`,
+};
+
+export default class NotFoundPage extends BaseComponent<'div'> {
+ private notFoundSection: HTMLElement;
+ private bannerSection: HTMLElement;
+
+ constructor() {
+ super('div', ['not-found-page']);
+
+ this.notFoundSection = new BaseComponent('section', ['not-found-section']).getElement();
+ this.renderSignupSection();
+
+ this.bannerSection = new Banner(bannerContent.title, bannerContent.text).getElement();
+
+ this.node.append(this.notFoundSection, this.bannerSection);
+ }
+
+ private renderSignupSection(): void {
+ const container: HTMLElement = new BaseComponent('div', ['not-found-section__container']).getElement();
+
+ const notFoundWrapper = new BaseComponent('div', ['not-found-section__wrapper']).getElement();
+ const notFoundTitle = new BaseComponent('h1', ['not-found-section__title'], sectionContent.title).getElement();
+ const notFoundDescr = new BaseComponent('h3', ['not-found-section__descr'], sectionContent.descr).getElement();
+ const notFoundBtn = new Button('button', 'Back to home page', ['button'], false, () =>
+ changeUrlEvent(AppRoutesPath.MAIN)
+ ).getElement();
+
+ notFoundWrapper.append(notFoundTitle, notFoundDescr, notFoundBtn);
+
+ container.append(notFoundWrapper);
+
+ this.notFoundSection.append(container);
+ }
+}
diff --git a/src/pages/product-page/product-page.scss b/src/pages/product-page/product-page.scss
new file mode 100644
index 0000000..7763634
--- /dev/null
+++ b/src/pages/product-page/product-page.scss
@@ -0,0 +1,15 @@
+.product-page {
+ padding-bottom: 48px;
+
+ &__container {
+ @include container;
+ display: flex;
+ justify-content: flex-end;
+ gap: 24px;
+
+ @include laptop {
+ flex-direction: column;
+ align-items: center;
+ }
+ }
+}
diff --git a/src/pages/product-page/product-page.ts b/src/pages/product-page/product-page.ts
new file mode 100644
index 0000000..b4db3d8
--- /dev/null
+++ b/src/pages/product-page/product-page.ts
@@ -0,0 +1,117 @@
+import './product-page.scss';
+import BaseComponent from '../../components/base-component';
+import Breadcrumbs from '../../components/breadcrumbs/breadcrumbs';
+import { IBreadcrumbLink } from '../../types/interfaces';
+import { AppRoutesPath } from '../../router/types';
+import Product from '../../components/product/product';
+import getProductById from '../../services/getProductById';
+import { ProductData } from '@commercetools/platform-sdk';
+import { changeUrlEvent } from '../../utils/change-url-event';
+import Notification from '../../components/notification/notification';
+import categories from '../../constants/categories';
+import subcategories from '../../constants/subcategories';
+import { ICategory } from '../../types/types';
+import ProductSlider from '../../components/slider/slider';
+
+export default class ProductPage extends BaseComponent<'div'> {
+ private productData: ProductData | null = null;
+ private productId: string = '';
+ private breadcrumbsLinks: IBreadcrumbLink[] = [];
+ private isPage: boolean;
+
+ constructor() {
+ super('div', ['product-page']);
+
+ this.isPage = this.parseUrl();
+ if (this.isPage) {
+ this.createMarkup();
+ } else {
+ changeUrlEvent(AppRoutesPath.NOT_FOUND);
+ }
+ }
+
+ private parseUrl(): boolean {
+ const url: string = window.location.pathname;
+ const parts: string[] = url.split('/').filter((part) => part !== '');
+
+ if (parts.length === 4) {
+ const categorySlug = parts[parts.length - 3];
+ const subcategorySlug = parts[parts.length - 2];
+ this.productId = parts[parts.length - 1];
+
+ const currentCategory: ICategory | undefined = categories.find((item) => item.slug === categorySlug);
+ const currentSubcategory: ICategory | undefined = subcategories[categorySlug]?.find(
+ (item) => item.slug === subcategorySlug
+ );
+
+ if (!currentCategory || !currentSubcategory) return false;
+
+ this.breadcrumbsLinks = [
+ { pageName: 'Home', pageHref: AppRoutesPath.MAIN },
+ { pageName: 'Shop', pageHref: AppRoutesPath.SHOP },
+ { pageName: currentCategory.label, pageHref: `/shop/${categorySlug}` },
+ { pageName: currentSubcategory.label, pageHref: `/shop/${categorySlug}/${subcategorySlug}` },
+ ];
+
+ return true;
+ }
+
+ if (parts.length === 3) {
+ const categorySlug = parts[parts.length - 2];
+ this.productId = parts[parts.length - 1];
+
+ const currentCategory: ICategory | undefined = categories.find((item) => item.slug === categorySlug);
+
+ if (!currentCategory) return false;
+
+ this.breadcrumbsLinks = [
+ { pageName: 'Home', pageHref: AppRoutesPath.MAIN },
+ { pageName: 'Shop', pageHref: AppRoutesPath.SHOP },
+ { pageName: currentCategory.label, pageHref: `/shop/${categorySlug}` },
+ ];
+
+ return true;
+ }
+
+ if (parts.length === 2) {
+ this.productId = parts[parts.length - 1];
+
+ this.breadcrumbsLinks = [
+ { pageName: 'Home', pageHref: AppRoutesPath.MAIN },
+ { pageName: 'Shop', pageHref: AppRoutesPath.SHOP },
+ ];
+
+ return true;
+ }
+
+ return true;
+ }
+
+ private async getProductData(id: string): Promise {
+ try {
+ const product = await getProductById(id);
+
+ this.productData = product.masterData.current;
+ } catch (err) {
+ if (err instanceof Error) new Notification('error', err.message).showNotification();
+
+ changeUrlEvent(AppRoutesPath.NOT_FOUND);
+ }
+ }
+
+ private async createMarkup(): Promise {
+ await this.getProductData(this.productId);
+
+ const productName = this.productData?.name.en || 'Unnamed tour';
+ const productImages = this.productData?.masterVariant.images || [];
+
+ const slider = new ProductSlider(productImages).getElement();
+ const product = new Product(this.productId, this.productData!).getElement();
+
+ const breadcrumbs = new Breadcrumbs(this.breadcrumbsLinks, productName).getElement();
+ const container = new BaseComponent('div', ['product-page__container']).getElement();
+
+ container.append(slider, product);
+ this.node.append(breadcrumbs, container);
+ }
+}
diff --git a/src/pages/signup-page/signup-page.scss b/src/pages/signup-page/signup-page.scss
new file mode 100644
index 0000000..bfec7fd
--- /dev/null
+++ b/src/pages/signup-page/signup-page.scss
@@ -0,0 +1,16 @@
+.signup-page {
+ display: flex;
+ flex-direction: column;
+}
+
+.signup-section {
+ margin-bottom: 104px;
+
+ @include mobile {
+ margin-bottom: 80px;
+ }
+
+ &__container {
+ @include container;
+ }
+}
diff --git a/src/pages/signup-page/signup-page.ts b/src/pages/signup-page/signup-page.ts
new file mode 100644
index 0000000..a0ee233
--- /dev/null
+++ b/src/pages/signup-page/signup-page.ts
@@ -0,0 +1,48 @@
+import BaseComponent from '../../components/base-component';
+import Breadcrumbs from '../../components/breadcrumbs/breadcrumbs';
+import SignupForm from '../../components/form/signup-form';
+import Banner from '../../components/banner/banner';
+import { IBannerContent, IBreadcrumbLink } from '../../types/interfaces';
+import { AppRoutesPath } from '../../router/types';
+import './signup-page.scss';
+
+const breadcrumbsLinks: IBreadcrumbLink[] = [
+ {
+ pageName: 'Home',
+ pageHref: AppRoutesPath.MAIN,
+ },
+];
+
+const bannerContent: IBannerContent = {
+ title: 'Discover the World: Book Unforgettable Journeys Today!',
+ text: 'Our expertly crafted itineraries take you beyond the ordinary, unveiling the hidden gems of captivating destinations across the globe.',
+};
+
+export default class SignupPage extends BaseComponent<'div'> {
+ private breadcrumbs: HTMLElement;
+ private signupSection: HTMLElement;
+ private bannerSection: HTMLElement;
+
+ constructor() {
+ super('div', ['signup-page']);
+
+ this.breadcrumbs = new Breadcrumbs(breadcrumbsLinks, 'Create Account').getElement();
+
+ this.signupSection = new BaseComponent('section', ['signup-section']).getElement();
+ this.renderSignupSection();
+
+ this.bannerSection = new Banner(bannerContent.title, bannerContent.text).getElement();
+
+ this.node.append(this.breadcrumbs, this.signupSection, this.bannerSection);
+ }
+
+ private renderSignupSection(): void {
+ const container: HTMLElement = new BaseComponent('div', ['signup-section__container']).getElement();
+
+ const signupForm = new SignupForm().getElement();
+
+ container.append(signupForm);
+
+ this.signupSection.append(container);
+ }
+}
diff --git a/src/router/index.ts b/src/router/index.ts
new file mode 100644
index 0000000..f30530a
--- /dev/null
+++ b/src/router/index.ts
@@ -0,0 +1,71 @@
+import { AppRoute, AppRoutesPath, MiddlewareTypes } from './types';
+import { ROUTES, NOT_FOUND_ROUTE, MAIN_ROUTE, LOGIN_ROUTE } from './routes';
+import { accountMiddleware, authMiddleware } from '../utils/router-middleware';
+import Notification from '../components/notification/notification';
+
+const LOGGED_IN_ERROR_DURATION: number = 3000;
+
+export class Router {
+ constructor(
+ private readonly routes: AppRoute[],
+ private onHashChange: (route: AppRoute) => void
+ ) {
+ window.addEventListener('changeURL', this.onHashChangeHandler.bind(this) as EventListener);
+ window.addEventListener('popstate', this.onHashChangeHandler.bind(this));
+ this.onHashChangeHandler();
+ }
+
+ private handleMiddlewareError(type: MiddlewareTypes): void {
+ if (type === MiddlewareTypes.AUTH) {
+ new Notification('error', 'You are already logged in!', LOGGED_IN_ERROR_DURATION).showNotification();
+ window.history.pushState({}, '', AppRoutesPath.MAIN);
+ this.onHashChange(MAIN_ROUTE);
+ } else {
+ new Notification('error', 'You need to be logged in!', LOGGED_IN_ERROR_DURATION).showNotification();
+ window.history.pushState({}, '', AppRoutesPath.LOGIN);
+ this.onHashChange(LOGIN_ROUTE);
+ }
+ }
+
+ private onHashChangeHandler(): void {
+ const pathname: string[] = location.pathname.split('/').slice(1);
+
+ const matchedRoute: AppRoute | undefined = this.routes.find((route) => {
+ const routePathSegments: string[] = route.path.split('/').slice(1);
+
+ if (routePathSegments.length !== pathname.length) {
+ return false;
+ }
+
+ const match: boolean = routePathSegments.every((routePathSegment: string, i: number): boolean => {
+ return routePathSegment === pathname[i] || routePathSegment[0] === ':';
+ });
+
+ return match;
+ });
+
+ if (!matchedRoute) {
+ this.onHashChange(NOT_FOUND_ROUTE);
+ } else if (authMiddleware(matchedRoute.path)) {
+ this.handleMiddlewareError(MiddlewareTypes.AUTH);
+ } else if (accountMiddleware(matchedRoute.path)) {
+ this.handleMiddlewareError(MiddlewareTypes.ACCOUNT);
+ } else {
+ this.onHashChange(matchedRoute);
+ }
+ }
+}
+
+export function createRouter(routerOutlet: HTMLElement): Router {
+ return new Router(ROUTES, (route) => {
+ if (route) {
+ routerOutlet.innerHTML = '';
+ routerOutlet.append(route.component());
+
+ document.body?.scrollIntoView({
+ behavior: 'smooth',
+ block: 'start',
+ });
+ }
+ });
+}
diff --git a/src/router/routes.ts b/src/router/routes.ts
new file mode 100644
index 0000000..41cb722
--- /dev/null
+++ b/src/router/routes.ts
@@ -0,0 +1,69 @@
+import { AppRoute, AppRoutesPath } from './types';
+
+import MainPage from '../pages/main-page/main-page';
+import LoginPage from '../pages/login-page/login-page';
+import SignupPage from '../pages/signup-page/signup-page';
+import NotFoundPage from '../pages/not-found-page/not-found-page';
+import CatalogPage from '../pages/catalog-page/catalog-page';
+import ProductPage from '../pages/product-page/product-page';
+import AccountPage from '../pages/account-page/account-page';
+import AddressesPage from '../pages/addresses-page/addresses-page';
+import BasketPage from '../pages/basket-page/basket-page';
+import AboutUsPage from '../pages/about-us-page/about-us-page';
+
+export const MAIN_ROUTE: AppRoute = {
+ path: AppRoutesPath.MAIN,
+ component: () => new MainPage().getElement(),
+};
+
+export const LOGIN_ROUTE: AppRoute = {
+ path: AppRoutesPath.LOGIN,
+ component: () => new LoginPage().getElement(),
+};
+
+export const NOT_FOUND_ROUTE: AppRoute = {
+ path: AppRoutesPath.NOT_FOUND,
+ component: () => new NotFoundPage().getElement(),
+};
+
+export const ROUTES: AppRoute[] = [
+ MAIN_ROUTE,
+ LOGIN_ROUTE,
+ {
+ path: AppRoutesPath.SIGN_UP,
+ component: () => new SignupPage().getElement(),
+ },
+ {
+ path: AppRoutesPath.ACCOUNT,
+ component: () => new AccountPage().getElement(),
+ },
+ {
+ path: AppRoutesPath.ACCOUNT_ADDRESSES,
+ component: () => new AddressesPage().getElement(), // TODO: Change page-component when implemented
+ },
+ {
+ path: AppRoutesPath.SHOP,
+ component: () => new CatalogPage().getElement(),
+ },
+ {
+ path: AppRoutesPath.CATEGORY,
+ component: () => new CatalogPage().getElement(),
+ },
+ {
+ path: AppRoutesPath.SUBCATEGORY,
+ component: () => new CatalogPage().getElement(),
+ },
+ {
+ path: AppRoutesPath.PRODUCT,
+ component: () => new ProductPage().getElement(),
+ },
+ {
+ path: AppRoutesPath.BASKET,
+ component: () => new BasketPage().getElement(),
+ },
+ {
+ path: AppRoutesPath.ABOUT_US,
+ component: () => new AboutUsPage().getElement(),
+ },
+ NOT_FOUND_ROUTE,
+];
diff --git a/src/router/types.ts b/src/router/types.ts
new file mode 100644
index 0000000..7151298
--- /dev/null
+++ b/src/router/types.ts
@@ -0,0 +1,25 @@
+export interface AppRoute {
+ path: AppRoutesPath;
+ component: () => HTMLElement;
+}
+
+export enum AppRoutesPath {
+ MAIN = '/',
+ LOGIN = '/login',
+ SIGN_UP = '/registration',
+ ACCOUNT = '/account',
+ ACCOUNT_ADDRESSES = '/account/addresses',
+ SHOP = '/shop',
+ CATEGORY = '/shop/:category',
+ SUBCATEGORY = '/shop/:category/:subcategory',
+ PRODUCT = '/shop/:category/:subcategory/:id',
+ BASKET = '/basket',
+ ABOUT_US = '/about-us',
+ NOT_FOUND = '/404',
+ ANCHOR = '#',
+}
+
+export enum MiddlewareTypes {
+ AUTH = 'auth',
+ ACCOUNT = 'account',
+}
diff --git a/src/services/TokenCache.ts b/src/services/TokenCache.ts
new file mode 100644
index 0000000..9bca4e0
--- /dev/null
+++ b/src/services/TokenCache.ts
@@ -0,0 +1,21 @@
+import { TokenCache, TokenStore } from '@commercetools/sdk-client-v2';
+
+export default class MyTokenCache implements TokenCache {
+ private token: TokenStore;
+
+ constructor() {
+ this.token = {
+ token: '',
+ refreshToken: '',
+ expirationTime: 0,
+ };
+ }
+
+ set(newToken: TokenStore) {
+ this.token = newToken;
+ }
+
+ get() {
+ return this.token;
+ }
+}
diff --git a/src/services/addresses/addAddress.ts b/src/services/addresses/addAddress.ts
new file mode 100644
index 0000000..49a83fc
--- /dev/null
+++ b/src/services/addresses/addAddress.ts
@@ -0,0 +1,28 @@
+import { ClientResponse, Customer, MyCustomerAddAddressAction, _BaseAddress } from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import apiExistingToken from '../apiExistingToken';
+
+export default async function addAddress(data: _BaseAddress): Promise {
+ const { customer } = userStore.getState();
+
+ const currentToken = localStorage.getItem('token');
+ const parsenToken = currentToken ? currentToken : '';
+
+ const action: MyCustomerAddAddressAction = {
+ action: 'addAddress',
+ address: data,
+ };
+
+ const body = {
+ body: {
+ version: Number(customer?.version),
+ actions: [action],
+ },
+ };
+
+ const response: ClientResponse = await apiExistingToken(parsenToken).me().post(body).execute();
+
+ userStore.dispatch({ type: 'ADD_CUSTOMER', customer: response.body });
+
+ return response.body;
+}
diff --git a/src/services/addresses/addTypeAddressID.ts b/src/services/addresses/addTypeAddressID.ts
new file mode 100644
index 0000000..83330e4
--- /dev/null
+++ b/src/services/addresses/addTypeAddressID.ts
@@ -0,0 +1,33 @@
+import {
+ ClientResponse,
+ Customer,
+ MyBusinessUnitAddBillingAddressIdAction,
+ MyBusinessUnitAddShippingAddressIdAction,
+} from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import apiExistingToken from '../apiExistingToken';
+
+export default async function addTypeAddressID(type: string, id: string): Promise {
+ const { customer } = userStore.getState();
+
+ const currentToken = localStorage.getItem('token');
+ const parsenToken = currentToken ? currentToken : '';
+
+ const action: MyBusinessUnitAddBillingAddressIdAction | MyBusinessUnitAddShippingAddressIdAction = {
+ action: type === 'Billing' ? 'addBillingAddressId' : 'addShippingAddressId',
+ addressId: id,
+ };
+
+ const body = {
+ body: {
+ version: Number(customer?.version),
+ actions: [action],
+ },
+ };
+
+ const response: ClientResponse = await apiExistingToken(parsenToken).me().post(body).execute();
+
+ userStore.dispatch({ type: 'ADD_CUSTOMER', customer: response.body });
+
+ return response.body;
+}
diff --git a/src/services/addresses/changeAddress.ts b/src/services/addresses/changeAddress.ts
new file mode 100644
index 0000000..bed69f2
--- /dev/null
+++ b/src/services/addresses/changeAddress.ts
@@ -0,0 +1,29 @@
+import { ClientResponse, Customer, MyCustomerChangeAddressAction, _BaseAddress } from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import apiExistingToken from '../apiExistingToken';
+
+export default async function changeAddress(id: string, data: _BaseAddress): Promise {
+ const { customer } = userStore.getState();
+
+ const currentToken = localStorage.getItem('token');
+ const parsenToken = currentToken ? currentToken : '';
+
+ const action: MyCustomerChangeAddressAction = {
+ action: 'changeAddress',
+ addressId: id,
+ address: data,
+ };
+
+ const body = {
+ body: {
+ version: Number(customer?.version),
+ actions: [action],
+ },
+ };
+
+ const response: ClientResponse = await apiExistingToken(parsenToken).me().post(body).execute();
+
+ userStore.dispatch({ type: 'ADD_CUSTOMER', customer: response.body });
+
+ return response.body;
+}
diff --git a/src/services/addresses/removeAddress.ts b/src/services/addresses/removeAddress.ts
new file mode 100644
index 0000000..882cdc2
--- /dev/null
+++ b/src/services/addresses/removeAddress.ts
@@ -0,0 +1,28 @@
+import { ClientResponse, Customer, MyCustomerRemoveAddressAction } from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import apiExistingToken from '../apiExistingToken';
+
+export default async function removeAddress(id: string): Promise {
+ const { customer } = userStore.getState();
+
+ const currentToken = localStorage.getItem('token');
+ const parsenToken = currentToken ? currentToken : '';
+
+ const action: MyCustomerRemoveAddressAction = {
+ action: 'removeAddress',
+ addressId: id,
+ };
+
+ const body = {
+ body: {
+ version: Number(customer?.version),
+ actions: [action],
+ },
+ };
+
+ const response: ClientResponse = await apiExistingToken(parsenToken).me().post(body).execute();
+
+ userStore.dispatch({ type: 'ADD_CUSTOMER', customer: response.body });
+
+ return response.body;
+}
diff --git a/src/services/addresses/removeTypeAddressID.ts b/src/services/addresses/removeTypeAddressID.ts
new file mode 100644
index 0000000..4e99352
--- /dev/null
+++ b/src/services/addresses/removeTypeAddressID.ts
@@ -0,0 +1,33 @@
+import {
+ ClientResponse,
+ Customer,
+ MyBusinessUnitRemoveBillingAddressIdAction,
+ MyBusinessUnitRemoveShippingAddressIdAction,
+} from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import apiExistingToken from '../apiExistingToken';
+
+export default async function removeTypeAddressID(type: string, id: string): Promise {
+ const { customer } = userStore.getState();
+
+ const currentToken = localStorage.getItem('token');
+ const parsenToken = currentToken ? currentToken : '';
+
+ const action: MyBusinessUnitRemoveBillingAddressIdAction | MyBusinessUnitRemoveShippingAddressIdAction = {
+ action: type === 'Billing' ? 'removeBillingAddressId' : 'removeShippingAddressId',
+ addressId: id,
+ };
+
+ const body = {
+ body: {
+ version: Number(customer?.version),
+ actions: [action],
+ },
+ };
+
+ const response: ClientResponse = await apiExistingToken(parsenToken).me().post(body).execute();
+
+ userStore.dispatch({ type: 'ADD_CUSTOMER', customer: response.body });
+
+ return response.body;
+}
diff --git a/src/services/addresses/setDefaultTypeAddress.ts b/src/services/addresses/setDefaultTypeAddress.ts
new file mode 100644
index 0000000..5acbe55
--- /dev/null
+++ b/src/services/addresses/setDefaultTypeAddress.ts
@@ -0,0 +1,33 @@
+import {
+ ClientResponse,
+ Customer,
+ MyCustomerSetDefaultBillingAddressAction,
+ MyCustomerSetDefaultShippingAddressAction,
+} from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import apiExistingToken from '../apiExistingToken';
+
+export default async function setDefaultTypeAddress(type: string, id: string): Promise {
+ const { customer } = userStore.getState();
+
+ const currentToken = localStorage.getItem('token');
+ const parsenToken = currentToken ? currentToken : '';
+
+ const action: MyCustomerSetDefaultBillingAddressAction | MyCustomerSetDefaultShippingAddressAction = {
+ action: type === 'Billing' ? 'setDefaultBillingAddress' : 'setDefaultShippingAddress',
+ addressId: id.trim() === '' ? undefined : id,
+ };
+
+ const body = {
+ body: {
+ version: Number(customer?.version),
+ actions: [action],
+ },
+ };
+
+ const response: ClientResponse = await apiExistingToken(parsenToken).me().post(body).execute();
+
+ userStore.dispatch({ type: 'ADD_CUSTOMER', customer: response.body });
+
+ return response.body;
+}
diff --git a/src/services/apiExistingToken.ts b/src/services/apiExistingToken.ts
new file mode 100644
index 0000000..6e121e1
--- /dev/null
+++ b/src/services/apiExistingToken.ts
@@ -0,0 +1,26 @@
+import {
+ ClientBuilder,
+ HttpMiddlewareOptions,
+ type ExistingTokenMiddlewareOptions,
+} from '@commercetools/sdk-client-v2';
+import { createApiBuilderFromCtpClient } from '@commercetools/platform-sdk';
+
+const projectKey: string = process.env.CTP_PROJECT_KEY || '';
+
+export default function apiExistingToken(token: string) {
+ const options: ExistingTokenMiddlewareOptions = {
+ force: false,
+ };
+
+ const httpMiddlewareOptions: HttpMiddlewareOptions = {
+ host: process.env.CTP_API_URL || '',
+ fetch,
+ };
+
+ const ctpClient = new ClientBuilder()
+ .withProjectKey(projectKey)
+ .withExistingTokenFlow(`Bearer ${token}`, options)
+ .withHttpMiddleware(httpMiddlewareOptions)
+ .build();
+ return createApiBuilderFromCtpClient(ctpClient).withProjectKey({ projectKey });
+}
diff --git a/src/services/apiRefreshToken.ts b/src/services/apiRefreshToken.ts
new file mode 100644
index 0000000..a47aa7a
--- /dev/null
+++ b/src/services/apiRefreshToken.ts
@@ -0,0 +1,35 @@
+import {
+ ClientBuilder,
+ type TokenCache,
+ type HttpMiddlewareOptions,
+ type RefreshAuthMiddlewareOptions,
+} from '@commercetools/sdk-client-v2';
+import { createApiBuilderFromCtpClient } from '@commercetools/platform-sdk';
+
+const projectKey: string = process.env.CTP_PROJECT_KEY || '';
+
+export default function apiRefreshToken(refreshToken: string, tokenCache: TokenCache) {
+ const options: RefreshAuthMiddlewareOptions = {
+ host: process.env.CTP_AUTH_URL || '',
+ projectKey,
+ credentials: {
+ clientId: process.env.CTP_CLIENT_ID || '',
+ clientSecret: process.env.CTP_CLIENT_SECRET || '',
+ },
+ refreshToken,
+ tokenCache,
+ fetch,
+ };
+
+ const httpMiddlewareOptions: HttpMiddlewareOptions = {
+ host: process.env.CTP_API_URL || '',
+ fetch,
+ };
+
+ const ctpClient = new ClientBuilder()
+ .withProjectKey(projectKey)
+ .withRefreshTokenFlow(options)
+ .withHttpMiddleware(httpMiddlewareOptions)
+ .build();
+ return createApiBuilderFromCtpClient(ctpClient).withProjectKey({ projectKey });
+}
diff --git a/src/services/apiRootAnonymus.ts b/src/services/apiRootAnonymus.ts
new file mode 100644
index 0000000..51a44ac
--- /dev/null
+++ b/src/services/apiRootAnonymus.ts
@@ -0,0 +1,36 @@
+import {
+ ClientBuilder,
+ type AnonymousAuthMiddlewareOptions,
+ type HttpMiddlewareOptions,
+ TokenCache,
+} from '@commercetools/sdk-client-v2';
+import { createApiBuilderFromCtpClient } from '@commercetools/platform-sdk';
+
+export default function apiRootAnonymus(tokenCache?: TokenCache) {
+ const projectKey: string = process.env.CTP_PROJECT_KEY || '';
+
+ const anonymousAuthMiddlewareOptions: AnonymousAuthMiddlewareOptions = {
+ host: process.env.CTP_AUTH_URL || '',
+ projectKey,
+ credentials: {
+ clientId: process.env.CTP_CLIENT_ID || '',
+ clientSecret: process.env.CTP_CLIENT_SECRET || '',
+ },
+ scopes: [process.env.CTP_SCOPES || ''],
+ tokenCache,
+ fetch,
+ };
+
+ const httpMiddlewareOptions: HttpMiddlewareOptions = {
+ host: process.env.CTP_API_URL || '',
+ fetch,
+ };
+
+ const ctpClient = new ClientBuilder()
+ .withProjectKey(projectKey)
+ .withAnonymousSessionFlow(anonymousAuthMiddlewareOptions)
+ .withHttpMiddleware(httpMiddlewareOptions)
+ .build();
+
+ return createApiBuilderFromCtpClient(ctpClient).withProjectKey({ projectKey });
+}
diff --git a/src/services/apiRootCredentials.ts b/src/services/apiRootCredentials.ts
new file mode 100644
index 0000000..31d74d4
--- /dev/null
+++ b/src/services/apiRootCredentials.ts
@@ -0,0 +1,30 @@
+import { ClientBuilder, type AuthMiddlewareOptions, type HttpMiddlewareOptions } from '@commercetools/sdk-client-v2';
+import { createApiBuilderFromCtpClient } from '@commercetools/platform-sdk';
+
+export default function apiRootCredentials() {
+ const projectKey: string = process.env.CTP_PROJECT_KEY || '';
+
+ const authMiddlewareOptions: AuthMiddlewareOptions = {
+ host: process.env.CTP_AUTH_URL || '',
+ projectKey,
+ credentials: {
+ clientId: process.env.CTP_CLIENT_ID || '',
+ clientSecret: process.env.CTP_CLIENT_SECRET || '',
+ },
+ scopes: [process.env.CTP_SCOPES || ''],
+ fetch,
+ };
+
+ const httpMiddlewareOptions: HttpMiddlewareOptions = {
+ host: process.env.CTP_API_URL || '',
+ fetch,
+ };
+
+ const ctpClient = new ClientBuilder()
+ .withProjectKey(projectKey)
+ .withClientCredentialsFlow(authMiddlewareOptions)
+ .withHttpMiddleware(httpMiddlewareOptions)
+ .build();
+
+ return createApiBuilderFromCtpClient(ctpClient).withProjectKey({ projectKey });
+}
diff --git a/src/services/apiRootPassword.ts b/src/services/apiRootPassword.ts
new file mode 100644
index 0000000..fbe0a0d
--- /dev/null
+++ b/src/services/apiRootPassword.ts
@@ -0,0 +1,40 @@
+import {
+ ClientBuilder,
+ TokenCache,
+ type PasswordAuthMiddlewareOptions,
+ type HttpMiddlewareOptions,
+} from '@commercetools/sdk-client-v2';
+import { createApiBuilderFromCtpClient } from '@commercetools/platform-sdk';
+
+const projectKey: string = process.env.CTP_PROJECT_KEY || '';
+
+export default function apiRootPassword(email: string, password: string, tokenCache: TokenCache) {
+ const options: PasswordAuthMiddlewareOptions = {
+ host: process.env.CTP_AUTH_URL || '',
+ projectKey,
+ credentials: {
+ clientId: process.env.CTP_CLIENT_ID || '',
+ clientSecret: process.env.CTP_CLIENT_SECRET || '',
+ user: {
+ username: email,
+ password,
+ },
+ },
+ scopes: [process.env.CTP_SCOPES || ''],
+ tokenCache,
+ fetch,
+ };
+
+ const httpMiddlewareOptions: HttpMiddlewareOptions = {
+ host: process.env.CTP_API_URL || '',
+ fetch,
+ };
+
+ const ctpClient = new ClientBuilder()
+ .withProjectKey(projectKey)
+ .withPasswordFlow(options)
+ .withHttpMiddleware(httpMiddlewareOptions)
+ .build();
+
+ return createApiBuilderFromCtpClient(ctpClient).withProjectKey({ projectKey });
+}
diff --git a/src/services/basket/addDiscountToCart.ts b/src/services/basket/addDiscountToCart.ts
new file mode 100644
index 0000000..d472682
--- /dev/null
+++ b/src/services/basket/addDiscountToCart.ts
@@ -0,0 +1,79 @@
+import { ClientResponse, Cart, MyCartRemoveDiscountCodeAction } from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import createAnonymusCart from './createAnonymusCart';
+import getActiveCart from './getActiveCart';
+import apiExistingToken from '../apiExistingToken';
+import Notification from '../../components/notification/notification';
+import createUserCart from './createUserCart';
+
+export default async function addDiscountToCart(code: string): Promise {
+ const { isAuth } = userStore.getState();
+ let cart: Cart;
+ let token: string | null;
+
+ if (!isAuth) {
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ await createAnonymusCart();
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+ }
+
+ cart = await getActiveCart(token);
+ } else {
+ token = localStorage.getItem('token');
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+
+ try {
+ cart = await getActiveCart(token);
+ } catch {
+ cart = await createUserCart(token);
+ }
+ }
+
+ function removeAllDiscountes(): MyCartRemoveDiscountCodeAction[] | [] {
+ const result: MyCartRemoveDiscountCodeAction[] = [];
+
+ cart.discountCodes.forEach((item) => {
+ result.push({
+ action: 'removeDiscountCode',
+ discountCode: {
+ typeId: item.discountCode.typeId,
+ id: item.discountCode.id,
+ },
+ });
+ });
+
+ return result;
+ }
+
+ const response: ClientResponse = await apiExistingToken(token)
+ .me()
+ .carts()
+ .withId({
+ ID: cart.id,
+ })
+ .post({
+ body: {
+ version: cart.version,
+ actions: [
+ ...removeAllDiscountes(),
+ {
+ action: 'addDiscountCode',
+ code,
+ },
+ ],
+ },
+ })
+ .execute();
+
+ return response?.body;
+}
diff --git a/src/services/basket/addToCart.ts b/src/services/basket/addToCart.ts
new file mode 100644
index 0000000..b860183
--- /dev/null
+++ b/src/services/basket/addToCart.ts
@@ -0,0 +1,62 @@
+import { ClientResponse, Cart } from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import createAnonymusCart from './createAnonymusCart';
+import getActiveCart from './getActiveCart';
+import apiExistingToken from '../apiExistingToken';
+import Notification from '../../components/notification/notification';
+import createUserCart from './createUserCart';
+
+export default async function addToCart(productId: string): Promise {
+ const { isAuth } = userStore.getState();
+ let cart: Cart;
+ let token: string | null;
+
+ if (!isAuth) {
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ await createAnonymusCart();
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+ }
+
+ cart = await getActiveCart(token);
+ } else {
+ token = localStorage.getItem('token');
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+
+ try {
+ cart = await getActiveCart(token);
+ } catch {
+ cart = await createUserCart(token);
+ }
+ }
+
+ const response: ClientResponse = await apiExistingToken(token)
+ .me()
+ .carts()
+ .withId({
+ ID: cart.id,
+ })
+ .post({
+ body: {
+ version: cart.version,
+ actions: [
+ {
+ action: 'addLineItem',
+ productId,
+ },
+ ],
+ },
+ })
+ .execute();
+
+ return response?.body;
+}
diff --git a/src/services/basket/changeCartItemQuantity.ts b/src/services/basket/changeCartItemQuantity.ts
new file mode 100644
index 0000000..0e0bd2e
--- /dev/null
+++ b/src/services/basket/changeCartItemQuantity.ts
@@ -0,0 +1,63 @@
+import { ClientResponse, Cart } from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import createAnonymusCart from './createAnonymusCart';
+import getActiveCart from './getActiveCart';
+import apiExistingToken from '../apiExistingToken';
+import Notification from '../../components/notification/notification';
+import createUserCart from './createUserCart';
+
+export default async function changeCartItemQuantity(lineItemId: string, quantity: number): Promise {
+ const { isAuth } = userStore.getState();
+ let cart: Cart;
+ let token: string | null;
+
+ if (!isAuth) {
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ await createAnonymusCart();
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+ }
+
+ cart = await getActiveCart(token);
+ } else {
+ token = localStorage.getItem('token');
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+
+ try {
+ cart = await getActiveCart(token);
+ } catch {
+ cart = await createUserCart(token);
+ }
+ }
+
+ const response: ClientResponse = await apiExistingToken(token)
+ .me()
+ .carts()
+ .withId({
+ ID: cart.id,
+ })
+ .post({
+ body: {
+ version: cart.version,
+ actions: [
+ {
+ action: 'changeLineItemQuantity',
+ lineItemId,
+ quantity,
+ },
+ ],
+ },
+ })
+ .execute();
+
+ return response?.body;
+}
diff --git a/src/services/basket/createAnonymusCart.ts b/src/services/basket/createAnonymusCart.ts
new file mode 100644
index 0000000..5916e00
--- /dev/null
+++ b/src/services/basket/createAnonymusCart.ts
@@ -0,0 +1,24 @@
+import { Cart, ClientResponse } from '@commercetools/platform-sdk';
+import apiRootAnonymus from '../apiRootAnonymus';
+import MyTokenCache from '../TokenCache';
+
+export default async function createAnonymusCart(): Promise {
+ const tokenCache = new MyTokenCache();
+
+ const response: ClientResponse = await apiRootAnonymus(tokenCache)
+ .me()
+ .carts()
+ .post({
+ body: {
+ currency: 'USD',
+ country: 'US',
+ },
+ })
+ .execute();
+
+ const { token, refreshToken } = tokenCache.get();
+ if (token) localStorage.setItem('tokenAnon', token);
+ if (refreshToken) localStorage.setItem('refreshTokenAnon', refreshToken);
+
+ return response.body;
+}
diff --git a/src/services/basket/createUserCart.ts b/src/services/basket/createUserCart.ts
new file mode 100644
index 0000000..8f16555
--- /dev/null
+++ b/src/services/basket/createUserCart.ts
@@ -0,0 +1,17 @@
+import { Cart, ClientResponse } from '@commercetools/platform-sdk';
+import apiExistingToken from '../apiExistingToken';
+
+export default async function createUserCart(token: string): Promise {
+ const response: ClientResponse = await apiExistingToken(token)
+ .me()
+ .carts()
+ .post({
+ body: {
+ currency: 'USD',
+ country: 'US',
+ },
+ })
+ .execute();
+
+ return response.body;
+}
diff --git a/src/services/basket/getActiveCart.ts b/src/services/basket/getActiveCart.ts
new file mode 100644
index 0000000..c3a63bb
--- /dev/null
+++ b/src/services/basket/getActiveCart.ts
@@ -0,0 +1,8 @@
+import { Cart, ClientResponse } from '@commercetools/platform-sdk';
+import apiExistingToken from '../apiExistingToken';
+
+export default async function getActiveCart(token: string): Promise {
+ const response: ClientResponse = await apiExistingToken(token).me().activeCart().get().execute();
+
+ return response.body;
+}
diff --git a/src/services/basket/getCart.ts b/src/services/basket/getCart.ts
new file mode 100644
index 0000000..c9b7442
--- /dev/null
+++ b/src/services/basket/getCart.ts
@@ -0,0 +1,69 @@
+import { Cart } from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import createUserCart from './createUserCart';
+import Notification from '../../components/notification/notification';
+import createAnonymusCart from './createAnonymusCart';
+import getAnonActiveCart from '../getAnonActiveCart';
+import getActiveCart from './getActiveCart';
+
+export default async function getCart(): Promise {
+ let token: string | null;
+ let refreshToken: string | null;
+ const { isAuth } = userStore.getState();
+
+ if (isAuth) {
+ token = localStorage.getItem('token');
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+
+ try {
+ return await getActiveCart(token);
+ } catch {
+ return await createUserCart(token);
+ }
+ } else {
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ try {
+ return await createAnonymusCart();
+ } catch (error) {
+ if (error instanceof Error) {
+ new Notification(
+ 'error',
+ 'Something went wrong! Please try to log in or try again later.'
+ ).showNotification();
+ } else {
+ console.error(error);
+ }
+ return;
+ }
+ }
+
+ try {
+ return await getActiveCart(token);
+ } catch (error) {
+ if (error instanceof Error) {
+ if (error.message === 'invalid_token') {
+ localStorage.removeItem('tokenAnon');
+ localStorage.removeItem('token');
+
+ refreshToken = localStorage.getItem('refreshTokenAnon');
+ if (!refreshToken) {
+ new Notification(
+ 'error',
+ 'Something went wrong! Please try to log in or try again later.'
+ ).showNotification();
+ return;
+ }
+ return await getAnonActiveCart(refreshToken);
+ }
+ } else {
+ console.error(error);
+ }
+ return await createAnonymusCart();
+ }
+ }
+}
diff --git a/src/services/basket/removeCart.ts b/src/services/basket/removeCart.ts
new file mode 100644
index 0000000..3d9a2d1
--- /dev/null
+++ b/src/services/basket/removeCart.ts
@@ -0,0 +1,37 @@
+import userStore from '../../store/user-store';
+import createAnonymusCart from './createAnonymusCart';
+import Notification from '../../components/notification/notification';
+import { Cart } from '@commercetools/platform-sdk';
+import createUserCart from './createUserCart';
+
+export default async function removeCart(): Promise {
+ const { isAuth } = userStore.getState();
+ let token: string | null;
+ let cart: Cart | undefined = undefined;
+
+ if (!isAuth) {
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+ }
+
+ cart = await createAnonymusCart();
+ } else {
+ token = localStorage.getItem('token');
+
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+
+ cart = await createUserCart(token);
+ }
+
+ return cart;
+}
diff --git a/src/services/basket/removeDiscountCart.ts b/src/services/basket/removeDiscountCart.ts
new file mode 100644
index 0000000..5374941
--- /dev/null
+++ b/src/services/basket/removeDiscountCart.ts
@@ -0,0 +1,73 @@
+import { ClientResponse, Cart, MyCartRemoveDiscountCodeAction } from '@commercetools/platform-sdk';
+import userStore from '../../store/user-store';
+import createAnonymusCart from './createAnonymusCart';
+import getActiveCart from './getActiveCart';
+import apiExistingToken from '../apiExistingToken';
+import Notification from '../../components/notification/notification';
+import createUserCart from './createUserCart';
+
+export default async function removeDiscountCart(): Promise {
+ const { isAuth } = userStore.getState();
+ let cart: Cart;
+ let token: string | null;
+
+ if (!isAuth) {
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ await createAnonymusCart();
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+ }
+
+ cart = await getActiveCart(token);
+ } else {
+ token = localStorage.getItem('token');
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+
+ try {
+ cart = await getActiveCart(token);
+ } catch {
+ cart = await createUserCart(token);
+ }
+ }
+
+ function removeAllDiscountes(): MyCartRemoveDiscountCodeAction[] | [] {
+ const result: MyCartRemoveDiscountCodeAction[] = [];
+
+ cart.discountCodes.forEach((item) => {
+ result.push({
+ action: 'removeDiscountCode',
+ discountCode: {
+ typeId: item.discountCode.typeId,
+ id: item.discountCode.id,
+ },
+ });
+ });
+
+ return result;
+ }
+
+ const response: ClientResponse = await apiExistingToken(token)
+ .me()
+ .carts()
+ .withId({
+ ID: cart.id,
+ })
+ .post({
+ body: {
+ version: cart.version,
+ actions: [...removeAllDiscountes()],
+ },
+ })
+ .execute();
+
+ return response?.body;
+}
diff --git a/src/services/basket/removeProductFromCart.ts b/src/services/basket/removeProductFromCart.ts
new file mode 100644
index 0000000..227bd01
--- /dev/null
+++ b/src/services/basket/removeProductFromCart.ts
@@ -0,0 +1,56 @@
+import userStore from '../../store/user-store';
+import createAnonymusCart from './createAnonymusCart';
+import Notification from '../../components/notification/notification';
+import getActiveCart from './getActiveCart';
+import apiExistingToken from '../apiExistingToken';
+import { Cart } from '@commercetools/platform-sdk';
+
+export default async function removeProductFromCart(productId: string): Promise {
+ const { isAuth } = userStore.getState();
+ let token: string | null;
+
+ if (!isAuth) {
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ await createAnonymusCart();
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+ }
+ } else {
+ token = localStorage.getItem('token');
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+ }
+
+ const cart: Cart = await getActiveCart(token);
+
+ const cartItem = cart.lineItems.filter((item) => item.productId === productId);
+
+ const response = await apiExistingToken(token)
+ .me()
+ .carts()
+ .withId({
+ ID: cart.id,
+ })
+ .post({
+ body: {
+ version: cart.version,
+ actions: [
+ {
+ action: 'removeLineItem',
+ lineItemId: cartItem[0].id,
+ },
+ ],
+ },
+ })
+ .execute();
+
+ return response?.body;
+}
diff --git a/src/services/changePassword.ts b/src/services/changePassword.ts
new file mode 100644
index 0000000..0b7d9aa
--- /dev/null
+++ b/src/services/changePassword.ts
@@ -0,0 +1,28 @@
+import { ClientResponse, Customer, MyCustomerChangePassword } from '@commercetools/platform-sdk';
+import userStore from '../store/user-store';
+import apiExistingToken from './apiExistingToken';
+
+export default async function changePassword(currentPassword: string, newPassword: string): Promise {
+ const { customer } = userStore.getState();
+
+ const currentToken = localStorage.getItem('token');
+ const parsenToken = currentToken ? currentToken : '';
+
+ const sendData: { body: MyCustomerChangePassword } = {
+ body: {
+ version: Number(customer?.version),
+ currentPassword,
+ newPassword,
+ },
+ };
+
+ const response: ClientResponse = await apiExistingToken(parsenToken)
+ .me()
+ .password()
+ .post(sendData)
+ .execute();
+
+ userStore.dispatch({ type: 'ADD_CUSTOMER', customer: response.body });
+
+ return response.body;
+}
diff --git a/src/services/getAllCategories.ts b/src/services/getAllCategories.ts
new file mode 100644
index 0000000..aa0838c
--- /dev/null
+++ b/src/services/getAllCategories.ts
@@ -0,0 +1,8 @@
+import { type Category } from '@commercetools/platform-sdk';
+import apiRootCredentials from './apiRootCredentials';
+
+export default async function getAllCategories(): Promise {
+ const response = await apiRootCredentials().categories().get().execute();
+
+ return response.body.results;
+}
diff --git a/src/services/getAnonActiveCart.ts b/src/services/getAnonActiveCart.ts
new file mode 100644
index 0000000..d79d04d
--- /dev/null
+++ b/src/services/getAnonActiveCart.ts
@@ -0,0 +1,17 @@
+import { Cart, ClientResponse } from '@commercetools/platform-sdk';
+import apiRefreshToken from './apiRefreshToken';
+import MyTokenCache from './TokenCache';
+
+export default async function getAnonActiveCart(refreshToken: string): Promise {
+ const tokenCache = new MyTokenCache();
+ const response: ClientResponse = await apiRefreshToken(refreshToken, tokenCache)
+ .me()
+ .activeCart()
+ .get()
+ .execute();
+
+ const { token } = tokenCache.get();
+ if (token) localStorage.setItem('tokenAnon', token);
+
+ return response.body;
+}
diff --git a/src/services/getDiscountCode.ts b/src/services/getDiscountCode.ts
new file mode 100644
index 0000000..ca211e7
--- /dev/null
+++ b/src/services/getDiscountCode.ts
@@ -0,0 +1,51 @@
+import { Cart, ClientResponse, DiscountCode } from '@commercetools/platform-sdk';
+import userStore from '../store/user-store';
+import createAnonymusCart from './basket/createAnonymusCart';
+import getActiveCart from './basket/getActiveCart';
+import apiExistingToken from './apiExistingToken';
+import Notification from '../components/notification/notification';
+import createUserCart from './basket/createUserCart';
+
+export default async function getDiscountCode(): Promise {
+ const { isAuth } = userStore.getState();
+ let cart: Cart;
+ let token: string | null;
+
+ if (!isAuth) {
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ await createAnonymusCart();
+ token = localStorage.getItem('tokenAnon');
+
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+ }
+
+ cart = await getActiveCart(token);
+ } else {
+ token = localStorage.getItem('token');
+ if (!token) {
+ new Notification('error', 'Something went wrong! Please try to log in or try again later.').showNotification();
+ return;
+ }
+
+ try {
+ cart = await getActiveCart(token);
+ } catch {
+ cart = await createUserCart(token);
+ }
+ }
+
+ const response: ClientResponse = await apiExistingToken(token)
+ .discountCodes()
+ .withId({
+ ID: cart?.discountCodes[0]?.discountCode?.id || '',
+ })
+ .get()
+ .execute();
+
+ return response?.body;
+}
diff --git a/src/services/getProductById.ts b/src/services/getProductById.ts
new file mode 100644
index 0000000..bdc7ac3
--- /dev/null
+++ b/src/services/getProductById.ts
@@ -0,0 +1,8 @@
+import { ClientResponse, Product } from '@commercetools/platform-sdk';
+import apiRootCredentials from './apiRootCredentials';
+
+export default async function getProductById(ID: string): Promise {
+ const response: ClientResponse = await apiRootCredentials().products().withId({ ID }).get().execute();
+
+ return response.body;
+}
diff --git a/src/services/getProducts.ts b/src/services/getProducts.ts
new file mode 100644
index 0000000..fdbf903
--- /dev/null
+++ b/src/services/getProducts.ts
@@ -0,0 +1,85 @@
+import {
+ Category,
+ type ClientResponse,
+ type ProductProjection,
+ type ProductProjectionPagedQueryResponse,
+} from '@commercetools/platform-sdk';
+import apiRootCredentials from './apiRootCredentials';
+import getAllCategories from './getAllCategories';
+import { BASE_PRODUCT_LIMIT, BASE_PRODUCT_OFFSET } from '../constants/productsOptions';
+
+interface IProductsResponse {
+ products: ProductProjection[];
+ offset: number;
+ total: number;
+}
+
+export default async function getProducts(
+ categoryName?: string,
+ subcategoryName?: string,
+ filterPrice: string = '',
+ filterDays: string = '',
+ sortValue: string = '',
+ searchValue: string = '',
+ offset: number = BASE_PRODUCT_OFFSET,
+ limit: number = BASE_PRODUCT_LIMIT
+): Promise {
+ try {
+ const allCategories: Category[] = await getAllCategories();
+
+ let categoryId = '';
+ const filter: string[] = [];
+ let filterQuery: string = '';
+ let sort: string = '';
+ const searchQuery = {
+ 'text.en': '',
+ };
+
+ if (subcategoryName) {
+ categoryId = allCategories.find((item) => item.key === subcategoryName)?.id || '';
+ filter.push(`categories.id:"${categoryId}"`);
+ } else if (categoryName) {
+ categoryId = allCategories.find((item) => item.key === categoryName)?.id || '';
+ filter.push(`categories.id: subtree("${categoryId}")`);
+ }
+
+ if (filterPrice) {
+ filterQuery = `variants.price.centAmount:${filterPrice}`;
+ }
+
+ if (filterDays) {
+ filter.push(`variants.attributes.days:${filterDays}`);
+ }
+
+ if (sortValue) {
+ sort = sortValue;
+ }
+
+ if (searchValue) {
+ searchQuery['text.en'] = searchValue;
+ }
+
+ const response: ClientResponse = await apiRootCredentials()
+ .productProjections()
+ .search()
+ .get({
+ queryArgs: {
+ ...(filter.length ? { filter } : {}),
+ ...(filterQuery ? { 'filter.query': filterQuery } : {}),
+ ...(sort ? { sort } : {}),
+ ...(searchValue ? searchQuery : {}),
+ limit,
+ offset,
+ },
+ })
+ .execute();
+
+ return {
+ products: response.body.results,
+ offset: response.body.offset ?? BASE_PRODUCT_OFFSET,
+ total: response.body.total ?? BASE_PRODUCT_LIMIT,
+ };
+ } catch (error) {
+ console.log(error);
+ }
+}
diff --git a/src/services/getUser.ts b/src/services/getUser.ts
new file mode 100644
index 0000000..ae39625
--- /dev/null
+++ b/src/services/getUser.ts
@@ -0,0 +1,8 @@
+import { ClientResponse, Customer } from '@commercetools/platform-sdk';
+import apiExistingToken from './apiExistingToken';
+
+export default async function getUser(token: string): Promise {
+ const customer: ClientResponse = await apiExistingToken(token).me().get().execute();
+
+ return customer.body;
+}
diff --git a/src/services/signinUser.ts b/src/services/signinUser.ts
new file mode 100644
index 0000000..8059273
--- /dev/null
+++ b/src/services/signinUser.ts
@@ -0,0 +1,43 @@
+import { ClientResponse, Customer, CustomerSignInResult } from '@commercetools/platform-sdk';
+import { ISigninData } from '../types/interfaces';
+import apiRootPassword from './apiRootPassword';
+import MyTokenCache from './TokenCache';
+import userStore from '../store/user-store';
+import apiExistingToken from './apiExistingToken';
+
+export default async function signinUser(body: ISigninData): Promise {
+ const tokenCache = new MyTokenCache();
+
+ const tokenAnon: string | null = localStorage.getItem('tokenAnon');
+
+ if (tokenAnon) {
+ await apiExistingToken(tokenAnon)
+ .me()
+ .login()
+ .post({
+ body: {
+ email: body.email,
+ password: body.password,
+ activeCartSignInMode: 'UseAsNewActiveCustomerCart',
+ },
+ })
+ .execute();
+
+ localStorage.removeItem('tokenAnon');
+ }
+
+ const response: ClientResponse = await apiRootPassword(body.email, body.password, tokenCache)
+ .me()
+ .login()
+ .post({
+ body,
+ })
+ .execute();
+
+ const { token } = tokenCache.get();
+ if (token) localStorage.setItem('token', token);
+ userStore.dispatch({ type: 'SET_IS_AUTH', isAuth: true });
+ userStore.dispatch({ type: 'ADD_CUSTOMER', customer: response?.body?.customer });
+
+ return response?.body?.customer;
+}
diff --git a/src/services/signupUser.ts b/src/services/signupUser.ts
new file mode 100644
index 0000000..ac4d3dc
--- /dev/null
+++ b/src/services/signupUser.ts
@@ -0,0 +1,21 @@
+import { Customer } from '@commercetools/platform-sdk';
+import { ISignupData } from '../types/interfaces';
+import apiRootCredentials from './apiRootCredentials';
+import signinUser from './signinUser';
+
+export default async function signupUser(body: ISignupData): Promise {
+ await apiRootCredentials()
+ .me()
+ .signup()
+ .post({
+ body,
+ })
+ .execute();
+
+ const customer: Customer = await signinUser({
+ email: body.email,
+ password: body.password,
+ });
+
+ return customer;
+}
diff --git a/src/services/updateUser.ts b/src/services/updateUser.ts
new file mode 100644
index 0000000..ff49078
--- /dev/null
+++ b/src/services/updateUser.ts
@@ -0,0 +1,23 @@
+import { ClientResponse, Customer, MyCustomerUpdateAction } from '@commercetools/platform-sdk';
+import userStore from '../store/user-store';
+import apiExistingToken from './apiExistingToken';
+
+export default async function updateUser(data: MyCustomerUpdateAction[]): Promise {
+ const { customer } = userStore.getState();
+
+ const currentToken = localStorage.getItem('token');
+ const parsenToken = currentToken ? currentToken : '';
+
+ const body = {
+ body: {
+ version: Number(customer?.version),
+ actions: data,
+ },
+ };
+
+ const response: ClientResponse = await apiExistingToken(parsenToken).me().post(body).execute();
+
+ userStore.dispatch({ type: 'ADD_CUSTOMER', customer: response.body });
+
+ return response.body;
+}
diff --git a/src/services/userLogout.ts b/src/services/userLogout.ts
new file mode 100644
index 0000000..e780c6a
--- /dev/null
+++ b/src/services/userLogout.ts
@@ -0,0 +1,7 @@
+import userStore from '../store/user-store';
+
+export default function userLogout() {
+ localStorage.removeItem('token');
+ userStore.dispatch({ type: 'SET_IS_AUTH', isAuth: false });
+ userStore.dispatch({ type: 'REMOVE_CUSTOMER' });
+}
diff --git a/src/store/base-store.ts b/src/store/base-store.ts
new file mode 100644
index 0000000..74fef45
--- /dev/null
+++ b/src/store/base-store.ts
@@ -0,0 +1,35 @@
+export interface IStore {
+ getState: () => T;
+ subscribe: (fn: (state: T) => void) => void;
+ dispatch: (action: A) => void;
+ unsubscribe: () => void;
+}
+
+export default class BaseStore implements IStore {
+ private subscribers: ((state: T) => void)[];
+ private currentState: T;
+ private reducer: (state: T, action: A) => T;
+
+ constructor(reducer: (state: T, action: A) => T, initialState: T) {
+ this.subscribers = [];
+ this.currentState = initialState;
+ this.reducer = reducer;
+ }
+
+ getState(): T {
+ return this.currentState;
+ }
+
+ subscribe(fn: (state: T) => void): void {
+ this.subscribers.push(fn);
+ }
+
+ dispatch(action: A): void {
+ this.currentState = this.reducer(this.currentState, action);
+ this.subscribers.forEach((fn) => fn(this.currentState));
+ }
+
+ unsubscribe(): void {
+ this.subscribers = [];
+ }
+}
diff --git a/src/store/cart-store.ts b/src/store/cart-store.ts
new file mode 100644
index 0000000..6e7d626
--- /dev/null
+++ b/src/store/cart-store.ts
@@ -0,0 +1,35 @@
+import { Cart } from '@commercetools/platform-sdk';
+import BaseStore, { IStore } from './base-store';
+
+interface ICartState {
+ cart: Cart | undefined;
+}
+
+interface ICartAction {
+ type: string;
+ cart?: Cart;
+}
+
+const initialState: ICartState = {
+ cart: undefined,
+};
+
+const reducer = (state: ICartState, action: ICartAction): ICartState => {
+ const newState: ICartState = JSON.parse(JSON.stringify(state));
+ switch (action.type) {
+ case 'UPDATE_CART':
+ if (action.cart) {
+ newState.cart = action.cart;
+ }
+ return newState;
+ case 'REMOVE_ITEMS':
+ newState.cart = undefined;
+ return newState;
+ default:
+ return newState;
+ }
+};
+
+const cartStore: IStore = new BaseStore(reducer, initialState);
+
+export default cartStore;
diff --git a/src/store/shop-store.ts b/src/store/shop-store.ts
new file mode 100644
index 0000000..6731d46
--- /dev/null
+++ b/src/store/shop-store.ts
@@ -0,0 +1,57 @@
+import BaseStore, { IStore } from './base-store';
+
+interface IShopState {
+ filterPrice: string;
+ filterDays: string;
+ sortValue: string;
+ searchValue: string;
+}
+
+interface IShopAction {
+ type: string;
+ newFilterPrice?: string;
+ newFilterDays?: string;
+ newSortValue?: string;
+ newSearchValue?: string;
+}
+
+const initialState: IShopState = {
+ filterPrice: '',
+ filterDays: '',
+ sortValue: '',
+ searchValue: '',
+};
+
+const reducer = (state: IShopState, action: IShopAction): IShopState => {
+ const newState: IShopState = JSON.parse(JSON.stringify(state));
+ switch (action.type) {
+ case 'SET_FILTER_PRICE':
+ if (action.newFilterPrice) newState.filterPrice = action.newFilterPrice;
+ return newState;
+ case 'SET_FILTER_DAYS':
+ if (action.newFilterDays) newState.filterDays = action.newFilterDays;
+ return newState;
+ case 'SET_SORT_VALUE':
+ if (action.newSortValue !== undefined) newState.sortValue = action.newSortValue;
+ return newState;
+ case 'SET_SEARCH_VALUE':
+ if (action.newSearchValue !== undefined) newState.searchValue = action.newSearchValue;
+ return newState;
+ case 'RESET_FILTER_PRICE':
+ newState.filterPrice = '';
+ return newState;
+ case 'RESET_FILTER_DAYS':
+ newState.filterDays = '';
+ return newState;
+ case 'RESET_ALL_FILTERS':
+ newState.filterPrice = '';
+ newState.filterDays = '';
+ return newState;
+ default:
+ return newState;
+ }
+};
+
+const shopStore: IStore = new BaseStore(reducer, initialState);
+
+export default shopStore;
diff --git a/src/store/user-store.ts b/src/store/user-store.ts
new file mode 100644
index 0000000..debf9b7
--- /dev/null
+++ b/src/store/user-store.ts
@@ -0,0 +1,39 @@
+import BaseStore, { IStore } from './base-store';
+import { Customer } from '@commercetools/platform-sdk';
+
+interface IUserState {
+ isAuth: boolean;
+ customer: Customer | null;
+}
+
+interface IUserAction {
+ type: string;
+ isAuth?: boolean;
+ customer?: Customer;
+}
+
+const initialState: IUserState = {
+ isAuth: false,
+ customer: null,
+};
+
+const reducer = (state: IUserState, action: IUserAction): IUserState => {
+ const newState: IUserState = JSON.parse(JSON.stringify(state));
+ switch (action.type) {
+ case 'SET_IS_AUTH':
+ if (action.isAuth !== undefined) newState.isAuth = action.isAuth;
+ return newState;
+ case 'ADD_CUSTOMER':
+ if (action.customer) newState.customer = action.customer;
+ return newState;
+ case 'REMOVE_CUSTOMER':
+ newState.customer = null;
+ return newState;
+ default:
+ return newState;
+ }
+};
+
+const userStore: IStore = new BaseStore(reducer, initialState);
+
+export default userStore;
diff --git a/src/styles/base/_fonts.scss b/src/styles/base/_fonts.scss
new file mode 100644
index 0000000..d812be5
--- /dev/null
+++ b/src/styles/base/_fonts.scss
@@ -0,0 +1,2 @@
+@import url('https://fonts.googleapis.com/css2?family=Gloock&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@500;600;700&display=swap');
diff --git a/src/styles/base/_variables.scss b/src/styles/base/_variables.scss
new file mode 100644
index 0000000..af834c2
--- /dev/null
+++ b/src/styles/base/_variables.scss
@@ -0,0 +1,165 @@
+// colors
+$color-black: #000000;
+$color-white: #ffffff;
+$color-primary: #001329;
+$color-secondary-40: #99a1a9;
+$color-secondary-60: #66717f;
+$color-bg-secondary: #d9d9d9;
+$color-bg-light: #f5f6f7;
+$color-gray: #f2f2f2;
+$color-price: #2b8813;
+$color-rating: #fcc400;
+$color-logo: #ff8a00;
+$color-button: #0058c1;
+$color-button-hover: #1969c7;
+$color-bg-card: #f5f6f6;
+$color-border: #e0e3e5;
+$color-error: #ef4444;
+$color-success: #2b8813;
+
+// breakpoints
+$width-small-mobile: 500px;
+$width-mobile: 768px;
+$width-tablet: 1024px;
+$width-pre-tablet: 1200px;
+$width-laptop: 1440px;
+
+@mixin small-mobile {
+ @media (max-width: $width-small-mobile) {
+ @content;
+ }
+}
+
+@mixin mobile {
+ @media (max-width: $width-mobile) {
+ @content;
+ }
+}
+
+@mixin tablet {
+ @media (max-width: $width-tablet) {
+ @content;
+ }
+}
+
+@mixin pre-tablet {
+ @media (max-width: $width-pre-tablet) {
+ @content;
+ }
+}
+
+@mixin laptop {
+ @media (max-width: $width-laptop) {
+ @content;
+ }
+}
+
+@mixin desktop {
+ @media (min-width: $width-tablet) {
+ @content;
+ }
+}
+
+// fonts
+$font-family-jakarta: 'Plus Jakarta Sans', sans-serif;
+$font-family-gloock: 'Gloock', serif;
+
+$font-main: 500 16px/1.5 $font-family-jakarta;
+$font-subtitle: 500 18px/1.5 $font-family-jakarta;
+$font-logo: 400 26px/0.92 $font-family-gloock;
+$font-button: 700 15px/1.5 $font-family-jakarta;
+$font-label: 600 15px/1.5 $font-family-jakarta;
+$font-xs: 600 12px/1.5 $font-family-jakarta;
+$font-about-label: 700 11px/1.2 $font-family-jakarta;
+
+@mixin font-h1 {
+ font: 400 60px/1.2 $font-family-gloock;
+
+ @include tablet {
+ font-size: 50px;
+ }
+
+ @include mobile {
+ font-size: 36px;
+ }
+}
+
+@mixin font-h2 {
+ font: 400 40px/1.2 $font-family-gloock;
+
+ @include tablet {
+ font-size: 36px;
+ }
+
+ @include mobile {
+ font-size: 24px;
+ }
+}
+
+@mixin font-h3 {
+ font: 400 32px/1.4 $font-family-gloock;
+
+ @include tablet {
+ font-size: 28px;
+ }
+
+ @include mobile {
+ font-size: 22px;
+ }
+}
+
+@mixin font-h4 {
+ font: 400 24px/1.4 $font-family-gloock;
+
+ @include tablet {
+ font-size: 20px;
+ }
+
+ @include mobile {
+ font-size: 18px;
+ }
+}
+
+// container
+@mixin container {
+ margin: 0 auto;
+ max-width: 1920px;
+ padding: 0 120px;
+
+ @include tablet {
+ padding: 0 60px;
+ }
+
+ @include mobile {
+ padding: 0 20px;
+ }
+}
+
+// another
+
+@mixin chevron {
+ position: absolute;
+ display: block;
+ content: '';
+ width: 20px;
+ height: 20px;
+ background-image: url('../../../assets/icons/chevron-up.svg');
+ background-position: center;
+ background-size: cover;
+ transition: all 0.1s linear;
+}
+
+@mixin account-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+ background: url('../../../assets/icons/account-icon.svg') center/cover;
+}
+
+@mixin cart-icon {
+ width: 20px;
+ height: 20px;
+ background: url('../../../assets/icons/bag-icon.svg') center/cover;
+}
diff --git a/src/styles/index.scss b/src/styles/index.scss
new file mode 100644
index 0000000..3ffb96e
--- /dev/null
+++ b/src/styles/index.scss
@@ -0,0 +1,30 @@
+@import './libs/_reset.scss';
+@import './base/_fonts.scss';
+
+html,
+body {
+ height: 100%;
+}
+
+body {
+ font: $font-main;
+ background-color: $color-white;
+ color: $color-primary;
+ display: flex;
+ flex-direction: column;
+ overflow-x: hidden;
+
+ &.hidden {
+ overflow: hidden;
+ }
+}
+
+header,
+footer {
+ flex-grow: 0;
+ flex-shrink: 0;
+}
+
+main {
+ flex-grow: 1;
+}
diff --git a/src/styles/libs/_reset.scss b/src/styles/libs/_reset.scss
new file mode 100644
index 0000000..f410622
--- /dev/null
+++ b/src/styles/libs/_reset.scss
@@ -0,0 +1,110 @@
+/* Reset and base styles */
+* {
+ padding: 0px;
+ margin: 0px;
+ border: none;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+/* Links */
+
+a,
+a:link,
+a:visited {
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: none;
+}
+
+/* Common */
+
+aside,
+nav,
+footer,
+header,
+section,
+main {
+ display: block;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p {
+ font-size: inherit;
+ font-weight: inherit;
+}
+
+ul,
+ul li {
+ list-style: none;
+}
+
+img {
+ vertical-align: top;
+}
+
+img,
+svg {
+ max-width: 100%;
+ height: auto;
+}
+
+address {
+ font-style: normal;
+}
+
+/* Form */
+
+input,
+textarea,
+button,
+select {
+ font-family: inherit;
+ font-size: inherit;
+ color: inherit;
+ background-color: transparent;
+}
+
+input::-ms-clear {
+ display: none;
+}
+
+button,
+input[type='submit'] {
+ display: inline-block;
+ box-shadow: none;
+ background-color: transparent;
+ background: none;
+ cursor: pointer;
+}
+
+input:focus,
+input:active,
+button:focus,
+button:active {
+ outline: none;
+}
+
+button::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
+
+label {
+ cursor: pointer;
+}
+
+legend {
+ display: block;
+}
diff --git a/src/types/enums.ts b/src/types/enums.ts
new file mode 100644
index 0000000..404bf07
--- /dev/null
+++ b/src/types/enums.ts
@@ -0,0 +1,10 @@
+export enum AccountInfoMode {
+ EDIT = 'edit',
+ SHOW = 'show',
+}
+
+export enum AddressesMode {
+ EDIT = 'edit',
+ SHOW = 'show',
+ NEW = 'new',
+}
diff --git a/src/types/interfaces.ts b/src/types/interfaces.ts
new file mode 100644
index 0000000..edc1c1d
--- /dev/null
+++ b/src/types/interfaces.ts
@@ -0,0 +1,87 @@
+import { BaseAddress } from '@commercetools/platform-sdk';
+import InputField from '../components/input/input';
+import { AppRoutesPath } from '../router/types';
+
+export interface IAddress {
+ key: string;
+ country: string;
+ streetName: string;
+ city: string;
+ postalCode: string;
+}
+
+export interface ISignupData {
+ firstName: string;
+ lastName: string;
+ email: string;
+ password: string;
+ dateOfBirth: string;
+ addresses: IAddress[];
+ shippingAddresses?: number[];
+ billingAddresses?: number[];
+ defaultShippingAddress?: number;
+ defaultBillingAddress?: number;
+}
+
+export interface ISigninData {
+ email: string;
+ password: string;
+}
+
+export interface IDetailsData {
+ firstName: string;
+ lastName: string;
+ email: string;
+ dateOfBirth: string;
+}
+
+export interface IDetailsPasswordData {
+ currentPassword: string;
+ newPassword: string;
+}
+
+export interface IBreadcrumbLink {
+ pageName: string;
+ pageHref: AppRoutesPath | string;
+}
+
+export interface IBannerContent {
+ title: string;
+ text: string;
+}
+
+export interface InputFilds {
+ [inputName: string]: InputField;
+}
+
+export interface IAddressData {
+ address: BaseAddress;
+ billingAddressIds: string[] | undefined;
+ shippingAddressIds: string[] | undefined;
+ defaultBillingAddressId: string | undefined;
+ defaultShippingAddressId: string | undefined;
+}
+
+export interface IAddressFormData {
+ type: string;
+ streetName: string;
+ city: string;
+ postalCode: string;
+ country: string;
+}
+
+export interface IAboutUsMember {
+ name: string;
+ role: string;
+ imgClass: string;
+ about: string;
+ contributions: string[];
+ link: string;
+}
+
+export interface IPromoCodes {
+ title: string;
+ descr: string;
+ code: string;
+ expirationDate: string;
+}
diff --git a/src/types/types.ts b/src/types/types.ts
new file mode 100644
index 0000000..db153dc
--- /dev/null
+++ b/src/types/types.ts
@@ -0,0 +1,20 @@
+import { AppRoutesPath } from '../router/types';
+
+interface IMenuLinks {
+ title: string;
+ href: AppRoutesPath | string;
+}
+
+interface IMenuItems extends IMenuLinks {
+ innerItems?: IMenuLinks[];
+}
+
+type ListDataType = { [key: string]: string };
+
+export { IMenuItems, ListDataType };
+
+export interface ICategory {
+ label: string;
+ url: string;
+ slug: string;
+}
diff --git a/src/utils/change-url-event.ts b/src/utils/change-url-event.ts
new file mode 100644
index 0000000..054a306
--- /dev/null
+++ b/src/utils/change-url-event.ts
@@ -0,0 +1,7 @@
+import { AppRoutesPath } from '../router/types';
+
+export function changeUrlEvent(href: AppRoutesPath | string): void {
+ window.history.pushState({}, '', href);
+ const changeURL = new CustomEvent('changeURL', { bubbles: true });
+ window.dispatchEvent(changeURL);
+}
diff --git a/src/utils/change-visible-addresses-btns.ts b/src/utils/change-visible-addresses-btns.ts
new file mode 100644
index 0000000..25b5fd4
--- /dev/null
+++ b/src/utils/change-visible-addresses-btns.ts
@@ -0,0 +1,11 @@
+export default function changeVisibleAddressesBtns(addresses: HTMLDivElement[], isDisabled: boolean): void {
+ addresses.forEach((item: HTMLDivElement) => {
+ for (const itemChild of item.children) {
+ if (itemChild.className === 'address__actions') {
+ for (const btn of itemChild.children) {
+ (btn as HTMLButtonElement).disabled = isDisabled;
+ }
+ }
+ }
+ });
+}
diff --git a/src/utils/createBasketDiscountTotal.ts b/src/utils/createBasketDiscountTotal.ts
new file mode 100644
index 0000000..dee3ed6
--- /dev/null
+++ b/src/utils/createBasketDiscountTotal.ts
@@ -0,0 +1,81 @@
+import { Cart } from '@commercetools/platform-sdk';
+import BaseComponent from '../components/base-component';
+import formatPrice from './formatPrice';
+
+export default function createBasketDiscountTotal(cart: Cart): HTMLDivElement[] {
+ const pricesWrapper: HTMLDivElement[] = [];
+
+ let subTotal: number = 0;
+
+ cart.lineItems.forEach((item) => {
+ if (item.price?.discounted) {
+ subTotal += item.price?.discounted.value.centAmount * item.quantity || 0;
+ } else {
+ subTotal += item.price.value.centAmount * item.quantity || 0;
+ }
+ });
+
+ function createSubTotal(): HTMLDivElement {
+ const subTotalBox: HTMLDivElement = new BaseComponent('div', ['basket-total__total']).getElement();
+ const subTotalLabel: HTMLSpanElement = new BaseComponent(
+ 'span',
+ ['basket-total__total-label'],
+ 'Subtotal'
+ ).getElement();
+ const subTotalPrice: HTMLSpanElement = new BaseComponent('span', ['basket-total__total-price']).getElement();
+
+ if (cart.totalPrice.centAmount) {
+ subTotalPrice.textContent = formatPrice(cart.totalPrice.currencyCode, subTotal, cart.totalPrice.fractionDigits);
+ }
+
+ subTotalBox.append(subTotalLabel, subTotalPrice);
+ return subTotalBox;
+ }
+
+ function createDiscountTotal(): HTMLDivElement {
+ const discountBox: HTMLDivElement = new BaseComponent('div', ['basket-total__total']).getElement();
+ const discountLabel: HTMLSpanElement = new BaseComponent(
+ 'span',
+ ['basket-total__total-label'],
+ 'Discount'
+ ).getElement();
+ const discountPrice: HTMLSpanElement = new BaseComponent('span', [
+ 'basket-total__total-price',
+ 'discount',
+ ]).getElement();
+
+ if (cart.totalPrice.centAmount) {
+ discountPrice.textContent =
+ '- ' +
+ formatPrice(
+ cart.totalPrice.currencyCode,
+ subTotal - cart.totalPrice.centAmount,
+ cart.totalPrice.fractionDigits
+ );
+ }
+
+ discountBox.append(discountLabel, discountPrice);
+ return discountBox;
+ }
+
+ function createTotal(): HTMLDivElement {
+ const totalBox: HTMLDivElement = new BaseComponent('div', ['basket-total__total']).getElement();
+ const totalLabel: HTMLSpanElement = new BaseComponent('span', ['basket-total__total-label'], 'Total').getElement();
+ const totalPrice: HTMLSpanElement = new BaseComponent('span', ['basket-total__total-price']).getElement();
+
+ if (cart.totalPrice.centAmount) {
+ totalPrice.textContent = formatPrice(
+ cart.totalPrice.currencyCode,
+ cart.totalPrice.centAmount,
+ cart.totalPrice.fractionDigits
+ );
+ }
+
+ totalBox.append(totalLabel, totalPrice);
+ return totalBox;
+ }
+
+ pricesWrapper.push(createSubTotal(), createDiscountTotal(), createTotal());
+
+ return pricesWrapper;
+}
diff --git a/src/utils/createBasketTotal.ts b/src/utils/createBasketTotal.ts
new file mode 100644
index 0000000..1832ee0
--- /dev/null
+++ b/src/utils/createBasketTotal.ts
@@ -0,0 +1,53 @@
+import { Cart } from '@commercetools/platform-sdk';
+import BaseComponent from '../components/base-component';
+import formatPrice from './formatPrice';
+
+export default function createBasketTotal(cart: Cart): HTMLDivElement[] {
+ const pricesWrapper: HTMLDivElement[] = [];
+
+ let subTotal: number = 0;
+
+ cart.lineItems.forEach((item) => {
+ subTotal += item.price.value.centAmount * item.quantity || 0;
+ });
+
+ function createSubTotal(): HTMLDivElement {
+ const subTotalBox: HTMLDivElement = new BaseComponent('div', ['basket-total__total']).getElement();
+ const subTotalLabel: HTMLSpanElement = new BaseComponent(
+ 'span',
+ ['basket-total__total-label'],
+ 'Subtotal'
+ ).getElement();
+ const subTotalPrice = new BaseComponent('span', ['basket-total__total-price']).getElement();
+
+ subTotalPrice.textContent = formatPrice('USD', subTotal, 2);
+
+ subTotalBox.append(subTotalLabel, subTotalPrice);
+ return subTotalBox;
+ }
+
+ function createTotal(): HTMLDivElement {
+ const totalBox: HTMLDivElement = new BaseComponent('div', ['basket-total__total']).getElement();
+ const totalLabel: HTMLSpanElement = new BaseComponent('span', ['basket-total__total-label'], 'Total').getElement();
+ const totalPrice = new BaseComponent('span', ['basket-total__total-price']).getElement();
+
+ if (cart.totalPrice.centAmount) {
+ totalPrice.textContent = formatPrice(
+ cart.totalPrice.currencyCode,
+ cart.totalPrice.centAmount,
+ cart.totalPrice.fractionDigits
+ );
+ }
+
+ totalBox.append(totalLabel, totalPrice);
+ return totalBox;
+ }
+
+ if (subTotal !== cart.totalPrice.centAmount) {
+ pricesWrapper.push(createSubTotal());
+ }
+
+ pricesWrapper.push(createTotal());
+
+ return pricesWrapper;
+}
diff --git a/src/utils/formatPrice.ts b/src/utils/formatPrice.ts
new file mode 100644
index 0000000..0c77320
--- /dev/null
+++ b/src/utils/formatPrice.ts
@@ -0,0 +1,10 @@
+export default function formatPrice(currency: string, price: number, fractionDigits: number): string {
+ return new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency,
+ minimumFractionDigits: fractionDigits,
+ })
+ .format(price / 100)
+ .split(',')
+ .join(' ');
+}
diff --git a/src/utils/remove-popup.ts b/src/utils/remove-popup.ts
new file mode 100644
index 0000000..6472be3
--- /dev/null
+++ b/src/utils/remove-popup.ts
@@ -0,0 +1,4 @@
+export function removePopupFromBody(className: string): void {
+ const el = document.querySelector(className);
+ el?.remove();
+}
diff --git a/src/utils/router-middleware.ts b/src/utils/router-middleware.ts
new file mode 100644
index 0000000..baa2f91
--- /dev/null
+++ b/src/utils/router-middleware.ts
@@ -0,0 +1,18 @@
+import { AppRoutesPath } from '../router/types';
+import userStore from '../store/user-store';
+
+function authMiddleware(path: AppRoutesPath): boolean {
+ const { isAuth } = userStore.getState();
+ const isAuthPath: boolean = path === AppRoutesPath.LOGIN || path === AppRoutesPath.SIGN_UP;
+
+ return isAuth && isAuthPath;
+}
+
+function accountMiddleware(path: AppRoutesPath): boolean {
+ const { isAuth } = userStore.getState();
+ const isAuthPath: boolean = path === AppRoutesPath.ACCOUNT || path === AppRoutesPath.ACCOUNT_ADDRESSES;
+
+ return !isAuth && isAuthPath;
+}
+
+export { authMiddleware, accountMiddleware };
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..42faea6
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "compilerOptions": {
+ "target": "es2022",
+ "module": "es2022",
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "strict": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "skipLibCheck": true,
+ "moduleResolution": "node"
+ }
+}
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000..82ba4e0
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,94 @@
+const path = require('path');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+const EslintPlugin = require('eslint-webpack-plugin');
+const Dotenv = require('dotenv-webpack');
+
+const mode = process.env.NODE_ENV || 'development';
+const devMode = mode === 'development';
+const target = devMode ? 'web' : 'browserslist';
+const devtool = devMode ? 'source-map' : undefined;
+
+module.exports = {
+ mode,
+ target,
+ devtool,
+ entry: path.resolve(__dirname, 'src', 'index.ts'),
+ output: {
+ filename: '[name].[contenthash:8].js',
+ path: path.resolve(__dirname, 'dist'),
+ assetModuleFilename: 'assets/[name].[contenthash:8][ext]',
+ clean: true,
+ publicPath: '/',
+ },
+ resolve: {
+ extensions: ['.ts', '.js'],
+ },
+ module: {
+ rules: [
+ {
+ test: /\.(c|sa|sc)ss$/i,
+ use: [
+ devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
+ 'css-loader',
+ {
+ loader: 'postcss-loader',
+ options: {
+ postcssOptions: {
+ plugins: [require('postcss-preset-env')],
+ },
+ },
+ },
+ {
+ loader: 'sass-loader',
+ options: {
+ additionalData: '@import "./src/styles/base/_variables.scss";',
+ },
+ },
+ ],
+ },
+ {
+ test: /\.ts$/,
+ use: 'ts-loader',
+ exclude: /node_modules/,
+ },
+ {
+ test: /\.woff2?$/i,
+ type: 'asset/resource',
+ generator: {
+ filename: 'assets/fonts/[name][ext]',
+ },
+ },
+ {
+ test: /\.(png|jpg|jpeg|gif|webp)$/i,
+ type: 'asset/resource',
+ },
+ {
+ test: /\.svg$/i,
+ type: 'asset/resource',
+ generator: {
+ filename: 'assets/icons/[name].[contenthash:8][ext]',
+ },
+ },
+ ],
+ },
+ plugins: [
+ new HtmlWebpackPlugin({
+ template: path.resolve(__dirname, 'src', 'index.html'),
+ title: 'eCommerce-Application | this-is-this-team',
+ filename: 'index.html',
+ favicon: './src/assets/favicon.png',
+ }),
+ new MiniCssExtractPlugin({
+ filename: 'style.[contenthash:8].css',
+ }),
+ new EslintPlugin({ extensions: ['ts', 'js'] }),
+ new Dotenv(),
+ ],
+ devServer: {
+ port: 8888,
+ open: true,
+ hot: true,
+ historyApiFallback: true,
+ },
+};