diff --git a/.env b/.env index b842b511..c5b0643c 100644 --- a/.env +++ b/.env @@ -6,3 +6,7 @@ VITE_APP_CTP_REGION=europe-west1 VITE_APP_CTP_AUTH_URL=https://auth.europe-west1.gcp.commercetools.com VITE_APP_CTP_API_URL=https://api.europe-west1.gcp.commercetools.com VITE_APP_CTP_SCOPES=manage_orders:green-shop manage_payments:green-shop manage_types:green-shop view_shopping_lists:green-shop manage_customers:green-shop manage_my_orders:green-shop view_orders:green-shop manage_quotes:green-shop view_discount_codes:green-shop view_quote_requests:green-shop manage_order_edits:green-shop manage_products:green-shop manage_quote_requests:green-shop view_quotes:green-shop view_api_clients:green-shop view_order_edits:green-shop manage_shipping_methods:green-shop manage_cart_discounts:green-shop manage_my_shopping_lists:green-shop view_products:green-shop view_categories:green-shop manage_my_payments:green-shop manage_my_profile:green-shop manage_discount_codes:green-shop manage_categories:green-shop manage_shopping_lists:green-shop manage_extensions:green-shop +VITE_APP_DEFAULT_SEGMENT='/' +VITE_APP_NEXT_SEGMENT=1 +VITE_APP_PATH_SEGMENTS_TO_KEEP=0 +VITE_APP_PROJECT_TITLE=Greenshop diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b2640969..015f5b67 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -3,10 +3,10 @@ 📍 conforms with the following format: - [ ] prefix (following the [convention](https://www.conventionalcommits.org/en/v1.0.0-beta.2/): `feat`, `fix`, `hotfix`, `chore`, `refactor`, `revert`, `docs`, `style`, `test`) -- [ ] sprint and issue number (e.g. `RSS-ECOMM-1_01`, where `1` - is the sprint number and `01` - is the issue number) +- [ ] sprint and issue number (e.g. `RSS-ECOMM-2_01`, where `2` - is the sprint number and `01` - is the issue number) - [ ] short description -👀 Example: `feat(RSS-ECOMM-1_01): description` +👀 Example: `feat(RSS-ECOMM-2_01): description` ## PR Description 🧙‍♂️ @@ -30,13 +30,20 @@ Specify if any documentation updates are required and provide details on what ne #### Provide any other relevant information 🦉 +## Auto-Review 🤖 + +- [x] The reviewers have been requested 📝 + [![Request Review on PR Open](https://github.com/stardustmeg/greenshop/actions/workflows/request_review.yml/badge.svg)](https://github.com/stardustmeg/greenshop/actions/workflows/request_review.yml) +- [x] The labels have been added 🎨 + [![Pull Request Labeler](https://github.com/stardustmeg/greenshop/actions/workflows/labeler.yml/badge.svg)](https://github.com/stardustmeg/greenshop/actions/workflows/labeler.yml) +- [x] My code doesn't generate any errors or warnings ⛓️ + [![Continuous Integration](https://github.com/stardustmeg/greenshop/actions/workflows/ci.yml/badge.svg)](https://github.com/stardustmeg/greenshop/actions/workflows/ci.yml) + ## Self-Check 🌟 - [ ] I wrote the correct title for the PR 🗝️ -- [ ] I wrote the correct description for the PR 📜 +- [ ] I wrote a comprehensive description for the PR 📜 - [ ] I have performed a self-review of my own code ✅ - [ ] I have commented my code where needed 📝 -- [ ] My code is formatted correctly and passes the check 🎨 -- [ ] My code passes the tests check ⛓️ - [ ] My code successfully builds ⚙️ - [ ] I am happy with my PR and ready to merge ❤️‍🔥 diff --git a/.gitignore b/.gitignore index ba275079..40d5314d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ pnpm-debug.log* lerna-debug.log* node_modules -.package-lock.json +package-lock.json dist dist-ssr *.local diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index a50d00ed..00000000 --- a/package-lock.json +++ /dev/null @@ -1,11076 +0,0 @@ -{ - "name": "Greenshop", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "Greenshop", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "@commercetools/api-request-builder": "^6.0.0", - "@commercetools/platform-sdk": "^7.7.0", - "@commercetools/sdk-client-v2": "^2.4.1", - "@commercetools/sdk-middleware-auth": "^7.0.1", - "@commercetools/sdk-middleware-http": "^7.0.4", - "autoprefixer": "^10.4.19", - "isomorphic-fetch": "^3.0.0", - "modern-normalize": "^2.0.0", - "vite-plugin-checker": "^0.6.4", - "vite-plugin-image-optimizer": "^1.1.7", - "vite-plugin-svg-spriter": "^1.0.0", - "vite-tsconfig-paths": "^4.3.2" - }, - "devDependencies": { - "@commitlint/cli": "^18.6.1", - "@commitlint/config-conventional": "^18.6.2", - "@eslint/eslintrc": "^3.0.2", - "@types/jest": "^29.5.12", - "@typescript-eslint/eslint-plugin": "^7.7.1", - "@typescript-eslint/parser": "^7.7.1", - "@vitest/coverage-v8": "^1.5.2", - "@vitest/ui": "^1.5.2", - "c8": "^9.1.0", - "dotenv": "^16.4.5", - "eslint": "^8.57.0", - "eslint-config-airbnb": "^19.0.4", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-prettier": "^9.1.0", - "eslint-import-resolver-alias": "^1.1.2", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-perfectionist": "^2.10.0", - "husky": "^9.0.11", - "import": "^0.0.6", - "jsdom": "^24.0.0", - "lint-staged": "^15.2.2", - "prettier": "^3.2.5", - "sass": "^1.71.1", - "sonarlint": "^1.1.0", - "stylelint": "^16.2.1", - "stylelint-config-clean-order": "^5.4.1", - "stylelint-config-standard": "^36.0.0", - "stylelint-config-standard-scss": "^13.0.0", - "stylelint-declaration-block-no-ignored-properties": "^2.8.0", - "stylelint-order": "^6.0.4", - "stylelint-scss": "^6.2.0", - "svgo": "^3.2.0", - "typescript": "^5.3.3", - "validate-branch-name": "^1.3.0", - "vite": "^5.1.4", - "vite-plugin-sass": "^0.1.0", - "vitest": "^1.5.2" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", - "dependencies": { - "@babel/highlight": "^7.24.2", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", - "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/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==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/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==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/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==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/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==" - }, - "node_modules/@babel/highlight/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==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/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==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/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==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", - "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", - "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", - "dev": true, - "peer": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "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/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@commercetools/api-request-builder": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@commercetools/api-request-builder/-/api-request-builder-6.0.0.tgz", - "integrity": "sha512-4QhfpWnW161XaRs/2o9h4ZVr21R31vYNHmpKbDh2Dp+lFR9IqdwiafP0fqfLzI+Xg6vTrA2s5coyxkh0qj7Gng==", - "engines": { - "node": ">=14" - } - }, - "node_modules/@commercetools/platform-sdk": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@commercetools/platform-sdk/-/platform-sdk-7.7.0.tgz", - "integrity": "sha512-9RpgjwYOAFhKKWLKaefXfWoz8siC3gH4inOhHYVVcIhQm8pkRX5dLbNLOE/AX7FpatcTHX65ws9OHuifHh+Quw==", - "dependencies": { - "@commercetools/sdk-client-v2": "^2.4.1", - "@commercetools/sdk-middleware-auth": "^7.0.0", - "@commercetools/sdk-middleware-http": "^7.0.0", - "@commercetools/sdk-middleware-logger": "^3.0.0", - "@commercetools/ts-client": "^1.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@commercetools/sdk-client-v2": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@commercetools/sdk-client-v2/-/sdk-client-v2-2.4.1.tgz", - "integrity": "sha512-zhsQz8dN/6D+kLyO8xX2SLppf3VcP0AWc80abmGwY2k1c+psb7s9xCCRZC553X+CZP8Z+2ajZ5PjTHnZxVMSjQ==", - "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.4", - "resolved": "https://registry.npmjs.org/@commercetools/sdk-middleware-http/-/sdk-middleware-http-7.0.4.tgz", - "integrity": "sha512-YpBDTA1NqjfwqPxrll6FzDc0A7hLSRwd9OLGMlPcvUG2Je1ks8Pe34pLdPqz7jgdURwfFXRBmXxPhezDzMbnZA==", - "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/@commercetools/ts-client": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@commercetools/ts-client/-/ts-client-1.2.0.tgz", - "integrity": "sha512-oMuv9AFFyx/lbkbw+/AYpUGPUNMa1AiCgAcAVU798fOHMrDn3/NrVmuMM+PDwaPoTISUUUoPRheMNXSwprxHrw==", - "dependencies": { - "abort-controller": "3.0.0", - "buffer": "^6.0.3", - "node-fetch": "^2.6.1", - "uuid": "9.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@commitlint/cli": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-18.6.1.tgz", - "integrity": "sha512-5IDE0a+lWGdkOvKH892HHAZgbAjcj1mT5QrfA/SVbLJV/BbBMGyKN0W5mhgjekPJJwEQdVNvhl9PwUacY58Usw==", - "dev": true, - "dependencies": { - "@commitlint/format": "^18.6.1", - "@commitlint/lint": "^18.6.1", - "@commitlint/load": "^18.6.1", - "@commitlint/read": "^18.6.1", - "@commitlint/types": "^18.6.1", - "execa": "^5.0.0", - "lodash.isfunction": "^3.0.9", - "resolve-from": "5.0.0", - "resolve-global": "1.0.0", - "yargs": "^17.0.0" - }, - "bin": { - "commitlint": "cli.js" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-conventional": { - "version": "18.6.3", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-18.6.3.tgz", - "integrity": "sha512-8ZrRHqF6je+TRaFoJVwszwnOXb/VeYrPmTwPhf0WxpzpGTcYy1p0SPyZ2eRn/sRi/obnWAcobtDAq6+gJQQNhQ==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.6.1", - "conventional-changelog-conventionalcommits": "^7.0.2" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-validator": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-18.6.1.tgz", - "integrity": "sha512-05uiToBVfPhepcQWE1ZQBR/Io3+tb3gEotZjnI4tTzzPk16NffN6YABgwFQCLmzZefbDcmwWqJWc2XT47q7Znw==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.6.1", - "ajv": "^8.11.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/ensure": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-18.6.1.tgz", - "integrity": "sha512-BPm6+SspyxQ7ZTsZwXc7TRQL5kh5YWt3euKmEIBZnocMFkJevqs3fbLRb8+8I/cfbVcAo4mxRlpTPfz8zX7SnQ==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.6.1", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/execute-rule": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-18.6.1.tgz", - "integrity": "sha512-7s37a+iWyJiGUeMFF6qBlyZciUkF8odSAnHijbD36YDctLhGKoYltdvuJ/AFfRm6cBLRtRk9cCVPdsEFtt/2rg==", - "dev": true, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/format": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-18.6.1.tgz", - "integrity": "sha512-K8mNcfU/JEFCharj2xVjxGSF+My+FbUHoqR+4GqPGrHNqXOGNio47ziiR4HQUPKtiNs05o8/WyLBoIpMVOP7wg==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.6.1", - "chalk": "^4.1.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/is-ignored": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-18.6.1.tgz", - "integrity": "sha512-MOfJjkEJj/wOaPBw5jFjTtfnx72RGwqYIROABudOtJKW7isVjFe9j0t8xhceA02QebtYf4P/zea4HIwnXg8rvA==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.6.1", - "semver": "7.6.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/lint": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-18.6.1.tgz", - "integrity": "sha512-8WwIFo3jAuU+h1PkYe5SfnIOzp+TtBHpFr4S8oJWhu44IWKuVx6GOPux3+9H1iHOan/rGBaiacicZkMZuluhfQ==", - "dev": true, - "dependencies": { - "@commitlint/is-ignored": "^18.6.1", - "@commitlint/parse": "^18.6.1", - "@commitlint/rules": "^18.6.1", - "@commitlint/types": "^18.6.1" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/load": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-18.6.1.tgz", - "integrity": "sha512-p26x8734tSXUHoAw0ERIiHyW4RaI4Bj99D8YgUlVV9SedLf8hlWAfyIFhHRIhfPngLlCe0QYOdRKYFt8gy56TA==", - "dev": true, - "dependencies": { - "@commitlint/config-validator": "^18.6.1", - "@commitlint/execute-rule": "^18.6.1", - "@commitlint/resolve-extends": "^18.6.1", - "@commitlint/types": "^18.6.1", - "chalk": "^4.1.0", - "cosmiconfig": "^8.3.6", - "cosmiconfig-typescript-loader": "^5.0.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/message": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-18.6.1.tgz", - "integrity": "sha512-VKC10UTMLcpVjMIaHHsY1KwhuTQtdIKPkIdVEwWV+YuzKkzhlI3aNy6oo1eAN6b/D2LTtZkJe2enHmX0corYRw==", - "dev": true, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/parse": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-18.6.1.tgz", - "integrity": "sha512-eS/3GREtvVJqGZrwAGRwR9Gdno3YcZ6Xvuaa+vUF8j++wsmxrA2En3n0ccfVO2qVOLJC41ni7jSZhQiJpMPGOQ==", - "dev": true, - "dependencies": { - "@commitlint/types": "^18.6.1", - "conventional-changelog-angular": "^7.0.0", - "conventional-commits-parser": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/read": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-18.6.1.tgz", - "integrity": "sha512-ia6ODaQFzXrVul07ffSgbZGFajpe8xhnDeLIprLeyfz3ivQU1dIoHp7yz0QIorZ6yuf4nlzg4ZUkluDrGN/J/w==", - "dev": true, - "dependencies": { - "@commitlint/top-level": "^18.6.1", - "@commitlint/types": "^18.6.1", - "git-raw-commits": "^2.0.11", - "minimist": "^1.2.6" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/resolve-extends": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-18.6.1.tgz", - "integrity": "sha512-ifRAQtHwK+Gj3Bxj/5chhc4L2LIc3s30lpsyW67yyjsETR6ctHAHRu1FSpt0KqahK5xESqoJ92v6XxoDRtjwEQ==", - "dev": true, - "dependencies": { - "@commitlint/config-validator": "^18.6.1", - "@commitlint/types": "^18.6.1", - "import-fresh": "^3.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/rules": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-18.6.1.tgz", - "integrity": "sha512-kguM6HxZDtz60v/zQYOe0voAtTdGybWXefA1iidjWYmyUUspO1zBPQEmJZ05/plIAqCVyNUTAiRPWIBKLCrGew==", - "dev": true, - "dependencies": { - "@commitlint/ensure": "^18.6.1", - "@commitlint/message": "^18.6.1", - "@commitlint/to-lines": "^18.6.1", - "@commitlint/types": "^18.6.1", - "execa": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/to-lines": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-18.6.1.tgz", - "integrity": "sha512-Gl+orGBxYSNphx1+83GYeNy5N0dQsHBQ9PJMriaLQDB51UQHCVLBT/HBdOx5VaYksivSf5Os55TLePbRLlW50Q==", - "dev": true, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/top-level": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-18.6.1.tgz", - "integrity": "sha512-HyiHQZUTf0+r0goTCDs/bbVv/LiiQ7AVtz6KIar+8ZrseB9+YJAIo8HQ2IC2QT1y3N1lbW6OqVEsTHjbT6hGSw==", - "dev": true, - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/types": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-18.6.1.tgz", - "integrity": "sha512-gwRLBLra/Dozj2OywopeuHj2ac26gjGkz2cZ+86cTJOdtWfiRRr4+e77ZDAGc6MDWxaWheI+mAV5TLWWRwqrFg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz", - "integrity": "sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA==", - "devOptional": 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.4" - } - }, - "node_modules/@csstools/css-tokenizer": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.4.tgz", - "integrity": "sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw==", - "devOptional": 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.9", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.9.tgz", - "integrity": "sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA==", - "devOptional": 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.6.1", - "@csstools/css-tokenizer": "^2.2.4" - } - }, - "node_modules/@csstools/selector-specificity": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.3.tgz", - "integrity": "sha512-KEPNw4+WW5AVEIyzC80rTbWEUatTW2lXpN8+8ILC8PiPeWPjwUzrPZDIOZ2wwqDmeqOYTdSGyL3+vE5GC3FB3Q==", - "devOptional": 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/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", - "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", - "integrity": "sha512-ZKXyJeFAzcpKM2kk8ipoGIPUqx9BX52omTGnfwjJvxOCaZTM2wtDK7zN0aIgPRbT9XYAlha0HtmZ+XKteuh0Gw==", - "devOptional": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", - "cpu": [ - "loong64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "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==", - "devOptional": 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.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "devOptional": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.0.2.tgz", - "integrity": "sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.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": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/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/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "devOptional": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "devOptional": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "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==", - "devOptional": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "devOptional": true - }, - "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/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "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==", - "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==", - "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==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.25", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", - "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", - "dev": true - }, - "node_modules/@resvg/resvg-js": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js/-/resvg-js-2.6.2.tgz", - "integrity": "sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q==", - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@resvg/resvg-js-android-arm-eabi": "2.6.2", - "@resvg/resvg-js-android-arm64": "2.6.2", - "@resvg/resvg-js-darwin-arm64": "2.6.2", - "@resvg/resvg-js-darwin-x64": "2.6.2", - "@resvg/resvg-js-linux-arm-gnueabihf": "2.6.2", - "@resvg/resvg-js-linux-arm64-gnu": "2.6.2", - "@resvg/resvg-js-linux-arm64-musl": "2.6.2", - "@resvg/resvg-js-linux-x64-gnu": "2.6.2", - "@resvg/resvg-js-linux-x64-musl": "2.6.2", - "@resvg/resvg-js-win32-arm64-msvc": "2.6.2", - "@resvg/resvg-js-win32-ia32-msvc": "2.6.2", - "@resvg/resvg-js-win32-x64-msvc": "2.6.2" - } - }, - "node_modules/@resvg/resvg-js-android-arm-eabi": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm-eabi/-/resvg-js-android-arm-eabi-2.6.2.tgz", - "integrity": "sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-android-arm64": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm64/-/resvg-js-android-arm64-2.6.2.tgz", - "integrity": "sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-darwin-arm64": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-arm64/-/resvg-js-darwin-arm64-2.6.2.tgz", - "integrity": "sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-darwin-x64": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-x64/-/resvg-js-darwin-x64-2.6.2.tgz", - "integrity": "sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-linux-arm-gnueabihf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm-gnueabihf/-/resvg-js-linux-arm-gnueabihf-2.6.2.tgz", - "integrity": "sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-linux-arm64-gnu": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-gnu/-/resvg-js-linux-arm64-gnu-2.6.2.tgz", - "integrity": "sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-linux-arm64-musl": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-musl/-/resvg-js-linux-arm64-musl-2.6.2.tgz", - "integrity": "sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-linux-x64-gnu": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-gnu/-/resvg-js-linux-x64-gnu-2.6.2.tgz", - "integrity": "sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-linux-x64-musl": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-musl/-/resvg-js-linux-x64-musl-2.6.2.tgz", - "integrity": "sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-win32-arm64-msvc": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-arm64-msvc/-/resvg-js-win32-arm64-msvc-2.6.2.tgz", - "integrity": "sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-win32-ia32-msvc": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-ia32-msvc/-/resvg-js-win32-ia32-msvc-2.6.2.tgz", - "integrity": "sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-win32-x64-msvc": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-x64-msvc/-/resvg-js-win32-x64-msvc-2.6.2.tgz", - "integrity": "sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.1.tgz", - "integrity": "sha512-P6Wg856Ou/DLpR+O0ZLneNmrv7QpqBg+hK4wE05ijbC/t349BRfMfx+UFj5Ha3fCFopIa6iSZlpdaB4agkWp2Q==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.1.tgz", - "integrity": "sha512-piwZDjuW2WiHr05djVdUkrG5JbjnGbtx8BXQchYCMfib/nhjzWoiScelZ+s5IJI7lecrwSxHCzW026MWBL+oJQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.1.tgz", - "integrity": "sha512-LsZXXIsN5Q460cKDT4Y+bzoPDhBmO5DTr7wP80d+2EnYlxSgkwdPfE3hbE+Fk8dtya+8092N9srjBTJ0di8RIA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.1.tgz", - "integrity": "sha512-S7TYNQpWXB9APkxu/SLmYHezWwCoZRA9QLgrDeml+SR2A1LLPD2DBUdUlvmCF7FUpRMKvbeeWky+iizQj65Etw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.1.tgz", - "integrity": "sha512-Lq2JR5a5jsA5um2ZoLiXXEaOagnVyCpCW7xvlcqHC7y46tLwTEgUSTM3a2TfmmTMmdqv+jknUioWXlmxYxE9Yw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.1.tgz", - "integrity": "sha512-9BfzwyPNV0IizQoR+5HTNBGkh1KXE8BqU0DBkqMngmyFW7BfuIZyMjQ0s6igJEiPSBvT3ZcnIFohZ19OqjhDPg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.1.tgz", - "integrity": "sha512-e2uWaoxo/rtzA52OifrTSXTvJhAXb0XeRkz4CdHBK2KtxrFmuU/uNd544Ogkpu938BzEfvmWs8NZ8Axhw33FDw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.1.tgz", - "integrity": "sha512-ekggix/Bc/d/60H1Mi4YeYb/7dbal1kEDZ6sIFVAE8pUSx7PiWeEh+NWbL7bGu0X68BBIkgF3ibRJe1oFTksQQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.1.tgz", - "integrity": "sha512-UGV0dUo/xCv4pkr/C8KY7XLFwBNnvladt8q+VmdKrw/3RUd3rD0TptwjisvE2TTnnlENtuY4/PZuoOYRiGp8Gw==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.1.tgz", - "integrity": "sha512-gEYmYYHaehdvX46mwXrU49vD6Euf1Bxhq9pPb82cbUU9UT2NV+RSckQ5tKWOnNXZixKsy8/cPGtiUWqzPuAcXQ==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.1.tgz", - "integrity": "sha512-xeae5pMAxHFp6yX5vajInG2toST5lsCTrckSRUFwNgzYqnUjNBcQyqk1bXUxX5yhjWFl2Mnz3F8vQjl+2FRIcw==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.1.tgz", - "integrity": "sha512-AsdnINQoDWfKpBzCPqQWxSPdAWzSgnYbrJYtn6W0H2E9It5bZss99PiLA8CgmDRfvKygt20UpZ3xkhFlIfX9zQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.1.tgz", - "integrity": "sha512-KoB4fyKXTR+wYENkIG3fFF+5G6N4GFvzYx8Jax8BR4vmddtuqSb5oQmYu2Uu067vT/Fod7gxeQYKupm8gAcMSQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.1.tgz", - "integrity": "sha512-J0d3NVNf7wBL9t4blCNat+d0PYqAx8wOoY+/9Q5cujnafbX7BmtYk3XvzkqLmFECaWvXGLuHmKj/wrILUinmQg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.1.tgz", - "integrity": "sha512-xjgkWUwlq7IbgJSIxvl516FJ2iuC/7ttjsAxSPpC9kkI5iQQFHKyEN5BjbhvJ/IXIZ3yIBcW5QDlWAyrA+TFag==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.1.tgz", - "integrity": "sha512-0QbCkfk6cnnVKWqqlC0cUrrUMDMfu5ffvYMTUHf+qMN2uAb3MKP31LPcwiMXBNsvoFGs/kYdFOsuLmvppCopXA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ] - }, - "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/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", - "dev": true, - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "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/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "devOptional": true - }, - "node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", - "devOptional": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "devOptional": true - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true - }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" - }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz", - "integrity": "sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.7.1", - "@typescript-eslint/type-utils": "7.7.1", - "@typescript-eslint/utils": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.1.tgz", - "integrity": "sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.7.1", - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/typescript-estree": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", - "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.1.tgz", - "integrity": "sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.7.1", - "@typescript-eslint/utils": "7.7.1", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", - "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", - "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/visitor-keys": "7.7.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.1.tgz", - "integrity": "sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.15", - "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.7.1", - "@typescript-eslint/types": "7.7.1", - "@typescript-eslint/typescript-estree": "7.7.1", - "semver": "^7.6.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", - "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.7.1", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "devOptional": true - }, - "node_modules/@vitest/coverage-v8": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.5.2.tgz", - "integrity": "sha512-QJqxRnbCwNtbbegK9E93rBmhN3dbfG1bC/o52Bqr0zGCYhQzwgwvrJBG7Q8vw3zilX6Ryy6oa/mkZku2lLJx1Q==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.1", - "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.4", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.4", - "istanbul-reports": "^3.1.6", - "magic-string": "^0.30.5", - "magicast": "^0.3.3", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "test-exclude": "^6.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "vitest": "1.5.2" - } - }, - "node_modules/@vitest/expect": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.5.2.tgz", - "integrity": "sha512-rf7MTD1WCoDlN3FfYJ9Llfp0PbdtOMZ3FIF0AVkDnKbp3oiMW1c8AmvRZBcqbAhDUAvF52e9zx4WQM1r3oraVA==", - "dev": true, - "dependencies": { - "@vitest/spy": "1.5.2", - "@vitest/utils": "1.5.2", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.5.2.tgz", - "integrity": "sha512-7IJ7sJhMZrqx7HIEpv3WrMYcq8ZNz9L6alo81Y6f8hV5mIE6yVZsFoivLZmr0D777klm1ReqonE9LyChdcmw6g==", - "dev": true, - "dependencies": { - "@vitest/utils": "1.5.2", - "p-limit": "^5.0.0", - "pathe": "^1.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner/node_modules/p-limit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", - "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@vitest/runner/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" - } - }, - "node_modules/@vitest/snapshot": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.5.2.tgz", - "integrity": "sha512-CTEp/lTYos8fuCc9+Z55Ga5NVPKUgExritjF5VY7heRFUfheoAqBneUlvXSUJHUZPjnPmyZA96yLRJDP1QATFQ==", - "dev": true, - "dependencies": { - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.5.2.tgz", - "integrity": "sha512-xCcPvI8JpCtgikT9nLpHPL1/81AYqZy1GCy4+MCHBE7xi8jgsYkULpW5hrx5PGLgOQjUpb6fd15lqcriJ40tfQ==", - "dev": true, - "dependencies": { - "tinyspy": "^2.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/ui": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-1.5.2.tgz", - "integrity": "sha512-pYDitwgCOn7i3FH7Ka94G70dmj85xpBA42BaWCx82blPehyVO8FU6OLHNP9iAKJIHaIOXwZ+bgOXYSj3wZCxFA==", - "dev": true, - "dependencies": { - "@vitest/utils": "1.5.2", - "fast-glob": "^3.3.2", - "fflate": "^0.8.1", - "flatted": "^3.2.9", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "sirv": "^2.0.4" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "vitest": "1.5.2" - } - }, - "node_modules/@vitest/utils": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.5.2.tgz", - "integrity": "sha512-sWOmyofuXLJ85VvXNsroZur7mOJGiQeM0JN3/0D1uU8U9bGFM69X1iqHaRXl6R8BwaLY6yPCogP257zxTzkUdA==", - "dev": true, - "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "devOptional": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "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==", - "devOptional": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "devOptional": 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/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "engines": { - "node": ">=8" - } - }, - "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==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "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==" - }, - "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "peer": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "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==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "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.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "peer": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", - "dev": true, - "peer": true, - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", - "es-shim-unscopables": "^1.0.2" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "devOptional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true, - "peer": true - }, - "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==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" - }, - "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.19", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", - "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "browserslist": "^4.23.0", - "caniuse-lite": "^1.0.30001599", - "fraction.js": "^4.3.7", - "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.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "dev": true, - "peer": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/babel-plugin-add-module-exports": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz", - "integrity": "sha512-3AN/9V/rKuv90NG65m4tTHsI04XrCKsWbztIcW7a8H5iIN7WlvWucRtVV0V/rT4QvtA11n5Vmp20fLwfMWqp6g==", - "dev": true - }, - "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==" - }, - "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/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==" - }, - "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==", - "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==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "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.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "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/c8": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-9.1.0.tgz", - "integrity": "sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^3.1.1", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.1.6", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=14.14.0" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "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==", - "devOptional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "devOptional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "devOptional": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001614", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001614.tgz", - "integrity": "sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==", - "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/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "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" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/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==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/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==" - }, - "node_modules/cliui/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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/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==", - "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/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==" - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/cloneable-readable/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/cloneable-readable/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==", - "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/cloneable-readable/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==" - }, - "node_modules/cloneable-readable/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==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/color": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" - } - }, - "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==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "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==" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/color/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==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color/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==" - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "devOptional": 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/colorspace": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", - "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", - "dependencies": { - "color": "^3.1.3", - "text-hex": "1.0.x" - } - }, - "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": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", - "dev": true, - "engines": { - "node": ">=16" - } - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/confbox": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", - "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", - "dev": true - }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true - }, - "node_modules/conventional-changelog-angular": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", - "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", - "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", - "dev": true, - "dependencies": { - "is-text-path": "^2.0.0", - "JSONStream": "^1.3.5", - "meow": "^12.0.1", - "split2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.mjs" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/conventional-commits-parser/node_modules/meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", - "dev": true, - "engines": { - "node": ">=16.10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/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==" - }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cosmiconfig-typescript-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz", - "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==", - "dev": true, - "dependencies": { - "jiti": "^1.19.1" - }, - "engines": { - "node": ">=v16" - }, - "peerDependencies": { - "@types/node": "*", - "cosmiconfig": ">=8.2", - "typescript": ">=4" - } - }, - "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==", - "devOptional": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-functions-list": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", - "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", - "devOptional": true, - "engines": { - "node": ">=12 || >=16" - } - }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-selector-parser": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.4.1.tgz", - "integrity": "sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g==" - }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "devOptional": true, - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "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==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "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==", - "devOptional": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, - "dependencies": { - "css-tree": "~2.2.0" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true - }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" - }, - "node_modules/cssstyle": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", - "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", - "dev": true, - "dependencies": { - "rrweb-cssom": "^0.6.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/current-git-branch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/current-git-branch/-/current-git-branch-1.1.0.tgz", - "integrity": "sha512-n5mwGZllLsFzxDPtTmadqGe4IIBPfqPbiIRX4xgFR9VK/Bx47U+94KiVkxSKAKN6/s43TlkztS2GZpgMKzwQ8A==", - "dev": true, - "dependencies": { - "babel-plugin-add-module-exports": "^0.2.1", - "execa": "^0.6.1", - "is-git-repository": "^1.0.0" - } - }, - "node_modules/current-git-branch/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "node_modules/current-git-branch/node_modules/execa": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", - "integrity": "sha512-/teX3MDLFBdYUhRk8WCBYboIMUmqeizu0m9Z3YF3JWrbEh/SlZg00vLJSaAGWw3wrZ9tE0buNw79eaAPYhUuvg==", - "dev": true, - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/current-git-branch/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/current-git-branch/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/current-git-branch/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/current-git-branch/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/current-git-branch/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/current-git-branch/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/current-git-branch/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/current-git-branch/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/current-git-branch/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true, - "peer": true - }, - "node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "dev": true, - "dependencies": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "devOptional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "devOptional": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "devOptional": true, - "engines": { - "node": ">=0.10.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/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "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==", - "devOptional": true - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "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/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "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==", - "devOptional": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "devOptional": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.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==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.750", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.750.tgz", - "integrity": "sha512-9ItEpeu15hW5m8jKdriL+BQrgwDTXEL9pn4SkillWFu73ZNNNQ2BKKLS+ZHv2vC9UkNhosAeyfxOf/5OSeTCPA==" - }, - "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, - "peer": true - }, - "node_modules/enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" - }, - "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/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "devOptional": true, - "engines": { - "node": ">=6" - } - }, - "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==", - "devOptional": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", - "dev": true, - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "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/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "engines": { - "node": ">=6" - } - }, - "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==", - "devOptional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "devOptional": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "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.3", - "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-airbnb": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", - "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", - "dev": true, - "dependencies": { - "eslint-config-airbnb-base": "^15.0.0", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5" - }, - "engines": { - "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0" - } - }, - "node_modules/eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", - "dev": true, - "dependencies": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.2" - } - }, - "node_modules/eslint-config-airbnb-base/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/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-import-resolver-alias": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz", - "integrity": "sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==", - "dev": true, - "engines": { - "node": ">= 4" - }, - "peerDependencies": { - "eslint-plugin-import": ">=1.4.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "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-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", - "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-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "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/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/eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-perfectionist": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-2.10.0.tgz", - "integrity": "sha512-P+tdrkHeMWBc55+DZsoDOAftV1WCsEoHaKm6JC7zajFus/syfT4vUPBFb3atGFSuyaVnGQGHlcKpP9X3Q0gH/w==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^6.13.0 || ^7.0.0", - "minimatch": "^9.0.3", - "natural-compare-lite": "^1.4.0" - }, - "peerDependencies": { - "astro-eslint-parser": "^0.16.0", - "eslint": ">=8.0.0", - "svelte": ">=3.0.0", - "svelte-eslint-parser": "^0.33.0", - "vue-eslint-parser": ">=9.0.0" - }, - "peerDependenciesMeta": { - "astro-eslint-parser": { - "optional": true - }, - "svelte": { - "optional": true - }, - "svelte-eslint-parser": { - "optional": true - }, - "vue-eslint-parser": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-perfectionist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/eslint-plugin-perfectionist/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.34.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", - "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", - "dev": true, - "peer": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlast": "^1.2.4", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.17", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7", - "object.hasown": "^1.1.3", - "object.values": "^1.1.7", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.10" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "peer": true, - "dependencies": { - "is-core-module": "^2.13.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/eslint-plugin-react/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, - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "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==", - "devOptional": 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-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "devOptional": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "devOptional": 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/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "devOptional": 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/eslint/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==", - "devOptional": 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/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "devOptional": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/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==", - "devOptional": true - }, - "node_modules/eslint/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==", - "devOptional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", - "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", - "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "devOptional": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "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==", - "devOptional": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "devOptional": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.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==", - "devOptional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true - }, - "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/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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==", - "devOptional": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "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-glob/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==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "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==", - "devOptional": 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==", - "devOptional": 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==", - "devOptional": true, - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fecha": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" - }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "dev": true - }, - "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==", - "devOptional": 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==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "devOptional": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "devOptional": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "devOptional": true - }, - "node_modules/fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" - }, - "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/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs-extra/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" - } - }, - "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==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "devOptional": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "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/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==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", - "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", - "dev": true, - "dependencies": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "git-raw-commits": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/git-raw-commits/node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/git-raw-commits/node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/git-raw-commits/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "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": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "devOptional": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", - "dev": true, - "dependencies": { - "ini": "^1.3.4" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "devOptional": true, - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "devOptional": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "devOptional": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "devOptional": 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/globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", - "devOptional": true - }, - "node_modules/globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" - }, - "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==" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "devOptional": true - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "devOptional": true, - "engines": { - "node": ">=6" - } - }, - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "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.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "devOptional": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "devOptional": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^3.1.1" - }, - "engines": { - "node": ">=18" - } - }, - "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-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "devOptional": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "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": "9.0.11", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", - "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", - "dev": true, - "bin": { - "husky": "bin.mjs" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "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/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.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "devOptional": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/immutable": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", - "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", - "devOptional": true - }, - "node_modules/import": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/import/-/import-0.0.6.tgz", - "integrity": "sha512-QPhTdjy9J4wUzmWSG7APkSgMFuPGPw+iJTYUblcfc2AfpqaatbwgCldK1HoLYx+v/+lWvab63GWZtNkcnj9JcQ==", - "dev": true, - "dependencies": { - "optimist": "0.3.x" - }, - "bin": { - "import": "import" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "devOptional": 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==", - "devOptional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "devOptional": 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==", - "devOptional": 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==", - "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==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "devOptional": true - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "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==", - "devOptional": true - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "peer": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "devOptional": true, - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dev": true, - "dependencies": { - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "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-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "peer": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "peer": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-git-repository": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-git-repository/-/is-git-repository-1.1.1.tgz", - "integrity": "sha512-hxLpJytJnIZ5Og5QsxSkzmb8Qx8rGau9bio1JN/QtXcGEFuSsQYau0IiqlsCwftsfVYjF1mOq6uLdmwNSspgpA==", - "dev": true, - "dependencies": { - "execa": "^0.6.1", - "path-is-absolute": "^1.0.1" - } - }, - "node_modules/is-git-repository/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "node_modules/is-git-repository/node_modules/execa": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", - "integrity": "sha512-/teX3MDLFBdYUhRk8WCBYboIMUmqeizu0m9Z3YF3JWrbEh/SlZg00vLJSaAGWw3wrZ9tE0buNw79eaAPYhUuvg==", - "dev": true, - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-git-repository/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-git-repository/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-git-repository/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/is-git-repository/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-git-repository/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-git-repository/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-git-repository/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-git-repository/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/is-git-repository/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, - "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==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "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==", - "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-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "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==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "devOptional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "devOptional": true, - "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-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "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==", - "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-text-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", - "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", - "dev": true, - "dependencies": { - "text-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "peer": true, - "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-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "dev": true, - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "devOptional": true - }, - "node_modules/isomorphic-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", - "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", - "dependencies": { - "node-fetch": "^2.6.1", - "whatwg-fetch": "^3.4.1" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "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-source-maps": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.4.tgz", - "integrity": "sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "peer": true, - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@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/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "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==" - }, - "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==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.0.0.tgz", - "integrity": "sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==", - "dev": true, - "dependencies": { - "cssstyle": "^4.0.1", - "data-urls": "^5.0.0", - "decimal.js": "^10.4.3", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.7", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.3", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0", - "ws": "^8.16.0", - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "canvas": "^2.11.2" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "devOptional": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "devOptional": true - }, - "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==", - "devOptional": 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==", - "devOptional": true - }, - "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/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonfile/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "peer": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "devOptional": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "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==", - "devOptional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/known-css-properties": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.30.0.tgz", - "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==", - "devOptional": true - }, - "node_modules/kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" - }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", - "dev": true, - "peer": true - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "peer": true, - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "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==", - "devOptional": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "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==", - "devOptional": true - }, - "node_modules/lint-staged": { - "version": "15.2.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", - "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", - "dev": true, - "dependencies": { - "chalk": "5.3.0", - "commander": "11.1.0", - "debug": "4.3.4", - "execa": "8.0.1", - "lilconfig": "3.0.0", - "listr2": "8.0.1", - "micromatch": "4.0.5", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.3.4" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": ">=18.12.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" - } - }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "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/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.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/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "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/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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": "8.0.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", - "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", - "dev": true, - "dependencies": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.0.0", - "rfdc": "^1.3.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/local-pkg": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", - "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", - "dev": true, - "dependencies": { - "mlly": "^1.4.2", - "pkg-types": "^1.0.3" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "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==", - "devOptional": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true - }, - "node_modules/lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==" - }, - "node_modules/lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", - "dev": true - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "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==" - }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "devOptional": true - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true - }, - "node_modules/log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", - "dev": true, - "dependencies": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/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/log-update/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/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", - "dev": true, - "dependencies": { - "get-east-asian-width": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/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/logform": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", - "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", - "dependencies": { - "@colors/colors": "1.6.0", - "@types/triple-beam": "^1.3.2", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "peer": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "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==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "node_modules/magicast": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", - "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.24.4", - "@babel/types": "^7.24.0", - "source-map-js": "^1.2.0" - } - }, - "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/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "devOptional": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mathml-tag-names": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", - "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", - "devOptional": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "devOptional": true - }, - "node_modules/meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "optional": true, - "peer": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - } - }, - "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==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "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/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "devOptional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "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/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "devOptional": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/mlly": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz", - "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==", - "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "pathe": "^1.1.2", - "pkg-types": "^1.0.3", - "ufo": "^1.3.2" - } - }, - "node_modules/modern-normalize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/modern-normalize/-/modern-normalize-2.0.0.tgz", - "integrity": "sha512-CxBoEVKh5U4DH3XuNbc5ONLF6dQBc8dSc7pdZ1957FGbIO5JBqGqqchhET9dTexri8/pk9xBL6+5ceOtCIp1QA==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mrmime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", - "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "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==" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "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==", - "devOptional": 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/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "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-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/node-fetch/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/node-fetch/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/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "devOptional": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "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==", - "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==", - "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==", - "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==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/nwsapi": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.9.tgz", - "integrity": "sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg==", - "dev": true - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "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.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.hasown": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", - "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", - "dev": true, - "peer": true, - "dependencies": { - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "dependencies": { - "fn.name": "1.x.x" - } - }, - "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/optimist": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", - "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", - "dev": true, - "dependencies": { - "wordwrap": "~0.0.2" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "devOptional": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "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==", - "devOptional": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "devOptional": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "devOptional": true, - "engines": { - "node": ">=6" - } - }, - "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==", - "devOptional": 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==", - "devOptional": 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/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==", - "devOptional": 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==", - "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==", - "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==", - "devOptional": 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==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "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/pkg-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.0.tgz", - "integrity": "sha512-/RpmvKdxKf8uILTtoOhAgf30wYbP2Qw+L9p3Rvshx1JZVX+XQNZQFjlbmGHEGIm4CkVPlSn+NXmIM8+9oWQaSA==", - "dev": true, - "dependencies": { - "confbox": "^0.1.7", - "mlly": "^1.6.1", - "pathe": "^1.1.2" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", - "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.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true - }, - "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", - "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", - "devOptional": true - }, - "node_modules/postcss-safe-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz", - "integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==", - "devOptional": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-scss": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", - "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-scss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.4.29" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", - "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", - "devOptional": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-sorting": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-8.0.2.tgz", - "integrity": "sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==", - "dev": true, - "peerDependencies": { - "postcss": "^8.4.20" - } - }, - "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==" - }, - "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==", - "devOptional": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "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/prettysize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prettysize/-/prettysize-2.0.0.tgz", - "integrity": "sha512-VVtxR7sOh0VsG8o06Ttq5TrI1aiZKmC+ClSn4eBPaNf4SHr5lzbYW+kYGX3HocBL/MfpVrRfFZ9V3vCbLaiplg==" - }, - "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==" - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "peer": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, - "peer": true - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, - "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.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "devOptional": true, - "engines": { - "node": ">=6" - } - }, - "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==", - "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/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "devOptional": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "devOptional": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/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==", - "devOptional": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/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==", - "devOptional": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/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==", - "devOptional": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/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==", - "devOptional": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "devOptional": true - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "devOptional": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "devOptional": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "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==", - "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==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "devOptional": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", - "dev": true, - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, - "peer": true - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==" - }, - "node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "engines": { - "node": ">= 0.10" - } - }, - "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==", - "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==", - "devOptional": 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.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "devOptional": true, - "dependencies": { - "is-core-module": "^2.13.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-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", - "dev": true, - "dependencies": { - "global-dirs": "^0.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", - "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==", - "devOptional": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.1.tgz", - "integrity": "sha512-0gG94inrUtg25sB2V/pApwiv1lUb0bQ25FPNuzO89Baa+B+c0ccaaBKM5zkZV/12pUUdH+lWCSm9wmHqyocuVQ==", - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.17.1", - "@rollup/rollup-android-arm64": "4.17.1", - "@rollup/rollup-darwin-arm64": "4.17.1", - "@rollup/rollup-darwin-x64": "4.17.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.17.1", - "@rollup/rollup-linux-arm-musleabihf": "4.17.1", - "@rollup/rollup-linux-arm64-gnu": "4.17.1", - "@rollup/rollup-linux-arm64-musl": "4.17.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.17.1", - "@rollup/rollup-linux-riscv64-gnu": "4.17.1", - "@rollup/rollup-linux-s390x-gnu": "4.17.1", - "@rollup/rollup-linux-x64-gnu": "4.17.1", - "@rollup/rollup-linux-x64-musl": "4.17.1", - "@rollup/rollup-win32-arm64-msvc": "4.17.1", - "@rollup/rollup-win32-ia32-msvc": "4.17.1", - "@rollup/rollup-win32-x64-msvc": "4.17.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", - "dev": true - }, - "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==", - "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/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", - "engines": { - "node": ">=10" - } - }, - "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.75.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.75.0.tgz", - "integrity": "sha512-ShMYi3WkrDWxExyxSZPst4/okE9ts46xZmJDSawJQrnte7M1V9fScVB+uNXOVKRBt0PggHOwoZcn8mYX4trnBw==", - "devOptional": 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/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/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "devOptional": 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==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true - }, - "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/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, - "node_modules/sirv": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", - "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", - "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "devOptional": 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/sonarlint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/sonarlint/-/sonarlint-1.1.0.tgz", - "integrity": "sha512-FSzPtaKNyNcKB1gtD+135JMP/JeFNXyjghZAWALBDU3Ilt9g9TmtihRfxtFS9Fw9BpPkccRQOKZcAA51YmD3FQ==", - "dev": true, - "bin": { - "sonarlint": "src/index.js" - } - }, - "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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "devOptional": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "devOptional": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "devOptional": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", - "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", - "devOptional": true - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true, - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "engines": { - "node": "*" - } - }, - "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/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true - }, - "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", - "dev": true - }, - "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==", - "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-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", - "dev": true, - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width/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/string-width/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true - }, - "node_modules/string-width/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/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", - "dev": true, - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", - "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.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==", - "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-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "devOptional": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "devOptional": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", - "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", - "dev": true, - "dependencies": { - "js-tokens": "^9.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/strip-literal/node_modules/js-tokens": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", - "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", - "dev": true - }, - "node_modules/stylelint": { - "version": "16.4.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.4.0.tgz", - "integrity": "sha512-uSx7VMuXwLuYcNSIg+0/fFNv0WinsfLAqsVVy7h7p80clKOHiGE8pfY6UjqwylTHiJrRIahTl6a8FPxGezhWoA==", - "devOptional": true, - "dependencies": { - "@csstools/css-parser-algorithms": "^2.6.1", - "@csstools/css-tokenizer": "^2.2.4", - "@csstools/media-query-list-parser": "^2.1.9", - "@csstools/selector-specificity": "^3.0.3", - "@dual-bundle/import-meta-resolve": "^4.0.0", - "balanced-match": "^2.0.0", - "colord": "^2.9.3", - "cosmiconfig": "^9.0.0", - "css-functions-list": "^3.2.2", - "css-tree": "^2.3.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^8.0.0", - "global-modules": "^2.0.0", - "globby": "^11.1.0", - "globjoin": "^0.1.4", - "html-tags": "^3.3.1", - "ignore": "^5.3.1", - "imurmurhash": "^0.1.4", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.30.0", - "mathml-tag-names": "^2.1.3", - "meow": "^13.2.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.38", - "postcss-resolve-nested-selector": "^0.1.1", - "postcss-safe-parser": "^7.0.0", - "postcss-selector-parser": "^6.0.16", - "postcss-value-parser": "^4.2.0", - "resolve-from": "^5.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^7.1.0", - "supports-hyperlinks": "^3.0.0", - "svg-tags": "^1.0.0", - "table": "^6.8.2", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "stylelint": "bin/stylelint.mjs" - }, - "engines": { - "node": ">=18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - } - }, - "node_modules/stylelint-config-clean-order": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/stylelint-config-clean-order/-/stylelint-config-clean-order-5.4.2.tgz", - "integrity": "sha512-lhPnDUL1gQbZYqG9kQx5dfEfiD/EpyVbb6jOiR7YfKzkIVv7Rw4jSKzvxr4v5PZqmRyCSzM3goc93jqfF+OZbA==", - "dev": true, - "dependencies": { - "stylelint-order": "^6.0.4" - }, - "peerDependencies": { - "stylelint": ">=14" - } - }, - "node_modules/stylelint-config-recommended": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.0.tgz", - "integrity": "sha512-jSkx290CglS8StmrLp2TxAppIajzIBZKYm3IxT89Kg6fGlxbPiTiyH9PS5YUuVAFwaJLl1ikiXX0QWjI0jmgZQ==", - "dev": true, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.0.0" - } - }, - "node_modules/stylelint-config-recommended-scss": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.0.0.tgz", - "integrity": "sha512-HDvpoOAQ1RpF+sPbDOT2Q2/YrBDEJDnUymmVmZ7mMCeNiFSdhRdyGEimBkz06wsN+HaFwUh249gDR+I9JR7Onw==", - "dev": true, - "dependencies": { - "postcss-scss": "^4.0.9", - "stylelint-config-recommended": "^14.0.0", - "stylelint-scss": "^6.0.0" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "postcss": "^8.3.3", - "stylelint": "^16.0.2" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - } - } - }, - "node_modules/stylelint-config-standard": { - "version": "36.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.0.tgz", - "integrity": "sha512-3Kjyq4d62bYFp/Aq8PMKDwlgUyPU4nacXsjDLWJdNPRUgpuxALu1KnlAHIj36cdtxViVhXexZij65yM0uNIHug==", - "dev": true, - "dependencies": { - "stylelint-config-recommended": "^14.0.0" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.1.0" - } - }, - "node_modules/stylelint-config-standard-scss": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-13.1.0.tgz", - "integrity": "sha512-Eo5w7/XvwGHWkeGLtdm2FZLOMYoZl1omP2/jgFCXyl2x5yNz7/8vv4Tj6slHvMSSUNTaGoam/GAZ0ZhukvalfA==", - "dev": true, - "dependencies": { - "stylelint-config-recommended-scss": "^14.0.0", - "stylelint-config-standard": "^36.0.0" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "postcss": "^8.3.3", - "stylelint": "^16.3.1" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - } - } - }, - "node_modules/stylelint-declaration-block-no-ignored-properties": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/stylelint-declaration-block-no-ignored-properties/-/stylelint-declaration-block-no-ignored-properties-2.8.0.tgz", - "integrity": "sha512-Ws8Cav7Y+SPN0JsV407LrnNXWOrqGjxShf+37GBtnU/C58Syve9c0+I/xpLcFOosST3ternykn3Lp77f3ITnFw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "stylelint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/stylelint-order": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-6.0.4.tgz", - "integrity": "sha512-0UuKo4+s1hgQ/uAxlYU4h0o0HS4NiQDud0NAUNI0aa8FJdmYHA5ZZTFHiV5FpmE3071e9pZx5j0QpVJW5zOCUA==", - "dev": true, - "dependencies": { - "postcss": "^8.4.32", - "postcss-sorting": "^8.0.2" - }, - "peerDependencies": { - "stylelint": "^14.0.0 || ^15.0.0 || ^16.0.1" - } - }, - "node_modules/stylelint-scss": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.2.1.tgz", - "integrity": "sha512-ZoGLbVb1keZYRVGQlhB8G6sZOoNqw61whzzzGFWp05N12ErqLFfBv3JPrXiMLZaW98sBS7K/vUQhRnvUj4vwdw==", - "dev": true, - "dependencies": { - "known-css-properties": "^0.29.0", - "postcss-media-query-parser": "^0.2.3", - "postcss-resolve-nested-selector": "^0.1.1", - "postcss-selector-parser": "^6.0.15", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.0.2" - } - }, - "node_modules/stylelint-scss/node_modules/known-css-properties": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", - "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", - "dev": true - }, - "node_modules/stylelint/node_modules/balanced-match": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "devOptional": true - }, - "node_modules/stylelint/node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "devOptional": true, - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/stylelint/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==", - "devOptional": true - }, - "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "devOptional": true, - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/stylelint/node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "devOptional": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/stylelint/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==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/stylelint/node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "devOptional": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stylelint/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==", - "devOptional": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/stylelint/node_modules/string-width/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==", - "devOptional": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/stylelint/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==", - "devOptional": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/stylelint/node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "devOptional": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "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==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", - "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", - "devOptional": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=14.18" - } - }, - "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==", - "devOptional": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-sprite": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-sprite/-/svg-sprite-2.0.4.tgz", - "integrity": "sha512-kjDoATgr4k6tdtfQczpkbuFW6RE7tPUPe/rbRd1n2NV92kdwaXEZMIxJqAZfMGOMfU/Kp1u89SUYsfHCbAvVHg==", - "dependencies": { - "@resvg/resvg-js": "^2.6.0", - "@xmldom/xmldom": "^0.8.10", - "async": "^3.2.5", - "css-selector-parser": "^1.4.1", - "csso": "^4.2.0", - "cssom": "^0.5.0", - "glob": "^7.2.3", - "js-yaml": "^4.1.0", - "lodash.escape": "^4.0.1", - "lodash.merge": "^4.6.2", - "mustache": "^4.2.0", - "prettysize": "^2.0.0", - "svgo": "^2.8.0", - "vinyl": "^2.2.1", - "winston": "^3.11.0", - "xpath": "^0.0.34", - "yargs": "^17.7.2" - }, - "bin": { - "svg-sprite": "bin/svg-sprite.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/svg-sprite/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/svg-sprite/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==", - "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/svg-sprite/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/svg-sprite/node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/svg-sprite/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==", - "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/svg-sprite/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/svg-sprite/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "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/svg-sprite/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/svg-sprite/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "node_modules/svg-sprite/node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "devOptional": true - }, - "node_modules/svgo": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", - "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", - "dev": true, - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^5.1.0", - "css-tree": "^2.3.1", - "css-what": "^6.1.0", - "csso": "^5.0.5", - "picocolors": "^1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/svgo" - } - }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "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/table": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", - "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", - "devOptional": true, - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/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==", - "devOptional": true - }, - "node_modules/table/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==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/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==", - "devOptional": 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/table/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==", - "devOptional": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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-extensions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", - "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" - }, - "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==", - "devOptional": 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/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" - }, - "node_modules/tinybench": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", - "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==", - "dev": true - }, - "node_modules/tinypool": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", - "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "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==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, - "engines": { - "node": ">=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": "5.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", - "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "dev": true, - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/triple-beam": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", - "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/tsconfck": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.0.3.tgz", - "integrity": "sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA==", - "bin": { - "tsconfck": "bin/tsconfck.js" - }, - "engines": { - "node": "^18 || >=20" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "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==", - "devOptional": 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.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "devOptional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "devOptional": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ufo": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", - "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", - "dev": true - }, - "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/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "devOptional": true - }, - "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/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "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==", - "devOptional": 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==" - }, - "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", - "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/validate-branch-name": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/validate-branch-name/-/validate-branch-name-1.3.0.tgz", - "integrity": "sha512-8U+soXh1scJpd8iuGn7DC9QY15PU529EyEBDKjIBhV65uFyS/sT8lCtnNq0DmxIS3VKQpgvdWf96FuM9ENX2uw==", - "dev": true, - "dependencies": { - "commander": "^8.3.0", - "cosmiconfig": "^7.0.1", - "current-git-branch": "^1.1.0" - }, - "bin": { - "validate-branch-name": "cli.js" - } - }, - "node_modules/validate-branch-name/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/validate-branch-name/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/validate-branch-name/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "devOptional": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vite": { - "version": "5.2.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz", - "integrity": "sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==", - "dependencies": { - "esbuild": "^0.20.1", - "postcss": "^8.4.38", - "rollup": "^4.13.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-node": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.5.2.tgz", - "integrity": "sha512-Y8p91kz9zU+bWtF7HGt6DVw2JbhyuB2RlZix3FPYAYmUyZ3n7iTp8eSyLyY6sxtPegvxQtmlTMhfPhUfCUF93A==", - "dev": true, - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.4", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite-plugin-checker": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.6.4.tgz", - "integrity": "sha512-2zKHH5oxr+ye43nReRbC2fny1nyARwhxdm0uNYp/ERy4YvU9iZpNOsueoi/luXw5gnpqRSvjcEPxXbS153O2wA==", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "ansi-escapes": "^4.3.0", - "chalk": "^4.1.1", - "chokidar": "^3.5.1", - "commander": "^8.0.0", - "fast-glob": "^3.2.7", - "fs-extra": "^11.1.0", - "npm-run-path": "^4.0.1", - "semver": "^7.5.0", - "strip-ansi": "^6.0.0", - "tiny-invariant": "^1.1.0", - "vscode-languageclient": "^7.0.0", - "vscode-languageserver": "^7.0.0", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-uri": "^3.0.2" - }, - "engines": { - "node": ">=14.16" - }, - "peerDependencies": { - "eslint": ">=7", - "meow": "^9.0.0", - "optionator": "^0.9.1", - "stylelint": ">=13", - "typescript": "*", - "vite": ">=2.0.0", - "vls": "*", - "vti": "*", - "vue-tsc": ">=1.3.9" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "meow": { - "optional": true - }, - "optionator": { - "optional": true - }, - "stylelint": { - "optional": true - }, - "typescript": { - "optional": true - }, - "vls": { - "optional": true - }, - "vti": { - "optional": true - }, - "vue-tsc": { - "optional": true - } - } - }, - "node_modules/vite-plugin-checker/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==", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vite-plugin-checker/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/vite-plugin-checker/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==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vite-plugin-image-optimizer": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/vite-plugin-image-optimizer/-/vite-plugin-image-optimizer-1.1.7.tgz", - "integrity": "sha512-KPJWndwqVi7Z2hYCudzKeNDw5U7w1DxAc266bqDBKV8taG8W3EtripFuUM4Y05IlFC19yBQndJCFA8+NJymH+w==", - "dependencies": { - "ansi-colors": "^4.1.3", - "pathe": "^1.1.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "vite": ">=3" - } - }, - "node_modules/vite-plugin-sass": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/vite-plugin-sass/-/vite-plugin-sass-0.1.0.tgz", - "integrity": "sha512-gLwvs3ozfDAOZCqs+PepkTd4078m8tfq50IlmTW/OphlWsW95uP7lQ5A3NezfUfTZDTCOA4nFlYnOWRpsKYOqw==", - "dev": true - }, - "node_modules/vite-plugin-svg-spriter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vite-plugin-svg-spriter/-/vite-plugin-svg-spriter-1.0.0.tgz", - "integrity": "sha512-WDvBa7s8ViDkcuTVfKvjaH8J6YlnsAap9xF/0mZSwHXvxSAPWHZkxIz5TdYrJsLLYSO20HXGVI/5DQwTBv7ezQ==", - "dependencies": { - "svg-sprite": "^2.0.2" - } - }, - "node_modules/vite-tsconfig-paths": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz", - "integrity": "sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==", - "dependencies": { - "debug": "^4.1.1", - "globrex": "^0.1.2", - "tsconfck": "^3.0.3" - }, - "peerDependencies": { - "vite": "*" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - }, - "node_modules/vitest": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.5.2.tgz", - "integrity": "sha512-l9gwIkq16ug3xY7BxHwcBQovLZG75zZL0PlsiYQbf76Rz6QGs54416UWMtC0jXeihvHvcHrf2ROEjkQRVpoZYw==", - "dev": true, - "dependencies": { - "@vitest/expect": "1.5.2", - "@vitest/runner": "1.5.2", - "@vitest/snapshot": "1.5.2", - "@vitest/spy": "1.5.2", - "@vitest/utils": "1.5.2", - "acorn-walk": "^8.3.2", - "chai": "^4.3.10", - "debug": "^4.3.4", - "execa": "^8.0.1", - "local-pkg": "^0.5.0", - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "tinybench": "^2.5.1", - "tinypool": "^0.8.3", - "vite": "^5.0.0", - "vite-node": "1.5.2", - "why-is-node-running": "^2.2.2" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.5.2", - "@vitest/ui": "1.5.2", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/vitest/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/vitest/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/vitest/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/vitest/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/vitest/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "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/vitest/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/vitest/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/vitest/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/vitest/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/vscode-jsonrpc": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", - "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", - "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", - "dependencies": { - "minimatch": "^3.0.4", - "semver": "^7.3.4", - "vscode-languageserver-protocol": "3.16.0" - }, - "engines": { - "vscode": "^1.52.0" - } - }, - "node_modules/vscode-languageserver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz", - "integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==", - "dependencies": { - "vscode-languageserver-protocol": "3.16.0" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", - "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", - "dependencies": { - "vscode-jsonrpc": "6.0.0", - "vscode-languageserver-types": "3.16.0" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", - "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", - "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" - }, - "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" - }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "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/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "dev": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/whatwg-fetch": { - "version": "3.6.20", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", - "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" - }, - "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/whatwg-url": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", - "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", - "dev": true, - "dependencies": { - "tr46": "^5.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "devOptional": 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-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "peer": true, - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "peer": true, - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/why-is-node-running": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", - "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", - "dev": true, - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/winston": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.13.0.tgz", - "integrity": "sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==", - "dependencies": { - "@colors/colors": "^1.6.0", - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.4.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.7.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/winston-transport": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", - "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", - "dependencies": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "devOptional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-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/wrap-ansi/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/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "devOptional": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "devOptional": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", - "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": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "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/xpath": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.34.tgz", - "integrity": "sha512-FxF6+rkr1rNSQrhUNYrAFJpRXNzlDoMxeXN5qI84939ylEv3qqPFKa85Oxr6tDaJKqwW6KKyo2v26TSv3k6LeA==", - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", - "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==", - "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==", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/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==" - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "devOptional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/package.json b/package.json index 6212fe4b..9e7d9354 100644 --- a/package.json +++ b/package.json @@ -21,13 +21,12 @@ }, "devDependencies": { "@commitlint/cli": "^18.6.1", - "@commitlint/config-conventional": "^18.6.2", + "@commitlint/config-conventional": "^18.6.3", "@eslint/eslintrc": "^3.0.2", - "@types/jest": "^29.5.12", - "@typescript-eslint/eslint-plugin": "^7.7.1", - "@typescript-eslint/parser": "^7.7.1", - "@vitest/coverage-v8": "^1.5.2", - "@vitest/ui": "^1.5.2", + "@typescript-eslint/eslint-plugin": "^7.8.0", + "@typescript-eslint/parser": "^7.8.0", + "@vitest/coverage-v8": "^1.6.0", + "@vitest/ui": "^1.6.0", "c8": "^9.1.0", "dotenv": "^16.4.5", "eslint": "^8.57.0", @@ -42,31 +41,33 @@ "jsdom": "^24.0.0", "lint-staged": "^15.2.2", "prettier": "^3.2.5", - "sass": "^1.71.1", + "sass": "^1.76.0", "sonarlint": "^1.1.0", - "stylelint": "^16.2.1", - "stylelint-config-clean-order": "^5.4.1", + "stylelint": "^16.5.0", + "stylelint-config-clean-order": "^5.4.2", "stylelint-config-standard": "^36.0.0", - "stylelint-config-standard-scss": "^13.0.0", + "stylelint-config-standard-scss": "^13.1.0", "stylelint-declaration-block-no-ignored-properties": "^2.8.0", "stylelint-order": "^6.0.4", - "stylelint-scss": "^6.2.0", + "stylelint-scss": "^6.3.0", "svgo": "^3.2.0", - "typescript": "^5.3.3", + "typescript": "^5.4.5", "validate-branch-name": "^1.3.0", - "vite": "^5.1.4", + "vite": "^5.2.11", "vite-plugin-sass": "^0.1.0", - "vitest": "^1.5.2" + "vitest": "^1.6.0" }, "dependencies": { "@commercetools/api-request-builder": "^6.0.0", - "@commercetools/platform-sdk": "^7.7.0", - "@commercetools/sdk-client-v2": "^2.4.1", + "@commercetools/platform-sdk": "^7.8.0", + "@commercetools/sdk-client-v2": "^2.5.0", "@commercetools/sdk-middleware-auth": "^7.0.1", "@commercetools/sdk-middleware-http": "^7.0.4", "autoprefixer": "^10.4.19", "isomorphic-fetch": "^3.0.0", "modern-normalize": "^2.0.0", + "postcode-validator": "^3.8.20", + "translate": "^3.0.0", "vite-plugin-checker": "^0.6.4", "vite-plugin-image-optimizer": "^1.1.7", "vite-plugin-svg-spriter": "^1.0.0", diff --git a/src/app/App/.gitkeep b/src/app/App/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/app/App/model/AppModel.ts b/src/app/App/model/AppModel.ts new file mode 100644 index 00000000..cb2a7014 --- /dev/null +++ b/src/app/App/model/AppModel.ts @@ -0,0 +1,48 @@ +import type { Page } from '@/shared/types/common.ts'; + +import RouterModel from '@/app/Router/model/RouterModel.ts'; +import LoginPageModel from '@/pages/LoginPage/model/LoginPageModel.ts'; +import MainPageModel from '@/pages/MainPage/model/MainPageModel.ts'; +import NotFoundPageModel from '@/pages/NotFoundPage/model/NotFoundPageModel.ts'; +import RegistrationPageModel from '@/pages/RegistrationPage/model/RegistrationPageModel.ts'; +import { PAGE_ID } from '@/shared/constants/pages.ts'; +import FooterModel from '@/widgets/Footer/model/FooterModel.ts'; +import HeaderModel from '@/widgets/Header/model/HeaderModel.ts'; + +import AppView from '../view/AppView.ts'; + +class AppModel { + private appView: AppView = new AppView(); + + private router = new RouterModel(); + + constructor() { + this.router.setPages(this.initPages()); + } + + private initPages(): Map { + const root = this.getHTML(); + root.append(new HeaderModel(this.router).getHTML()); + const loginPage = new LoginPageModel(root, this.router); + const mainPage = new MainPageModel(root, this.router); + const registrationPage = new RegistrationPageModel(root, this.router); + const notFoundPage = new NotFoundPageModel(root, this.router); + const pages: Map = new Map( + Object.entries({ + [PAGE_ID.DEFAULT_PAGE]: mainPage, + [PAGE_ID.LOGIN_PAGE]: loginPage, + [PAGE_ID.MAIN_PAGE]: mainPage, + [PAGE_ID.NOT_FOUND_PAGE]: notFoundPage, + [PAGE_ID.REGISTRATION_PAGE]: registrationPage, + }), + ); + root.append(new FooterModel(this.router).getHTML()); + return pages; + } + + public getHTML(): HTMLDivElement { + return this.appView.getHTML(); + } +} + +export default AppModel; diff --git a/src/app/App/tests/App.spec.ts b/src/app/App/tests/App.spec.ts new file mode 100644 index 00000000..4ddd25c6 --- /dev/null +++ b/src/app/App/tests/App.spec.ts @@ -0,0 +1,9 @@ +import AppModel from '../model/AppModel.ts'; + +const app = new AppModel(); + +describe('Checking AppModel class', () => { + it('the getHTML method should return HTMLDivElement', () => { + expect(app.getHTML()).toBeInstanceOf(HTMLDivElement); + }); +}); diff --git a/src/app/App/view/AppView.ts b/src/app/App/view/AppView.ts new file mode 100644 index 00000000..49b58b13 --- /dev/null +++ b/src/app/App/view/AppView.ts @@ -0,0 +1,27 @@ +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; + +import styles from './appView.module.scss'; + +class AppView { + private pagesContainer: HTMLDivElement; + + constructor() { + this.pagesContainer = this.createHTML(); + } + + private createHTML(): HTMLDivElement { + this.pagesContainer = createBaseElement({ + cssClasses: [styles.siteWrapper], + tag: TAG_NAME.DIV, + }); + + return this.pagesContainer; + } + + public getHTML(): HTMLDivElement { + return this.pagesContainer; + } +} + +export default AppView; diff --git a/src/app/App/view/appView.module.scss b/src/app/App/view/appView.module.scss new file mode 100644 index 00000000..f4a6d30e --- /dev/null +++ b/src/app/App/view/appView.module.scss @@ -0,0 +1,10 @@ +.siteWrapper { + position: relative; + display: flex; + flex-direction: column; + justify-content: space-between; + margin: 0 auto; + width: 100%; + min-height: 100vh; + max-width: 1440px; +} diff --git a/src/app/Router/.gitkeep b/src/app/Router/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/app/Router/model/RouterModel.ts b/src/app/Router/model/RouterModel.ts new file mode 100644 index 00000000..f1f6c0b4 --- /dev/null +++ b/src/app/Router/model/RouterModel.ts @@ -0,0 +1,63 @@ +import type { Page } from '@/shared/types/common.ts'; + +import EventMediatorModel from '@/shared/EventMediator/model/EventMediatorModel.ts'; +import { EVENT_NAME, MEDIATOR_EVENT } from '@/shared/constants/events.ts'; +import { PAGE_ID } from '@/shared/constants/pages.ts'; + +const DEFAULT_SEGMENT = import.meta.env.VITE_APP_DEFAULT_SEGMENT; +const NEXT_SEGMENT = import.meta.env.VITE_APP_NEXT_SEGMENT; +const PATH_SEGMENTS_TO_KEEP = import.meta.env.VITE_APP_PATH_SEGMENTS_TO_KEEP; +const PROJECT_TITLE = import.meta.env.VITE_APP_PROJECT_TITLE; + +class RouterModel { + private eventMediator = EventMediatorModel.getInstance(); + + private pages: Map = new Map(); + + constructor() { + document.addEventListener(EVENT_NAME.DOM_CONTENT_LOADED, () => { + const currentPath = window.location.pathname + .split(DEFAULT_SEGMENT) + .slice(PATH_SEGMENTS_TO_KEEP + NEXT_SEGMENT) + .join(DEFAULT_SEGMENT); + this.handleRequest(currentPath); + }); + } + + private handleRequest(path: string): null | string { + const pathParts = path.split(DEFAULT_SEGMENT); + const hasRoute = this.pages.has(pathParts.join('')); + if (!hasRoute) { + document.title = `${PROJECT_TITLE} | ${PAGE_ID.NOT_FOUND_PAGE}`; + this.eventMediator.notify(MEDIATOR_EVENT.CHANGE_PAGE, PAGE_ID.NOT_FOUND_PAGE); + return null; + } + document.title = `${PROJECT_TITLE} | ${pathParts.join('')}`; + this.eventMediator.notify(MEDIATOR_EVENT.CHANGE_PAGE, pathParts.join('')); + return pathParts.join(''); + } + + public navigateTo(route: string): History { + if (this.pages.has(route)) { + const pathnameApp = window.location.pathname + .split(DEFAULT_SEGMENT) + .slice(NEXT_SEGMENT, PATH_SEGMENTS_TO_KEEP + NEXT_SEGMENT) + .join(DEFAULT_SEGMENT); + const url = `${pathnameApp}/${route}`; + const titleRoute = route === '' ? PAGE_ID.MAIN_PAGE : route; + document.title = `${PROJECT_TITLE} | ${titleRoute}`; + + history.pushState(route, '', url); + + this.eventMediator.notify(MEDIATOR_EVENT.CHANGE_PAGE, route); + } + return window.history; + } + + public setPages(pages: Map): Map { + this.pages = pages; + return this.pages; + } +} + +export default RouterModel; diff --git a/src/app/styles/common.scss b/src/app/styles/common.scss index 69a64e5a..0fb605e7 100644 --- a/src/app/styles/common.scss +++ b/src/app/styles/common.scss @@ -8,7 +8,6 @@ body { margin: 0 auto; width: 100%; min-width: 320px; - max-width: 1440px; font-family: 'Cerapro', sans-serif; font-weight: 400; background-color: var(--noble-white-100); @@ -23,9 +22,3 @@ body { img { max-width: 100%; } - -.container { - margin: 0 auto; - padding: 0 var(--small-offset); - max-width: 1440px; -} diff --git a/src/app/styles/reset.scss b/src/app/styles/reset.scss index b532bc23..a85031b8 100644 --- a/src/app/styles/reset.scss +++ b/src/app/styles/reset.scss @@ -26,6 +26,7 @@ button { a { text-decoration: none; color: inherit; + user-select: none; } input, diff --git a/src/app/styles/variables.scss b/src/app/styles/variables.scss index f5b4bfe7..2d710107 100644 --- a/src/app/styles/variables.scss +++ b/src/app/styles/variables.scss @@ -4,6 +4,7 @@ --small-offset: 40px; --medium-offset: 60px; --large-offset: 80px; + --extra-large-offset: 100px; // border-radius --small-br: 5px; @@ -14,6 +15,7 @@ --white: #fff; --black: #000; --noble-white-100: #f5f5f5; + --noble-gray-200: #eaeaea; --noble-gray-300: #cbcbcb; --noble-gray-400: #c4c4c4; --noble-gray-500: #acacac; @@ -23,14 +25,15 @@ --red-power-600: #d0302f; --steam-green-400: #c8f4b4; --steam-green-500: #b6f09c; + --steam-green-700: #70d27a; --steam-green-800: #46a358; // fonts - --regular-font: 400 16px 'Cerapro', sans-serif; + --regular-font: 400 13px 'Cerapro', sans-serif; --extra-regular-font: 400 24px 'Cerapro', sans-serif; - --medium-font: 500 24px 'Cerapro', sans-serif; + --medium-font: 500 20px 'Cerapro', sans-serif; --extra-medium-font: 500 30px 'Cerapro', sans-serif; - --bold-font: 700 30px 'Cerapro', sans-serif; + --bold-font: 700 16px 'Cerapro', sans-serif; --extra-bold-font: 700 35px 'Cerapro', sans-serif; --black-font: 900 35px 'Cerapro', sans-serif; --extra-black-font: 900 40px 'Cerapro', sans-serif; @@ -40,7 +43,8 @@ --small-offset: 20px; --medium-offset: 30px; --large-offset: 40px; - --small-br: 2px; + --extra-large-offset: 50px; + --small-br: 5px; --medium-br: 5px; --large-br: 10px; } diff --git a/src/entities/InputField/.gitkeep b/src/entities/InputField/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/entities/InputField/model/InputFieldModel.ts b/src/entities/InputField/model/InputFieldModel.ts new file mode 100644 index 00000000..95c08fd5 --- /dev/null +++ b/src/entities/InputField/model/InputFieldModel.ts @@ -0,0 +1,79 @@ +import type { InputFieldParams, InputFieldValidatorParams } from '@/shared/types/form.ts'; + +import InputFieldValidatorModel from '@/features/InputFieldValidator/model/InputFieldValidatorModel.ts'; +import observeStore, { selectCurrentLanguage } from '@/shared/Store/observer.ts'; +import { EVENT_NAME } from '@/shared/constants/events.ts'; +import { INPUT_TYPE, PASSWORD_TEXT } from '@/shared/constants/forms.ts'; + +import InputFieldView from '../view/InputFieldView.ts'; + +class InputFieldModel { + private isValid = false; + + private validator: InputFieldValidatorModel | null = null; + + private view: InputFieldView; + + constructor(inputFieldParams: InputFieldParams, validParams: InputFieldValidatorParams | null) { + this.view = new InputFieldView(inputFieldParams); + + if (validParams) { + this.validator = new InputFieldValidatorModel(validParams, this.isValid); + this.setInputHandler(); + } + + observeStore(selectCurrentLanguage, () => this.inputHandler()); + + this.setSwitchPasswordVisibilityHandler(); + } + + private inputHandler(): boolean { + const errorField = this.view.getErrorField(); + const errors = this.validator?.validate(this.view.getValue()); + if (errors === true) { + if (errorField) { + errorField.textContent = ''; + } + this.isValid = true; + } else { + if (errorField && errors) { + const [firstError] = errors; + errorField.textContent = firstError; + } + this.isValid = false; + } + + return true; + } + + private setInputHandler(): boolean { + const input = this.view.getInput().getHTML(); + input.addEventListener(EVENT_NAME.INPUT, () => this.inputHandler()); + + return true; + } + + private setSwitchPasswordVisibilityHandler(): boolean { + const button = this.view.getShowPasswordButton().getHTML(); + button.addEventListener(EVENT_NAME.CLICK, () => this.switchPasswordVisibilityHandler()); + return true; + } + + private switchPasswordVisibilityHandler(): boolean { + const input = this.view.getInput().getHTML(); + input.type = input.type === INPUT_TYPE.PASSWORD ? INPUT_TYPE.TEXT : INPUT_TYPE.PASSWORD; + input.placeholder = input.type === INPUT_TYPE.PASSWORD ? PASSWORD_TEXT.HIDDEN : PASSWORD_TEXT.SHOWN; + this.view.switchPasswordButtonSVG(input.type); + return true; + } + + public getIsValid(): boolean { + return this.isValid; + } + + public getView(): InputFieldView { + return this.view; + } +} + +export default InputFieldModel; diff --git a/src/entities/InputField/view/InputFieldView.ts b/src/entities/InputField/view/InputFieldView.ts new file mode 100644 index 00000000..1ab649b1 --- /dev/null +++ b/src/entities/InputField/view/InputFieldView.ts @@ -0,0 +1,109 @@ +import type { InputFieldParams, InputParams, LabelParams } from '@/shared/types/form'; + +import ButtonModel from '@/shared/Button/model/ButtonModel.ts'; +import InputModel from '@/shared/Input/model/InputModel.ts'; +import { INPUT_TYPE } from '@/shared/constants/forms.ts'; +import SVG_DETAILS from '@/shared/constants/svg.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; +import createSVGUse from '@/shared/utils/createSVGUse.ts'; + +class InputFieldView { + private errorField: HTMLSpanElement | null = null; + + private input: InputModel; + + private inputField: HTMLLabelElement | InputModel; + + private label: HTMLLabelElement | null = null; + + private showPasswordButton: ButtonModel; + + constructor(params: InputFieldParams) { + this.input = this.createInput(params.inputParams); + this.showPasswordButton = this.createShowPasswordButton(); + this.inputField = this.createHTML(params); + } + + private createErrorField(): HTMLSpanElement { + this.errorField = createBaseElement({ + tag: TAG_NAME.SPAN, + }); + return this.errorField; + } + + private createHTML(params: InputFieldParams): HTMLLabelElement | InputModel { + const { labelParams } = params; + if (labelParams) { + this.inputField = this.createLabel(labelParams); + this.errorField = this.createErrorField(); + this.label?.append(this.input.getHTML(), this.errorField); + } else { + this.inputField = this.input; + } + + if (this.getInput().getHTML().type === INPUT_TYPE.PASSWORD) { + this.label?.append(this.showPasswordButton.getHTML()); + } + + return this.inputField; + } + + private createInput(inputParams: InputParams): InputModel { + this.input = new InputModel(inputParams); + // TBD fix show password on pressing enter + return this.input; + } + + private createLabel(labelParams: LabelParams): HTMLLabelElement { + const { for: htmlFor, text } = labelParams; + this.label = createBaseElement({ + attributes: { + for: htmlFor, + }, + innerContent: text || '', + tag: TAG_NAME.LABEL, + }); + + return this.label; + } + + private createShowPasswordButton(): ButtonModel { + this.showPasswordButton = new ButtonModel({}); + this.switchPasswordButtonSVG(INPUT_TYPE.PASSWORD); + return this.showPasswordButton; + } + + public getErrorField(): HTMLSpanElement | null { + return this.errorField; + } + + public getHTML(): HTMLLabelElement | InputModel { + return this.inputField; + } + + public getInput(): InputModel { + return this.input; + } + + public getShowPasswordButton(): ButtonModel { + return this.showPasswordButton; + } + + public getValue(): string { + if (this.inputField instanceof InputModel) { + return this.inputField.getValue(); + } + return this.input.getValue(); + } + + public switchPasswordButtonSVG(type: string): SVGSVGElement { + const svg = document.createElementNS(SVG_DETAILS.SVG_URL, TAG_NAME.SVG); + this.showPasswordButton.getHTML().innerHTML = ''; + svg.append(createSVGUse(type === INPUT_TYPE.PASSWORD ? SVG_DETAILS.CLOSE_EYE : SVG_DETAILS.OPEN_EYE)); + this.showPasswordButton.getHTML().append(svg); + return svg; + } +} + +export default InputFieldView; diff --git a/src/entities/Navigation/.gitkeep b/src/entities/Navigation/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/entities/Navigation/model/NavigationModel.ts b/src/entities/Navigation/model/NavigationModel.ts new file mode 100644 index 00000000..555eaa11 --- /dev/null +++ b/src/entities/Navigation/model/NavigationModel.ts @@ -0,0 +1,76 @@ +import type RouterModel from '@/app/Router/model/RouterModel'; + +import EventMediatorModel from '@/shared/EventMediator/model/EventMediatorModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import observeStore, { selectCurrentUser } from '@/shared/Store/observer.ts'; +import { EVENT_NAME, MEDIATOR_EVENT } from '@/shared/constants/events.ts'; +import { PAGE_ID } from '@/shared/constants/pages.ts'; + +import NavigationView from '../view/NavigationView.ts'; + +class NavigationModel { + private eventMediator = EventMediatorModel.getInstance(); + + private router: RouterModel; + + private view = new NavigationView(); + + constructor(router: RouterModel) { + this.router = router; + this.init(); + } + + private checkCurrentUser(): boolean { + const { currentUser } = getStore().getState(); + const navigationLinks = this.view.getNavigationLinks(); + if (!currentUser) { + navigationLinks.get(PAGE_ID.LOGIN_PAGE)?.setEnabled(); + } else { + navigationLinks.get(PAGE_ID.LOGIN_PAGE)?.setDisabled(); + } + return true; + } + + private init(): boolean { + this.setNavigationLinksHandlers(); + this.observeCurrentUser(); + this.subscribeToEventMediator(); + return true; + } + + private observeCurrentUser(): boolean { + observeStore(selectCurrentUser, () => this.checkCurrentUser.bind(this)); + return true; + } + + private setNavigationLinksHandlers(): boolean { + const navigationLinks = this.view.getNavigationLinks(); + navigationLinks.forEach((link, route) => { + link.getHTML().addEventListener(EVENT_NAME.CLICK, (event) => { + event.preventDefault(); + this.router.navigateTo(route); + }); + }); + + return true; + } + + private subscribeToEventMediator(): boolean { + this.eventMediator.subscribe(MEDIATOR_EVENT.CHANGE_PAGE, (route) => { + const currentRoute = route === '' ? PAGE_ID.MAIN_PAGE : route; + const navigationLinks = this.view.getNavigationLinks(); + const currentLink = navigationLinks.get(String(currentRoute)); + navigationLinks.forEach((link) => link.setEnabled()); + this.checkCurrentUser(); + currentLink?.setDisabled(); + this.view.switchActiveLink(String(currentRoute)); + }); + return true; + } + + public getHTML(): HTMLElement { + return this.view.getHTML(); + } +} + +export default NavigationModel; diff --git a/src/entities/Navigation/view/NavigationView.ts b/src/entities/Navigation/view/NavigationView.ts new file mode 100644 index 00000000..05c32877 --- /dev/null +++ b/src/entities/Navigation/view/NavigationView.ts @@ -0,0 +1,102 @@ +import LinkModel from '@/shared/Link/model/LinkModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { PAGE_ID, PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS } from '@/shared/constants/pages.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; +import observeCurrentLanguage from '@/shared/utils/observeCurrentLanguage.ts'; + +import styles from './navigationView.module.scss'; + +class NavigationView { + private navigation: HTMLElement; + + private navigationLinks: Map = new Map(); + + private toLoginLink: LinkModel; + + private toMainLink: LinkModel; + + private toRegisterLink: LinkModel; + + constructor() { + this.toMainLink = this.createToMainLink(); + this.toLoginLink = this.createToLoginLink(); + this.toRegisterLink = this.createToRegisterLink(); + this.navigation = this.createHTML(); + } + + private createHTML(): HTMLElement { + this.navigation = createBaseElement({ + cssClasses: [styles.navigation], + tag: TAG_NAME.NAV, + }); + this.navigation.append(this.toMainLink.getHTML(), this.toLoginLink.getHTML(), this.toRegisterLink.getHTML()); + return this.navigation; + } + + private createToLoginLink(): LinkModel { + const { currentLanguage } = getStore().getState(); + this.toLoginLink = new LinkModel({ + attrs: { + href: PAGE_ID.LOGIN_PAGE, + }, + classes: [styles.link], + text: PAGE_LINK_TEXT[currentLanguage].LOGIN, + }); + + observeCurrentLanguage(this.toLoginLink.getHTML(), PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS.LOGIN); + + this.navigationLinks.set(PAGE_ID.LOGIN_PAGE, this.toLoginLink); + return this.toLoginLink; + } + + private createToMainLink(): LinkModel { + const { currentLanguage } = getStore().getState(); + this.toMainLink = new LinkModel({ + attrs: { + href: PAGE_ID.MAIN_PAGE, + }, + classes: [styles.link], + text: PAGE_LINK_TEXT[currentLanguage].MAIN, + }); + + observeCurrentLanguage(this.toMainLink.getHTML(), PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS.MAIN); + + this.navigationLinks.set(PAGE_ID.MAIN_PAGE, this.toMainLink); + return this.toMainLink; + } + + private createToRegisterLink(): LinkModel { + const { currentLanguage } = getStore().getState(); + this.toRegisterLink = new LinkModel({ + attrs: { + href: PAGE_ID.REGISTRATION_PAGE, + }, + classes: [styles.link], + text: PAGE_LINK_TEXT[currentLanguage].REGISTRATION, + }); + + observeCurrentLanguage(this.toRegisterLink.getHTML(), PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS.REGISTRATION); + + this.navigationLinks.set(PAGE_ID.REGISTRATION_PAGE, this.toRegisterLink); + return this.toRegisterLink; + } + + public getHTML(): HTMLElement { + return this.navigation; + } + + public getNavigationLinks(): Map { + return this.navigationLinks; + } + + public switchActiveLink(route: string): void { + this.navigationLinks.forEach((link) => { + link.getHTML().classList.remove(styles.active); + }); + + this.navigationLinks.get(route)?.getHTML().classList.add(styles.active); + } +} + +export default NavigationView; diff --git a/src/entities/Navigation/view/navigationView.module.scss b/src/entities/Navigation/view/navigationView.module.scss new file mode 100644 index 00000000..4657a9cf --- /dev/null +++ b/src/entities/Navigation/view/navigationView.module.scss @@ -0,0 +1,54 @@ +.navigation { + display: flex; + align-self: center; + justify-content: center; + grid-column: 2; + grid-row: 1; + gap: var(--extra-small-offset); +} + +.link { + position: relative; + font: var(--regular-font); + letter-spacing: 1px; + text-transform: uppercase; + color: var(--noble-gray-800); + transition: color 0.2s; + + &::after { + content: ''; + position: absolute; + left: 0; + bottom: -4px; + width: 100%; + height: 2px; + background-color: currentcolor; + opacity: 0; + transform: scaleX(0); + transform-origin: center; + transition: + transform 0.2s, + opacity 0.2s; + } + + @media (hover: hover) { + &:hover { + color: var(--steam-green-800); + + &::after { + opacity: 1; + transform: scaleX(1); + } + } + } +} + +.active { + color: var(--steam-green-800); + opacity: 1; + + &::after { + opacity: 1; + transform: scaleX(1); + } +} diff --git a/src/features/CountryChoice/model/CountryChoiceModel.ts b/src/features/CountryChoice/model/CountryChoiceModel.ts new file mode 100644 index 00000000..c41f3111 --- /dev/null +++ b/src/features/CountryChoice/model/CountryChoiceModel.ts @@ -0,0 +1,90 @@ +import getStore from '@/shared/Store/Store.ts'; +import { setBillingCountry, setShippingCountry } from '@/shared/Store/actions.ts'; +import observeStore, { + selectBillingCountry, + selectCurrentLanguage, + selectShippingCountry, +} from '@/shared/Store/observer.ts'; +import COUNTRIES_LIST from '@/shared/constants/countriesList.ts'; +import { EVENT_NAME } from '@/shared/constants/events.ts'; +import { BILLING_ADDRESS_COUNTRY } from '@/shared/constants/forms/register/fieldParams.ts'; +import getCountryIndex from '@/shared/utils/getCountryIndex.ts'; + +import CountryChoiceView from '../view/CountryChoiceView.ts'; + +class CountryChoiceModel { + private view: CountryChoiceView; + + constructor(input: HTMLInputElement) { + this.view = new CountryChoiceView(input); + this.setCountryItemsHandlers(input); + this.setInputHandler(input); + + const action = input.id === BILLING_ADDRESS_COUNTRY.inputParams.id ? selectBillingCountry : selectShippingCountry; + + observeStore(action, () => { + const event = new Event(EVENT_NAME.INPUT); + input.dispatchEvent(event); + }); + } + + private observeCurrentLanguage(item: HTMLDivElement): boolean { + observeStore(selectCurrentLanguage, () => { + const currentItem = item; + const currentCountriesList = COUNTRIES_LIST[getStore().getState().currentLanguage]; + Object.entries(currentCountriesList).forEach(([countryName, countryCode]) => { + if (countryCode === currentItem.id) { + currentItem.textContent = countryName; + } + }); + }); + return true; + } + + private setCountryItemsHandlers(input: HTMLInputElement): boolean { + const inputHTML = input; + this.view.getCountryItems().forEach((countryItem) => { + const currentItem = countryItem; + this.observeCurrentLanguage(currentItem); + currentItem.addEventListener(EVENT_NAME.CLICK, () => { + if (currentItem.textContent) { + inputHTML.value = currentItem.textContent; + this.setCountryToStore(currentItem, inputHTML.id); + const event = new Event(EVENT_NAME.INPUT); + inputHTML.dispatchEvent(event); + this.view.hideCountryChoice(); + } + }); + }); + return true; + } + + private setCountryToStore(element: HTMLDivElement | HTMLInputElement, key: string): boolean { + const currentCountryIndex = getCountryIndex( + element instanceof HTMLDivElement ? element.textContent || '' : element.value, + ); + + const action = key === BILLING_ADDRESS_COUNTRY.inputParams.id ? setBillingCountry : setShippingCountry; + getStore().dispatch(action(currentCountryIndex)); + return true; + } + + private setInputHandler(input: HTMLInputElement): boolean { + input.addEventListener(EVENT_NAME.FOCUS, () => this.view.showCountryChoice()); + input.addEventListener(EVENT_NAME.INPUT, () => { + this.view.switchVisibilityCountryItems(input); + this.setCountryToStore(input, input.id); + }); + return true; + } + + public getHTML(): HTMLDivElement { + return this.view.getHTML(); + } + + public getView(): CountryChoiceView { + return this.view; + } +} + +export default CountryChoiceModel; diff --git a/src/features/CountryChoice/view/CountryChoiceView.ts b/src/features/CountryChoice/view/CountryChoiceView.ts new file mode 100644 index 00000000..2c7b9570 --- /dev/null +++ b/src/features/CountryChoice/view/CountryChoiceView.ts @@ -0,0 +1,108 @@ +import getStore from '@/shared/Store/Store.ts'; +import COUNTRIES_LIST from '@/shared/constants/countriesList.ts'; +import { EVENT_NAME } from '@/shared/constants/events.ts'; +import { KEYBOARD_KEYS } from '@/shared/constants/keyboard.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; + +import styles from './countryChoiceView.module.scss'; + +class CountryChoiceView { + private countryChoice: HTMLDivElement; + + private countryDropList: HTMLDivElement; + + private countryItems: HTMLDivElement[] = []; + + constructor(input: HTMLInputElement) { + this.countryDropList = this.createCountryDropList(); + this.countryChoice = this.createHTML(); + + document.addEventListener(EVENT_NAME.CLICK, (event) => { + if (!this.countryDropList.classList.contains(styles.hidden) && event.target !== input) { + this.hideCountryChoice(); + } else { + this.showCountryChoice(); + } + }); + + document.addEventListener(EVENT_NAME.KEYDOWN, (event) => { + if (event.key === KEYBOARD_KEYS.TAB && !this.getHTML().classList.contains(styles.hidden)) { + this.hideCountryChoice(); + } + }); + } + + private createCountryDropList(): HTMLDivElement { + this.countryDropList = createBaseElement({ + cssClasses: [styles.countryDropList], + tag: TAG_NAME.DIV, + }); + + const { currentLanguage } = getStore().getState(); + + Object.entries(COUNTRIES_LIST[currentLanguage]).forEach(([countryName, countryCode]) => + this.countryDropList.append(this.createCountryItem(countryName, countryCode)), + ); + + return this.countryDropList; + } + + private createCountryItem(countryName: string, countryCode: string): HTMLDivElement { + const countryItem = createBaseElement({ + attributes: { id: countryCode }, + cssClasses: [styles.countryItem], + innerContent: countryName, + tag: TAG_NAME.DIV, + }); + + this.countryItems.push(countryItem); + + return countryItem; + } + + private createHTML(): HTMLDivElement { + this.countryChoice = createBaseElement({ + cssClasses: [styles.countryChoice, styles.hidden], + tag: TAG_NAME.DIV, + }); + + this.countryChoice.append(this.countryDropList); + + return this.countryChoice; + } + + public getCountryDropList(): HTMLDivElement { + return this.countryDropList; + } + + public getCountryItems(): HTMLDivElement[] { + return this.countryItems; + } + + public getHTML(): HTMLDivElement { + return this.countryChoice; + } + + public hideCountryChoice(): void { + this.countryChoice.classList.add(styles.hidden); + document.body.classList.remove(styles.stopScroll); + } + + public showCountryChoice(): void { + this.countryChoice.classList.remove(styles.hidden); + document.body.classList.add(styles.stopScroll); + } + + public switchVisibilityCountryItems(inputHTML: HTMLInputElement): boolean { + const filterValue = inputHTML.value.toLowerCase(); + this.countryItems.forEach((countryItem) => { + const itemValue = countryItem.textContent?.toLowerCase(); + countryItem.classList.toggle(styles.hidden, !itemValue?.includes(filterValue)); + }); + + return true; + } +} + +export default CountryChoiceView; diff --git a/src/features/CountryChoice/view/countryChoiceView.module.scss b/src/features/CountryChoice/view/countryChoiceView.module.scss new file mode 100644 index 00000000..3e71d321 --- /dev/null +++ b/src/features/CountryChoice/view/countryChoiceView.module.scss @@ -0,0 +1,112 @@ +.countryChoice { + position: sticky; + z-index: 5; + grid-column: 1; + grid-row: 4; + transition: + opacity 0.2s, + visibility 0.2s; + + @media (max-width: 768px) { + grid-column: 1; + grid-row: 5; + } +} + +.countryItem { + padding: calc(var(--extra-small-offset) / 4) calc(var(--extra-small-offset) / 2); + font: var(--regular-font); + letter-spacing: 1px; + text-align: end; + color: var(--noble-gray-800); + transition: + color 0.2s, + background-color 0.2s; + animation: show 0.5s ease-in forwards; + cursor: pointer; + + @media (hover: hover) { + &:hover { + color: var(--steam-green-800); + background-color: var(--noble-gray-200); + } + } + + @media (max-width: 768px) { + text-align: start; + } + + &.hidden { + animation: hide 0.5s ease-in forwards; + } +} + +@keyframes hide { + 0% { + opacity: 1; + visibility: visible; + } + + 50% { + opacity: 0; + visibility: hidden; + } + + 100% { + display: none; + } +} + +@keyframes show { + 0% { + display: block; + opacity: 0; + visibility: hidden; + } + + 100% { + opacity: 1; + visibility: visible; + } +} + +.hidden { + opacity: 0; + visibility: hidden; + pointer-events: none; +} + +.countryDropList { + position: absolute; + right: 0; + overflow-y: scroll; + border: 1px solid var(--noble-gray-300); + border-radius: var(--small-br); + width: 100%; + min-height: 200px; + max-height: 200px; + background-color: var(--white); + opacity: 1; + visibility: visible; + transition: + opacity 0.2s, + visibility 0.2s; + + &::-webkit-scrollbar { + width: 8px; + } + + &::-webkit-scrollbar-track { + background: var(--noble-gray-200); + } + + &::-webkit-scrollbar-thumb { + border-radius: var(--small-br); + background-color: var(--steam-green-800); + cursor: pointer; + } +} + +.stopScroll { + overflow-y: hidden; +} diff --git a/src/features/InputFieldValidator/.gitkeep b/src/features/InputFieldValidator/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/features/InputFieldValidator/model/InputFieldValidatorModel.ts b/src/features/InputFieldValidator/model/InputFieldValidatorModel.ts new file mode 100644 index 00000000..4162c8f1 --- /dev/null +++ b/src/features/InputFieldValidator/model/InputFieldValidatorModel.ts @@ -0,0 +1,192 @@ +import type { InputFieldValidatorParams } from '@/shared/types/form'; + +import getStore from '@/shared/Store/Store.ts'; +import { LANGUAGE_CHOICE } from '@/shared/constants/buttons.ts'; +import COUNTRIES_LIST from '@/shared/constants/countriesList.ts'; +import { USER_POSTAL_CODE } from '@/shared/constants/forms.ts'; +import { ERROR_MESSAGE } from '@/shared/constants/messages.ts'; +import { postcodeValidator } from 'postcode-validator'; + +class InputFieldValidatorModel { + private isValid: boolean; + + private validParams; + + constructor(validParams: InputFieldValidatorParams, isValid: boolean) { + this.validParams = validParams; + this.isValid = isValid; + } + + private checkMaxAge(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + const today = new Date(); + const birthDate = new Date(value); + const age = today.getFullYear() - birthDate.getFullYear(); + if (this.validParams.validBirthday && age > this.validParams.validBirthday.maxAge) { + const errorMessage = + currentLanguage === LANGUAGE_CHOICE.EN + ? `You must be at most ${this.validParams.validBirthday.maxAge} years old` + : `Вам должно быть не более ${this.validParams.validBirthday.maxAge} лет`; + return errorMessage; + } + return true; + } + + private checkMaxLength(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + if (this.validParams.maxLength && value.length > this.validParams.maxLength) { + const errorMessage = + currentLanguage === LANGUAGE_CHOICE.EN + ? `Max length should not exceed ${this.validParams.maxLength}` + : `Максимальная длина не должна превышать ${this.validParams.maxLength} символов`; + return errorMessage; + } + return true; + } + + private checkMinAge(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + const today = new Date(); + const birthDate = new Date(value); + const age = today.getFullYear() - birthDate.getFullYear(); + if (this.validParams.validBirthday && age < this.validParams.validBirthday.minAge) { + const errorMessage = + currentLanguage === LANGUAGE_CHOICE.EN + ? `You must be at least ${this.validParams.validBirthday.minAge} years old` + : `Вам должно быть не менее ${this.validParams.validBirthday.minAge} лет`; + return errorMessage; + } + return true; + } + + private checkMinLength(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + if (this.validParams.minLength && value.length < this.validParams.minLength) { + const errorMessage = + currentLanguage === LANGUAGE_CHOICE.EN + ? `Min length should be at least ${this.validParams.minLength}` + : `Минимальная длина должна быть не менее ${this.validParams.minLength} символов`; + return errorMessage; + } + return true; + } + + private checkNotSpecialSymbols(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + if (this.validParams.notSpecialSymbols && !this.validParams.notSpecialSymbols.pattern.test(value)) { + const errorMessage = this.validParams.notSpecialSymbols.messages[currentLanguage]; + return errorMessage; + } + return true; + } + + private checkRequired(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + if (this.validParams.required && value.trim() === '') { + return ERROR_MESSAGE[currentLanguage].REQUIRED_FIELD; + } + return true; + } + + private checkRequiredSymbols(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + if (this.validParams.requiredSymbols && !this.validParams.requiredSymbols.pattern.test(value)) { + const errorMessage = this.validParams.requiredSymbols.messages[currentLanguage]; + return errorMessage; + } + return true; + } + + private checkValidAge(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + if (this.validParams.validBirthday && !this.validParams.validBirthday.pattern.test(value)) { + const errorMessage = this.validParams.validBirthday.messages[currentLanguage]; + return errorMessage; + } + return true; + } + + private checkValidCountry(value: string): boolean | string { + if (this.validParams.validCountry) { + const { currentLanguage } = getStore().getState(); + if ( + !Object.keys(COUNTRIES_LIST[currentLanguage]).find( + (countryName) => countryName.toLowerCase() === value.toLowerCase(), + ) + ) { + return ERROR_MESSAGE[currentLanguage].INVALID_COUNTRY; + } + } + return true; + } + + private checkValidMail(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + if (this.validParams.validMail && !this.validParams.validMail.pattern.test(value)) { + const errorMessage = this.validParams.validMail.messages[currentLanguage]; + return errorMessage; + } + return true; + } + + private checkValidPostalCode(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + if (this.validParams.validPostalCode) { + const { billingCountry, shippingCountry } = getStore().getState(); + const currentCountry = this.validParams.key === USER_POSTAL_CODE.POSTAL_CODE ? shippingCountry : billingCountry; + try { + const result = postcodeValidator(value, currentCountry); + if (!result) { + return ERROR_MESSAGE[currentLanguage].INVALID_POSTAL_CODE; + } + } catch (error) { + return ERROR_MESSAGE[currentLanguage].WRONG_REGION; + } + } + return true; + } + + private checkWhitespace(value: string): boolean | string { + const { currentLanguage } = getStore().getState(); + if (this.validParams.notWhitespace && !this.validParams.notWhitespace.pattern.test(value)) { + const errorMessage = this.validParams.notWhitespace.messages[currentLanguage]; + return errorMessage; + } + + return true; + } + + public validate(value: string): boolean | string[] { + const errors = [ + this.checkRequired(value), + this.checkRequired(value), + this.checkWhitespace(value), + this.checkNotSpecialSymbols(value), + this.checkMinLength(value), + this.checkMaxLength(value), + this.checkRequiredSymbols(value), + this.checkValidMail(value), + this.checkValidAge(value), + this.checkMinAge(value), + this.checkMaxAge(value), + this.checkValidCountry(value), + this.checkValidPostalCode(value), + ]; + + const errorMessages: string[] = []; + errors.forEach((error) => { + if (typeof error === 'string') { + errorMessages.push(error); + } + }); + + if (errorMessages.length) { + return errorMessages; + } + + this.isValid = true; + return this.isValid; + } +} + +export default InputFieldValidatorModel; diff --git a/src/features/InputFieldValidator/test/InputFieldValidator.spec.ts b/src/features/InputFieldValidator/test/InputFieldValidator.spec.ts new file mode 100644 index 00000000..275ed8f4 --- /dev/null +++ b/src/features/InputFieldValidator/test/InputFieldValidator.spec.ts @@ -0,0 +1,35 @@ +import type { InputFieldValidatorParams } from '@/shared/types/form'; + +import InputFieldValidatorModel from '../model/InputFieldValidatorModel.ts'; + +const validatorParams: InputFieldValidatorParams = { + key: '', + maxLength: 10, + minLength: 2, + notSpecialSymbols: { + messages: { + en: 'Not special symbols', + ru: 'Не специальные символы', + }, + pattern: /[a-zA-Z0-9]/, + }, + notWhitespace: { + messages: { + en: 'Not white spaces', + ru: 'Не пробелы', + }, + pattern: /\S/, + }, +}; + +const validator = new InputFieldValidatorModel(validatorParams, true); + +describe('Checking InputFieldValidatorModel', () => { + it('InputFieldValidatorModel instance should be defined', () => { + expect(InputFieldValidatorModel).toBeDefined(); + }); + + it('should return true', () => { + expect(validator.validate('test')).toStrictEqual(true); + }); +}); diff --git a/src/global.d.ts b/src/global.d.ts index b90c0e68..f4364473 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -25,5 +25,9 @@ interface ImportMeta { VITE_APP_CTP_PROJECT_KEY: string; VITE_APP_CTP_REGION: string; VITE_APP_CTP_SCOPES: string; + VITE_APP_DEFAULT_SEGMENT: string; + VITE_APP_NEXT_SEGMENT: number; + VITE_APP_PATH_SEGMENTS_TO_KEEP: number; + VITE_APP_PROJECT_TITLE: string; }; } diff --git a/src/main.ts b/src/main.ts index 55c91530..a827903a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1 +1,5 @@ +import AppModel from '@/app/App/model/AppModel.ts'; import '@/styles.scss'; + +const myApp = new AppModel(); +document.body.append(myApp.getHTML()); diff --git a/src/pages/LoginPage/.gitkeep b/src/pages/LoginPage/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/pages/LoginPage/model/LoginPageModel.ts b/src/pages/LoginPage/model/LoginPageModel.ts new file mode 100644 index 00000000..6f6f0315 --- /dev/null +++ b/src/pages/LoginPage/model/LoginPageModel.ts @@ -0,0 +1,81 @@ +import type RouterModel from '@/app/Router/model/RouterModel.ts'; +import type { Page } from '@/shared/types/common.ts'; + +import EventMediatorModel from '@/shared/EventMediator/model/EventMediatorModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { EVENT_NAME, MEDIATOR_EVENT } from '@/shared/constants/events.ts'; +import { PAGE_ID, PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS } from '@/shared/constants/pages.ts'; +import observeCurrentLanguage from '@/shared/utils/observeCurrentLanguage.ts'; +import LoginFormModel from '@/widgets/LoginForm/model/LoginFormModel.ts'; + +import LoginPageView from '../view/LoginPageView.ts'; + +class LoginPageModel implements Page { + private eventMediator = EventMediatorModel.getInstance(); + + private loginForm = new LoginFormModel(); + + private router: RouterModel; + + private view: LoginPageView; + + constructor(parent: HTMLDivElement, router: RouterModel) { + this.router = router; + this.view = new LoginPageView(parent); + this.init(); + } + + private checkAuthUser(): boolean { + if (!getStore().getState().currentUser) { + this.view.show(); + this.loginForm.getFirstInputField().getView().getInput().getHTML().focus(); + return false; + } + this.router.navigateTo(PAGE_ID.MAIN_PAGE); + return true; + } + + private init(): boolean { + this.subscribeToEventMediator(); + this.view.getAuthWrapper().append(this.loginForm.getHTML()); + this.setRegisterLinkHandler(); + return true; + } + + private registerLinkHandler(event: Event): void { + event.preventDefault(); + this.router.navigateTo(PAGE_ID.REGISTRATION_PAGE); + } + + private setRegisterLinkHandler(): void { + const toRegisterPageWrapper = this.view.getToRegisterPageWrapper(); + const registerLink = this.view.getRegisterLink().getHTML(); + const registerLinkCopy = registerLink.cloneNode(true); + + observeCurrentLanguage(registerLinkCopy, PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS.REGISTRATION); + + registerLink.addEventListener(EVENT_NAME.CLICK, (event) => this.registerLinkHandler(event)); + registerLinkCopy.addEventListener(EVENT_NAME.CLICK, (event) => this.registerLinkHandler(event)); + toRegisterPageWrapper.append(registerLinkCopy); + } + + private subscribeToEventMediator(): void { + this.eventMediator.subscribe(MEDIATOR_EVENT.CHANGE_PAGE, (route) => this.switchPageVisibility(route)); + } + + private switchPageVisibility(route: unknown): boolean { + if (route === PAGE_ID.LOGIN_PAGE) { + this.checkAuthUser(); + } else { + this.view.hide(); + return false; + } + return true; + } + + public getHTML(): HTMLDivElement { + return this.view.getHTML(); + } +} + +export default LoginPageModel; diff --git a/src/pages/LoginPage/view/LoginPageView.ts b/src/pages/LoginPage/view/LoginPageView.ts new file mode 100644 index 00000000..eb921856 --- /dev/null +++ b/src/pages/LoginPage/view/LoginPageView.ts @@ -0,0 +1,161 @@ +import LinkModel from '@/shared/Link/model/LinkModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { PAGE_TIMEOUT_DURATION } from '@/shared/constants/animations.ts'; +import { + PAGE_ANSWER, + PAGE_ANSWER_KEYS, + PAGE_DESCRIPTION, + PAGE_DESCRIPTION_KEYS, + PAGE_ID, + PAGE_LINK_TEXT, + PAGE_LINK_TEXT_KEYS, +} from '@/shared/constants/pages.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; +import observeCurrentLanguage from '@/shared/utils/observeCurrentLanguage.ts'; + +import styles from './loginPageView.module.scss'; + +class LoginPageView { + private authDescription: HTMLHeadingElement; + + private authWrapper: HTMLDivElement; + + private linksWrapper: HTMLDivElement; + + private loginSpan: HTMLSpanElement; + + private page: HTMLDivElement; + + private parent: HTMLDivElement; + + private registerLink: LinkModel; + + private toRegisterPageWrapper: HTMLSpanElement; + + constructor(parent: HTMLDivElement) { + this.parent = parent; + this.toRegisterPageWrapper = this.createToRegisterPageWrapper(); + this.loginSpan = this.createLoginSpan(); + this.registerLink = this.createRegisterLink(); + this.authDescription = this.createAuthDescription(); + this.linksWrapper = this.createLinksWrapper(); + this.authWrapper = this.createAuthWrapper(); + this.page = this.createHTML(); + } + + private createAuthDescription(): HTMLHeadingElement { + const { currentLanguage } = getStore().getState(); + this.authDescription = createBaseElement({ + cssClasses: [styles.authDescription], + innerContent: PAGE_DESCRIPTION[currentLanguage].LOGIN, + tag: TAG_NAME.H3, + }); + + observeCurrentLanguage(this.authDescription, PAGE_DESCRIPTION, PAGE_DESCRIPTION_KEYS.LOGIN); + + return this.authDescription; + } + + private createAuthWrapper(): HTMLDivElement { + this.authWrapper = createBaseElement({ + cssClasses: [styles.authWrapper], + tag: TAG_NAME.DIV, + }); + + this.authWrapper.append(this.linksWrapper, this.authDescription, this.createToRegisterPageWrapper()); + return this.authWrapper; + } + + private createHTML(): HTMLDivElement { + this.page = createBaseElement({ + cssClasses: [styles.loginPage], + tag: TAG_NAME.DIV, + }); + + this.page.append(this.authWrapper); + this.parent.append(this.page); + + return this.page; + } + + private createLinksWrapper(): HTMLDivElement { + this.linksWrapper = createBaseElement({ + cssClasses: [styles.linksWrapper], + tag: TAG_NAME.DIV, + }); + + this.linksWrapper.append(this.loginSpan, this.registerLink.getHTML()); + return this.linksWrapper; + } + + private createLoginSpan(): HTMLSpanElement { + const { currentLanguage } = getStore().getState(); + this.loginSpan = createBaseElement({ + cssClasses: [styles.loginSpan], + innerContent: PAGE_LINK_TEXT[currentLanguage].LOGIN, + tag: TAG_NAME.SPAN, + }); + + observeCurrentLanguage(this.loginSpan, PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS.LOGIN); + + return this.loginSpan; + } + + private createRegisterLink(): LinkModel { + const { currentLanguage } = getStore().getState(); + this.registerLink = new LinkModel({ + attrs: { + href: PAGE_ID.REGISTRATION_PAGE, + }, + classes: [styles.registerLink], + text: PAGE_LINK_TEXT[currentLanguage].REGISTRATION, + }); + + observeCurrentLanguage(this.registerLink.getHTML(), PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS.REGISTRATION); + + return this.registerLink; + } + + private createToRegisterPageWrapper(): HTMLSpanElement { + const { currentLanguage } = getStore().getState(); + this.toRegisterPageWrapper = createBaseElement({ + cssClasses: [styles.toRegisterPageWrapper], + innerContent: PAGE_ANSWER[currentLanguage].LOGIN, + tag: TAG_NAME.SPAN, + }); + + observeCurrentLanguage(this.toRegisterPageWrapper, PAGE_ANSWER, PAGE_ANSWER_KEYS.LOGIN); + + return this.toRegisterPageWrapper; + } + + public getAuthWrapper(): HTMLDivElement { + return this.authWrapper; + } + + public getHTML(): HTMLDivElement { + return this.page; + } + + public getRegisterLink(): LinkModel { + return this.registerLink; + } + + public getToRegisterPageWrapper(): HTMLSpanElement { + return this.toRegisterPageWrapper; + } + + public hide(): boolean { + this.page.classList.add(styles.loginPage_hidden); + return true; + } + + public show(): boolean { + setTimeout(() => { + this.page.classList.remove(styles.loginPage_hidden); + }, PAGE_TIMEOUT_DURATION); + return true; + } +} +export default LoginPageView; diff --git a/src/pages/LoginPage/view/loginPageView.module.scss b/src/pages/LoginPage/view/loginPageView.module.scss new file mode 100644 index 00000000..9ff6899b --- /dev/null +++ b/src/pages/LoginPage/view/loginPageView.module.scss @@ -0,0 +1,136 @@ +.loginPage { + position: relative; + display: block; + padding: 0 var(--small-offset); + animation: show 0.2s ease-out forwards; + + &_hidden { + animation: hide 0.2s ease-in forwards; + } +} + +@keyframes show { + 0% { + opacity: 0; + } + + 100% { + display: block; + opacity: 1; + } +} + +@keyframes hide { + 0% { + opacity: 1; + } + + 100% { + display: none; + opacity: 0; + } +} + +.authWrapper { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(4, max-content); + margin: 0 auto; + border-bottom: 10px solid var(--steam-green-800); + border-radius: var(--medium-br); + padding: calc(var(--extra-large-offset) / 2) var(--extra-large-offset); + max-width: 500px; + background-color: var(--white); +} + +.linksWrapper { + position: relative; + display: flex; + align-self: center; + justify-content: space-between; + grid-column: 2 span; + grid-row: 1; + margin: 0 auto; + margin-bottom: calc(var(--extra-large-offset) / 2); + width: 100%; + max-width: 160px; + + &::after { + content: ''; + position: absolute; + right: calc(50% - 3px); + top: 50%; + width: 3px; + height: 16px; + background-color: var(--noble-gray-800); + transform: translate(calc(-50% - 14px), -50%); + } +} + +.loginSpan, +.registerLink { + font: var(--medium-font); + letter-spacing: 1px; +} + +.loginSpan { + color: var(--steam-green-800); +} + +.registerLink { + position: relative; + color: var(--noble-gray-800); + transition: color 0.2s; + + &::after { + content: ''; + position: absolute; + left: 0; + bottom: -4px; + width: 100%; + height: 2px; + background-color: currentcolor; + opacity: 0; + transform: scaleX(0); + transform-origin: center; + transition: + transform 0.2s, + opacity 0.2s; + } + + @media (hover: hover) { + &:hover { + color: var(--steam-green-800); + + &::after { + opacity: 1; + transform: scaleX(1); + } + } + } +} + +.authDescription { + grid-column: 2 span; + grid-row: 2; + margin-bottom: calc(var(--extra-small-offset) / 2); + font: var(--regular-font); + letter-spacing: 1px; + text-align: center; +} + +.toRegisterPageWrapper { + display: flex; + justify-content: center; + grid-column: 2 span; + grid-row: 4; + font: var(--regular-font); + text-align: center; + color: var(--steam-green-800); + gap: calc(var(--extra-small-offset) / 4); + + a { + margin-right: 0; + font: var(--regular-font); + } +} diff --git a/src/pages/MainPage/.gitkeep b/src/pages/MainPage/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/pages/MainPage/model/MainPageModel.ts b/src/pages/MainPage/model/MainPageModel.ts new file mode 100644 index 00000000..75454894 --- /dev/null +++ b/src/pages/MainPage/model/MainPageModel.ts @@ -0,0 +1,55 @@ +import type RouterModel from '@/app/Router/model/RouterModel.ts'; +import type { Page } from '@/shared/types/common.ts'; + +import EventMediatorModel from '@/shared/EventMediator/model/EventMediatorModel.ts'; +import observeStore, { selectCurrentUser } from '@/shared/Store/observer.ts'; +import { MEDIATOR_EVENT } from '@/shared/constants/events.ts'; +import { PAGE_ID } from '@/shared/constants/pages.ts'; + +import MainPageView from '../view/MainPageView.ts'; + +class MainPageModel implements Page { + private eventMediator = EventMediatorModel.getInstance(); + + private router: RouterModel; + + private view: MainPageView; + + constructor(parent: HTMLDivElement, router: RouterModel) { + this.router = router; + this.view = new MainPageView(parent); + this.init(); + } + + private init(): void { + this.subscribeToEventMediator(); + this.subscribeToStore(); + } + + private subscribeToEventMediator(): void { + this.eventMediator.subscribe(MEDIATOR_EVENT.CHANGE_PAGE, (route) => this.switchPageVisibility(route)); + } + + private subscribeToStore(): boolean { + observeStore(selectCurrentUser, () => { + this.router.navigateTo(PAGE_ID.MAIN_PAGE); + }); + return true; + } + + private switchPageVisibility(route: unknown): boolean { + if (route === PAGE_ID.MAIN_PAGE || route === PAGE_ID.DEFAULT_PAGE) { + this.view.show(); + } else { + this.view.hide(); + return false; + } + return true; + } + + public getHTML(): HTMLDivElement { + return this.view.getHTML(); + } +} + +export default MainPageModel; diff --git a/src/pages/MainPage/view/MainPageView.ts b/src/pages/MainPage/view/MainPageView.ts new file mode 100644 index 00000000..3cda999f --- /dev/null +++ b/src/pages/MainPage/view/MainPageView.ts @@ -0,0 +1,44 @@ +import { PAGE_TIMEOUT_DURATION } from '@/shared/constants/animations.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; + +import styles from './mainPageView.module.scss'; + +class MainPageView { + private page: HTMLDivElement; + + private parent: HTMLDivElement; + + constructor(parent: HTMLDivElement) { + this.parent = parent; + this.page = this.createHTML(); + } + + private createHTML(): HTMLDivElement { + this.page = createBaseElement({ + cssClasses: [styles.mainPage], + tag: TAG_NAME.DIV, + }); + + this.parent.append(this.page); + + return this.page; + } + + public getHTML(): HTMLDivElement { + return this.page; + } + + public hide(): boolean { + this.page.classList.add(styles.mainPage_hidden); + return true; + } + + public show(): boolean { + setTimeout(() => { + this.page.classList.remove(styles.mainPage_hidden); + }, PAGE_TIMEOUT_DURATION); + return true; + } +} +export default MainPageView; diff --git a/src/pages/MainPage/view/mainPageView.module.scss b/src/pages/MainPage/view/mainPageView.module.scss new file mode 100644 index 00000000..df1156b7 --- /dev/null +++ b/src/pages/MainPage/view/mainPageView.module.scss @@ -0,0 +1,32 @@ +.mainPage { + position: relative; + display: block; + padding: 0 var(--small-offset); + animation: show 0.2s ease-out forwards; + + &_hidden { + animation: hide 0.2s ease-in forwards; + } +} + +@keyframes show { + 0% { + opacity: 0; + } + + 100% { + display: block; + opacity: 1; + } +} + +@keyframes hide { + 0% { + opacity: 1; + } + + 100% { + display: none; + opacity: 0; + } +} diff --git a/src/pages/NotFoundPage/.gitkeep b/src/pages/NotFoundPage/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/pages/NotFoundPage/model/NotFoundPageModel.ts b/src/pages/NotFoundPage/model/NotFoundPageModel.ts new file mode 100644 index 00000000..619f32cc --- /dev/null +++ b/src/pages/NotFoundPage/model/NotFoundPageModel.ts @@ -0,0 +1,74 @@ +import type RouterModel from '@/app/Router/model/RouterModel.ts'; +import type { Page } from '@/shared/types/common.ts'; + +import EventMediatorModel from '@/shared/EventMediator/model/EventMediatorModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import observeStore, { selectCurrentLanguage } from '@/shared/Store/observer.ts'; +import { EVENT_NAME, MEDIATOR_EVENT } from '@/shared/constants/events.ts'; +import { PAGE_DESCRIPTION, PAGE_ID } from '@/shared/constants/pages.ts'; + +import NotFoundPageView from '../view/NotFoundPageView.ts'; + +class NotFoundPageModel implements Page { + private eventMediator = EventMediatorModel.getInstance(); + + private router: RouterModel; + + private view: NotFoundPageView; + + constructor(parent: HTMLDivElement, router: RouterModel) { + this.view = new NotFoundPageView(parent); + this.router = router; + this.init(); + } + + private createPageDescription(): string { + const { currentLanguage, currentUser } = getStore().getState(); + const { GREETING } = PAGE_DESCRIPTION[currentLanguage]; + const textDescription = currentUser + ? `${GREETING}${currentUser.firstName}. ${PAGE_DESCRIPTION[currentLanguage][404]}` + : PAGE_DESCRIPTION[currentLanguage][404]; + return textDescription; + } + + private init(): boolean { + this.subscribeToEventMediator(); + this.toMainButtonHandler(); + this.observeStoreLanguage(); + return true; + } + + private observeStoreLanguage(): boolean { + observeStore(selectCurrentLanguage, () => { + this.view.setPageDescription(this.createPageDescription()); + }); + return true; + } + + private subscribeToEventMediator(): void { + this.eventMediator.subscribe(MEDIATOR_EVENT.CHANGE_PAGE, (route) => this.switchPageVisibility(route)); + } + + private switchPageVisibility(route: unknown): boolean { + if (route === PAGE_ID.NOT_FOUND_PAGE) { + this.view.show(); + this.view.setPageDescription(this.createPageDescription()); + } else { + this.view.hide(); + return false; + } + return true; + } + + private toMainButtonHandler(): boolean { + const toMainButton = this.view.getToMainButton().getHTML(); + toMainButton.addEventListener(EVENT_NAME.CLICK, this.router.navigateTo.bind(this.router, PAGE_ID.MAIN_PAGE)); + return true; + } + + public getHTML(): HTMLDivElement { + return this.view.getHTML(); + } +} + +export default NotFoundPageModel; diff --git a/src/pages/NotFoundPage/view/NotFoundPageView.ts b/src/pages/NotFoundPage/view/NotFoundPageView.ts new file mode 100644 index 00000000..07830405 --- /dev/null +++ b/src/pages/NotFoundPage/view/NotFoundPageView.ts @@ -0,0 +1,109 @@ +import ButtonModel from '@/shared/Button/model/ButtonModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { PAGE_TIMEOUT_DURATION } from '@/shared/constants/animations.ts'; +import { BUTTON_TEXT, BUTTON_TEXT_KEYS } from '@/shared/constants/buttons.ts'; +import { PAGE_DESCRIPTION_KEYS } from '@/shared/constants/pages.ts'; +import SVG_DETAILS from '@/shared/constants/svg.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; +import createSVGUse from '@/shared/utils/createSVGUse.ts'; +import observeCurrentLanguage from '@/shared/utils/observeCurrentLanguage.ts'; + +import styles from './notFoundPageView.module.scss'; + +class NotFoundPageView { + private description: HTMLParagraphElement; + + private logo: HTMLDivElement; + + private page: HTMLDivElement; + + private parent: HTMLDivElement; + + private title: HTMLHeadingElement; + + private toMainButton: ButtonModel; + + constructor(parent: HTMLDivElement) { + this.parent = parent; + this.logo = this.createPageLogo(); + this.title = this.createPageTitle(); + this.description = this.createPageDescription(); + this.toMainButton = this.createToMainButton(); + this.page = this.createHTML(); + } + + private createHTML(): HTMLDivElement { + this.page = createBaseElement({ + cssClasses: [styles.notFoundPage], + tag: TAG_NAME.DIV, + }); + + this.page.append(this.logo, this.title, this.description, this.toMainButton.getHTML()); + this.parent.append(this.page); + + return this.page; + } + + private createPageDescription(): HTMLParagraphElement { + this.description = createBaseElement({ + cssClasses: [styles.pageDescription], + tag: TAG_NAME.P, + }); + return this.description; + } + + private createPageLogo(): HTMLDivElement { + this.logo = createBaseElement({ cssClasses: [styles.pageLogo], tag: TAG_NAME.DIV }); + const svg = document.createElementNS(SVG_DETAILS.SVG_URL, TAG_NAME.SVG); + svg.append(createSVGUse(SVG_DETAILS.LOGO)); + this.logo.append(svg); + return this.logo; + } + + private createPageTitle(): HTMLHeadingElement { + this.title = createBaseElement({ + cssClasses: [styles.pageTitle], + innerContent: PAGE_DESCRIPTION_KEYS[404], + tag: TAG_NAME.H1, + }); + return this.title; + } + + private createToMainButton(): ButtonModel { + const { currentLanguage } = getStore().getState(); + this.toMainButton = new ButtonModel({ + classes: [styles.toMainButton], + text: BUTTON_TEXT[currentLanguage].BACK_TO_MAIN, + }); + observeCurrentLanguage(this.toMainButton.getHTML(), BUTTON_TEXT, BUTTON_TEXT_KEYS.BACK_TO_MAIN); + return this.toMainButton; + } + + public getHTML(): HTMLDivElement { + return this.page; + } + + public getToMainButton(): ButtonModel { + return this.toMainButton; + } + + public hide(): boolean { + this.page.classList.add(styles.notFoundPage_hidden); + return true; + } + + public setPageDescription(text: string): HTMLParagraphElement { + this.description.innerText = text; + return this.description; + } + + public show(): boolean { + setTimeout(() => { + this.page.classList.remove(styles.notFoundPage_hidden); + }, PAGE_TIMEOUT_DURATION); + return true; + } +} + +export default NotFoundPageView; diff --git a/src/pages/NotFoundPage/view/notFoundPageView.module.scss b/src/pages/NotFoundPage/view/notFoundPageView.module.scss new file mode 100644 index 00000000..e3fcc2af --- /dev/null +++ b/src/pages/NotFoundPage/view/notFoundPageView.module.scss @@ -0,0 +1,87 @@ +.notFoundPage { + position: relative; + display: flex; + flex-direction: column; + margin: 0 auto; + border-bottom: calc(var(--extra-small-offset) / 2) solid var(--steam-green-800); + padding: calc(var(--extra-large-offset) / 2) var(--extra-large-offset); + padding-bottom: calc(var(--extra-large-offset) / 2 + calc(var(--extra-small-offset) / 2)); + max-width: 500px; + background-color: var(--white); + animation: show 0.2s ease-out forwards; + gap: var(--extra-small-offset); + + &_hidden { + animation: hide 0.2s ease-in forwards; + } +} + +@keyframes show { + 0% { + opacity: 0; + } + + 100% { + display: flex; + opacity: 1; + } +} + +@keyframes hide { + 0% { + opacity: 1; + } + + 100% { + display: none; + opacity: 0; + } +} + +.pageLogo { + display: flex; + margin: 0 auto; + + svg { + width: var(--large-offset); + height: var(--large-offset); + fill: var(--steam-green-800); + } +} + +.pageTitle { + display: flex; + margin: 0 auto; + font: var(--extra-medium-font); + letter-spacing: 1px; + color: var(--steam-green-800); +} + +.pageDescription { + font: var(--regular-font) '*' 1.5; + letter-spacing: 1px; + text-align: center; + color: var(--noble-gray-700); +} + +.toMainButton { + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 2) var(--small-offset); + font: var(--bold-font); + letter-spacing: 1px; + color: var(--white); + background-color: var(--steam-green-800); + transition: + color 0.2s, + background-color 0.2s; + + &:focus { + background-color: var(--steam-green-700); + } + + @media (hover: hover) { + &:hover { + background-color: var(--steam-green-700); + } + } +} diff --git a/src/pages/RegistrationPage/.gitkeep b/src/pages/RegistrationPage/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/pages/RegistrationPage/model/RegistrationPageModel.ts b/src/pages/RegistrationPage/model/RegistrationPageModel.ts new file mode 100644 index 00000000..670c6c9d --- /dev/null +++ b/src/pages/RegistrationPage/model/RegistrationPageModel.ts @@ -0,0 +1,70 @@ +import type RouterModel from '@/app/Router/model/RouterModel.ts'; +import type { Page } from '@/shared/types/common.ts'; + +import EventMediatorModel from '@/shared/EventMediator/model/EventMediatorModel.ts'; +import { EVENT_NAME, MEDIATOR_EVENT } from '@/shared/constants/events.ts'; +import { PAGE_ID, PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS } from '@/shared/constants/pages.ts'; +import observeCurrentLanguage from '@/shared/utils/observeCurrentLanguage.ts'; +import RegisterFormModel from '@/widgets/RegistrationForm/model/RegistrationFormModel.ts'; + +import RegistrationPageView from '../view/RegistrationPageView.ts'; + +class RegistrationPageModel implements Page { + private eventMediator = EventMediatorModel.getInstance(); + + private registerForm = new RegisterFormModel(); + + private router: RouterModel; + + private view: RegistrationPageView; + + constructor(parent: HTMLDivElement, router: RouterModel) { + this.view = new RegistrationPageView(parent); + this.router = router; + this.init(); + } + + private init(): void { + this.view.getAuthWrapper().append(this.registerForm.getHTML()); + this.subscribeToEventMediator(); + this.setLoginLinkHandler(); + } + + private loginLinkHandler(event: Event): void { + event.preventDefault(); + this.router.navigateTo(PAGE_ID.LOGIN_PAGE); + } + + private setLoginLinkHandler(): void { + const toLoginPageWrapper = this.view.getToLoginPageWrapper(); + const loginLink = this.view.getLoginLink().getHTML(); + const loginLinkCopy = loginLink.cloneNode(true); + + observeCurrentLanguage(loginLinkCopy, PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS.LOGIN); + + loginLink.addEventListener(EVENT_NAME.CLICK, (event) => this.loginLinkHandler(event)); + loginLinkCopy.addEventListener(EVENT_NAME.CLICK, (event) => this.loginLinkHandler(event)); + toLoginPageWrapper.append(loginLinkCopy); + } + + private subscribeToEventMediator(): void { + this.eventMediator.subscribe(MEDIATOR_EVENT.CHANGE_PAGE, (route) => this.switchPageVisibility(route)); + } + + private switchPageVisibility(route: unknown): boolean { + if (route === PAGE_ID.REGISTRATION_PAGE) { + this.view.show(); + this.registerForm.getFirstInputField().getView().getInput().getHTML().focus(); + } else { + this.view.hide(); + return false; + } + return true; + } + + public getHTML(): HTMLDivElement { + return this.view.getHTML(); + } +} + +export default RegistrationPageModel; diff --git a/src/pages/RegistrationPage/view/RegistrationPageView.ts b/src/pages/RegistrationPage/view/RegistrationPageView.ts new file mode 100644 index 00000000..027b3634 --- /dev/null +++ b/src/pages/RegistrationPage/view/RegistrationPageView.ts @@ -0,0 +1,161 @@ +import LinkModel from '@/shared/Link/model/LinkModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { PAGE_TIMEOUT_DURATION } from '@/shared/constants/animations.ts'; +import { + PAGE_ANSWER, + PAGE_ANSWER_KEYS, + PAGE_DESCRIPTION, + PAGE_DESCRIPTION_KEYS, + PAGE_ID, + PAGE_LINK_TEXT, + PAGE_LINK_TEXT_KEYS, +} from '@/shared/constants/pages.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; +import observeCurrentLanguage from '@/shared/utils/observeCurrentLanguage.ts'; + +import styles from './registrationPageView.module.scss'; + +class RegistrationPageView { + private authDescription: HTMLHeadingElement; + + private authWrapper: HTMLDivElement; + + private linksWrapper: HTMLDivElement; + + private loginLink: LinkModel; + + private page: HTMLDivElement; + + private parent: HTMLDivElement; + + private registerSpan: HTMLSpanElement; + + private toLoginPageWrapper: HTMLSpanElement; + + constructor(parent: HTMLDivElement) { + this.parent = parent; + this.toLoginPageWrapper = this.createToLoginPageWrapper(); + this.registerSpan = this.createRegisterSpan(); + this.loginLink = this.createLoginLink(); + this.authDescription = this.createAuthDescription(); + this.linksWrapper = this.createLinksWrapper(); + this.authWrapper = this.createAuthWrapper(); + this.page = this.createHTML(); + } + + private createAuthDescription(): HTMLHeadingElement { + const { currentLanguage } = getStore().getState(); + this.authDescription = createBaseElement({ + cssClasses: [styles.authDescription], + innerContent: PAGE_DESCRIPTION[currentLanguage].REGISTRATION, + tag: TAG_NAME.H3, + }); + + observeCurrentLanguage(this.authDescription, PAGE_DESCRIPTION, PAGE_DESCRIPTION_KEYS.REGISTRATION); + + return this.authDescription; + } + + private createAuthWrapper(): HTMLDivElement { + this.authWrapper = createBaseElement({ + cssClasses: [styles.authWrapper], + tag: TAG_NAME.DIV, + }); + + this.authWrapper.append(this.linksWrapper, this.authDescription, this.toLoginPageWrapper); + return this.authWrapper; + } + + private createHTML(): HTMLDivElement { + this.page = createBaseElement({ + cssClasses: [styles.registrationPage], + tag: TAG_NAME.DIV, + }); + + this.page.append(this.authWrapper); + this.parent.append(this.page); + + return this.page; + } + + private createLinksWrapper(): HTMLDivElement { + this.linksWrapper = createBaseElement({ + cssClasses: [styles.linksWrapper], + tag: TAG_NAME.DIV, + }); + + this.linksWrapper.append(this.loginLink.getHTML(), this.registerSpan); + return this.linksWrapper; + } + + private createLoginLink(): LinkModel { + const { currentLanguage } = getStore().getState(); + this.loginLink = new LinkModel({ + attrs: { + href: PAGE_ID.LOGIN_PAGE, + }, + classes: [styles.loginLink], + text: PAGE_LINK_TEXT[currentLanguage].LOGIN, + }); + + observeCurrentLanguage(this.loginLink.getHTML(), PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS.LOGIN); + + return this.loginLink; + } + + private createRegisterSpan(): HTMLSpanElement { + const { currentLanguage } = getStore().getState(); + this.registerSpan = createBaseElement({ + cssClasses: [styles.registerSpan], + innerContent: PAGE_LINK_TEXT[currentLanguage].REGISTRATION, + tag: TAG_NAME.SPAN, + }); + + observeCurrentLanguage(this.registerSpan, PAGE_LINK_TEXT, PAGE_LINK_TEXT_KEYS.REGISTRATION); + + return this.registerSpan; + } + + private createToLoginPageWrapper(): HTMLSpanElement { + const { currentLanguage } = getStore().getState(); + this.toLoginPageWrapper = createBaseElement({ + cssClasses: [styles.toLoginPageWrapper], + innerContent: PAGE_ANSWER[currentLanguage].REGISTRATION, + tag: TAG_NAME.SPAN, + }); + + observeCurrentLanguage(this.toLoginPageWrapper, PAGE_ANSWER, PAGE_ANSWER_KEYS.REGISTRATION); + + return this.toLoginPageWrapper; + } + + public getAuthWrapper(): HTMLDivElement { + return this.authWrapper; + } + + public getHTML(): HTMLDivElement { + return this.page; + } + + public getLoginLink(): LinkModel { + return this.loginLink; + } + + public getToLoginPageWrapper(): HTMLSpanElement { + return this.toLoginPageWrapper; + } + + public hide(): boolean { + this.page.classList.add(styles.registrationPage_hidden); + return true; + } + + public show(): boolean { + setTimeout(() => { + this.page.classList.remove(styles.registrationPage_hidden); + }, PAGE_TIMEOUT_DURATION); + return true; + } +} +export default RegistrationPageView; diff --git a/src/pages/RegistrationPage/view/registrationPageView.module.scss b/src/pages/RegistrationPage/view/registrationPageView.module.scss new file mode 100644 index 00000000..4123d6a2 --- /dev/null +++ b/src/pages/RegistrationPage/view/registrationPageView.module.scss @@ -0,0 +1,141 @@ +.registrationPage { + position: relative; + display: block; + padding: 0 var(--small-offset); + animation: show 0.2s ease-out forwards; + + &_hidden { + animation: hide 0.2s ease-in forwards; + } +} + +@keyframes show { + 0% { + opacity: 0; + } + + 100% { + display: block; + opacity: 1; + } +} + +@keyframes hide { + 0% { + opacity: 1; + } + + 100% { + display: none; + opacity: 0; + } +} + +.authWrapper { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(4, max-content); + margin: 0 auto; + border-bottom: 10px solid var(--steam-green-800); + border-radius: var(--medium-br); + padding: calc(var(--large-offset) / 2) var(--small-offset); + background-color: var(--white); +} + +.linksWrapper { + position: relative; + display: flex; + align-self: center; + justify-content: space-between; + grid-column: 2 span; + grid-row: 1; + margin: 0 auto; + margin-bottom: calc(var(--large-offset) / 2); + width: max-content; + + &::after { + content: ''; + position: absolute; + right: calc(36% - 3px); + top: 50%; + width: 3px; + height: 16px; + background-color: var(--noble-gray-800); + transform: translate(calc(-50% - 14px), -50%); + } + + @media (max-width: 768px) { + margin: 0 auto; + margin-bottom: calc(var(--large-offset) / 2); + } +} + +.loginLink, +.registerSpan { + font: var(--medium-font); + letter-spacing: 1px; +} + +.registerSpan { + margin-left: 10%; + color: var(--steam-green-800); +} + +.loginLink { + position: relative; + margin-right: 20%; + color: var(--noble-gray-800); + transition: color 0.2s; + + &::after { + content: ''; + position: absolute; + left: 0; + bottom: -4px; + width: 100%; + height: 2px; + background-color: currentcolor; + opacity: 0; + transform: scaleX(0); + transform-origin: center; + transition: + transform 0.2s, + opacity 0.2s; + } + + @media (hover: hover) { + &:hover { + color: var(--steam-green-800); + + &::after { + opacity: 1; + transform: scaleX(1); + } + } + } +} + +.authDescription { + grid-column: 2 span; + grid-row: 2; + margin-bottom: var(--extra-small-offset); + font: var(--regular-font); + letter-spacing: 1px; + text-align: center; +} + +.toLoginPageWrapper { + display: flex; + justify-content: center; + grid-column: 2 span; + grid-row: 4; + font: var(--regular-font); + text-align: center; + color: var(--steam-green-800); + gap: calc(var(--extra-small-offset) / 4); + + a { + margin-right: 0; + font: var(--regular-font); + } +} diff --git a/src/shared/API/customer/model/CustomerModel.ts b/src/shared/API/customer/model/CustomerModel.ts new file mode 100644 index 00000000..5e972cb6 --- /dev/null +++ b/src/shared/API/customer/model/CustomerModel.ts @@ -0,0 +1,216 @@ +import type { Address, User, UserLoginData } from '@/shared/types/user.ts'; +import type { + Address as AddressResponse, + BaseAddress, + ClientResponse, + Customer, + CustomerPagedQueryResponse, + CustomerSignInResult, + CustomerUpdateAction, +} from '@commercetools/platform-sdk'; + +import getRoot, { type RootApi } from '../../sdk/root.ts'; +import { + isClientResponse, + isCustomerPagedQueryResponse, + isCustomerResponse, + isCustomerSignInResultResponse, +} from '../../types/validation.ts'; + +export class CustomerModel { + private root: RootApi; + + constructor() { + this.root = getRoot(); + } + + public static actionAddAddress(address: Address): CustomerUpdateAction { + return { action: 'addAddress', address: CustomerModel.adaptAddressToServer(address) }; + } + + public static actionEditAddress(address: Address): CustomerUpdateAction { + return { action: 'changeAddress', address: CustomerModel.adaptAddressToServer(address), addressId: address.id }; + } + + public static actionEditDateOfBirth(dateOfBirth: string): CustomerUpdateAction { + return { action: 'setDateOfBirth', dateOfBirth }; + } + + public static actionEditDefaultBillingAddress(addressId: string): CustomerUpdateAction { + return { action: 'setDefaultBillingAddress', addressId }; + } + + public static actionEditDefaultShippingAddress(addressId: string): CustomerUpdateAction { + return { action: 'setDefaultShippingAddress', addressId }; + } + + public static actionEditEmail(email: string): CustomerUpdateAction { + return { action: 'changeEmail', email }; + } + + public static actionEditFirstName(firstName: string): CustomerUpdateAction { + return { action: 'setFirstName', firstName }; + } + + public static actionEditLastName(lastName: string): CustomerUpdateAction { + return { action: 'setLastName', lastName }; + } + + public static actionRemoveAddress(address: Address): CustomerUpdateAction { + return { action: 'removeAddress', addressId: address.id }; + } + + public static actionRemoveBillingAddress(address: Address): CustomerUpdateAction { + return { action: 'removeBillingAddressId', addressId: address.id }; + } + + public static actionRemoveShippingAddress(address: Address): CustomerUpdateAction { + return { action: 'removeShippingAddressId', addressId: address.id }; + } + + public static actionSetLocale(locale: string): CustomerUpdateAction { + return { action: 'setLocale', locale }; + } + + private adaptAddress(address: AddressResponse[]): Address[] { + return address.map((addressItem) => ({ + city: addressItem?.city || '', + country: addressItem?.country || '', + email: addressItem?.email || '', + firstName: addressItem?.firstName || '', + id: addressItem?.id || '', + lastName: addressItem?.lastName || '', + postalCode: addressItem?.postalCode || '', + state: addressItem?.state || '', + streetName: addressItem?.streetName || '', + streetNumber: addressItem?.streetNumber || '', + })); + } + + private static adaptAddressToServer(data: Address): BaseAddress { + return { + city: data.city, + country: data.country, + email: data.email, + firstName: data.firstName, + lastName: data.lastName, + postalCode: data.postalCode, + state: data.state, + streetName: data.streetName, + streetNumber: data.streetNumber, + }; + } + + private adaptCustomerData(customerData: { customer: Customer } | Customer): User { + const data = 'customer' in customerData ? customerData.customer : customerData; + + return { + addresses: this.adaptAddress(data.addresses), + birthDate: data.dateOfBirth || '', + defaultBillingAddressId: null, + defaultShippingAddressId: null, + email: data.email || '', + firstName: data.firstName || '', + id: data.id || '', + lastName: data.lastName || '', + locale: data.locale || 'en', + password: data.password || '', + version: data.version || 0, + }; + } + + private adaptCustomerToClient(data: Customer): User { + const adaptedCustomer = this.adaptCustomerData(data); + + adaptedCustomer.defaultBillingAddressId = this.adaptDefaultAddress( + data.defaultBillingAddressId, + adaptedCustomer.addresses, + ); + adaptedCustomer.defaultShippingAddressId = this.adaptDefaultAddress( + data.defaultShippingAddressId, + adaptedCustomer.addresses, + ); + return adaptedCustomer; + } + + private adaptDefaultAddress(addressId: string | undefined, address: Address[]): Address | null { + if (addressId) { + const addressFound = address.find((address) => address.id === addressId); + return addressFound || null; + } + return null; + } + + private adaptSignInToClient(data: CustomerSignInResult): User { + const adaptedCustomer = this.adaptCustomerData(data); + + adaptedCustomer.defaultBillingAddressId = this.adaptDefaultAddress( + data.customer.defaultBillingAddressId, + adaptedCustomer.addresses, + ); + adaptedCustomer.defaultShippingAddressId = this.adaptDefaultAddress( + data.customer.defaultShippingAddressId, + adaptedCustomer.addresses, + ); + return adaptedCustomer; + } + + private getCustomerFromData( + data: ClientResponse, + ): User | null { + let customer: User | null = null; + if (isClientResponse(data)) { + if (isCustomerSignInResultResponse(data.body)) { + customer = this.adaptSignInToClient(data.body); + } else if (isCustomerResponse(data.body)) { + customer = this.adaptCustomerToClient(data.body); + } else if (isCustomerPagedQueryResponse(data.body)) { + customer = data.body.results.length > 0 ? this.adaptCustomerToClient(data.body.results[0]) : null; + } + } + return customer; + } + + public async authCustomer(userLoginData: UserLoginData): Promise { + const data = await this.root.authenticateUser(userLoginData); + return this.getCustomerFromData(data); + } + + public async deleteCustomer(customer: User): Promise { + const data = await this.root.deleteCustomer(customer.id, customer.version); + return this.getCustomerFromData(data) !== null; + } + + public async editCustomer(actions: CustomerUpdateAction[], customer: User): Promise { + const data = await this.root.editCustomer(actions, customer.version, customer.id); + return this.getCustomerFromData(data); + } + + public async editPassword(customer: User, currentPassword: string, newPassword: string): Promise { + const data = await this.root.editPassword(customer.id, customer.version, currentPassword, newPassword); + return this.getCustomerFromData(data); + } + + public async getCustomerByID(id: string): Promise { + const data = await this.root.getCustomerByID(id); + return this.getCustomerFromData(data); + } + + public async hasEmail(email: string): Promise { + const data = await this.root.getCustomerByEmail(email); + return this.getCustomerFromData(data); + } + + public async registerNewCustomer(userData: User): Promise { + const data = await this.root.registrationUser(userData); + return this.getCustomerFromData(data); + } +} + +const createCustomerModel = (): CustomerModel => new CustomerModel(); + +const customerModel = createCustomerModel(); + +export default function getCustomerModel(): CustomerModel { + return customerModel; +} diff --git a/src/shared/API/customer/tests/Customer.spec.ts b/src/shared/API/customer/tests/Customer.spec.ts new file mode 100644 index 00000000..da249c1d --- /dev/null +++ b/src/shared/API/customer/tests/Customer.spec.ts @@ -0,0 +1,183 @@ +import type { Address, User } from '@/shared/types/user.ts'; + +import getCustomerModel, { CustomerModel } from '../model/CustomerModel.ts'; + +const customerModel = getCustomerModel(); + +describe('Checking Customer Model', () => { + let user: User; + let address: Address; + let customer: User | null = null; + let editCustomer: User | null = null; + let editAddress: User | null = null; + let editPassword: User | null = null; + let auth: User | null = null; + + beforeAll(() => { + user = { + addresses: [], + birthDate: '1990-01-01', + defaultBillingAddressId: null, + defaultShippingAddressId: null, + email: 'test-test@example.com', + firstName: 'Jane', + id: '1', + lastName: 'Smith', + locale: 'en', + password: 'Qqq11', + version: 0, + }; + + address = { + city: 'Anytown', + country: 'DE', + email: 'test-test-test@example.com', + firstName: 'John', + id: '', + lastName: 'Doe', + postalCode: '12345', + state: '', + streetName: 'Main Street', + streetNumber: '123', + }; + }); + + it('should check if customerModel is defined', () => { + expect(customerModel).toBeDefined(); + }); + + it('should check if customerModel is an instance of CustomerModel', () => { + expect(customerModel).toBeInstanceOf(CustomerModel); + }); + + it('should return true for valid email', async () => { + const result = await customerModel.hasEmail('getting-started@example.com'); + expect(result?.email).toBe('getting-started@example.com'); + }); + + it('should return false for invalid email', async () => { + const result = await customerModel.hasEmail('gettingstarted@example.com'); + expect(result).toBe(null); + }); + + it('should register a new customer', async () => { + customer = await customerModel.registerNewCustomer(user); + expect(typeof customer).toBe('object'); + expect(customer).toHaveProperty('addresses'); + expect(customer).toHaveProperty('defaultBillingAddressId'); + expect(customer).toHaveProperty('defaultShippingAddressId'); + expect(customer).toHaveProperty('email'); + expect(customer).toHaveProperty('firstName'); + expect(customer).toHaveProperty('id'); + expect(customer).toHaveProperty('lastName'); + expect(customer).toHaveProperty('password'); + expect(customer).toHaveProperty('version'); + }); + + it('should edit the customer', async () => { + if (customer) { + editCustomer = await customerModel.editCustomer( + [ + CustomerModel.actionEditFirstName('John'), + CustomerModel.actionEditLastName('Doe'), + CustomerModel.actionEditEmail('test-test-test@example.com'), + CustomerModel.actionAddAddress(address), + CustomerModel.actionEditDateOfBirth('1990-01-01'), + ], + customer, + ); + expect(typeof editCustomer).toBe('object'); + expect(editCustomer).toHaveProperty('addresses'); + expect(editCustomer).toHaveProperty('defaultBillingAddressId'); + expect(editCustomer).toHaveProperty('defaultShippingAddressId'); + expect(editCustomer).toHaveProperty('email'); + expect(editCustomer).toHaveProperty('firstName'); + expect(editCustomer).toHaveProperty('id'); + expect(editCustomer).toHaveProperty('lastName'); + expect(editCustomer).toHaveProperty('password'); + expect(editCustomer).toHaveProperty('version'); + } + }); + + it('should edit the address', async () => { + if (editCustomer) { + const newAddressData = editCustomer.addresses[0]; + newAddressData.city = 'New York'; + newAddressData.country = 'US'; + + editAddress = await customerModel.editCustomer( + [ + CustomerModel.actionEditAddress(newAddressData), + CustomerModel.actionEditDefaultBillingAddress(newAddressData.id), + CustomerModel.actionEditDefaultShippingAddress(newAddressData.id), + CustomerModel.actionRemoveAddress(newAddressData), + ], + editCustomer, + ); + expect(typeof editAddress).toBe('object'); + expect(typeof editAddress).toBe('object'); + expect(editAddress).toHaveProperty('addresses'); + expect(editAddress).toHaveProperty('defaultBillingAddressId'); + expect(editAddress).toHaveProperty('defaultShippingAddressId'); + expect(editAddress).toHaveProperty('email'); + expect(editAddress).toHaveProperty('firstName'); + expect(editAddress).toHaveProperty('id'); + expect(editAddress).toHaveProperty('lastName'); + expect(editAddress).toHaveProperty('password'); + expect(editAddress).toHaveProperty('version'); + } + }); + + it('should found the customer by id', async () => { + if (customer) { + const getCustomer = await customerModel.getCustomerByID(customer.id); + expect(typeof getCustomer).toBe('object'); + expect(getCustomer).toHaveProperty('addresses'); + expect(getCustomer).toHaveProperty('defaultBillingAddressId'); + expect(getCustomer).toHaveProperty('defaultShippingAddressId'); + expect(getCustomer).toHaveProperty('email'); + expect(getCustomer).toHaveProperty('firstName'); + expect(getCustomer).toHaveProperty('id'); + expect(getCustomer).toHaveProperty('lastName'); + expect(getCustomer).toHaveProperty('password'); + expect(getCustomer).toHaveProperty('version'); + } + }); + + it('should authenticate the customer', async () => { + auth = await customerModel.authCustomer({ email: 'test-test-test@example.com', password: 'Qqq11' }); + expect(typeof auth).toBe('object'); + expect(auth).toHaveProperty('addresses'); + expect(auth).toHaveProperty('defaultBillingAddressId'); + expect(auth).toHaveProperty('defaultShippingAddressId'); + expect(auth).toHaveProperty('email'); + expect(auth).toHaveProperty('firstName'); + expect(auth).toHaveProperty('id'); + expect(auth).toHaveProperty('lastName'); + expect(auth).toHaveProperty('password'); + expect(auth).toHaveProperty('version'); + }); + + it('should edit the customer password', async () => { + if (auth) { + editPassword = await customerModel.editPassword(auth, 'Qqq11', 'Qqq11'); + expect(typeof editPassword).toBe('object'); + expect(editPassword).toHaveProperty('addresses'); + expect(editPassword).toHaveProperty('defaultBillingAddressId'); + expect(editPassword).toHaveProperty('defaultShippingAddressId'); + expect(editPassword).toHaveProperty('email'); + expect(editPassword).toHaveProperty('firstName'); + expect(editPassword).toHaveProperty('id'); + expect(editPassword).toHaveProperty('lastName'); + expect(editPassword).toHaveProperty('password'); + expect(editPassword).toHaveProperty('version'); + } + }); + + it('should delete the customer', async () => { + if (editPassword) { + const deleteCustomer = await customerModel.deleteCustomer(editPassword); + expect(deleteCustomer).toBe(true); + } + }); +}); diff --git a/src/shared/API/product/model/ProductModel.ts b/src/shared/API/product/model/ProductModel.ts new file mode 100644 index 00000000..99c46e33 --- /dev/null +++ b/src/shared/API/product/model/ProductModel.ts @@ -0,0 +1,298 @@ +import type { Category, Product, Size, localization } from '@/shared/types/product.ts'; +import type { + Attribute as AttributeResponse, + CategoryPagedQueryResponse, + CategoryReference, + ClientResponse, + LocalizedString, + ProductPagedQueryResponse, + ProductProjectionPagedSearchResponse, + Product as ProductResponse, + ProductVariant, +} from '@commercetools/platform-sdk'; + +import getStore from '@/shared/Store/Store.ts'; +import { setCategories, setProducts } from '@/shared/Store/actions.ts'; +import getSize from '@/shared/utils/size.ts'; + +import getRoot, { type RootApi } from '../../sdk/root.ts'; +import { Attribute, type CategoriesProductCount, type OptionsRequest, type PriceRange } from '../../types/type.ts'; +import { + isAttributePlainEnumValue, + isCategoryPagedQueryResponse, + isClientResponse, + isFacetRange, + isFacetTerm, + isLocalizationObj, + isProductPagedQueryResponse, + isProductProjectionPagedSearchResponse, + isProductResponse, + isRangeFacetResult, + isTermFacetResult, +} from '../../types/validation.ts'; + +const PRICE_FRACTIONS = 100; + +export class ProductModel { + private root: RootApi; + + constructor() { + this.root = getRoot(); + } + + private adaptCategoryPagedQueryToClient(data: CategoryPagedQueryResponse): Category[] { + const response = data.results.map((category) => { + const result: Category = { + id: category.id || '', + key: category.key || '', + name: [], + }; + Object.entries(category.name).forEach(([language, value]) => { + result.name.push({ + language, + value, + }); + }); + + return result; + }); + + return response; + } + + private adaptCategoryReference(data: CategoryReference[]): Category[] { + const categoryList = getStore().getState().categories; + const response: Category[] = []; + data.forEach((category) => { + const categoryEl = categoryList.find((el) => el.id === category.id); + if (categoryEl) { + response.push(categoryEl); + } + }); + return response; + } + + private adaptDiscount(variant: ProductVariant): number { + let minPrice = 0; + + if (variant.prices && variant.prices.length && variant.prices[0].discounted) { + const priceRow = variant.prices[0]; + if (priceRow.discounted) { + minPrice = priceRow.discounted.value.centAmount / PRICE_FRACTIONS; + } + } + return minPrice; + } + + private adaptFullDescription(attribute: AttributeResponse): localization[] { + if (isLocalizationObj(attribute.value)) { + return this.adaptLocalizationValue(attribute.value); + } + return []; + } + + private adaptLocalizationValue(data: LocalizedString | undefined): localization[] { + const result: localization[] = []; + Object.entries(data || {}).forEach(([language, value]) => { + result.push({ + language, + value, + }); + }); + return result; + } + + private adaptPrice(variant: ProductVariant): number { + let price = 0; + + if (variant.prices && variant.prices.length) { + const priceRow = variant.prices[0]; + price = priceRow.value.centAmount / PRICE_FRACTIONS; + } + return price; + } + + private adaptProductPagedQueryToClient(data: ProductPagedQueryResponse): Product[] { + const response = data.results.map((product) => this.adaptProductToClient(product)); + return response; + } + + private adaptProductToClient(product: ProductResponse): Product { + const result: Product = { + category: [], + description: [], + fullDescription: [], + id: product.id || '', + images: [], + key: product.key || '', + name: [], + variant: [], + }; + result.category.push(...this.adaptCategoryReference(product.masterData.staged.categories)); + result.description.push(...this.adaptLocalizationValue(product.masterData.staged.description)); + result.name.push(...this.adaptLocalizationValue(product.masterData.staged.name)); + + Object.assign(result, this.adaptVariants(result, product)); + + result.fullDescription = [...new Set(result.fullDescription)]; + result.variant = [...new Set(result.variant)]; + result.images = [...new Set(result.images)]; + + return result; + } + + private adaptSize(attribute: AttributeResponse): Size | null { + if (Array.isArray(attribute.value) && attribute.value.length && isAttributePlainEnumValue(attribute.value[0])) { + return getSize(attribute.value[0].key); + } + return null; + } + + private adaptVariants(product: Product, response: ProductResponse): Product { + const variants = response.masterData.staged.variants.length + ? response.masterData.staged.variants + : [response.masterData.staged.masterVariant]; + variants.forEach((variant) => { + let size: Size | null = null; + + if (variant.attributes && variant.attributes.length) { + variant.attributes.forEach((attribute) => { + if (attribute.name === Attribute.FULL_DESCRIPTION && !product.fullDescription.length) { + product.fullDescription.push(...this.adaptFullDescription(attribute)); + } + if (attribute.name === Attribute.SIZE) { + size = this.adaptSize(attribute); + } + }); + } + + product.variant.push({ + discount: this.adaptDiscount(variant) || 0, + price: this.adaptPrice(variant) || 0, + size, + }); + + if (variant.images && variant.images.length) { + variant.images.forEach((image) => { + product.images.push(image.url); + }); + } + }); + return product; + } + + private getCategoriesFromData(data: ClientResponse): Category[] | null { + let category: Category[] | null = null; + if (isClientResponse(data)) { + if (isCategoryPagedQueryResponse(data.body)) { + category = this.adaptCategoryPagedQueryToClient(data.body); + getStore().dispatch(setCategories(category)); + } + } + return category; + } + + private getCategoriesProductCountFromData( + data: ClientResponse, + ): CategoriesProductCount[] { + const category: CategoriesProductCount[] = []; + if ( + isClientResponse(data) && + isProductProjectionPagedSearchResponse(data.body) && + 'categories.id' in data.body.facets + ) { + const categoriesFacet = data.body.facets['categories.id']; + if (isTermFacetResult(categoriesFacet)) { + const categoryList = getStore().getState().categories; + categoriesFacet.terms.forEach((term) => { + if (isFacetTerm(term)) { + const currentCategory = categoryList.find((el) => el.id === term.term); + if (currentCategory) { + category.push({ + category: currentCategory, + count: term.productCount || 0, + }); + } + } + }); + } + } + return category; + } + + private getPriceRangeFromData(date: ClientResponse): PriceRange { + const priceRange: PriceRange = { + max: 0, + min: 0, + }; + if ( + isClientResponse(date) && + isProductProjectionPagedSearchResponse(date.body) && + 'variants.price.centAmount' in date.body.facets + ) { + const variantsPrice = date.body.facets['variants.price.centAmount']; + if (isRangeFacetResult(variantsPrice)) { + variantsPrice.ranges.forEach((range) => { + if (isFacetRange(range)) { + priceRange.min = range.min / PRICE_FRACTIONS; + priceRange.max = range.max / PRICE_FRACTIONS; + } + }); + } + } + return priceRange; + } + + private getProductFromData(data: ClientResponse): Product | null { + let product: Product | null = null; + if (isClientResponse(data) && isProductResponse(data.body)) { + product = this.adaptProductToClient(data.body); + } + return product; + } + + private getProductsFromData(data: ClientResponse): Product[] | null { + let productList: Product[] | null = null; + if (isClientResponse(data) && isProductPagedQueryResponse(data.body)) { + productList = this.adaptProductPagedQueryToClient(data.body); + } + return productList; + } + + public async getCategories(): Promise { + const data = await this.root.getCategories(); + return this.getCategoriesFromData(data); + } + + public async getCategoriesProductCount(): Promise { + const data = await this.root.getCategoriesProductCount(); + return this.getCategoriesProductCountFromData(data); + } + + public async getPriceRange(): Promise { + const data = await this.root.getPriceRange(); + return this.getPriceRangeFromData(data); + } + + public async getProductById(id: string): Promise { + const data = await this.root.getProductByID(id); + return this.getProductFromData(data); + } + + public async getProducts(options?: OptionsRequest): Promise { + const data = await this.root.getProducts(options); + const products = this.getProductsFromData(data); + if (products) { + getStore().dispatch(setProducts(products)); + } + return products; + } +} + +const createProductModel = (): ProductModel => new ProductModel(); + +const productModel = createProductModel(); + +export default function getProductModel(): ProductModel { + return productModel; +} diff --git a/src/shared/API/product/tests/Product.spec.ts b/src/shared/API/product/tests/Product.spec.ts new file mode 100644 index 00000000..88b22ca7 --- /dev/null +++ b/src/shared/API/product/tests/Product.spec.ts @@ -0,0 +1,105 @@ +import { Size, type localization } from '@/shared/types/product.ts'; +import getSize from '@/shared/utils/size.ts'; + +import getProductModel, { ProductModel } from '../model/ProductModel.ts'; + +const productModel = getProductModel(); + +describe('Checking Product Model', () => { + it('should check if productModel is defined', () => { + expect(productModel).toBeDefined(); + }); + + it('should check if productModel is an instance of ProductModel', () => { + expect(productModel).toBeInstanceOf(ProductModel); + }); + + it('should get the categories', async () => { + const categoryArr = await productModel.getCategories(); + if (categoryArr) { + expect(categoryArr).toBeDefined(); + categoryArr.forEach((category) => { + expect(typeof category.id).toBe('string'); + expect(typeof category.key).toBe('string'); + expect(Array.isArray(category.name)).toBe(true); + category.name.forEach((localization: localization) => { + expect(typeof localization.language).toBe('string'); + expect(typeof localization.value).toBe('string'); + }); + }); + } + }); + + it('should get the products list', async () => { + const productsArr = await productModel.getProducts(); + if (productsArr) { + expect(productsArr).toBeDefined(); + productsArr.forEach((product) => { + expect(typeof product.id).toBe('string'); + expect(typeof product.key).toBe('string'); + expect(Array.isArray(product.name)).toBe(true); + product.name.forEach((localization: localization) => { + expect(typeof localization.language).toBe('string'); + expect(typeof localization.value).toBe('string'); + }); + expect(Array.isArray(product.description)).toBe(true); + product.description.forEach((localization: localization) => { + expect(typeof localization.language).toBe('string'); + expect(typeof localization.value).toBe('string'); + }); + expect(Array.isArray(product.fullDescription)).toBe(true); + product.fullDescription.forEach((localization: localization) => { + expect(typeof localization.language).toBe('string'); + expect(typeof localization.value).toBe('string'); + }); + expect(Array.isArray(product.images)).toBe(true); + expect(Array.isArray(product.category)).toBe(true); + expect(Array.isArray(product.variant)).toBe(true); + }); + } + }); + + it('should get the product by id', async () => { + const product = await productModel.getProductById('e5381b83-a7c4-4060-9fdb-f4123db54dd2'); + if (product) { + expect(product).toBeDefined(); + expect(typeof product.id).toBe('string'); + expect(typeof product.key).toBe('string'); + expect(Array.isArray(product.name)).toBe(true); + product.name.forEach((localization: localization) => { + expect(typeof localization.language).toBe('string'); + expect(typeof localization.value).toBe('string'); + }); + expect(Array.isArray(product.description)).toBe(true); + product.description.forEach((localization: localization) => { + expect(typeof localization.language).toBe('string'); + expect(typeof localization.value).toBe('string'); + }); + expect(Array.isArray(product.fullDescription)).toBe(true); + product.fullDescription.forEach((localization: localization) => { + expect(typeof localization.language).toBe('string'); + expect(typeof localization.value).toBe('string'); + }); + expect(Array.isArray(product.images)).toBe(true); + expect(Array.isArray(product.category)).toBe(true); + expect(Array.isArray(product.variant)).toBe(true); + } + }); +}); + +describe('getSize function', () => { + it('should return Size.S when called with "S"', () => { + const result = getSize('S'); + expect(result).toBe(Size.S); + }); + + it('should return Size.M when called with "M"', () => { + const result = getSize('M'); + expect(result).toBe(Size.M); + }); + + it('should return null when called with an unknown size', () => { + const result = getSize('unknown size'); + expect(result).toBeNull(); + }); +}); diff --git a/src/shared/API/sdk/client.ts b/src/shared/API/sdk/client.ts index de70f9c6..365ff021 100644 --- a/src/shared/API/sdk/client.ts +++ b/src/shared/API/sdk/client.ts @@ -5,9 +5,12 @@ import { type HttpMiddlewareOptions, } from '@commercetools/sdk-client-v2'; +const URL_AUTH = 'https://auth.europe-west1.gcp.commercetools.com'; +const URL_HTTP = 'https://api.europe-west1.gcp.commercetools.com'; + const httpMiddlewareOptions: HttpMiddlewareOptions = { fetch, - host: 'https://api.europe-west1.gcp.commercetools.com', + host: URL_HTTP, }; export default function client(projectKey: string, clientID: string, clientSecret: string, scopes: string): Client { @@ -18,7 +21,7 @@ export default function client(projectKey: string, clientID: string, clientSecre clientSecret, }, fetch, - host: 'https://auth.europe-west1.gcp.commercetools.com', + host: URL_AUTH, projectKey, scopes: scopesArr, }; diff --git a/src/shared/API/sdk/request.ts b/src/shared/API/sdk/request.ts deleted file mode 100644 index f4137692..00000000 --- a/src/shared/API/sdk/request.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type ClientResponse, type ProductPagedQueryResponse } from '@commercetools/platform-sdk'; - -import root, { type Credentials } from './root.ts'; - -export default function request(credentials: Credentials): Promise | Error> { - return root(credentials) - .products() - .get() - .execute() - .catch((err: Error) => err); -} diff --git a/src/shared/API/sdk/root.ts b/src/shared/API/sdk/root.ts index 7153a970..127539b6 100644 --- a/src/shared/API/sdk/root.ts +++ b/src/shared/API/sdk/root.ts @@ -1,8 +1,29 @@ -import { type ByProjectKeyRequestBuilder, createApiBuilderFromCtpClient } from '@commercetools/platform-sdk'; +import type { User, UserLoginData } from '@/shared/types/user.ts'; + +import { + type ByProjectKeyRequestBuilder, + type CategoryPagedQueryResponse, + type ClientResponse, + type Customer, + type CustomerPagedQueryResponse, + type CustomerSignInResult, + type CustomerUpdateAction, + type Product, + type ProductPagedQueryResponse, + type ProductProjectionPagedSearchResponse, + createApiBuilderFromCtpClient, +} from '@commercetools/platform-sdk'; +import { type Client } from '@commercetools/sdk-client-v2'; + +import type { OptionsRequest, SortOptions } from '../types/type.ts'; import client from './client.ts'; type Nullable = T | null; +const PRODUCT_LIMIT = 9; +const DEFAULT_PAGE = 1; +const MIN_PRICE = 0; +const MAX_PRICE = 1000000; export type Credentials = { clientID: Nullable; @@ -11,8 +32,162 @@ export type Credentials = { scopes: Nullable; }; -export default function root({ clientID, clientSecret, projectKey, scopes }: Credentials): ByProjectKeyRequestBuilder { - return createApiBuilderFromCtpClient( - client(projectKey || '', clientID || '', clientSecret || '', scopes || ''), - ).withProjectKey({ projectKey: projectKey || '' }); +const projectKey = import.meta.env.VITE_APP_CTP_PROJECT_KEY; +const scopes = import.meta.env.VITE_APP_CTP_SCOPES; +const clientID = import.meta.env.VITE_APP_CTP_CLIENT_ID; +const clientSecret = import.meta.env.VITE_APP_CTP_CLIENT_SECRET; + +export class RootApi { + private client: Client; + + private connection: ByProjectKeyRequestBuilder; + + private credentials: Credentials; + + constructor() { + this.credentials = { + clientID, + clientSecret, + projectKey, + scopes, + }; + + this.client = client( + this.credentials.projectKey || '', + this.credentials.clientID || '', + this.credentials.clientSecret || '', + this.credentials.scopes || '', + ); + + this.connection = this.root(this.client, projectKey); + } + + private makeSortRequest(sortOptions: SortOptions): string { + return `${sortOptions.field}${sortOptions.locale ? `.${sortOptions.locale}` : ''} ${sortOptions.direction}`; + } + + private root(client: Client, projectKey: string): ByProjectKeyRequestBuilder { + return createApiBuilderFromCtpClient(client).withProjectKey({ projectKey }); + } + + public async authenticateUser(userLoginData: UserLoginData): Promise> { + const data = await this.connection.login().post({ body: userLoginData }).execute(); + return data; + } + + public async deleteCustomer(ID: string, version: number): Promise> { + const data = await this.connection.customers().withId({ ID }).delete({ queryArgs: { version } }).execute(); + return data; + } + + public async editCustomer( + actions: CustomerUpdateAction[], + version: number, + ID: string, + ): Promise> { + const data = await this.connection.customers().withId({ ID }).post({ body: { actions, version } }).execute(); + return data; + } + + public async editPassword( + id: string, + version: number, + currentPassword: string, + newPassword: string, + ): Promise> { + const data = await this.connection + .customers() + .password() + .post({ body: { currentPassword, id, newPassword, version } }) + .execute(); + return data; + } + + public async getCategories(): Promise> { + const data = await this.connection.categories().get().execute(); + return data; + } + + public async getCategoriesProductCount(): Promise> { + const data = await this.connection + .productProjections() + .search() + .get({ + queryArgs: { + facet: [`categories.id counting products`], + limit: 0, + }, + }) + .execute(); + return data; + } + + public async getCustomerByEmail(email: string): Promise> { + const data = await this.connection + .customers() + .get({ queryArgs: { where: `email="${email}"` } }) + .execute(); + return data; + } + + public async getCustomerByID(ID: string): Promise> { + const data = await this.connection.customers().withId({ ID }).get().execute(); + return data; + } + + public async getPriceRange(): Promise> { + const data = await this.connection + .productProjections() + .search() + .get({ + queryArgs: { + facet: [`variants.price.centAmount:range(${MIN_PRICE} to ${MAX_PRICE})`], + limit: 0, + }, + }) + .execute(); + return data; + } + + public async getProductByID(ID: string): Promise> { + const data = await this.connection.products().withId({ ID }).get().execute(); + return data; + } + + public async getProducts(options?: OptionsRequest): Promise> { + const { limit = PRODUCT_LIMIT, page = DEFAULT_PAGE, sort } = options || {}; + + const data = await this.connection + .products() + .get({ + queryArgs: { + limit, + offset: (page - 1) * PRODUCT_LIMIT, + ...(sort && { sort: this.makeSortRequest(sort) }), + // where: `masterData(staged(variants(prices(value(centAmount >= 5000))) or + // masterVariant(prices(value(centAmount >= 5000)))))`, + // where: `key = 10594917538474`, + withTotal: true, + }, + }) + .execute(); + return data; + } + + public async registrationUser(userData: User): Promise> { + const userCredentials = { + email: userData.email, + password: userData.password, + }; + const data = await this.connection.customers().post({ body: userCredentials }).execute(); + return data; + } +} + +const createRoot = (): RootApi => new RootApi(); + +const rootApi = createRoot(); + +export default function getRoot(): RootApi { + return rootApi; } diff --git a/src/shared/API/sdk/sdk.spec.ts b/src/shared/API/sdk/sdk.spec.ts new file mode 100644 index 00000000..6ff693ca --- /dev/null +++ b/src/shared/API/sdk/sdk.spec.ts @@ -0,0 +1,13 @@ +import getRoot, { RootApi } from './root.ts'; + +const root = getRoot(); + +describe('Checking Root Api', () => { + it('should check if root is defined', () => { + expect(root).toBeDefined(); + }); + + it('should check if customerModel is an instance of CustomerModel', () => { + expect(root).toBeInstanceOf(RootApi); + }); +}); diff --git a/src/shared/API/test.ts b/src/shared/API/test.ts deleted file mode 100644 index 7d86c4c1..00000000 --- a/src/shared/API/test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import request from './sdk/request.ts'; -import { type Credentials } from './sdk/root.ts'; - -const projectKey = import.meta.env.VITE_APP_CTP_PROJECT_KEY; -const scopes = import.meta.env.VITE_APP_CTP_SCOPES; -const clientID = import.meta.env.VITE_APP_CTP_CLIENT_ID; -const clientSecret = import.meta.env.VITE_APP_CTP_CLIENT_SECRET; - -const initCredentials: Credentials = { - clientID, - clientSecret, - projectKey, - scopes, -}; - -const productsList = await request(initCredentials); -export default productsList; diff --git a/src/shared/API/types/type.ts b/src/shared/API/types/type.ts new file mode 100644 index 00000000..fef9ad95 --- /dev/null +++ b/src/shared/API/types/type.ts @@ -0,0 +1,38 @@ +import { type Category } from '@/shared/types/product.ts'; + +export const Attribute = { + FULL_DESCRIPTION: 'full_description', + SIZE: 'size', +}; + +export enum SortFields { + NAME = 'masterData.staged.name', + PRICE = 'masterData.staged.variants.price.value', +} + +export enum SortDirection { + ASC = 'asc', + DESC = 'desc', +} + +export type SortOptions = { + direction: SortDirection; + field: SortFields; + locale?: string; +}; + +export type OptionsRequest = { + limit?: number; + page?: number; + sort?: SortOptions; +}; + +export type PriceRange = { + max: number; + min: number; +}; + +export type CategoriesProductCount = { + category: Category; + count: number; +}; diff --git a/src/shared/API/types/validation.ts b/src/shared/API/types/validation.ts new file mode 100644 index 00000000..f9965a22 --- /dev/null +++ b/src/shared/API/types/validation.ts @@ -0,0 +1,169 @@ +import type { + AttributePlainEnumValue, + CategoryPagedQueryResponse, + ClientResponse, + Customer, + CustomerPagedQueryResponse, + CustomerSignInResult, + FacetRange, + FacetTerm, + LocalizedString, + Product, + ProductPagedQueryResponse, + RangeFacetResult, + TermFacetResult, +} from '@commercetools/platform-sdk'; + +export function isClientResponse(data: unknown): data is ClientResponse { + return Boolean( + typeof data === 'object' && + data && + 'body' in data && + typeof data.body === 'object' && + 'statusCode' in data && + data.statusCode !== 'undefined', + ); +} + +export function isCustomerSignInResultResponse(data: unknown): data is CustomerSignInResult { + return Boolean(typeof data === 'object' && data && 'customer' in data && typeof data.customer === 'object'); +} + +export function isCustomerResponse(data: unknown): data is Customer { + return Boolean( + typeof data === 'object' && + data && + 'firstName' in data && + typeof data.firstName === 'string' && + 'lastName' in data && + typeof data.lastName === 'string' && + 'id' in data && + typeof data.id === 'string' && + 'email' in data && + typeof data.email === 'string', + ); +} + +export function isCustomerPagedQueryResponse(data: unknown): data is CustomerPagedQueryResponse { + return Boolean( + typeof data === 'object' && + data && + 'count' in data && + typeof data.count === 'number' && + 'limit' in data && + typeof data.limit === 'number' && + 'results' in data && + typeof Array.isArray(data.results), + ); +} + +export function isCategoryPagedQueryResponse(data: unknown): data is CategoryPagedQueryResponse { + return Boolean( + typeof data === 'object' && + data && + 'count' in data && + typeof data.count === 'number' && + 'limit' in data && + typeof data.limit === 'number' && + 'results' in data && + typeof Array.isArray(data.results), + ); +} + +export function isProductPagedQueryResponse(data: unknown): data is ProductPagedQueryResponse { + return Boolean( + typeof data === 'object' && + data && + 'count' in data && + typeof data.count === 'number' && + 'limit' in data && + typeof data.limit === 'number' && + 'total' in data && + typeof data.total === 'number' && + 'results' in data && + typeof Array.isArray(data.results), + ); +} + +export function isLocalizationObj(data: unknown): data is LocalizedString { + return Boolean(typeof data === 'object' && data && Object.keys(data).every((key) => typeof key === 'string')); +} + +export function isAttributePlainEnumValue(data: unknown): data is AttributePlainEnumValue { + return Boolean( + typeof data === 'object' && + data && + 'key' in data && + typeof data.key === 'string' && + 'label' in data && + typeof data.label === 'string', + ); +} + +export function isProductResponse(data: unknown): data is Product { + return Boolean( + typeof data === 'object' && + data && + 'id' in data && + typeof data.id === 'string' && + 'key' in data && + typeof data.id === 'string' && + 'masterData' in data && + typeof data.masterData === 'object' && + data.masterData !== null && + 'staged' in data.masterData && + typeof data.masterData.staged === 'object' && + data.masterData.staged !== null && + 'categories' in data.masterData.staged && + 'description' in data.masterData.staged && + 'name' in data.masterData.staged && + 'variants' in data.masterData.staged, + ); +} + +export function isProductProjectionPagedSearchResponse(data: unknown): data is ProductPagedQueryResponse { + return Boolean(typeof data === 'object' && data && 'facets' in data && typeof data.facets === 'object'); +} + +export function isRangeFacetResult(data: unknown): data is RangeFacetResult { + return Boolean( + typeof data === 'object' && data && 'ranges' in data && Array.isArray(data.ranges) && data.ranges.length, + ); +} + +export function isFacetRange(data: unknown): data is FacetRange { + return Boolean( + typeof data === 'object' && + data && + 'min' in data && + typeof data.min === 'number' && + 'max' in data && + typeof data.max === 'number', + ); +} + +export function isTermFacetResult(data: unknown): data is TermFacetResult { + return Boolean( + typeof data === 'object' && + data && + 'type' in data && + typeof data.type === 'string' && + data.type === 'terms' && + 'terms' in data && + Array.isArray(data.terms) && + data.terms.length, + ); +} + +export function isFacetTerm(data: unknown): data is FacetTerm { + return Boolean( + typeof data === 'object' && + data && + 'term' in data && + typeof data.term === 'string' && + 'count' in data && + typeof data.count === 'number' && + 'productCount' in data && + typeof data.productCount === 'number', + ); +} diff --git a/src/shared/Button/model/ButtonModel.ts b/src/shared/Button/model/ButtonModel.ts index af13c628..e78e1570 100644 --- a/src/shared/Button/model/ButtonModel.ts +++ b/src/shared/Button/model/ButtonModel.ts @@ -1,13 +1,13 @@ -import type ButtonAttributesInterface from '@/shared/types/interfaces.ts'; +import type { ButtonAttributes } from '@/shared/types/button.ts'; -import { IS_DISABLED } from '@/shared/constants/enums.ts'; +import { IS_DISABLED } from '@/shared/constants/buttons.ts'; import ButtonView from '../view/ButtonView.ts'; class ButtonModel { private view: ButtonView; - constructor(params: ButtonAttributesInterface) { + constructor(params: ButtonAttributes) { this.view = new ButtonView(params); } diff --git a/src/shared/Button/view/ButtonView.ts b/src/shared/Button/view/ButtonView.ts index 4cb0407e..7515d5f5 100644 --- a/src/shared/Button/view/ButtonView.ts +++ b/src/shared/Button/view/ButtonView.ts @@ -1,21 +1,21 @@ -import type ButtonAttributesInterface from '@/shared/types/interfaces.ts'; +import type { ButtonAttributes } from '@/shared/types/button.ts'; -import { TAG_NAMES } from '@/shared/constants/enums.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; import createBaseElement from '@/shared/utils/createBaseElement.ts'; class ButtonView { private button: HTMLButtonElement; - constructor(params: ButtonAttributesInterface) { + constructor(params: ButtonAttributes) { this.button = this.createHTML(params); } - private createHTML(params: ButtonAttributesInterface): HTMLButtonElement { + private createHTML(params: ButtonAttributes): HTMLButtonElement { this.button = createBaseElement({ attributes: params.attrs, cssClasses: params.classes, innerContent: params.text, - tag: TAG_NAMES.BUTTON, + tag: TAG_NAME.BUTTON, }); if (params.action) { diff --git a/src/shared/EventMediator/.gitkeep b/src/shared/EventMediator/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/shared/EventMediator/model/EventMediatorModel.ts b/src/shared/EventMediator/model/EventMediatorModel.ts new file mode 100644 index 00000000..1d0924dd --- /dev/null +++ b/src/shared/EventMediator/model/EventMediatorModel.ts @@ -0,0 +1,46 @@ +import type { ListenerCallback } from '@/shared/types/action'; + +class EventMediatorModel { + private listeners: Map>> = new Map(); + + private static mediator = new EventMediatorModel(); + + public static getInstance(): EventMediatorModel { + return EventMediatorModel.mediator; + } + + public notify(eventName: string, params: T): void { + const eventListeners = this.listeners.get(eventName); + if (eventListeners) { + eventListeners.forEach((listener) => listener(params)); + } + } + + public subscribe(eventName: string, listener: ListenerCallback): void { + if (this.listeners.has(eventName)) { + const listeners = this.listeners.get(eventName); + listeners?.push(listener); + } else { + const newListeners = []; + newListeners.push(listener); + this.listeners.set(eventName, newListeners); + } + } + + public unsubscribe(eventName: string, listener: ListenerCallback): void { + if (this.listeners.has(eventName)) { + const listeners = this.listeners.get(eventName); + const index = listeners?.findIndex((l) => l.toString() === listener.toString()); + + if (index !== undefined && index !== -1) { + listeners?.splice(index, 1); + + if (listeners) { + this.listeners.set(eventName, listeners); + } + } + } + } +} + +export default EventMediatorModel; diff --git a/src/shared/Input/model/InputModel.ts b/src/shared/Input/model/InputModel.ts index b6b52f70..56cb7984 100644 --- a/src/shared/Input/model/InputModel.ts +++ b/src/shared/Input/model/InputModel.ts @@ -1,11 +1,13 @@ -import { IS_DISABLED } from '@/shared/constants/enums.ts'; +import type { InputParams } from '@/shared/types/form.ts'; + +import { IS_DISABLED } from '@/shared/constants/buttons.ts'; import InputView from '../view/InputView.ts'; class InputModel { private view: InputView; - constructor(attrs: Record) { + constructor(attrs: InputParams) { this.view = new InputView(attrs); } diff --git a/src/shared/Input/tests/Input.spec.ts b/src/shared/Input/tests/Input.spec.ts index 7ba608d8..5928e9bd 100644 --- a/src/shared/Input/tests/Input.spec.ts +++ b/src/shared/Input/tests/Input.spec.ts @@ -1,9 +1,16 @@ +import type { InputParams } from '@/shared/types/form.ts'; + import InputModel from '../model/InputModel.ts'; -const input = new InputModel({ - id: 'test', +const params: InputParams = { + autocomplete: 'on', + id: 'password', + lang: 'en', + placeholder: 'Enter password', type: 'password', -}); +}; + +const input = new InputModel(params); describe('Checking InputModel class', () => { it('should be defined', () => { expect(InputModel).toBeDefined(); diff --git a/src/shared/Input/view/InputView.ts b/src/shared/Input/view/InputView.ts index 73e27165..923b7307 100644 --- a/src/shared/Input/view/InputView.ts +++ b/src/shared/Input/view/InputView.ts @@ -1,17 +1,25 @@ -import { TAG_NAMES } from '@/shared/constants/enums.ts'; +import type { InputParams } from '@/shared/types/form'; + +import TAG_NAME from '@/shared/constants/tags.ts'; import createBaseElement from '@/shared/utils/createBaseElement.ts'; class InputView { private input: HTMLInputElement; - constructor(attrs: Record) { + constructor(attrs: InputParams) { this.input = this.createHTML(attrs); } - private createHTML(attrs: Record): HTMLInputElement { + private createHTML(attrs: InputParams): HTMLInputElement { this.input = createBaseElement({ - attributes: attrs, - tag: TAG_NAMES.INPUT, + attributes: { + autocomplete: attrs.autocomplete, + id: attrs.id, + lang: attrs.lang || '', + placeholder: attrs.placeholder || '', + type: attrs.type, + }, + tag: TAG_NAME.INPUT, }); return this.input; diff --git a/src/shared/Link/model/LinkModel.ts b/src/shared/Link/model/LinkModel.ts new file mode 100644 index 00000000..3f50c9b5 --- /dev/null +++ b/src/shared/Link/model/LinkModel.ts @@ -0,0 +1,31 @@ +import type { LinkAttributes } from '@/shared/types/link.ts'; + +import LinkView from '../view/LinkView.ts'; + +class LinkModel { + private params: LinkAttributes; + + private view: LinkView; + + constructor(params: LinkAttributes) { + this.params = params; + + this.view = new LinkView(this.params); + } + + public getHTML(): HTMLAnchorElement { + return this.view.getHTML(); + } + + public setDisabled(): boolean { + this.view.setDisabled(); + return true; + } + + public setEnabled(): boolean { + this.view.setEnabled(); + return true; + } +} + +export default LinkModel; diff --git a/src/shared/Link/view/LinkView.ts b/src/shared/Link/view/LinkView.ts new file mode 100644 index 00000000..e75ee000 --- /dev/null +++ b/src/shared/Link/view/LinkView.ts @@ -0,0 +1,41 @@ +import type { LinkAttributes } from '@/shared/types/link.ts'; + +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; + +import styles from './linkView.module.scss'; + +class LinkView { + private link: HTMLAnchorElement; + + constructor(params: LinkAttributes) { + this.link = this.createHTML(params); + } + + private createHTML(params: LinkAttributes): HTMLAnchorElement { + this.link = createBaseElement({ + attributes: params.attrs, + cssClasses: params.classes, + innerContent: params.text, + tag: TAG_NAME.A, + }); + + return this.link; + } + + public getHTML(): HTMLAnchorElement { + return this.link; + } + + public setDisabled(): boolean { + this.link.classList.add(styles.disabled); + return true; + } + + public setEnabled(): boolean { + this.link.classList.remove(styles.disabled); + return true; + } +} + +export default LinkView; diff --git a/src/shared/Link/view/linkView.module.scss b/src/shared/Link/view/linkView.module.scss new file mode 100644 index 00000000..8a5758d9 --- /dev/null +++ b/src/shared/Link/view/linkView.module.scss @@ -0,0 +1,4 @@ +.disabled { + opacity: 0.5; + pointer-events: none; +} diff --git a/src/shared/Loader/model/LoaderModel.ts b/src/shared/Loader/model/LoaderModel.ts new file mode 100644 index 00000000..28a2f0a2 --- /dev/null +++ b/src/shared/Loader/model/LoaderModel.ts @@ -0,0 +1,17 @@ +import type { SizesType } from '@/shared/constants/sizes.ts'; + +import LoaderView from '../view/LoaderView.ts'; + +class LoaderModel { + private view: LoaderView; + + constructor(size: SizesType) { + this.view = new LoaderView(size); + } + + public getHTML(): HTMLDivElement { + return this.view.getHTML(); + } +} + +export default LoaderModel; diff --git a/src/shared/Loader/view/LoaderView.ts b/src/shared/Loader/view/LoaderView.ts new file mode 100644 index 00000000..eeca6420 --- /dev/null +++ b/src/shared/Loader/view/LoaderView.ts @@ -0,0 +1,61 @@ +import type { SizesType } from '@/shared/constants/sizes.ts'; + +import { SIZES } from '@/shared/constants/sizes.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; + +import styles from './loaderView.module.scss'; + +class LoaderView { + private loader: HTMLDivElement; + + constructor(size: SizesType) { + this.loader = this.createHTML(size); + } + + private createHTML(size: SizesType): HTMLDivElement { + this.loader = createBaseElement({ + cssClasses: [styles.loader], + tag: TAG_NAME.DIV, + }); + + this.selectSize(size); + + return this.loader; + } + + private selectSize(size: SizesType): void { + switch (size) { + case SIZES.SMALL: + this.setSmallStyle(); + break; + case SIZES.MEDIUM: + this.setMediumStyle(); + break; + case SIZES.LARGE: + this.setLargeStyle(); + break; + default: + this.setSmallStyle(); + break; + } + } + + private setLargeStyle(): void { + this.loader.classList.add(styles.large); + } + + private setMediumStyle(): void { + this.loader.classList.add(styles.medium); + } + + private setSmallStyle(): void { + this.loader.classList.add(styles.small); + } + + public getHTML(): HTMLDivElement { + return this.loader; + } +} + +export default LoaderView; diff --git a/src/shared/Loader/view/loaderView.module.scss b/src/shared/Loader/view/loaderView.module.scss new file mode 100644 index 00000000..61c8d172 --- /dev/null +++ b/src/shared/Loader/view/loaderView.module.scss @@ -0,0 +1,38 @@ +.loader { + margin: 0 calc(var(--extra-small-offset) / 4); + border: 2px solid var(--noble-gray-200); + border-top: 2px solid var(--steam-green-800); + border-radius: 50%; + animation: spin 1s linear infinite; +} + +.small { + border: 2px solid var(--noble-gray-200); + border-top: 2px solid var(--steam-green-800); + width: 10px; + height: 10px; +} + +.medium { + border: 4px solid var(--noble-gray-200); + border-top: 4px solid var(--steam-green-800); + width: 20px; + height: 20px; +} + +.large { + border: 8px solid var(--noble-gray-200); + border-top: 8px solid var(--steam-green-800); + width: 30px; + height: 30px; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} diff --git a/src/shared/ServerMessage/model/ServerMessageModel.ts b/src/shared/ServerMessage/model/ServerMessageModel.ts new file mode 100644 index 00000000..fcb78dce --- /dev/null +++ b/src/shared/ServerMessage/model/ServerMessageModel.ts @@ -0,0 +1,15 @@ +import type { MessageStatusType } from '@/shared/constants/messages.ts'; + +import ServerMessageView from '../view/ServerMessageView.ts'; + +class ServerMessageModel { + private view: ServerMessageView = new ServerMessageView(); + + public showServerMessage(message: string, status: MessageStatusType): boolean { + return this.view.setServerMessage(message, status); + } +} + +const serverMessageModel = new ServerMessageModel(); + +export default serverMessageModel; diff --git a/src/shared/ServerMessage/test/ServerMessage.spec.ts b/src/shared/ServerMessage/test/ServerMessage.spec.ts new file mode 100644 index 00000000..3406f2f5 --- /dev/null +++ b/src/shared/ServerMessage/test/ServerMessage.spec.ts @@ -0,0 +1,14 @@ +import serverMessageModel from '../model/ServerMessageModel.ts'; +import ServerMessageView from '../view/ServerMessageView.ts'; + +describe('check serverMessageModel', () => { + it('serverMessageModel instance should be defined', () => { + expect(serverMessageModel).toBeDefined(); + }); +}); + +describe('check ServerMessageView', () => { + it('ServerMessageView instance should be defined', () => { + expect(ServerMessageView).toBeDefined(); + }); +}); diff --git a/src/shared/ServerMessage/view/ServerMessageView.ts b/src/shared/ServerMessage/view/ServerMessageView.ts new file mode 100644 index 00000000..841722a1 --- /dev/null +++ b/src/shared/ServerMessage/view/ServerMessageView.ts @@ -0,0 +1,59 @@ +import SERVER_MESSAGE_ANIMATE_DETAILS from '@/shared/constants/animations.ts'; +import { MESSAGE_STATUS, type MessageStatusType } from '@/shared/constants/messages.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; + +import styles from './serverMessageView.module.scss'; + +class ServerMessageView { + private serverMessage: HTMLSpanElement; + + private serverWrapper: HTMLDivElement; + + constructor() { + this.serverMessage = this.createServerMessage(); + this.serverWrapper = this.createHTML(); + } + + private createHTML(): HTMLDivElement { + this.serverWrapper = createBaseElement({ + cssClasses: [styles.serverMessageWrapper], + tag: TAG_NAME.DIV, + }); + + this.serverWrapper.append(this.serverMessage); + document.body.append(this.serverWrapper); + return this.serverWrapper; + } + + private createServerMessage(): HTMLSpanElement { + this.serverMessage = createBaseElement({ + cssClasses: [styles.serverMessage], + tag: TAG_NAME.SPAN, + }); + + return this.serverMessage; + } + + private startAnimation(): boolean { + this.serverWrapper.animate(SERVER_MESSAGE_ANIMATE_DETAILS.params, { + duration: SERVER_MESSAGE_ANIMATE_DETAILS.duration, + easing: SERVER_MESSAGE_ANIMATE_DETAILS.easing, + }); + return true; + } + + public getHTML(): HTMLDivElement { + return this.serverWrapper; + } + + public setServerMessage(message: string, status: MessageStatusType): boolean { + this.serverWrapper.classList.toggle(styles.error, status === MESSAGE_STATUS.ERROR); + this.serverWrapper.classList.toggle(styles.success, status === MESSAGE_STATUS.SUCCESS); + this.serverMessage.textContent = message; + this.startAnimation(); + return true; + } +} + +export default ServerMessageView; diff --git a/src/shared/ServerMessage/view/serverMessageView.module.scss b/src/shared/ServerMessage/view/serverMessageView.module.scss new file mode 100644 index 00000000..bc8f9b3c --- /dev/null +++ b/src/shared/ServerMessage/view/serverMessageView.module.scss @@ -0,0 +1,27 @@ +.serverMessageWrapper { + position: fixed; + right: 0; + top: 50%; + z-index: 1000; + border: 2px solid var(--steam-green-800); + border-top: 10px solid var(--steam-green-800); + border-radius: var(--medium-br); + padding: calc(var(--extra-small-offset) / 2) var(--extra-small-offset); + max-width: 200px; + font: var(--regular-font); + letter-spacing: 1px; + word-break: break-word; + text-align: center; + background-color: var(--white); + transform: translate(110%, -50%); +} + +.error { + border-color: var(--red-power-600); + color: var(--red-power-600); +} + +.success { + border-color: var(--steam-green-800); + color: var(--steam-green-800); +} diff --git a/src/shared/Store/Store.ts b/src/shared/Store/Store.ts index 91c82218..1eef1517 100644 --- a/src/shared/Store/Store.ts +++ b/src/shared/Store/Store.ts @@ -1,16 +1,12 @@ -/* eslint-disable import/no-unresolved */ /* eslint-disable @typescript-eslint/consistent-type-assertions */ -// import { saveCurrentStateToLocalStorage } from ''; - import type { Action, State } from './reducer.ts'; import type { Reducer, ReduxStore } from './types'; +import { EVENT_NAME } from '../constants/events.ts'; +import initialState from '../constants/initialState.ts'; +import { STORAGE_KEY, saveCurrentStateToLocalStorage } from '../services/localStorage.ts'; import { rootReducer } from './reducer.ts'; -const initialState: State = { - currentUser: null, -}; - export class Store implements ReduxStore { private listeners: VoidFunction[] = []; @@ -19,7 +15,7 @@ export class Store implements ReduxStore { private state: S; constructor(initialData: S, rootReducer: Reducer) { - const storedData: null | string = sessionStorage.getItem(''); + const storedData: null | string = localStorage.getItem(STORAGE_KEY); let stateToSet: S; @@ -32,7 +28,7 @@ export class Store implements ReduxStore { this.state = structuredClone(stateToSet); this.rootReducer = rootReducer; - // window.addEventListener('beforeunload', () => saveCurrentStateToLocalStorage(this.state)); + window.addEventListener(EVENT_NAME.BEFOREUNLOAD, () => saveCurrentStateToLocalStorage(this.state)); } public dispatch(action: A): A { diff --git a/src/shared/Store/actions.ts b/src/shared/Store/actions.ts index abcc798b..77494a3d 100644 --- a/src/shared/Store/actions.ts +++ b/src/shared/Store/actions.ts @@ -1,18 +1,50 @@ -/* eslint-disable import/prefer-default-export */ +import type { Category, Product } from '../types/product'; +import type { User } from '../types/user'; + const ACTION = { + SET_BILLING_COUNTRY: 'setBillingCountry', + SET_CATEGORIES: 'setCategories', + SET_CURRENT_LANGUAGE: 'setCurrentLanguage', SET_CURRENT_USER: 'setCurrentUser', + SET_PRODUCTS: 'setProducts', + SET_SHIPPING_COUNTRY: 'setShippingCountry', } as const; -type ActionType = (typeof ACTION)[keyof typeof ACTION]; +export type ActionType = (typeof ACTION)[keyof typeof ACTION]; interface ActionWithPayload { payload: T; type: U; } -export const setCurrentUser = ( - value: null | string, -): ActionWithPayload => ({ +export const setCategories = (value: Category[]): ActionWithPayload => ({ + payload: value, + type: ACTION.SET_CATEGORIES, +}); + +export const setProducts = (value: Product[]): ActionWithPayload => ({ + payload: value, + type: ACTION.SET_PRODUCTS, +}); + +export const setCurrentUser = (value: User | null): ActionWithPayload => ({ payload: value, type: ACTION.SET_CURRENT_USER, }); + +export const setBillingCountry = (value: string): ActionWithPayload => ({ + payload: value, + type: ACTION.SET_BILLING_COUNTRY, +}); + +export const setShippingCountry = (value: string): ActionWithPayload => ({ + payload: value, + type: ACTION.SET_SHIPPING_COUNTRY, +}); + +export const setCurrentLanguage = ( + value: 'en' | 'ru', +): ActionWithPayload<'en' | 'ru', typeof ACTION.SET_CURRENT_LANGUAGE> => ({ + payload: value, + type: ACTION.SET_CURRENT_LANGUAGE, +}); diff --git a/src/shared/Store/observer.ts b/src/shared/Store/observer.ts index a444a380..2739e96e 100644 --- a/src/shared/Store/observer.ts +++ b/src/shared/Store/observer.ts @@ -1,23 +1,29 @@ -import type { Action, State } from './reducer.ts'; -import type { ReduxStore } from './types'; +import type { User } from '../types/user.ts'; +import type { State } from './reducer.ts'; -function observeStore( - store: ReduxStore, - select: (state: State) => T, - onChange: (selectedState: T) => void, -): VoidFunction { - let currentState = select(store.getState()); +import getStore from './Store.ts'; + +function observeStore(select: (state: State) => T, onChange: (selectedState: T) => void): VoidFunction { + let currentState = select(getStore().getState()); function handleChange(): void { - const nextState = select(store.getState()); - if (nextState !== currentState) { + const nextState = select(getStore().getState()); + if (JSON.stringify(nextState) !== JSON.stringify(currentState)) { currentState = nextState; onChange(currentState); } } - const unsubscribe = store.subscribe(handleChange); + const unsubscribe = getStore().subscribe(handleChange); return unsubscribe; } +export const selectCurrentUser = (state: State): User | null => state.currentUser; + +export const selectBillingCountry = (state: State): string => state.billingCountry; + +export const selectShippingCountry = (state: State): string => state.shippingCountry; + +export const selectCurrentLanguage = (state: State): string => state.currentLanguage; + export default observeStore; diff --git a/src/shared/Store/reducer.ts b/src/shared/Store/reducer.ts index 5e30201d..7b1cbd17 100644 --- a/src/shared/Store/reducer.ts +++ b/src/shared/Store/reducer.ts @@ -1,9 +1,16 @@ /* eslint-disable max-lines-per-function */ +import type { Category, Product } from '../types/product.ts'; +import type { User } from '../types/user.ts'; import type * as actions from './actions.ts'; import type { Reducer } from './types.ts'; export interface State { - currentUser: null | string; + billingCountry: string; + categories: Category[]; + currentLanguage: 'en' | 'ru'; + currentUser: User | null; + products: Product[]; + shippingCountry: string; } type InferValueTypes = T extends { [key: string]: infer U } ? U : never; @@ -16,6 +23,31 @@ export const rootReducer: Reducer = (state: State, action: Action ...state, currentUser: action.payload, }; + case 'setShippingCountry': + return { + ...state, + shippingCountry: action.payload, + }; + case 'setBillingCountry': + return { + ...state, + billingCountry: action.payload, + }; + case 'setCategories': + return { + ...state, + categories: action.payload, + }; + case 'setProducts': + return { + ...state, + products: action.payload, + }; + case 'setCurrentLanguage': + return { + ...state, + currentLanguage: action.payload, + }; default: return state; } diff --git a/src/shared/Store/test.spec.ts b/src/shared/Store/test.spec.ts index fded5d63..e4edd73d 100644 --- a/src/shared/Store/test.spec.ts +++ b/src/shared/Store/test.spec.ts @@ -1,16 +1,229 @@ +import type { Category, Product } from '../types/product.ts'; +import type { User } from '../types/user.ts'; +import type { State } from './reducer.ts'; + import getStore, { Store } from './Store.ts'; +import * as actions from './actions.ts'; +import observeStore, { selectBillingCountry, selectCurrentUser, selectShippingCountry } from './observer.ts'; +import { rootReducer } from './reducer.ts'; -const store = getStore(); describe('Checking Store', () => { + const mockStore = getStore(); it('should check if store is defined', () => { - expect(store).toBeDefined(); + expect(mockStore).toBeDefined(); }); it('should check if store is an instance of Store', () => { - expect(store).toBeInstanceOf(Store); + expect(mockStore).toBeInstanceOf(Store); }); it('should check to return an instance of Store', () => { - expect(store.getState() instanceof Object).toBe(true); + expect(mockStore.getState() instanceof Object).toBe(true); + }); +}); + +describe('Actions', () => { + it('Checking actions', () => { + expect(actions).toBeDefined(); + }); +}); + +it('should check if setCurrentUser is a function', () => { + expect(actions.setCurrentUser).toBeInstanceOf(Function); +}); + +it('should check if setShippingCountry is a function', () => { + expect(actions.setShippingCountry).toBeInstanceOf(Function); +}); + +it('should check if setBillingCountry is a function', () => { + expect(actions.setBillingCountry).toBeInstanceOf(Function); +}); + +it('should check if setCategories is a function', () => { + expect(actions.setCategories).toBeInstanceOf(Function); +}); + +it('should check if setProducts is a function', () => { + expect(actions.setProducts).toBeInstanceOf(Function); +}); + +it('setCategories should create a correct action', () => { + const value: Category[] = []; + const action = actions.setCategories(value); + expect(action.type).toBe('setCategories'); + expect(action.payload).toBe(value); +}); + +it('setProducts should create a correct action', () => { + const value: Product[] = []; + const action = actions.setProducts(value); + expect(action.type).toBe('setProducts'); + expect(action.payload).toBe(value); +}); + +it('setCurrentUser should create a correct action', () => { + const value: User | null = null; + const action = actions.setCurrentUser(value); + expect(action.type).toBe('setCurrentUser'); + expect(action.payload).toBe(value); +}); + +it('setShippingCountry should create a correct action', () => { + const value = ''; + const action = actions.setShippingCountry(value); + expect(action.type).toBe('setShippingCountry'); + expect(action.payload).toBe(value); +}); + +it('setBillingCountry should create a correct action', () => { + const value = ''; + const action = actions.setBillingCountry(value); + expect(action.type).toBe('setBillingCountry'); + expect(action.payload).toBe(value); +}); + +vi.mock('./Store.ts', async (importOriginal) => { + const actual: typeof importOriginal = await importOriginal(); + return { + ...actual, + getState: (): State => ({ + billingCountry: '', + categories: [], + currentLanguage: 'en', + currentUser: null, + products: [], + shippingCountry: '', + }), + }; +}); + +describe('ObserveStore', () => { + it('should check if observeStore is a function', () => { + expect(observeStore).toBeInstanceOf(Function); + }); +}); + +it('should check if selectCurrentUser is a function', () => { + expect(selectCurrentUser).toBeInstanceOf(Function); +}); + +it('should check if selectBillingCountry is a function', () => { + expect(selectBillingCountry).toBeInstanceOf(Function); +}); + +it('should check if selectShippingCountry is a function', () => { + expect(selectShippingCountry).toBeInstanceOf(Function); +}); + +it('observeStore should call select and onChange when state changes', () => { + const mockUser = { + addresses: [], + birthDate: '1990-01-01', + defaultBillingAddressId: null, + defaultShippingAddressId: null, + email: 'test@test.test', + firstName: 'Test', + id: 'test', + lastName: 'Test', + locale: 'en', + password: 'Testtest1', + version: 0, + }; + + const mockState: State = { + billingCountry: '', + categories: [], + currentLanguage: 'en', + currentUser: mockUser, + products: [], + shippingCountry: '', + }; + + const mockOnChange = vitest.fn(); + const selelectCurrentUserSpy = vitest.spyOn(actions, 'setCurrentUser'); + const mockSelect = vitest.fn(() => selectCurrentUser(mockState)); + const unsubscribe = observeStore(mockSelect, mockOnChange); + + expect(selectCurrentUser(mockState)).toBe(mockUser); + actions.setCurrentUser(mockUser); + + expect(selelectCurrentUserSpy).toHaveBeenCalledWith(mockUser); + + unsubscribe(); +}); + +describe('rootReducer', () => { + let initialState: State; + + beforeEach(() => { + initialState = { + billingCountry: '', + categories: [], + currentLanguage: 'en', + currentUser: null, + products: [], + shippingCountry: '', + }; + }); + + it('should handle setCurrentUser action', () => { + const user: User = { + addresses: [], + birthDate: '1990-01-01', + defaultBillingAddressId: null, + defaultShippingAddressId: null, + email: 'test@test.test', + firstName: 'Test', + id: 'test', + lastName: 'Test', + locale: 'en', + password: 'Testtest1', + version: 0, + }; + const action = actions.setCurrentUser(user); + const newState = rootReducer(initialState, action); + expect(newState.currentUser).toEqual(user); + }); + + it('should handle setShippingCountry action', () => { + const country = 'US'; + const action = actions.setShippingCountry(country); + const newState = rootReducer(initialState, action); + expect(newState.shippingCountry).toEqual(country); + }); + + it('should handle setBillingCountry action', () => { + const country = 'UK'; + const action = actions.setBillingCountry(country); + const newState = rootReducer(initialState, action); + expect(newState.billingCountry).toEqual(country); + }); + + it('should handle setCategories action', () => { + const categories: Category[] = []; + const action = actions.setCategories(categories); + const newState = rootReducer(initialState, action); + expect(newState.categories).toEqual(categories); + }); + + it('should handle setProducts action', () => { + const products: Product[] = []; + const action = actions.setProducts(products); + const newState = rootReducer(initialState, action); + expect(newState.products).toEqual(products); + }); + + it('should handle setCurrentLanguage action', () => { + const language = 'ru'; + const action = actions.setCurrentLanguage(language); + const newState = rootReducer(initialState, action); + expect(newState.currentLanguage).toEqual(language); + }); + + it('should return the same state for unknown action types', () => { + const action = actions.setCurrentUser(null); + const newState = rootReducer(initialState, action); + expect(newState).toEqual(initialState); }); }); diff --git a/src/shared/constants/animations.ts b/src/shared/constants/animations.ts new file mode 100644 index 00000000..b74c279b --- /dev/null +++ b/src/shared/constants/animations.ts @@ -0,0 +1,17 @@ +const SERVER_MESSAGE_ANIMATE_PARAMS = [ + { transform: 'translateX(110%)' }, + { transform: 'translateX(-10%)' }, + { transform: 'translateX(-10%)' }, + { opacity: 1, transform: 'translateX(-10%)' }, + { opacity: 0, transform: 'translate(-10%, -110%)' }, +]; + +const SERVER_MESSAGE_ANIMATE_DETAILS = { + duration: 5500, + easing: 'cubic-bezier(0, 0.2, 0.58, 0.7)', + params: SERVER_MESSAGE_ANIMATE_PARAMS, +}; + +export const PAGE_TIMEOUT_DURATION = 200; + +export default SERVER_MESSAGE_ANIMATE_DETAILS; diff --git a/src/shared/constants/buttons.ts b/src/shared/constants/buttons.ts new file mode 100644 index 00000000..b5d91fa5 --- /dev/null +++ b/src/shared/constants/buttons.ts @@ -0,0 +1,39 @@ +export const BUTTON_TYPE = { + BUTTON: 'button', + RESET: 'reset', + SUBMIT: 'submit', +} as const; + +export const BUTTON_TEXT = { + en: { + BACK_TO_MAIN: 'Back to main', + LOG_OUT: 'Log out', + LOGIN: 'Login', + REGISTRATION: 'Register', + }, + ru: { + BACK_TO_MAIN: 'Вернуться на главную', + LOG_OUT: 'Выйти', + LOGIN: 'Войти', + REGISTRATION: 'Зарегистрироваться', + }, +} as const; + +export const BUTTON_TEXT_KEYS = { + BACK_TO_MAIN: 'BACK_TO_MAIN', + LOG_OUT: 'LOG_OUT', + LOGIN: 'LOGIN', + REGISTRATION: 'REGISTRATION', +} as const; + +export type ButtonTextKeysType = (typeof BUTTON_TEXT_KEYS)[keyof typeof BUTTON_TEXT_KEYS]; + +export const IS_DISABLED = { + DISABLED: true, + ENABLED: false, +} as const; + +export const LANGUAGE_CHOICE = { + EN: 'en', + RU: 'ru', +} as const; diff --git a/src/shared/constants/countriesList.ts b/src/shared/constants/countriesList.ts new file mode 100644 index 00000000..ad9ffa7b --- /dev/null +++ b/src/shared/constants/countriesList.ts @@ -0,0 +1,412 @@ +type CountryCodes = { + [countryName: string]: string; +}; + +const COUNTRIES_LIST: Record = { + en: { + Afghanistan: 'AF', + Albania: 'AL', + Algeria: 'DZ', + Andorra: 'AD', + Angola: 'AO', + 'Antigua and Barbuda': 'AG', + Argentina: 'AR', + Armenia: 'AM', + Australia: 'AU', + Austria: 'AT', + Azerbaijan: 'AZ', + Bahamas: 'BS', + Bahrain: 'BH', + Bangladesh: 'BD', + Barbados: 'BB', + Belarus: 'BY', + Belgium: 'BE', + Belize: 'BZ', + Benin: 'BJ', + Bhutan: 'BT', + Bolivia: 'BO', + 'Bosnia and Herzegovina': 'BA', + Botswana: 'BW', + Brazil: 'BR', + Brunei: 'BN', + Bulgaria: 'BG', + 'Burkina Faso': 'BF', + Burundi: 'BI', + 'Cabo Verde': 'CV', + Cambodia: 'KH', + Cameroon: 'CM', + Canada: 'CA', + 'Central African Republic': 'CF', + Chad: 'TD', + Chile: 'CL', + China: 'CN', + 'Christmas Island': 'CX', + 'Cocos (Keeling) Islands': 'CC', + Colombia: 'CO', + Comoros: 'KM', + 'Congo, Democratic Republic of the': 'CD', + 'Congo, Republic of the': 'CG', + 'Costa Rica': 'CR', + Croatia: 'HR', + Cuba: 'CU', + Curaçao: 'CW', + Cyprus: 'CY', + 'Czech Republic': 'CZ', + "Côte d'Ivoire": 'CI', + Denmark: 'DK', + Djibouti: 'DJ', + Dominica: 'DM', + 'Dominican Republic': 'DO', + Ecuador: 'EC', + Egypt: 'EG', + 'El Salvador': 'SV', + 'Equatorial Guinea': 'GQ', + Eritrea: 'ER', + Estonia: 'EE', + Eswatini: 'SZ', + Ethiopia: 'ET', + Fiji: 'FJ', + Finland: 'FI', + France: 'FR', + Gabon: 'GA', + Gambia: 'GM', + Georgia: 'GE', + Germany: 'DE', + Ghana: 'GH', + Greece: 'GR', + Grenada: 'GD', + Guatemala: 'GT', + Guinea: 'GN', + 'Guinea-Bissau': 'GW', + Guyana: 'GY', + Haiti: 'HT', + Honduras: 'HN', + Hungary: 'HU', + Iceland: 'IS', + India: 'IN', + Indonesia: 'ID', + Iran: 'IR', + Iraq: 'IQ', + Ireland: 'IE', + Israel: 'IL', + Italy: 'IT', + Jamaica: 'JM', + Japan: 'JP', + Jordan: 'JO', + Kazakhstan: 'KZ', + Kenya: 'KE', + Kiribati: 'KI', + 'Korea, North': 'KP', + 'Korea, South': 'KR', + Kosovo: 'XK', + Kuwait: 'KW', + Kyrgyzstan: 'KG', + Laos: 'LA', + Latvia: 'LV', + Lebanon: 'LB', + Lesotho: 'LS', + Liberia: 'LR', + Libya: 'LY', + Liechtenstein: 'LI', + Lithuania: 'LT', + Luxembourg: 'LU', + Madagascar: 'MG', + Malawi: 'MW', + Malaysia: 'MY', + Maldives: 'MV', + Mali: 'ML', + Malta: 'MT', + 'Marshall Islands': 'MH', + Mauritania: 'MR', + Mauritius: 'MU', + Mexico: 'MX', + Micronesia: 'FM', + Moldova: 'MD', + Monaco: 'MC', + Mongolia: 'MN', + Montenegro: 'ME', + Morocco: 'MA', + Mozambique: 'MZ', + Myanmar: 'MM', + Namibia: 'NA', + Nauru: 'NR', + Nepal: 'NP', + Netherlands: 'NL', + 'New Zealand': 'NZ', + Nicaragua: 'NI', + Niger: 'NE', + Nigeria: 'NG', + 'North Macedonia': 'MK', + Norway: 'NO', + Oman: 'OM', + Pakistan: 'PK', + Palau: 'PW', + Palestine: 'PS', + Panama: 'PA', + 'Papua New Guinea': 'PG', + Paraguay: 'PY', + Peru: 'PE', + Philippines: 'PH', + Poland: 'PL', + Portugal: 'PT', + Qatar: 'QA', + Romania: 'RO', + Russia: 'RU', + Rwanda: 'RW', + 'Saint Kitts and Nevis': 'KN', + 'Saint Lucia': 'LC', + 'Saint Vincent and the Grenadines': 'VC', + Samoa: 'WS', + 'San Marino': 'SM', + 'Sao Tome and Principe': 'ST', + 'Saudi Arabia': 'SA', + Senegal: 'SN', + Serbia: 'RS', + Seychelles: 'SC', + 'Sierra Leone': 'SL', + Singapore: 'SG', + Slovakia: 'SK', + Slovenia: 'SI', + 'Solomon Islands': 'SB', + Somalia: 'SO', + 'South Africa': 'ZA', + 'South Sudan': 'SS', + Spain: 'ES', + 'Sri Lanka': 'LK', + Sudan: 'SD', + Suriname: 'SR', + Sweden: 'SE', + Switzerland: 'CH', + Syria: 'SY', + Taiwan: 'TW', + Tajikistan: 'TJ', + Tanzania: 'TZ', + Thailand: 'TH', + 'Timor-Leste': 'TL', + Togo: 'TG', + Tonga: 'TO', + 'Trinidad and Tobago': 'TT', + Tunisia: 'TN', + Turkey: 'TR', + Turkmenistan: 'TM', + Tuvalu: 'TV', + Uganda: 'UG', + Ukraine: 'UA', + 'United Arab Emirates': 'AE', + 'United Kingdom': 'GB', + 'United States': 'US', + Uruguay: 'UY', + Uzbekistan: 'UZ', + Vanuatu: 'VU', + 'Vatican City': 'VA', + Venezuela: 'VE', + Vietnam: 'VN', + Yemen: 'YE', + Zambia: 'ZM', + Zimbabwe: 'ZW', + }, + ru: { + Австралия: 'AU', + Австрия: 'AT', + Азербайджан: 'AZ', + Албания: 'AL', + Алжир: 'DZ', + Ангола: 'AO', + Андорра: 'AD', + 'Антигуа и Барбуда': 'AG', + Аргентина: 'AR', + Армения: 'AM', + Афганистан: 'AF', + Багамы: 'BS', + Бангладеш: 'BD', + Барбадос: 'BB', + Бахрейн: 'BH', + Беларусь: 'BY', + Белиз: 'BZ', + Бельгия: 'BE', + Бенин: 'BJ', + Болгария: 'BG', + Боливия: 'BO', + 'Босния и Герцеговина': 'BA', + Ботсвана: 'BW', + Бразилия: 'BR', + Бруней: 'BN', + 'Буркина-Фасо': 'BF', + Бурунди: 'BI', + Бутан: 'BT', + Вануату: 'VU', + Ватикан: 'VA', + Великобритания: 'GB', + Венгрия: 'HU', + Венесуэла: 'VE', + 'Восточный Тимор': 'TL', + Вьетнам: 'VN', + Габон: 'GA', + Гаити: 'HT', + Гайана: 'GY', + Гамбия: 'GM', + Гана: 'GH', + Гватемала: 'GT', + Гвинея: 'GN', + 'Гвинея-Бисау': 'GW', + Германия: 'DE', + Гондурас: 'HN', + Гренада: 'GD', + Греция: 'GR', + Грузия: 'GE', + Дания: 'DK', + 'Демократическая Республика Конго': 'CD', + Джибути: 'DJ', + Доминика: 'DM', + 'Доминиканская Республика': 'DO', + Египет: 'EG', + Замбия: 'ZM', + Зимбабве: 'ZW', + Израиль: 'IL', + Индия: 'IN', + Индонезия: 'ID', + Иордания: 'JO', + Ирак: 'IQ', + Иран: 'IR', + Ирландия: 'IE', + Исландия: 'IS', + Испания: 'ES', + Италия: 'IT', + Йемен: 'YE', + КНДР: 'KP', + 'Кабо-Верде': 'CV', + Казахстан: 'KZ', + Камбоджа: 'KH', + Камерун: 'CM', + Канада: 'CA', + Катар: 'QA', + Кения: 'KE', + Кипр: 'CY', + Киргизия: 'KG', + Кирибати: 'KI', + Китай: 'CN', + 'Кокосовые (Килинг) острова': 'CC', + Колумбия: 'CO', + 'Коморские острова': 'KM', + Косово: 'XK', + 'Коста-Рика': 'CR', + 'Кот-д’Ивуар': 'CI', + Куба: 'CU', + Кувейт: 'KW', + Кюрасао: 'CW', + Лаос: 'LA', + Латвия: 'LV', + Лесото: 'LS', + Либерия: 'LR', + Ливан: 'LB', + Ливия: 'LY', + Литва: 'LT', + Лихтенштейн: 'LI', + Люксембург: 'LU', + Маврикий: 'MU', + Мавритания: 'MR', + Мадагаскар: 'MG', + Малави: 'MW', + Малайзия: 'MY', + Мали: 'ML', + Мальдивы: 'MV', + Мальта: 'MT', + Марокко: 'MA', + 'Маршалловы острова': 'MH', + Мексика: 'MX', + Микронезия: 'FM', + Мозамбик: 'MZ', + Молдавия: 'MD', + Монако: 'MC', + Монголия: 'MN', + Мьянма: 'MM', + Намибия: 'NA', + Науру: 'NR', + Непал: 'NP', + Нигер: 'NE', + Нигерия: 'NG', + Нидерланды: 'NL', + Никарагуа: 'NI', + 'Новая Зеландия': 'NZ', + Норвегия: 'NO', + 'Объединенные Арабские Эмираты': 'AE', + Оман: 'OM', + 'Остров Рождества': 'CX', + Пакистан: 'PK', + Палау: 'PW', + Палестина: 'PS', + Панама: 'PA', + 'Папуа — Новая Гвинея': 'PG', + Парагвай: 'PY', + Перу: 'PE', + Польша: 'PL', + Португалия: 'PT', + 'Республика Конго': 'CG', + 'Республика Корея': 'KR', + Россия: 'RU', + Руанда: 'RW', + Румыния: 'RO', + Сальвадор: 'SV', + Самоа: 'WS', + 'Сан-Марино': 'SM', + 'Сан-Томе и Принсипи': 'ST', + 'Саудовская Аравия': 'SA', + Свазиленд: 'SZ', + 'Северная Македония': 'MK', + 'Сейшельские Острова': 'SC', + Сенегал: 'SN', + 'Сент-Винсент и Гренадины': 'VC', + 'Сент-Китс и Невис': 'KN', + 'Сент-Люсия': 'LC', + Сербия: 'RS', + Сингапур: 'SG', + Сирия: 'SY', + Словакия: 'SK', + Словения: 'SI', + 'Соединенные Штаты': 'US', + 'Соломоновы Острова': 'SB', + Сомали: 'SO', + Судан: 'SD', + Суринам: 'SR', + 'Сьерра-Леоне': 'SL', + Таджикистан: 'TJ', + Таиланд: 'TH', + Тайвань: 'TW', + Танзания: 'TZ', + Того: 'TG', + Тонга: 'TO', + 'Тринидад и Тобаго': 'TT', + Тувалу: 'TV', + Тунис: 'TN', + Туркменистан: 'TM', + Турция: 'TR', + Уганда: 'UG', + Узбекистан: 'UZ', + Украина: 'UA', + Уругвай: 'UY', + Фиджи: 'FJ', + Филиппины: 'PH', + Финляндия: 'FI', + Франция: 'FR', + Хорватия: 'HR', + 'Центральноафриканская Республика': 'CF', + Чад: 'TD', + Черногория: 'ME', + 'Чешская Республика': 'CZ', + Чили: 'CL', + Швейцария: 'CH', + Швеция: 'SE', + 'Шри-Ланка': 'LK', + Эквадор: 'EC', + 'Экваториальная Гвинея': 'GQ', + Эритрея: 'ER', + Эстония: 'EE', + Эфиопия: 'ET', + 'Южная Африка': 'ZA', + 'Южный Судан': 'SS', + Ямайка: 'JM', + Япония: 'JP', + }, +} as const; + +export default COUNTRIES_LIST; diff --git a/src/shared/constants/enums.ts b/src/shared/constants/enums.ts deleted file mode 100644 index bd41a15d..00000000 --- a/src/shared/constants/enums.ts +++ /dev/null @@ -1,103 +0,0 @@ -export const INPUT_TYPES = { - COLOR: 'color', - DATE: 'date', - EMAIL: 'email', - NUMBER: 'number', - PASSWORD: 'password', - RANGE: 'range', - SEARCH: 'search', - TEXT: 'text', -} as const; - -export const BUTTON_TYPES = { - BUTTON: 'button', - RESET: 'reset', - SUBMIT: 'submit', -} as const; - -export const IS_DISABLED = { - DISABLED: true, - ENABLED: false, -} as const; - -export const TAG_NAMES = { - A: 'a', - ADDRESS: 'address', - ARTICLE: 'article', - ASIDE: 'aside', - AUDIO: 'audio', - BLOCKQUOTE: 'blockquote', - BUTTON: 'button', - CANVAS: 'canvas', - DETAILS: 'details', - DIV: 'div', - DIVIDER: 'hr', - FOOTER: 'footer', - FORM: 'form', - H1: 'h1', - H2: 'h2', - H3: 'h3', - H4: 'h4', - H5: 'h5', - H6: 'h6', - HEADER: 'header', - I: 'i', - IMG: 'img', - INPUT: 'input', - LABEL: 'label', - LI: 'li', - MAIN: 'main', - MAP: 'map', - MARK: 'mark', - NAV: 'nav', - OL: 'ol', - P: 'p', - PRE: 'pre', - SECTION: 'section', - SELECT: 'select', - SOURCE: 'source', - SPAN: 'span', - SUMMARY: 'summary', - SVG: 'svg', - TABLE: 'table', - TBODY: 'tbody', - TD: 'td', - TEXTAREA: 'textarea', - TFOOT: 'tfoot', - TH: 'th', - THEAD: 'thead', - TR: 'tr', - TRACK: 'track', - UL: 'ul', - VIDEO: 'video', -} as const; - -export const EVENT_NAMES = { - ANIMATIONEND: 'animationend', - ANIMATIONITERATION: 'animationiteration', - ANIMATIONSTART: 'animationstart', - BEFOREUNLOAD: 'beforeunload', - BLUR: 'blur', - CHANGE: 'change', - CLICK: 'click', - CLOSE: 'close', - CONTEXTMENU: 'contextmenu', - DOM_CONTENT_LOADED: 'DOMContentLoaded', - ERROR: 'error', - FOCUS: 'focus', - HASHCHANGE: 'hashchange', - INPUT: 'input', - KEYDOWN: 'keydown', - KEYUP: 'keyup', - LOAD: 'load', - MESSAGE: 'message', - MOUSEENTER: 'mouseenter', - MOUSELEAVE: 'mouseleave', - MOUSEWHEEL: 'mousewheel', - OPEN: 'open', - POPSTATE: 'popstate', - RESIZE: 'resize', - SCROLL: 'scroll', - SUBMIT: 'submit', - TRANSITIONEND: 'transitionend', -} as const; diff --git a/src/shared/constants/events.ts b/src/shared/constants/events.ts new file mode 100644 index 00000000..ddfb3fcd --- /dev/null +++ b/src/shared/constants/events.ts @@ -0,0 +1,34 @@ +export const EVENT_NAME = { + ANIMATIONEND: 'animationend', + ANIMATIONITERATION: 'animationiteration', + ANIMATIONSTART: 'animationstart', + BEFOREUNLOAD: 'beforeunload', + BLUR: 'blur', + CHANGE: 'change', + CLICK: 'click', + CLOSE: 'close', + CONTEXTMENU: 'contextmenu', + DOM_CONTENT_LOADED: 'DOMContentLoaded', + ERROR: 'error', + FOCUS: 'focus', + HASHCHANGE: 'hashchange', + INPUT: 'input', + KEYDOWN: 'keydown', + KEYUP: 'keyup', + LOAD: 'load', + MESSAGE: 'message', + MOUSEENTER: 'mouseenter', + MOUSELEAVE: 'mouseleave', + MOUSEWHEEL: 'mousewheel', + OPEN: 'open', + POPSTATE: 'popstate', + RESIZE: 'resize', + SCROLL: 'scroll', + SUBMIT: 'submit', + TRANSITIONEND: 'transitionend', +} as const; + +export const MEDIATOR_EVENT = { + CHANGE_PAGE: 'changePage', + USER_LOGIN: 'userLogin', +} as const; diff --git a/src/shared/constants/forms.ts b/src/shared/constants/forms.ts new file mode 100644 index 00000000..d0342ecf --- /dev/null +++ b/src/shared/constants/forms.ts @@ -0,0 +1,36 @@ +export const INPUT_TYPE = { + CHECK_BOX: 'checkbox', + COLOR: 'color', + DATE: 'date', + EMAIL: 'email', + NUMBER: 'number', + PASSWORD: 'password', + RANGE: 'range', + SEARCH: 'search', + TEXT: 'text', +} as const; + +export const FORM_TEXT = { + DEFAULT_ADDRESS: 'Use as default address', + SINGLE_ADDRESS: 'Use as billing address', +}; + +export const USER_COUNTRY_ADDRESS = { + BILLING: 'billingCountry', + SHIPPING: 'shippingCountry', +} as const; + +export const USER_ADDRESS_TYPE = { + BILLING: 'billingAddress', + SHIPPING: 'shippingAddress', +} as const; + +export const USER_POSTAL_CODE = { + BILLING_POSTAL_CODE: 'billing_PostalCode', + POSTAL_CODE: 'postalCode', +} as const; + +export const PASSWORD_TEXT = { + HIDDEN: '********', + SHOWN: 'Password123', +}; diff --git a/src/shared/constants/forms/login/constants.ts b/src/shared/constants/forms/login/constants.ts new file mode 100644 index 00000000..20036780 --- /dev/null +++ b/src/shared/constants/forms/login/constants.ts @@ -0,0 +1,3 @@ +const KEY = 'login_'; + +export default KEY; diff --git a/src/shared/constants/forms/login/fieldParams.ts b/src/shared/constants/forms/login/fieldParams.ts new file mode 100644 index 00000000..e10374f4 --- /dev/null +++ b/src/shared/constants/forms/login/fieldParams.ts @@ -0,0 +1,29 @@ +import KEY from './constants.ts'; + +export const EMAIL_FIELD = { + inputParams: { + autocomplete: 'off', + id: `${KEY}email`, + placeholder: 'user@example.com', + type: 'text', + }, + labelParams: { + for: `${KEY}email`, + text: '', + }, +} as const; + +export const PASSWORD_FIELD = { + inputParams: { + autocomplete: 'off', + id: `${KEY}password`, + placeholder: '***********', + type: 'password', + }, + labelParams: { + for: `${KEY}password`, + text: '', + }, +} as const; + +export const INPUT_FIELD = [EMAIL_FIELD, PASSWORD_FIELD]; diff --git a/src/shared/constants/forms/login/validationParams.ts b/src/shared/constants/forms/login/validationParams.ts new file mode 100644 index 00000000..0fa23703 --- /dev/null +++ b/src/shared/constants/forms/login/validationParams.ts @@ -0,0 +1,38 @@ +import KEY from './constants.ts'; + +const EMAIL_FIELD_VALIDATE = { + key: `${KEY}email`, + notWhitespace: { + messages: { en: 'Email must not contain white spaces', ru: 'Почтовый адрес не может содержать пробелы' }, + pattern: /^\S+$/, + }, + required: true, + validMail: { + messages: { + en: 'Enter correct email (user@example.com)', + ru: 'Введите корректный почтовый адрес (user@example.com)', + }, + pattern: /^([a-z0-9_-]+\.)*[a-z0-9_-]+@[a-z0-9_-]+(\.[a-z0-9_-]+)*\.[a-z]{2,6}$/, + }, +} as const; + +const PASSWORD_FIELD_VALIDATE = { + key: `${KEY}password`, + minLength: 8, + notWhitespace: { + messages: { en: 'Password must not contain white spaces', ru: 'Пароль не может содержать пробелы' }, + pattern: /^\S+$/, + }, + required: true, + requiredSymbols: { + messages: { + en: 'Password must contain English letters, at least one letter in upper and lower case and at least one number', + ru: 'Пароль должен содержать английские буквы, хотя бы одну букву в верхнем регистре и в нижнем регистре и хотя бы одну цифру', + }, + pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+/, + }, +} as const; + +const INPUT_FIELD_VALIDATION = [EMAIL_FIELD_VALIDATE, PASSWORD_FIELD_VALIDATE]; + +export default INPUT_FIELD_VALIDATION; diff --git a/src/shared/constants/forms/register/constant.ts b/src/shared/constants/forms/register/constant.ts new file mode 100644 index 00000000..0bada779 --- /dev/null +++ b/src/shared/constants/forms/register/constant.ts @@ -0,0 +1,25 @@ +export const KEY = 'registration_'; + +export const TITLE_TEXT = { + en: { + BILLING_ADDRESS: 'Billing address', + CREDENTIALS: 'Credentials', + PERSONAL: 'Personal', + SHIPPING_ADDRESS: 'Shipping address', + }, + ru: { + BILLING_ADDRESS: 'Адрес выставления счетов', + CREDENTIALS: 'Логин и пароль', + PERSONAL: 'Личные данные', + SHIPPING_ADDRESS: 'Адрес доставки', + }, +} as const; + +export const TITLE_TEXT_KEYS = { + BILLING_ADDRESS: 'BILLING_ADDRESS', + CREDENTIALS: 'CREDENTIALS', + PERSONAL: 'PERSONAL', + SHIPPING_ADDRESS: 'SHIPPING_ADDRESS', +} as const; + +export type TitleTextKeysType = (typeof TITLE_TEXT_KEYS)[keyof typeof TITLE_TEXT_KEYS]; diff --git a/src/shared/constants/forms/register/fieldParams.ts b/src/shared/constants/forms/register/fieldParams.ts new file mode 100644 index 00000000..489ba1eb --- /dev/null +++ b/src/shared/constants/forms/register/fieldParams.ts @@ -0,0 +1,192 @@ +export const EMAIL = { + inputParams: { + autocomplete: 'off', + id: 'registration_email', + placeholder: 'user@example.com', + type: 'text', + }, + labelParams: { + for: 'registration_email', + text: 'Email *', + }, +} as const; + +export const PASSWORD = { + inputParams: { + autocomplete: 'off', + id: 'registration_password', + placeholder: '***********', + type: 'password', + }, + labelParams: { + for: 'registration_password', + text: 'Password *', + }, +} as const; + +export const FIRST_NAME = { + inputParams: { + autocomplete: 'off', + id: 'firstName', + placeholder: 'John', + type: 'text', + }, + labelParams: { + for: 'firstName', + text: 'First name *', + }, +} as const; + +export const LAST_NAME = { + inputParams: { + autocomplete: 'off', + id: 'lastName', + placeholder: 'Doe', + type: 'text', + }, + labelParams: { + for: 'lastName', + text: 'Last name *', + }, +} as const; + +export const BIRTHDAY = { + inputParams: { + autocomplete: 'off', + id: 'birthDate', + lang: 'en', + placeholder: '01.01.2000', + type: 'date', + }, + labelParams: { + for: 'birthDate', + text: 'Date of Birth *', + }, +} as const; + +export const SHIPPING_ADDRESS_STREET = { + inputParams: { + autocomplete: 'off', + id: 'address', + placeholder: '595 Hornby St. 5th Floor', + type: 'text', + }, + labelParams: { + for: 'address', + text: 'Address *', + }, +} as const; + +export const SHIPPING_ADDRESS_CITY = { + inputParams: { + autocomplete: 'off', + id: 'city', + placeholder: 'Vancouver', + type: 'text', + }, + labelParams: { + for: 'city', + text: 'City *', + }, +} as const; + +export const SHIPPING_ADDRESS_COUNTRY = { + inputParams: { + autocomplete: 'off', + id: 'shippingCountry', + placeholder: 'Canada', + type: 'text', + }, + labelParams: { + for: 'shippingCountry', + text: 'Country *', + }, +} as const; + +export const SHIPPING_ADDRESS_POSTAL_CODE = { + inputParams: { + autocomplete: 'off', + id: 'postalCode', + placeholder: 'A1B 2C3', + type: 'text', + }, + labelParams: { + for: 'postalCode', + text: 'Postal code *', + }, +} as const; + +export const BILLING_ADDRESS_STREET = { + inputParams: { + autocomplete: 'off', + id: 'billing_address', + placeholder: '595 Hornby St. 5th Floor', + type: 'text', + }, + labelParams: { + for: 'billing_address', + text: 'Address *', + }, +} as const; + +export const BILLING_ADDRESS_CITY = { + inputParams: { + autocomplete: 'off', + id: 'billing_city', + placeholder: 'Vancouver', + type: 'text', + }, + labelParams: { + for: 'billing_city', + text: 'City *', + }, +} as const; + +export const BILLING_ADDRESS_COUNTRY = { + inputParams: { + autocomplete: 'off', + id: 'billing_country', + placeholder: 'Canada', + type: 'text', + }, + labelParams: { + for: 'billing_country', + text: 'Country *', + }, +} as const; + +export const BILLING_ADDRESS_POSTAL_CODE = { + inputParams: { + autocomplete: 'off', + id: 'billing_postalCode', + placeholder: 'A1B 2C3', + type: 'text', + }, + labelParams: { + for: 'billing_postalCode', + text: 'Postal code *', + }, +} as const; + +export const INPUT = [ + EMAIL, + PASSWORD, + FIRST_NAME, + LAST_NAME, + BIRTHDAY, + SHIPPING_ADDRESS_STREET, + SHIPPING_ADDRESS_CITY, + SHIPPING_ADDRESS_COUNTRY, + SHIPPING_ADDRESS_POSTAL_CODE, + BILLING_ADDRESS_STREET, + BILLING_ADDRESS_CITY, + BILLING_ADDRESS_COUNTRY, + BILLING_ADDRESS_POSTAL_CODE, +]; + +export const CHECKBOX = { + AUTOCOMPLETE: 'off', + BILLING_ID: 'billingDefault', + SHIPPING_ID: 'shippingDefault', + SINGLE_ID: 'singleDefault', +} as const; diff --git a/src/shared/constants/forms/register/validationParams.ts b/src/shared/constants/forms/register/validationParams.ts new file mode 100644 index 00000000..04b138c2 --- /dev/null +++ b/src/shared/constants/forms/register/validationParams.ts @@ -0,0 +1,165 @@ +const EMAIL_VALIDATE = { + key: 'registration_email', + notWhitespace: { + messages: { en: 'Email must not contain white spaces', ru: 'Почтовый адрес не может содержать пробелы' }, + pattern: /^\S+$/, + }, + required: true, + validMail: { + messages: { + en: 'Enter correct email (user@example.com)', + ru: 'Введите корректный почтовый адрес (user@example.com)', + }, + pattern: /^([a-z0-9_-]+\.)*[a-z0-9_-]+@[a-z0-9_-]+(\.[a-z0-9_-]+)*\.[a-z]{2,6}$/, + }, +} as const; + +const PASSWORD_VALIDATE = { + key: 'registration_password', + minLength: 8, + notWhitespace: { + messages: { en: 'Password must not contain white spaces', ru: 'Пароль не может содержать пробелы' }, + pattern: /^\S+$/, + }, + required: true, + requiredSymbols: { + messages: { + en: 'Password must contain English letters, at least one letter in upper and lower case and at least one number', + ru: 'Пароль должен содержать английские буквы, хотя бы одну букву в верхнем регистре и в нижнем регистре и хотя бы одну цифру', + }, + pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+/, + }, +} as const; + +const FIRST_NAME_VALIDATE = { + key: 'firstName', + minLength: 1, + notSpecialSymbols: { + messages: { + en: 'First name must contain only letters', + ru: 'Имя должно содержать только буквы', + }, + pattern: /^[a-zA-Z]*$/, + }, + notWhitespace: { + messages: { + en: 'First name must not contain white spaces', + ru: 'Имя не может содержать пробелы', + }, + pattern: /^\S+$/, + }, + required: true, +} as const; + +const LAST_NAME_VALIDATE = { + key: 'lastName', + minLength: 1, + notSpecialSymbols: { + messages: { + en: 'Last name must contain only letters', + ru: 'Фамилия должна содержать только буквы', + }, + pattern: /^[a-zA-Z]*$/, + }, + notWhitespace: { + messages: { + en: 'Last name must not contain white spaces', + ru: 'Фамилия не может содержать пробелы', + }, + pattern: /^\S+$/, + }, + required: true, +} as const; + +const BIRTHDAY_VALIDATE = { + key: 'birthDate', + required: true, + validBirthday: { + maxAge: 120, + messages: { + en: 'Enter correct birthday (01.01.2000)', + ru: 'Введите корректный день рождения (01.01.2000)', + }, + minAge: 18, + pattern: /^\d{4}-\d{2}-\d{2}$/, + }, +} as const; + +export const SHIPPING_ADDRESS_STREET_VALIDATE = { + key: 'address', + minLength: 1, + required: true, +}; + +export const SHIPPING_ADDRESS_CITY_VALIDATE = { + key: 'city', + minLength: 1, + notSpecialSymbols: { + messages: { + en: 'City must contain only letters', + ru: 'Город должен содержать только буквы', + }, + pattern: /^[a-zA-Z]*$/, + }, + + required: true, +}; + +export const SHIPPING_ADDRESS_COUNTRY_VALIDATE = { + key: 'shippingCountry', + required: true, + validCountry: true, +}; + +export const SHIPPING_ADDRESS_POSTAL_CODE_VALIDATE = { + key: 'postalCode', + required: true, + validPostalCode: true, +}; + +export const BILLING_ADDRESS_STREET_VALIDATE = { + key: 'billing_address', + minLength: 1, + required: true, +}; + +export const BILLING_ADDRESS_CITY_VALIDATE = { + key: 'billing_city', + minLength: 1, + notSpecialSymbols: { + messages: { + en: 'City must contain only letters', + ru: 'Город должен содержать только буквы', + }, + pattern: /^[a-zA-Z]*$/, + }, + required: true, +}; + +export const BILLING_ADDRESS_COUNTRY_VALIDATE = { + key: 'billing_country', + required: true, + validCountry: true, +}; + +export const BILLING_ADDRESS_POSTAL_CODE_VALIDATE = { + key: 'billing_postalCode', + required: true, + validPostalCode: true, +}; + +export const INPUT_VALIDATION = [ + EMAIL_VALIDATE, + PASSWORD_VALIDATE, + FIRST_NAME_VALIDATE, + LAST_NAME_VALIDATE, + BIRTHDAY_VALIDATE, + SHIPPING_ADDRESS_STREET_VALIDATE, + SHIPPING_ADDRESS_CITY_VALIDATE, + SHIPPING_ADDRESS_COUNTRY_VALIDATE, + SHIPPING_ADDRESS_POSTAL_CODE_VALIDATE, + BILLING_ADDRESS_STREET_VALIDATE, + BILLING_ADDRESS_CITY_VALIDATE, + BILLING_ADDRESS_COUNTRY_VALIDATE, + BILLING_ADDRESS_POSTAL_CODE_VALIDATE, +]; diff --git a/src/shared/constants/initialState.ts b/src/shared/constants/initialState.ts new file mode 100644 index 00000000..e70a5248 --- /dev/null +++ b/src/shared/constants/initialState.ts @@ -0,0 +1,12 @@ +import type { State } from '../Store/reducer'; + +const initialState: State = { + billingCountry: '', + categories: [], + currentLanguage: 'en', + currentUser: null, + products: [], + shippingCountry: '', +}; + +export default initialState; diff --git a/src/shared/constants/keyboard.ts b/src/shared/constants/keyboard.ts new file mode 100644 index 00000000..5af32cb0 --- /dev/null +++ b/src/shared/constants/keyboard.ts @@ -0,0 +1,7 @@ +export const KEYBOARD_KEYS = { + ENTER: 'Enter', + ESC: 'Escape', + TAB: 'Tab', +} as const; + +export type KeyboardKeysType = (typeof KEYBOARD_KEYS)[keyof typeof KEYBOARD_KEYS]; diff --git a/src/shared/constants/messages.ts b/src/shared/constants/messages.ts new file mode 100644 index 00000000..48706d4f --- /dev/null +++ b/src/shared/constants/messages.ts @@ -0,0 +1,37 @@ +export const MESSAGE_STATUS = { + ERROR: 'error', + SUCCESS: 'success', +} as const; + +export type MessageStatusType = (typeof MESSAGE_STATUS)[keyof typeof MESSAGE_STATUS]; + +export const SERVER_MESSAGE = { + BAD_REQUEST: 'Sorry, something went wrong. Try again later.', + INCORRECT_PASSWORD: 'Please, enter a correct password', + INVALID_EMAIL: "User with this email doesn't exist. Please, register first", + SUCCESSFUL_LOGIN: 'Enjoy shopping!', + SUCCESSFUL_REGISTRATION: 'Your registration was successful', + USER_EXISTS: 'User with this email already exists, please check your email', +} as const; + +export const ERROR_MESSAGE = { + en: { + INVALID_COUNTRY: 'Invalid country', + INVALID_POSTAL_CODE: 'Invalid postal code', + REQUIRED_FIELD: 'Field is required', + WRONG_REGION: "Sorry, we don't deliver to your region yet", + }, + ru: { + INVALID_COUNTRY: 'Неверный код страны', + INVALID_POSTAL_CODE: 'Неверный почтовый индекс', + REQUIRED_FIELD: 'Поле обязательно для заполнения', + WRONG_REGION: 'Извините, мы не доставляем в вашу область', + }, +} as const; + +export const ERROR_MESSAGE_KEYS = { + INVALID_COUNTRY: 'INVALID_COUNTRY', + INVALID_POSTAL_CODE: 'INVALID_POSTAL_CODE', + REQUIRED_FIELD: 'REQUIRED_FIELD', + WRONG_REGION: 'WRONG_REGION', +} as const; diff --git a/src/shared/constants/pages.ts b/src/shared/constants/pages.ts new file mode 100644 index 00000000..4d148022 --- /dev/null +++ b/src/shared/constants/pages.ts @@ -0,0 +1,66 @@ +export const PAGE_LINK_TEXT = { + en: { + LOGIN: 'Login', + MAIN: 'Main', + REGISTRATION: 'Register', + }, + ru: { + LOGIN: 'Вход', + MAIN: 'Главная', + REGISTRATION: 'Регистрация', + }, +} as const; + +export const PAGE_LINK_TEXT_KEYS = { + LOGIN: 'LOGIN', + MAIN: 'MAIN', + REGISTRATION: 'REGISTRATION', +} as const; + +export const PAGE_DESCRIPTION = { + en: { + 404: 'This is not the page you are looking for. Please go back to the main page.', + GREETING: 'Hi, ', + LOGIN: 'Enter your email and password to login.', + REGISTRATION: 'Enter your information to register.', + }, + ru: { + 404: 'Это не та страница, которую ты ищешь. Пожалуйста, вернись на главную страницу.', + GREETING: 'Привет, ', + LOGIN: 'Введите почту и пароль для входа.', + REGISTRATION: 'Введите информацию о себе для регистрации.', + }, +} as const; + +export const PAGE_DESCRIPTION_KEYS = { + 404: '404', + GREETING: 'GREETING', + LOGIN: 'LOGIN', + REGISTRATION: 'REGISTRATION', +} as const; + +export type PageDescriptionKeysType = (typeof PAGE_DESCRIPTION_KEYS)[keyof typeof PAGE_DESCRIPTION_KEYS]; + +export const PAGE_ANSWER = { + en: { + LOGIN: `Don't have an account yet?`, + REGISTRATION: `Already have an account?`, + }, + ru: { + LOGIN: `Ещё нет аккаунта?`, + REGISTRATION: `Уже есть аккаунт?`, + }, +} as const; + +export const PAGE_ANSWER_KEYS = { + LOGIN: 'LOGIN', + REGISTRATION: 'REGISTRATION', +} as const; + +export const PAGE_ID = { + DEFAULT_PAGE: '', + LOGIN_PAGE: 'login', + MAIN_PAGE: 'main', + NOT_FOUND_PAGE: '404', + REGISTRATION_PAGE: 'register', +} as const; diff --git a/src/shared/constants/sizes.ts b/src/shared/constants/sizes.ts new file mode 100644 index 00000000..59ff07b3 --- /dev/null +++ b/src/shared/constants/sizes.ts @@ -0,0 +1,9 @@ +export const SIZES = { + EXTRA_LARGE: 'xl', + EXTRA_SMALL: 'xs', + LARGE: 'l', + MEDIUM: 'm', + SMALL: 's', +} as const; + +export type SizesType = (typeof SIZES)[keyof typeof SIZES]; diff --git a/src/shared/constants/svg.ts b/src/shared/constants/svg.ts new file mode 100644 index 00000000..0204c3fe --- /dev/null +++ b/src/shared/constants/svg.ts @@ -0,0 +1,9 @@ +const SVG_DETAILS = { + CLOSE_EYE: 'closeEye', + LOGO: 'logo', + OPEN_EYE: 'openEye', + + SVG_URL: 'http://www.w3.org/2000/svg', +} as const; + +export default SVG_DETAILS; diff --git a/src/shared/constants/tags.ts b/src/shared/constants/tags.ts new file mode 100644 index 00000000..ccac45ae --- /dev/null +++ b/src/shared/constants/tags.ts @@ -0,0 +1,54 @@ +const TAG_NAME = { + A: 'a', + ADDRESS: 'address', + ARTICLE: 'article', + ASIDE: 'aside', + AUDIO: 'audio', + BLOCKQUOTE: 'blockquote', + BUTTON: 'button', + CANVAS: 'canvas', + DETAILS: 'details', + DIV: 'div', + DIVIDER: 'hr', + FOOTER: 'footer', + FORM: 'form', + H1: 'h1', + H2: 'h2', + H3: 'h3', + H4: 'h4', + H5: 'h5', + H6: 'h6', + HEADER: 'header', + I: 'i', + IMG: 'img', + INPUT: 'input', + LABEL: 'label', + LI: 'li', + MAIN: 'main', + MAP: 'map', + MARK: 'mark', + NAV: 'nav', + OL: 'ol', + P: 'p', + PRE: 'pre', + SECTION: 'section', + SELECT: 'select', + SOURCE: 'source', + SPAN: 'span', + STRONG: 'strong', + SUMMARY: 'summary', + SVG: 'svg', + TABLE: 'table', + TBODY: 'tbody', + TD: 'td', + TEXTAREA: 'textarea', + TFOOT: 'tfoot', + TH: 'th', + THEAD: 'thead', + TR: 'tr', + TRACK: 'track', + UL: 'ul', + VIDEO: 'video', +} as const; + +export default TAG_NAME; diff --git a/src/shared/img/svg/calendar.svg b/src/shared/img/svg/calendar.svg new file mode 100644 index 00000000..c7a34389 --- /dev/null +++ b/src/shared/img/svg/calendar.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/shared/img/svg/closeEye.svg b/src/shared/img/svg/closeEye.svg new file mode 100644 index 00000000..36cdc7af --- /dev/null +++ b/src/shared/img/svg/closeEye.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/shared/img/svg/logo.svg b/src/shared/img/svg/logo.svg new file mode 100644 index 00000000..2ce33218 --- /dev/null +++ b/src/shared/img/svg/logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/shared/img/svg/openEye.svg b/src/shared/img/svg/openEye.svg new file mode 100644 index 00000000..5f4f6d68 --- /dev/null +++ b/src/shared/img/svg/openEye.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/shared/services/localStorage.spec.ts b/src/shared/services/localStorage.spec.ts new file mode 100644 index 00000000..deb0083e --- /dev/null +++ b/src/shared/services/localStorage.spec.ts @@ -0,0 +1,11 @@ +import { clearLocalStorage, saveCurrentStateToLocalStorage } from './localStorage.ts'; + +describe('Checking Local Storage', () => { + it('{} should return {}', () => { + expect(saveCurrentStateToLocalStorage({})).toStrictEqual({}); + }); + + it('clearLocalStorage should return {}', () => { + expect(clearLocalStorage()).toStrictEqual({}); + }); +}); diff --git a/src/shared/services/localStorage.ts b/src/shared/services/localStorage.ts new file mode 100644 index 00000000..c4eae09b --- /dev/null +++ b/src/shared/services/localStorage.ts @@ -0,0 +1,11 @@ +export const STORAGE_KEY = '3a981d01-2a98-4e10-8869-8b5839202195'; + +export function saveCurrentStateToLocalStorage(state: S): S { + localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); + return state; +} + +export function clearLocalStorage(): Record { + localStorage.removeItem(STORAGE_KEY); + return {}; +} diff --git a/src/shared/types/types.ts b/src/shared/types/action.ts similarity index 72% rename from src/shared/types/types.ts rename to src/shared/types/action.ts index 109b6e94..06dd67a9 100644 --- a/src/shared/types/types.ts +++ b/src/shared/types/action.ts @@ -1,4 +1,4 @@ -type ActionsType = +type ActionType = | 'animationend' | 'animationiteration' | 'animationstart' @@ -24,5 +24,5 @@ type ActionsType = | 'transitionrun' | 'transitionstart'; -type ButtonActionType = { key: ActionsType; value: () => void }; -export default ButtonActionType; +export type ButtonActionType = { key: ActionType; value: () => void }; +export type ListenerCallback = (params: T) => void; diff --git a/src/shared/types/button.ts b/src/shared/types/button.ts new file mode 100644 index 00000000..d5c74962 --- /dev/null +++ b/src/shared/types/button.ts @@ -0,0 +1,8 @@ +import type { ButtonActionType } from './action.ts'; + +export interface ButtonAttributes { + action?: ButtonActionType; + attrs?: Record; + classes?: string[]; + text?: string; +} diff --git a/src/shared/types/common.ts b/src/shared/types/common.ts new file mode 100644 index 00000000..a06f777e --- /dev/null +++ b/src/shared/types/common.ts @@ -0,0 +1,3 @@ +export interface Page { + getHTML(): HTMLDivElement; +} diff --git a/src/shared/types/form.ts b/src/shared/types/form.ts new file mode 100644 index 00000000..b4838a8f --- /dev/null +++ b/src/shared/types/form.ts @@ -0,0 +1,48 @@ +export interface InputParams { + autocomplete: 'off' | 'on'; + id: string; + lang?: string; + placeholder: null | string; + type: 'checkbox' | 'color' | 'date' | 'email' | 'number' | 'password' | 'search' | 'tel' | 'text'; +} + +export interface LabelParams { + for: string; + text: null | string; +} + +export interface InputFieldParams { + inputParams: InputParams; + labelParams?: LabelParams | null; +} + +export interface InputFieldValidatorParams { + key: string; + maxLength?: null | number; + minLength?: null | number; + notSpecialSymbols?: { + messages: Record; + pattern: RegExp; + } | null; + notWhitespace?: { + messages: Record; + pattern: RegExp; + } | null; + required?: boolean | null; + requiredSymbols?: { + messages: Record; + pattern: RegExp; + } | null; + validBirthday?: { + maxAge: number; + messages: Record; + minAge: number; + pattern: RegExp; + } | null; + validCountry?: boolean; + validMail?: { + messages: Record; + pattern: RegExp; + } | null; + validPostalCode?: boolean; +} diff --git a/src/shared/types/interfaces.ts b/src/shared/types/interfaces.ts deleted file mode 100644 index 3074be3d..00000000 --- a/src/shared/types/interfaces.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type ButtonActionType from './types.ts'; - -interface ButtonAttributesInterface { - action?: ButtonActionType; - attrs?: Record; - classes?: string[]; - text?: string; -} - -export default ButtonAttributesInterface; diff --git a/src/shared/types/link.ts b/src/shared/types/link.ts new file mode 100644 index 00000000..c2114b5e --- /dev/null +++ b/src/shared/types/link.ts @@ -0,0 +1,5 @@ +export interface LinkAttributes { + attrs?: Record; + classes?: string[]; + text?: string; +} diff --git a/src/shared/types/product.ts b/src/shared/types/product.ts new file mode 100644 index 00000000..3375bdbc --- /dev/null +++ b/src/shared/types/product.ts @@ -0,0 +1,34 @@ +export interface localization { + language: string; + value: string; +} + +export interface Category { + id: string; + key: string; + name: localization[]; +} + +export enum Size { + L = 'L', + M = 'M', + S = 'S', + XL = 'XL', +} + +export interface Variant { + discount: number; + price: number; + size: Size | null; +} + +export interface Product { + category: Category[]; + description: localization[]; + fullDescription: localization[]; + id: string; + images: string[]; + key: string; + name: localization[]; + variant: Variant[]; +} diff --git a/src/shared/types/user.ts b/src/shared/types/user.ts new file mode 100644 index 00000000..c6127070 --- /dev/null +++ b/src/shared/types/user.ts @@ -0,0 +1,34 @@ +export interface UserLoginData { + email: string; + password: string; +} + +export interface User { + addresses: Address[]; + birthDate: string; + defaultBillingAddressId: Address | null; + defaultShippingAddressId: Address | null; + email: string; + firstName: string; + id: string; + lastName: string; + locale: string; + password: string; + version: number; +} + +export interface FormAddress { + city: string; + country: string; + postalCode: string; + streetName: string; +} + +export interface Address extends FormAddress { + email: string; + firstName: string; + id: string; + lastName: string; + state: string; + streetNumber: string; +} diff --git a/src/shared/types/validation/test.spec.ts b/src/shared/types/validation/test.spec.ts new file mode 100644 index 00000000..b006436b --- /dev/null +++ b/src/shared/types/validation/test.spec.ts @@ -0,0 +1,63 @@ +import * as User from './user.ts'; + +describe('test', () => { + it('isUserLoginData', () => { + expect(User.isUserLoginData({ email: 'a', password: 'b' })).toBe(true); + expect(User.isUserLoginData({ email: 1, password: 'b' })).toBe(false); + expect(User.isUserLoginData({ email: 'a', password: 2 })).toBe(false); + expect(User.isUserLoginData({ email: true, password: null })).toBe(false); + expect(User.isUserLoginData({ email: {}, password: [] })).toBe(false); + }); + + it('isFormAddress', () => { + expect(User.isFormAddress({ city: 'a', country: 'b', postalCode: 'c', streetName: 'd' })).toBe(true); + expect(User.isFormAddress({ city: 1, country: 'b', postalCode: 'c', streetName: 'd' })).toBe(false); + expect(User.isFormAddress({ city: 'a', country: 2, postalCode: 'c', streetName: 'd' })).toBe(false); + expect(User.isFormAddress({ city: 'a', country: 'b', postalCode: 3, streetName: 'd' })).toBe(false); + expect(User.isFormAddress({ city: 'a', country: 'b', postalCode: 'c', streetName: 4 })).toBe(false); + expect(User.isFormAddress({ city: true, country: null, postalCode: {}, streetName: [] })).toBe(false); + expect(User.isFormAddress({ city: {}, country: [], postalCode: {}, streetName: {} })).toBe(false); + expect(User.isFormAddress({})).toBe(false); + }); + + it('isUser', () => { + expect( + User.isUser({ + addresses: [], + birthDate: 'b', + defaultBillingAddressId: null, + defaultShippingAddressId: null, + email: 'c', + firstName: 'd', + id: 'e', + lastName: 'f', + locale: 'g', + password: 'h', + version: 1, + }), + ).toBe(true); + expect(User.isUser({})).toBe(false); + }); + + it('isUserLoginData', () => { + expect(User.isFormAddress({})).toBe(false); + }); + + it('isAddress', () => { + expect(User.isAddress({})).toBe(false); + expect( + User.isAddress({ + city: 'a', + country: 'b', + email: 'e', + firstName: 'f', + id: 'h', + lastName: 'g', + postalCode: 'c', + state: 'j', + streetName: 'd', + streetNumber: 'k', + }), + ).toBe(true); + }); +}); diff --git a/src/shared/types/validation/user.ts b/src/shared/types/validation/user.ts new file mode 100644 index 00000000..12e46e0f --- /dev/null +++ b/src/shared/types/validation/user.ts @@ -0,0 +1,72 @@ +import type { Address, FormAddress, User, UserLoginData } from '../user'; + +export const isUserLoginData = (data: unknown): data is UserLoginData => + typeof data === 'object' && + data !== null && + 'email' in data && + 'password' in data && + typeof data.email === 'string' && + typeof data.password === 'string'; + +export const isFormAddress = (data: unknown): data is FormAddress => + typeof data === 'object' && + data !== null && + 'city' in data && + 'country' in data && + 'postalCode' in data && + 'streetName' in data && + typeof data.city === 'string' && + typeof data.country === 'string' && + typeof data.postalCode === 'string' && + typeof data.streetName === 'string'; + +export const isAddress = (data: unknown): data is Address => + typeof data === 'object' && + data !== null && + 'city' in data && + 'country' in data && + 'postalCode' in data && + 'streetName' in data && + 'email' in data && + 'firstName' in data && + 'id' in data && + 'lastName' in data && + 'state' in data && + 'streetNumber' in data && + typeof data.city === 'string' && + typeof data.country === 'string' && + typeof data.postalCode === 'string' && + typeof data.streetName === 'string' && + typeof data.email === 'string' && + typeof data.firstName === 'string' && + typeof data.id === 'string' && + typeof data.lastName === 'string' && + typeof data.state === 'string' && + typeof data.streetNumber === 'string'; + +export const isUser = (data: unknown): data is User => + typeof data === 'object' && + data !== null && + 'addresses' in data && + 'birthDate' in data && + 'defaultBillingAddressId' in data && + 'defaultShippingAddressId' in data && + 'email' in data && + 'firstName' in data && + 'id' in data && + 'lastName' in data && + 'locale' in data && + 'password' in data && + 'version' in data && + Array.isArray(data.addresses) && + data.addresses.every((address) => isAddress(address)) && + typeof data.birthDate === 'string' && + (isAddress(data.defaultBillingAddressId) || data.defaultBillingAddressId === null) && + (isAddress(data.defaultShippingAddressId) || data.defaultBillingAddressId === null) && + typeof data.email === 'string' && + typeof data.firstName === 'string' && + typeof data.id === 'string' && + typeof data.lastName === 'string' && + typeof data.locale === 'string' && + typeof data.password === 'string' && + typeof data.version === 'number'; diff --git a/src/shared/utils/getCountryIndex.ts b/src/shared/utils/getCountryIndex.ts new file mode 100644 index 00000000..34f36250 --- /dev/null +++ b/src/shared/utils/getCountryIndex.ts @@ -0,0 +1,8 @@ +import getStore from '../Store/Store.ts'; +import COUNTRIES_LIST from '../constants/countriesList.ts'; + +export default function getCountryIndex(country: string): string { + const { currentLanguage } = getStore().getState(); + const countryIndex: string = COUNTRIES_LIST[currentLanguage][country]; + return countryIndex; +} diff --git a/src/shared/utils/isKeyOfUserData.ts b/src/shared/utils/isKeyOfUserData.ts new file mode 100644 index 00000000..403b36dc --- /dev/null +++ b/src/shared/utils/isKeyOfUserData.ts @@ -0,0 +1,6 @@ +import type { UserLoginData } from '../types/user'; + +const isKeyOfUserData = (context: UserLoginData, key: string): key is keyof UserLoginData => + Object.hasOwnProperty.call(context, key); + +export default isKeyOfUserData; diff --git a/src/shared/utils/observeCurrentLanguage.ts b/src/shared/utils/observeCurrentLanguage.ts new file mode 100644 index 00000000..61fa8de5 --- /dev/null +++ b/src/shared/utils/observeCurrentLanguage.ts @@ -0,0 +1,20 @@ +import getStore from '../Store/Store.ts'; +import observeStore, { selectCurrentLanguage } from '../Store/observer.ts'; + +function observeCurrentLanguage( + el: HTMLElement | Node, + map: Record>, + text: string, +): boolean { + const element = el; + const textNode = [...element.childNodes].find((child) => child.nodeType === Node.TEXT_NODE); + + if (textNode) { + observeStore(selectCurrentLanguage, () => { + textNode.textContent = map[getStore().getState().currentLanguage][text]; + }); + } + return true; +} + +export default observeCurrentLanguage; diff --git a/src/shared/utils/size.ts b/src/shared/utils/size.ts new file mode 100644 index 00000000..262394ef --- /dev/null +++ b/src/shared/utils/size.ts @@ -0,0 +1,13 @@ +import { Size } from '../types/product.ts'; + +export default function getSize(sizeString: string): Size | null { + const sizeValues = Object.values(Size); + + const foundValue = sizeValues.find((value) => value.toLowerCase() === sizeString.toLowerCase()); + + if (foundValue) { + return foundValue; + } + + return null; +} diff --git a/src/shared/utils/tests.spec.ts b/src/shared/utils/tests.spec.ts index 4c3ace0c..da0336d0 100644 --- a/src/shared/utils/tests.spec.ts +++ b/src/shared/utils/tests.spec.ts @@ -2,6 +2,8 @@ import { BaseComponent } from './baseComponent.ts'; import BaseElement from './baseElement.ts'; import createBaseElement from './createBaseElement.ts'; import createSVGUse from './createSVGUse.ts'; +import getCountryIndex from './getCountryIndex.ts'; +import isKeyOfUserData from './isKeyOfUserData.ts'; import { isNotNullable, isNullable } from './isNullable.ts'; import { a, div, h2, h3, iconFromCode, img, input, label, main, span } from './tags.ts'; @@ -228,3 +230,24 @@ describe('Checking tags functions', () => { expect(img({ src: 'test' }).getNode()).toBeInstanceOf(HTMLImageElement); }); }); + +describe('Checking getCountryIndex function', () => { + it('Afghanistan country should return AF', () => { + expect(getCountryIndex('Afghanistan')).toBe('AF'); + }); + + it('Canada country should return CA', () => { + expect(getCountryIndex('Canada')).toBe('CA'); + }); +}); + +const userData = { + email: 'user@example.com', + password: 'test', +}; + +describe('Checking isKeyOfUserData function', () => { + it('Email should return true', () => { + expect(isKeyOfUserData(userData, 'email')).toBe(true); + }); +}); diff --git a/src/widgets/Footer/.gitkeep b/src/widgets/Footer/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/widgets/Footer/model/FooterModel.ts b/src/widgets/Footer/model/FooterModel.ts new file mode 100644 index 00000000..32072b08 --- /dev/null +++ b/src/widgets/Footer/model/FooterModel.ts @@ -0,0 +1,27 @@ +import type RouterModel from '@/app/Router/model/RouterModel.ts'; + +import NavigationModel from '@/entities/Navigation/model/NavigationModel.ts'; + +import FooterView from '../view/FooterView.ts'; + +class FooterModel { + private navigation: NavigationModel; + + private view = new FooterView(); + + constructor(router: RouterModel) { + this.navigation = new NavigationModel(router); + this.init(); + } + + private init(): boolean { + this.getHTML().append(this.navigation.getHTML()); + return true; + } + + public getHTML(): HTMLElement { + return this.view.getHTML(); + } +} + +export default FooterModel; diff --git a/src/widgets/Footer/view/FooterView.ts b/src/widgets/Footer/view/FooterView.ts new file mode 100644 index 00000000..fa72034c --- /dev/null +++ b/src/widgets/Footer/view/FooterView.ts @@ -0,0 +1,26 @@ +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; + +import styles from './footerView.module.scss'; + +class FooterView { + private footer: HTMLElement; + + constructor() { + this.footer = this.createHTML(); + } + + private createHTML(): HTMLElement { + this.footer = createBaseElement({ + cssClasses: [styles.footer], + tag: TAG_NAME.FOOTER, + }); + return this.footer; + } + + public getHTML(): HTMLElement { + return this.footer; + } +} + +export default FooterView; diff --git a/src/widgets/Footer/view/footerView.module.scss b/src/widgets/Footer/view/footerView.module.scss new file mode 100644 index 00000000..5b748941 --- /dev/null +++ b/src/widgets/Footer/view/footerView.module.scss @@ -0,0 +1,10 @@ +.footer { + display: flex; + align-items: center; + justify-content: center; + margin-top: var(--medium-offset); + border-top: 10px solid var(--steam-green-800); + border-radius: var(--medium-br); + padding: calc(var(--small-offset) / 2) var(--small-offset); + background-color: var(--white); +} diff --git a/src/widgets/Header/.gitkeep b/src/widgets/Header/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/widgets/Header/model/HeaderModel.ts b/src/widgets/Header/model/HeaderModel.ts new file mode 100644 index 00000000..f64311f7 --- /dev/null +++ b/src/widgets/Header/model/HeaderModel.ts @@ -0,0 +1,94 @@ +import type RouterModel from '@/app/Router/model/RouterModel.ts'; + +import NavigationModel from '@/entities/Navigation/model/NavigationModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { setCurrentLanguage, setCurrentUser } from '@/shared/Store/actions.ts'; +import observeStore, { selectCurrentUser } from '@/shared/Store/observer.ts'; +import { LANGUAGE_CHOICE } from '@/shared/constants/buttons.ts'; +import { EVENT_NAME } from '@/shared/constants/events.ts'; +import { PAGE_ID } from '@/shared/constants/pages.ts'; + +import HeaderView from '../view/HeaderView.ts'; + +class HeaderModel { + private navigation: NavigationModel; + + private router: RouterModel; + + private view = new HeaderView(); + + constructor(router: RouterModel) { + this.router = router; + this.navigation = new NavigationModel(this.router); + this.init(); + } + + private checkCurrentUser(): boolean { + const { currentUser } = getStore().getState(); + const logoutButton = this.view.getLogoutButton(); + if (currentUser) { + logoutButton.setEnabled(); + } else { + logoutButton.setDisabled(); + } + return true; + } + + private init(): boolean { + this.getHTML().append(this.navigation.getHTML()); + this.checkCurrentUser(); + this.setLogoHandler(); + this.observeCurrentUser(); + this.setLogoutButtonHandler(); + this.setChangeLanguageButtonHandler(); + return true; + } + + private logoutHandler(): boolean { + localStorage.clear(); + getStore().dispatch(setCurrentUser(null)); + this.router.navigateTo(PAGE_ID.LOGIN_PAGE); + return true; + } + + private observeCurrentUser(): boolean { + observeStore(selectCurrentUser, () => { + this.checkCurrentUser(); + }); + return true; + } + + private setChangeLanguageButtonHandler(): boolean { + const changeLanguageButton = this.view.getChangeLanguageButton(); + changeLanguageButton.getHTML().addEventListener(EVENT_NAME.CLICK, () => { + const { currentLanguage } = getStore().getState(); + const newLanguage = currentLanguage === LANGUAGE_CHOICE.EN ? LANGUAGE_CHOICE.RU : LANGUAGE_CHOICE.EN; + changeLanguageButton.getHTML().innerText = newLanguage; + getStore().dispatch(setCurrentLanguage(newLanguage)); + }); + return true; + } + + private setLogoHandler(): boolean { + const logo = this.view.getLinkLogo().getHTML(); + logo.addEventListener(EVENT_NAME.CLICK, (event) => { + event.preventDefault(); + this.router.navigateTo(PAGE_ID.DEFAULT_PAGE); + }); + return true; + } + + private setLogoutButtonHandler(): boolean { + const logoutButton = this.view.getLogoutButton(); + logoutButton.getHTML().addEventListener(EVENT_NAME.CLICK, () => { + this.logoutHandler(); + logoutButton.setDisabled(); + }); + return true; + } + + public getHTML(): HTMLElement { + return this.view.getHTML(); + } +} +export default HeaderModel; diff --git a/src/widgets/Header/view/HeaderView.ts b/src/widgets/Header/view/HeaderView.ts new file mode 100644 index 00000000..e8f1012c --- /dev/null +++ b/src/widgets/Header/view/HeaderView.ts @@ -0,0 +1,92 @@ +import ButtonModel from '@/shared/Button/model/ButtonModel.ts'; +import LinkModel from '@/shared/Link/model/LinkModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { BUTTON_TEXT, BUTTON_TEXT_KEYS } from '@/shared/constants/buttons.ts'; +import { PAGE_ID } from '@/shared/constants/pages.ts'; +import SVG_DETAILS from '@/shared/constants/svg.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; +import createSVGUse from '@/shared/utils/createSVGUse.ts'; +import observeCurrentLanguage from '@/shared/utils/observeCurrentLanguage.ts'; + +import styles from './headerView.module.scss'; + +class HeaderView { + private changeLanguageButton: ButtonModel; + + private header: HTMLElement; + + private linkLogo: LinkModel; + + private logoutButton: ButtonModel; + + constructor() { + this.logoutButton = this.createLogoutButton(); + this.linkLogo = this.createLinkLogo(); + this.changeLanguageButton = this.createChangeLanguageButton(); + this.header = this.createHTML(); + } + + private createChangeLanguageButton(): ButtonModel { + const { currentLanguage } = getStore().getState(); + this.changeLanguageButton = new ButtonModel({ + classes: [styles.changeLanguageButton], + text: currentLanguage, + }); + return this.changeLanguageButton; + } + + private createHTML(): HTMLElement { + this.header = createBaseElement({ + cssClasses: [styles.header], + tag: TAG_NAME.HEADER, + }); + + this.header.append(this.linkLogo.getHTML(), this.changeLanguageButton.getHTML(), this.logoutButton.getHTML()); + return this.header; + } + + private createLinkLogo(): LinkModel { + this.linkLogo = new LinkModel({ + attrs: { + href: PAGE_ID.DEFAULT_PAGE, + }, + classes: [styles.logo], + }); + + const svg = document.createElementNS(SVG_DETAILS.SVG_URL, TAG_NAME.SVG); + svg.append(createSVGUse(SVG_DETAILS.LOGO)); + this.linkLogo.getHTML().append(svg); + return this.linkLogo; + } + + private createLogoutButton(): ButtonModel { + const { currentLanguage } = getStore().getState(); + this.logoutButton = new ButtonModel({ + classes: [styles.logoutButton], + text: BUTTON_TEXT[currentLanguage].LOG_OUT, + }); + + observeCurrentLanguage(this.logoutButton.getHTML(), BUTTON_TEXT, BUTTON_TEXT_KEYS.LOG_OUT); + + return this.logoutButton; + } + + public getChangeLanguageButton(): ButtonModel { + return this.changeLanguageButton; + } + + public getHTML(): HTMLElement { + return this.header; + } + + public getLinkLogo(): LinkModel { + return this.linkLogo; + } + + public getLogoutButton(): ButtonModel { + return this.logoutButton; + } +} + +export default HeaderView; diff --git a/src/widgets/Header/view/headerView.module.scss b/src/widgets/Header/view/headerView.module.scss new file mode 100644 index 00000000..d80b4572 --- /dev/null +++ b/src/widgets/Header/view/headerView.module.scss @@ -0,0 +1,69 @@ +.header { + position: sticky; + left: 0; + right: 0; + top: 0; + z-index: 1; + display: grid; + align-items: center; + justify-content: space-between; + grid-template-columns: repeat(4, max-content); + margin-bottom: var(--medium-offset); + border-bottom: 10px solid var(--steam-green-800); + border-radius: var(--medium-br); + padding: calc(var(--small-offset) / 4) var(--small-offset); + width: 100%; + background-color: var(--white); +} + +.logo { + grid-column: 1; + + svg { + width: 40px; + height: 40px; + fill: var(--steam-green-800); + transition: fill 0.2s; + } + + @media (hover: hover) { + &:hover { + svg { + fill: var(--steam-green-700); + } + } + } +} + +.logoutButton, +.changeLanguageButton { + grid-column: 4; + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 2) var(--extra-small-offset); + font: var(--regular-font); + letter-spacing: 1px; + color: var(--white); + background-color: var(--steam-green-800); + transition: + color 0.2s, + background-color 0.2s; + + &:focus { + background-color: var(--steam-green-700); + } + + @media (hover: hover) { + &:hover { + background-color: var(--steam-green-700); + } + } + + &:disabled { + background-color: var(--noble-gray-300); + pointer-events: none; + } +} + +.changeLanguageButton { + grid-column: 3; +} diff --git a/src/widgets/LoginForm/.gitkeep b/src/widgets/LoginForm/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/widgets/LoginForm/model/LoginFormModel.ts b/src/widgets/LoginForm/model/LoginFormModel.ts new file mode 100644 index 00000000..2cea6108 --- /dev/null +++ b/src/widgets/LoginForm/model/LoginFormModel.ts @@ -0,0 +1,163 @@ +import type InputFieldModel from '@/entities/InputField/model/InputFieldModel.ts'; +import type { User, UserLoginData } from '@/shared/types/user.ts'; + +import getCustomerModel from '@/shared/API/customer/model/CustomerModel.ts'; +import EventMediatorModel from '@/shared/EventMediator/model/EventMediatorModel.ts'; +import LoaderModel from '@/shared/Loader/model/LoaderModel.ts'; +import serverMessageModel from '@/shared/ServerMessage/model/ServerMessageModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { setCurrentUser } from '@/shared/Store/actions.ts'; +import { EVENT_NAME, MEDIATOR_EVENT } from '@/shared/constants/events.ts'; +import KEY from '@/shared/constants/forms/login/constants.ts'; +import { MESSAGE_STATUS, SERVER_MESSAGE } from '@/shared/constants/messages.ts'; +import { SIZES } from '@/shared/constants/sizes.ts'; +import { isUserLoginData } from '@/shared/types/validation/user.ts'; +import isKeyOfUserData from '@/shared/utils/isKeyOfUserData.ts'; + +import LoginFormView from '../view/LoginFormView.ts'; + +class LoginFormModel { + private eventMediator = EventMediatorModel.getInstance(); + + private inputFields: InputFieldModel[] = []; + + private isValidInputFields: Record = {}; + + private userData: UserLoginData = { + email: '', + password: '', + }; + + private view: LoginFormView = new LoginFormView(); + + constructor() { + this.init(); + } + + private async checkHasEmailHandler(email: string): Promise { + const response = await getCustomerModel().hasEmail(email); + return response; + } + + private createGreetingMessage(name: string): string { + const greeting = `Welcome, ${name}! ${SERVER_MESSAGE.SUCCESSFUL_LOGIN}`; + return greeting; + } + + private getFormData(): UserLoginData { + this.inputFields.forEach((inputField) => { + const input = inputField.getView().getInput(); + const inputHTML = input.getHTML(); + const inputValue = input.getValue(); + + const key = inputHTML.id.replace(KEY, ''); + + if (isKeyOfUserData(this.userData, key)) { + this.userData[key] = inputValue; + this.isValidInputFields[inputHTML.id] = false; + } + + input.clear(); + }); + + this.view.getSubmitFormButton().setDisabled(); + return this.userData; + } + + private init(): boolean { + this.inputFields = this.view.getInputFields(); + this.inputFields.forEach((inputField) => this.setInputFieldHandlers(inputField)); + this.setPreventDefaultToForm(); + this.setSubmitFormHandler(); + this.subscribeToEventMediator(); + return true; + } + + private loginUser(userLoginData: UserLoginData): void { + const loader = new LoaderModel(SIZES.MEDIUM).getHTML(); + this.view.getSubmitFormButton().getHTML().append(loader); + this.checkHasEmailHandler(userLoginData.email) + .then((response) => { + if (response) { + this.loginUserHandler(userLoginData); + } else { + serverMessageModel.showServerMessage(SERVER_MESSAGE.INVALID_EMAIL, MESSAGE_STATUS.ERROR); + } + }) + .catch(() => { + serverMessageModel.showServerMessage(SERVER_MESSAGE.BAD_REQUEST, MESSAGE_STATUS.ERROR); + }) + .finally(() => loader.remove()); + } + + private loginUserHandler(userLoginData: UserLoginData): void { + const loader = new LoaderModel(SIZES.MEDIUM).getHTML(); + this.view.getSubmitFormButton().getHTML().append(loader); + getCustomerModel() + .authCustomer(userLoginData) + .then((data) => { + getStore().dispatch(setCurrentUser(data)); + if (data) { + serverMessageModel.showServerMessage(this.createGreetingMessage(data.firstName), MESSAGE_STATUS.SUCCESS); + } + }) + .catch(() => { + serverMessageModel.showServerMessage(SERVER_MESSAGE.INCORRECT_PASSWORD, MESSAGE_STATUS.ERROR); + }) + .finally(() => loader.remove()); + } + + private setInputFieldHandlers(inputField: InputFieldModel): boolean { + const inputHTML = inputField.getView().getInput().getHTML(); + this.isValidInputFields[inputHTML.id] = false; + inputHTML.addEventListener(EVENT_NAME.INPUT, () => { + this.isValidInputFields[inputHTML.id] = inputField.getIsValid(); + this.switchSubmitFormButtonAccess(); + }); + return true; + } + + private setPreventDefaultToForm(): boolean { + this.getHTML().addEventListener(EVENT_NAME.SUBMIT, (event) => event.preventDefault()); + return true; + } + + private setSubmitFormHandler(): boolean { + const submitButton = this.view.getSubmitFormButton().getHTML(); + submitButton.addEventListener(EVENT_NAME.CLICK, () => { + const formData = this.getFormData(); + this.loginUser(formData); + }); + return true; + } + + private subscribeToEventMediator(): boolean { + this.eventMediator.subscribe(MEDIATOR_EVENT.USER_LOGIN, (userLoginData) => { + if (isUserLoginData(userLoginData)) { + this.loginUser(userLoginData); + } + }); + return true; + } + + private switchSubmitFormButtonAccess(): boolean { + if (Object.values(this.isValidInputFields).every((value) => value)) { + this.view.getSubmitFormButton().setEnabled(); + this.view.getSubmitFormButton().getHTML().focus(); + } else { + this.view.getSubmitFormButton().setDisabled(); + } + + return true; + } + + public getFirstInputField(): InputFieldModel { + return this.inputFields[0]; + } + + public getHTML(): HTMLFormElement { + return this.view.getHTML(); + } +} + +export default LoginFormModel; diff --git a/src/widgets/LoginForm/view/LoginFormView.ts b/src/widgets/LoginForm/view/LoginFormView.ts new file mode 100644 index 00000000..ff6ac327 --- /dev/null +++ b/src/widgets/LoginForm/view/LoginFormView.ts @@ -0,0 +1,93 @@ +import InputFieldModel from '@/entities/InputField/model/InputFieldModel.ts'; +import ButtonModel from '@/shared/Button/model/ButtonModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { BUTTON_TEXT, BUTTON_TEXT_KEYS, BUTTON_TYPE } from '@/shared/constants/buttons.ts'; +import * as FORM_INPUTS from '@/shared/constants/forms/login/fieldParams.ts'; +import * as FORM_VALIDATION from '@/shared/constants/forms/login/validationParams.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; +import observeCurrentLanguage from '@/shared/utils/observeCurrentLanguage.ts'; + +import styles from './loginForm.module.scss'; + +class LoginFormView { + private form: HTMLFormElement; + + private inputFields: InputFieldModel[] = []; + + private submitFormButton: ButtonModel; + + constructor() { + this.inputFields = this.createInputFields(); + this.submitFormButton = this.createSubmitFormButton(); + this.form = this.createHTML(); + } + + private createHTML(): HTMLFormElement { + this.form = createBaseElement({ + cssClasses: [styles.loginForm], + tag: TAG_NAME.FORM, + }); + + this.inputFields.forEach((inputField) => { + const inputFieldElement = inputField.getView().getHTML(); + + if (inputFieldElement instanceof HTMLLabelElement) { + this.form.append(inputFieldElement); + } else { + this.form.append(inputFieldElement.getHTML()); + } + }); + + this.form.append(this.submitFormButton.getHTML()); + return this.form; + } + + private createInputFields(): InputFieldModel[] { + FORM_INPUTS.INPUT_FIELD.forEach((inputFieldParams) => { + const currentValidateParams = FORM_VALIDATION.default.find( + (validParams) => validParams.key === inputFieldParams.inputParams.id, + ); + + if (currentValidateParams) { + const inputField = new InputFieldModel(inputFieldParams, currentValidateParams); + this.inputFields.push(inputField); + } else { + this.inputFields.push(new InputFieldModel(inputFieldParams, null)); + } + }); + + return this.inputFields; + } + + private createSubmitFormButton(): ButtonModel { + const { currentLanguage } = getStore().getState(); + this.submitFormButton = new ButtonModel({ + attrs: { + type: BUTTON_TYPE.SUBMIT, + }, + classes: [styles.submitFormButton], + text: BUTTON_TEXT[currentLanguage].LOGIN, + }); + + observeCurrentLanguage(this.submitFormButton.getHTML(), BUTTON_TEXT, BUTTON_TEXT_KEYS.LOGIN); + + this.submitFormButton.setDisabled(); + + return this.submitFormButton; + } + + public getHTML(): HTMLFormElement { + return this.form; + } + + public getInputFields(): InputFieldModel[] { + return this.inputFields; + } + + public getSubmitFormButton(): ButtonModel { + return this.submitFormButton; + } +} + +export default LoginFormView; diff --git a/src/widgets/LoginForm/view/loginForm.module.scss b/src/widgets/LoginForm/view/loginForm.module.scss new file mode 100644 index 00000000..c1ac616e --- /dev/null +++ b/src/widgets/LoginForm/view/loginForm.module.scss @@ -0,0 +1,112 @@ +.loginForm { + display: flex; + flex-direction: column; + grid-column: 2 span; + margin: 0 auto; + margin-bottom: calc(var(--extra-small-offset) / 2); + width: 100%; + gap: var(--extra-small-offset); + + label { + position: relative; + display: flex; + flex-direction: column; + gap: calc(var(--extra-small-offset) / 2); + + button { + position: absolute; + right: 0; + top: 7px; + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 8); + width: 24px; + height: 24px; + background-color: transparent; + transform: translate(-12%, 0); + + svg { + width: 20px; + height: 20px; + stroke: var(--noble-gray-600); + transition: stroke 0.2s; + } + + @media (hover: hover) { + &:hover { + background-color: var(--noble-gray-200); + + svg { + stroke: var(--steam-green-800); + } + } + } + } + + @media (max-width: 768px) { + button { + top: 2px; + } + } + } + + input { + border: 1px solid var(--noble-gray-200); + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 2) var(--extra-small-offset); + font: var(--regular-font); + letter-spacing: 1px; + color: var(--noble-gray-800); + transition: border 0.2s; + + &::placeholder { + color: var(--noble-gray-600); + } + + &:focus { + border: 1px solid var(--steam-green-800); + } + + @media (hover: hover) { + &:hover { + border: 1px solid var(--steam-green-800); + } + } + } + + span { + font: var(--regular-font); + letter-spacing: 1px; + text-align: center; + color: var(--red-power-600); + } +} + +.submitFormButton { + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 2) var(--small-offset); + font: var(--bold-font); + letter-spacing: 1px; + color: var(--white); + background-color: var(--steam-green-800); + transition: + color 0.2s, + background-color 0.2s; + + &:focus { + background-color: var(--steam-green-700); + } + + @media (hover: hover) { + &:hover { + background-color: var(--steam-green-700); + } + } + + &:disabled { + background-color: var(--noble-gray-300); + pointer-events: none; + } +} diff --git a/src/widgets/RegistrationForm/.gitkeep b/src/widgets/RegistrationForm/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/widgets/RegistrationForm/model/RegistrationFormModel.ts b/src/widgets/RegistrationForm/model/RegistrationFormModel.ts new file mode 100644 index 00000000..7edf640f --- /dev/null +++ b/src/widgets/RegistrationForm/model/RegistrationFormModel.ts @@ -0,0 +1,377 @@ +import type InputFieldModel from '@/entities/InputField/model/InputFieldModel.ts'; +import type { Address, User } from '@/shared/types/user.ts'; + +import CountryChoiceModel from '@/features/CountryChoice/model/CountryChoiceModel.ts'; +import getCustomerModel, { CustomerModel } from '@/shared/API/customer/model/CustomerModel.ts'; +import EventMediatorModel from '@/shared/EventMediator/model/EventMediatorModel.ts'; +import LoaderModel from '@/shared/Loader/model/LoaderModel.ts'; +import serverMessageModel from '@/shared/ServerMessage/model/ServerMessageModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { setCurrentUser } from '@/shared/Store/actions.ts'; +import { EVENT_NAME, MEDIATOR_EVENT } from '@/shared/constants/events.ts'; +import * as CONSTANT_FORMS from '@/shared/constants/forms.ts'; +import * as FORM_CONSTANT from '@/shared/constants/forms/register/constant.ts'; +import * as FORM_FIELDS from '@/shared/constants/forms/register/fieldParams.ts'; +import { MESSAGE_STATUS, SERVER_MESSAGE } from '@/shared/constants/messages.ts'; +import { SIZES } from '@/shared/constants/sizes.ts'; +import isKeyOfUserData from '@/shared/utils/isKeyOfUserData.ts'; + +import RegistrationFormView from '../view/RegistrationFormView.ts'; + +class RegisterFormModel { + private eventMediator = EventMediatorModel.getInstance(); + + private inputFields: InputFieldModel[] = []; + + private isValidInputFields: Record = {}; + + private userData: User = { + addresses: [], + birthDate: '', + defaultBillingAddressId: null, + defaultShippingAddressId: null, + email: '', + firstName: '', + id: '', + lastName: '', + locale: '', + password: '', + version: 0, + }; + + private view: RegistrationFormView = new RegistrationFormView(); + + constructor() { + this.init(); + } + + private async addAddress(address: Address, userData: User | null): Promise { + let currentUserData = userData; + if (currentUserData) { + currentUserData = await getCustomerModel().editCustomer( + [CustomerModel.actionAddAddress(address)], + currentUserData, + ); + } + return currentUserData; + } + + private createBillingCountryChoice(): boolean { + return this.createCountryChoice( + FORM_FIELDS.BILLING_ADDRESS_COUNTRY.inputParams.id, + this.view.getBillingAddressWrapper(), + ); + } + + private createCountryChoice(inputFieldId: string, wrapper: HTMLElement): boolean { + const addressInput = this.view + .getInputFields() + .find((inputField) => inputField.getView().getInput().getHTML().id === inputFieldId) + ?.getView() + .getInput() + .getHTML(); + + if (addressInput) { + const countryChoiceModel = new CountryChoiceModel(addressInput); + wrapper.append(countryChoiceModel.getHTML()); + } + return true; + } + + private createShippingCountryChoice(): boolean { + return this.createCountryChoice( + FORM_FIELDS.SHIPPING_ADDRESS_COUNTRY.inputParams.id, + this.view.getShippingAddressWrapper(), + ); + } + + private async editDefaultBillingAddress(addressId: string, userData: User | null): Promise { + let currentUserData = userData; + if (currentUserData) { + currentUserData = await getCustomerModel().editCustomer( + [CustomerModel.actionEditDefaultBillingAddress(addressId)], + currentUserData, + ); + } + return currentUserData; + } + + private async editDefaultShippingAddress(addressId: string, userData: User | null): Promise { + let currentUserData = userData; + if (currentUserData) { + currentUserData = await getCustomerModel().editCustomer( + [CustomerModel.actionEditDefaultShippingAddress(addressId)], + currentUserData, + ); + } + return currentUserData; + } + + private getAddressData(key: string): Address { + const addressData = + key === CONSTANT_FORMS.USER_ADDRESS_TYPE.BILLING + ? this.getAddressDataHandler( + [ + FORM_FIELDS.BILLING_ADDRESS_CITY, + FORM_FIELDS.BILLING_ADDRESS_POSTAL_CODE, + FORM_FIELDS.BILLING_ADDRESS_STREET, + ], + CONSTANT_FORMS.USER_COUNTRY_ADDRESS.BILLING, + ) + : this.getAddressDataHandler( + [ + FORM_FIELDS.SHIPPING_ADDRESS_CITY, + FORM_FIELDS.SHIPPING_ADDRESS_POSTAL_CODE, + FORM_FIELDS.SHIPPING_ADDRESS_STREET, + ], + CONSTANT_FORMS.USER_COUNTRY_ADDRESS.SHIPPING, + ); + + return addressData; + } + + private getAddressDataHandler( + [city, postalCode, street]: { inputParams: { id: string } }[], + country: string, + ): Address { + const store = getStore().getState(); + const addressData: Address = { + city: this.getAddressValue(city), + country: country === CONSTANT_FORMS.USER_COUNTRY_ADDRESS.BILLING ? store.billingCountry : store.shippingCountry, + email: this.userData.email, + firstName: this.userData.firstName, + id: '', + lastName: this.userData.lastName, + postalCode: this.getAddressValue(postalCode), + state: '', + streetName: this.getAddressValue(street), + streetNumber: '', + }; + return addressData; + } + + private getAddressValue(field: { inputParams: { id: string } }): string { + return ( + this.inputFields + .find((inputField) => inputField.getView().getInput().getHTML().id === field.inputParams.id) + ?.getView() + .getValue() || '' + ); + } + + private getFormUserData(): User { + this.inputFields.forEach((inputField) => { + const input = inputField.getView().getInput(); + const inputHTML = input.getHTML(); + const inputValue = input.getValue(); + + const key = inputHTML.id.replace(FORM_CONSTANT.KEY, ''); + + if (isKeyOfUserData(this.userData, key)) { + this.userData[key] = inputValue; + this.isValidInputFields[inputHTML.id] = false; + input.clear(); + } + }); + + this.view.getSubmitFormButton().setDisabled(); + return this.userData; + } + + private init(): boolean { + this.inputFields = this.view.getInputFields(); + this.inputFields.forEach((inputField) => this.setInputFieldHandlers(inputField)); + this.setPreventDefaultToForm(); + this.setSubmitFormHandler(); + this.createBillingCountryChoice(); + this.createShippingCountryChoice(); + const checkboxSingleAddress = this.view.getSingleAddressCheckBox().getHTML(); + checkboxSingleAddress.addEventListener(EVENT_NAME.CHANGE, () => + this.singleAddressCheckBoxHandler(checkboxSingleAddress.checked), + ); + return true; + } + + private registerUser(): void { + const loader = new LoaderModel(SIZES.MEDIUM).getHTML(); + this.view.getSubmitFormButton().getHTML().append(loader); + this.getFormUserData(); + getCustomerModel() + .registerNewCustomer(this.userData) + .then((newUserData) => { + if (newUserData) { + this.successfulUserRegistration(newUserData); + serverMessageModel.showServerMessage(SERVER_MESSAGE.SUCCESSFUL_REGISTRATION, MESSAGE_STATUS.SUCCESS); + } + }) + .catch(() => { + serverMessageModel.showServerMessage(SERVER_MESSAGE.USER_EXISTS, MESSAGE_STATUS.ERROR); + }) + .finally(() => loader.remove()); + } + + private resetInputFieldsValidation(): void { + Object.entries(this.isValidInputFields).forEach(([key]) => { + this.isValidInputFields[key] = false; + }); + } + + private setInputFieldHandlers(inputField: InputFieldModel): boolean { + const inputHTML = inputField.getView().getInput().getHTML(); + this.isValidInputFields[inputHTML.id] = false; + inputHTML.addEventListener(EVENT_NAME.INPUT, () => { + this.isValidInputFields[inputHTML.id] = inputField.getIsValid(); + this.switchSubmitFormButtonAccess(); + }); + return true; + } + + private setPreventDefaultToForm(): boolean { + this.getHTML().addEventListener(EVENT_NAME.SUBMIT, (event) => { + event.preventDefault(); + }); + + return true; + } + + private setSubmitFormHandler(): boolean { + const submitButton = this.view.getSubmitFormButton().getHTML(); + submitButton.addEventListener(EVENT_NAME.CLICK, () => this.registerUser()); + return true; + } + + private singleAddressCheckBoxHandler(isChecked: boolean): boolean { + const billingAddressFieldID = [ + FORM_FIELDS.BILLING_ADDRESS_COUNTRY.inputParams.id, + FORM_FIELDS.BILLING_ADDRESS_STREET.inputParams.id, + FORM_FIELDS.BILLING_ADDRESS_CITY.inputParams.id, + FORM_FIELDS.BILLING_ADDRESS_POSTAL_CODE.inputParams.id, + ]; + + this.view.switchVisibilityBillingAddressWrapper(isChecked); + + if (!isChecked) { + window.scrollTo({ + top: document.documentElement.scrollHeight, + }); + } + + billingAddressFieldID.forEach((id) => { + this.inputFields + .find((inputField) => inputField.getView().getInput().getHTML().id === id) + ?.getView() + .getInput() + .clear(); + this.isValidInputFields[id] = isChecked; + }); + + this.switchSubmitFormButtonAccess(); + + return true; + } + + private successfulUserRegistration(newUserData: User): void { + const userDataWithLogin = { + email: this.userData.email, + password: this.userData.password, + }; + this.eventMediator.notify(MEDIATOR_EVENT.USER_LOGIN, userDataWithLogin); + this.updateUserData(newUserData).catch(() => { + serverMessageModel.showServerMessage(SERVER_MESSAGE.BAD_REQUEST, MESSAGE_STATUS.ERROR); + }); + this.resetInputFieldsValidation(); + } + + private switchSubmitFormButtonAccess(): boolean { + if (Object.values(this.isValidInputFields).every((value) => value)) { + this.view.getSubmitFormButton().setEnabled(); + this.view.getSubmitFormButton().getHTML().focus(); + } else { + this.view.getSubmitFormButton().setDisabled(); + } + + return true; + } + + private async updatePersonalData(userData: User | null): Promise { + let currentUserData = userData; + if (currentUserData) { + currentUserData = await getCustomerModel().editCustomer( + [ + CustomerModel.actionEditFirstName(this.userData.firstName), + CustomerModel.actionEditLastName(this.userData.lastName), + CustomerModel.actionEditDateOfBirth(this.userData.birthDate), + ], + currentUserData, + ); + } + + return currentUserData; + } + + private async updateUserAddresses(userData: User | null): Promise { + const shippingAddress = this.getAddressData(CONSTANT_FORMS.USER_ADDRESS_TYPE.SHIPPING); + const billingAddress = this.getAddressData(CONSTANT_FORMS.USER_ADDRESS_TYPE.BILLING); + const checkboxSingleAddress = this.view.getSingleAddressCheckBox().getHTML(); + const checkboxDefaultShippingAddress = this.view.getCheckboxDefaultShippingAddress().getHTML(); + const checkboxDefaultBillingAddress = this.view.getCheckboxDefaultBillingAddress().getHTML(); + let currentUserData = userData; + + currentUserData = await this.addAddress(shippingAddress, currentUserData); + + if (checkboxDefaultShippingAddress.checked && currentUserData) { + currentUserData = await this.editDefaultShippingAddress( + currentUserData.addresses[currentUserData.addresses.length - 1].id, + currentUserData, + ); + } + + if (checkboxSingleAddress.checked && checkboxDefaultShippingAddress.checked) { + currentUserData = await this.addAddress(shippingAddress, currentUserData); + if (currentUserData) { + currentUserData = await this.editDefaultBillingAddress( + currentUserData.addresses[currentUserData.addresses.length - 1].id, + currentUserData, + ); + } + return currentUserData; + } + + if (checkboxDefaultBillingAddress.checked) { + currentUserData = await this.addAddress(billingAddress, currentUserData); + if (currentUserData) { + currentUserData = await this.editDefaultBillingAddress( + currentUserData.addresses[currentUserData.addresses.length - 1].id, + currentUserData, + ); + } + } + + return currentUserData; + } + + private async updateUserData(newUserData: User): Promise { + let currentUserData: User | null = newUserData; + + currentUserData = await this.updatePersonalData(currentUserData); + + if (currentUserData) { + this.userData = currentUserData; + } + + currentUserData = await this.updateUserAddresses(currentUserData); + + getStore().dispatch(setCurrentUser(this.userData)); + return this.userData; + } + + public getFirstInputField(): InputFieldModel { + return this.inputFields[0]; + } + + public getHTML(): HTMLFormElement { + return this.view.getHTML(); + } +} + +export default RegisterFormModel; diff --git a/src/widgets/RegistrationForm/view/RegistrationFormView.ts b/src/widgets/RegistrationForm/view/RegistrationFormView.ts new file mode 100644 index 00000000..783b24f8 --- /dev/null +++ b/src/widgets/RegistrationForm/view/RegistrationFormView.ts @@ -0,0 +1,317 @@ +import type { InputParams } from '@/shared/types/form'; + +import InputFieldModel from '@/entities/InputField/model/InputFieldModel.ts'; +import ButtonModel from '@/shared/Button/model/ButtonModel.ts'; +import InputModel from '@/shared/Input/model/InputModel.ts'; +import getStore from '@/shared/Store/Store.ts'; +import { BUTTON_TEXT, BUTTON_TEXT_KEYS, BUTTON_TYPE } from '@/shared/constants/buttons.ts'; +import { FORM_TEXT, INPUT_TYPE } from '@/shared/constants/forms.ts'; +import * as FORM_CONSTANT from '@/shared/constants/forms/register/constant.ts'; +import * as FORM_FIELDS from '@/shared/constants/forms/register/fieldParams.ts'; +import * as FORM_VALIDATION from '@/shared/constants/forms/register/validationParams.ts'; +import TAG_NAME from '@/shared/constants/tags.ts'; +import createBaseElement from '@/shared/utils/createBaseElement.ts'; +import observeCurrentLanguage from '@/shared/utils/observeCurrentLanguage.ts'; + +import styles from './registrationForm.module.scss'; + +class RegistrationFormView { + private billingAddressWrapper: HTMLDivElement; + + private checkboxDefaultBillingAddress: InputModel; + + private checkboxDefaultShippingAddress: InputModel; + + private checkboxSingleAddress: InputModel; + + private credentialsWrapper: HTMLDivElement; + + private form: HTMLFormElement; + + private inputFields: InputFieldModel[] = []; + + private personalDataWrapper: HTMLDivElement; + + private shippingAddressWrapper: HTMLDivElement; + + private submitFormButton: ButtonModel; + + constructor() { + this.inputFields = this.createInputFields(); + this.credentialsWrapper = this.createCredentialsWrapper(); + this.personalDataWrapper = this.createPersonalDataWrapper(); + this.checkboxSingleAddress = this.createCheckboxSingleAddress(); + this.checkboxDefaultShippingAddress = this.createCheckboxDefaultShippingAddress(); + this.shippingAddressWrapper = this.createShippingAddressWrapper(); + this.checkboxDefaultBillingAddress = this.createCheckboxDefaultBillingAddress(); + this.billingAddressWrapper = this.createBillingAddressWrapper(); + this.submitFormButton = this.createSubmitFormButton(); + this.form = this.createHTML(); + } + + private createBillingAddressWrapper(): HTMLDivElement { + const copyInputFields = this.inputFields; + const filteredInputFields = copyInputFields.filter( + (inputField) => + inputField.getView().getInput().getHTML().id === FORM_FIELDS.BILLING_ADDRESS_STREET.inputParams.id || + inputField.getView().getInput().getHTML().id === FORM_FIELDS.BILLING_ADDRESS_CITY.inputParams.id || + inputField.getView().getInput().getHTML().id === FORM_FIELDS.BILLING_ADDRESS_COUNTRY.inputParams.id || + inputField.getView().getInput().getHTML().id === FORM_FIELDS.BILLING_ADDRESS_POSTAL_CODE.inputParams.id, + ); + + this.billingAddressWrapper = this.createWrapperElement( + FORM_CONSTANT.TITLE_TEXT_KEYS.BILLING_ADDRESS, + [styles.billingAddressWrapper], + filteredInputFields, + ); + + const checkBoxLabel = createBaseElement({ + cssClasses: [styles.checkboxLabel], + tag: TAG_NAME.LABEL, + }); + + const checkBoxText = createBaseElement({ + cssClasses: [styles.checkboxText], + innerContent: FORM_TEXT.DEFAULT_ADDRESS, + tag: TAG_NAME.SPAN, + }); + + checkBoxLabel.append(checkBoxText, this.checkboxDefaultBillingAddress.getHTML()); + + this.billingAddressWrapper.append(checkBoxLabel); + + return this.billingAddressWrapper; + } + + private createCheckBoxLabel(innerContent: string, checkBoxElement: HTMLInputElement): HTMLLabelElement { + const checkboxLabel = createBaseElement({ + cssClasses: [styles.checkboxLabel], + tag: TAG_NAME.LABEL, + }); + + const checkBoxText = createBaseElement({ + cssClasses: [styles.checkboxText], + innerContent, + tag: TAG_NAME.SPAN, + }); + + checkboxLabel.append(checkBoxText, checkBoxElement); + return checkboxLabel; + } + + private createCheckboxDefaultBillingAddress(): InputModel { + const checkboxParams: InputParams = { + autocomplete: FORM_FIELDS.CHECKBOX.AUTOCOMPLETE, + id: FORM_FIELDS.CHECKBOX.BILLING_ID, + placeholder: '', + type: INPUT_TYPE.CHECK_BOX, + }; + this.checkboxDefaultBillingAddress = new InputModel(checkboxParams); + return this.checkboxDefaultBillingAddress; + } + + private createCheckboxDefaultShippingAddress(): InputModel { + const checkboxParams: InputParams = { + autocomplete: FORM_FIELDS.CHECKBOX.AUTOCOMPLETE, + id: FORM_FIELDS.CHECKBOX.SHIPPING_ID, + placeholder: '', + type: INPUT_TYPE.CHECK_BOX, + }; + this.checkboxDefaultShippingAddress = new InputModel(checkboxParams); + return this.checkboxDefaultShippingAddress; + } + + private createCheckboxSingleAddress(): InputModel { + const checkboxParams: InputParams = { + autocomplete: FORM_FIELDS.CHECKBOX.AUTOCOMPLETE, + id: FORM_FIELDS.CHECKBOX.SINGLE_ID, + placeholder: '', + type: INPUT_TYPE.CHECK_BOX, + }; + this.checkboxSingleAddress = new InputModel(checkboxParams); + + return this.checkboxSingleAddress; + } + + private createCredentialsWrapper(): HTMLDivElement { + const copyInputFields = this.inputFields; + const filteredInputFields = copyInputFields.filter( + (inputField) => + inputField.getView().getInput().getHTML().id === FORM_FIELDS.PASSWORD.inputParams.id || + inputField.getView().getInput().getHTML().id === FORM_FIELDS.EMAIL.inputParams.id, + ); + + this.credentialsWrapper = this.createWrapperElement( + FORM_CONSTANT.TITLE_TEXT_KEYS.CREDENTIALS, + [styles.credentialsWrapper], + filteredInputFields, + ); + + return this.credentialsWrapper; + } + + private createHTML(): HTMLFormElement { + this.form = createBaseElement({ + cssClasses: [styles.registrationForm], + tag: TAG_NAME.FORM, + }); + + this.form.append( + this.credentialsWrapper, + this.personalDataWrapper, + this.shippingAddressWrapper, + this.billingAddressWrapper, + this.submitFormButton.getHTML(), + ); + return this.form; + } + + private createInputFields(): InputFieldModel[] { + FORM_FIELDS.INPUT.forEach((inputFieldParams) => { + const currentValidateParams = FORM_VALIDATION.INPUT_VALIDATION.find( + (validParams) => validParams.key === inputFieldParams.inputParams.id, + ); + + if (currentValidateParams) { + const inputField = new InputFieldModel(inputFieldParams, currentValidateParams); + this.inputFields.push(inputField); + } else { + this.inputFields.push(new InputFieldModel(inputFieldParams, null)); + } + }); + + return this.inputFields; + } + + private createPersonalDataWrapper(): HTMLDivElement { + const copyInputFields = this.inputFields; + const filteredInputFields = copyInputFields.filter( + (inputField) => + inputField.getView().getInput().getHTML().id === FORM_FIELDS.FIRST_NAME.inputParams.id || + inputField.getView().getInput().getHTML().id === FORM_FIELDS.LAST_NAME.inputParams.id || + inputField.getView().getInput().getHTML().id === FORM_FIELDS.BIRTHDAY.inputParams.id, + ); + + this.personalDataWrapper = this.createWrapperElement( + FORM_CONSTANT.TITLE_TEXT_KEYS.PERSONAL, + [styles.personalDataWrapper], + filteredInputFields, + ); + + return this.personalDataWrapper; + } + + private createShippingAddressWrapper(): HTMLDivElement { + const copyInputFields = this.inputFields; + const filteredInputFields = copyInputFields.filter( + (inputField) => + inputField.getView().getInput().getHTML().id === FORM_FIELDS.SHIPPING_ADDRESS_STREET.inputParams.id || + inputField.getView().getInput().getHTML().id === FORM_FIELDS.SHIPPING_ADDRESS_CITY.inputParams.id || + inputField.getView().getInput().getHTML().id === FORM_FIELDS.SHIPPING_ADDRESS_COUNTRY.inputParams.id || + inputField.getView().getInput().getHTML().id === FORM_FIELDS.SHIPPING_ADDRESS_POSTAL_CODE.inputParams.id, + ); + + this.shippingAddressWrapper = this.createWrapperElement( + FORM_CONSTANT.TITLE_TEXT_KEYS.SHIPPING_ADDRESS, + [styles.shippingAddressWrapper], + filteredInputFields, + ); + + const settingsAddressWrapper = createBaseElement({ + cssClasses: [styles.settingsAddressWrapper], + tag: TAG_NAME.DIV, + }); + + settingsAddressWrapper.append( + this.createCheckBoxLabel(FORM_TEXT.DEFAULT_ADDRESS, this.checkboxDefaultShippingAddress.getHTML()), + this.createCheckBoxLabel(FORM_TEXT.SINGLE_ADDRESS, this.checkboxSingleAddress.getHTML()), + ); + + this.shippingAddressWrapper.append(settingsAddressWrapper); + + return this.shippingAddressWrapper; + } + + private createSubmitFormButton(): ButtonModel { + const { currentLanguage } = getStore().getState(); + this.submitFormButton = new ButtonModel({ + attrs: { + type: BUTTON_TYPE.SUBMIT, + }, + text: BUTTON_TEXT[currentLanguage].REGISTRATION, + }); + + observeCurrentLanguage(this.submitFormButton.getHTML(), BUTTON_TEXT, BUTTON_TEXT_KEYS.REGISTRATION); + + this.submitFormButton.setDisabled(); + + return this.submitFormButton; + } + + private createWrapperElement( + title: FORM_CONSTANT.TitleTextKeysType, + cssClasses: string[], + inputFields: InputFieldModel[], + ): HTMLDivElement { + const { currentLanguage } = getStore().getState(); + const wrapperElement = createBaseElement({ + cssClasses, + tag: TAG_NAME.DIV, + }); + const titleElement = createBaseElement({ + cssClasses: [styles.title], + innerContent: FORM_CONSTANT.TITLE_TEXT[currentLanguage][title], + tag: TAG_NAME.H3, + }); + wrapperElement.append(titleElement); + observeCurrentLanguage(titleElement, FORM_CONSTANT.TITLE_TEXT, title); + + inputFields.forEach((inputField) => { + const inputFieldElement = inputField.getView().getHTML(); + if (inputFieldElement instanceof HTMLLabelElement) { + wrapperElement.append(inputFieldElement); + } else if (inputFieldElement instanceof InputModel) { + wrapperElement.append(inputFieldElement.getHTML()); + } + }); + return wrapperElement; + } + + public getBillingAddressWrapper(): HTMLDivElement { + return this.billingAddressWrapper; + } + + public getCheckboxDefaultBillingAddress(): InputModel { + return this.checkboxDefaultBillingAddress; + } + + public getCheckboxDefaultShippingAddress(): InputModel { + return this.checkboxDefaultShippingAddress; + } + + public getHTML(): HTMLFormElement { + return this.form; + } + + public getInputFields(): InputFieldModel[] { + return this.inputFields; + } + + public getShippingAddressWrapper(): HTMLDivElement { + return this.shippingAddressWrapper; + } + + public getSingleAddressCheckBox(): InputModel { + return this.checkboxSingleAddress; + } + + public getSubmitFormButton(): ButtonModel { + return this.submitFormButton; + } + + public switchVisibilityBillingAddressWrapper(isVisible: boolean): void { + this.billingAddressWrapper.classList.toggle(styles.hidden, isVisible); + } +} + +export default RegistrationFormView; diff --git a/src/widgets/RegistrationForm/view/registrationForm.module.scss b/src/widgets/RegistrationForm/view/registrationForm.module.scss new file mode 100644 index 00000000..cd0fe977 --- /dev/null +++ b/src/widgets/RegistrationForm/view/registrationForm.module.scss @@ -0,0 +1,271 @@ +.registrationForm { + display: grid; + grid-column: 2 span; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat((6, max-content)); + margin: 0 auto; + width: 100%; + gap: var(--extra-small-offset); + + .checkboxLabel { + display: flex; + flex-direction: row; + align-items: center; + justify-content: end; + cursor: pointer; + user-select: none; + gap: calc(var(--extra-small-offset) / 4); + + input { + cursor: pointer; + } + + @media (hover: hover) { + &:hover { + .checkboxText { + color: var(--steam-green-800); + } + } + } + } + + .checkboxText { + font: var(--regular-font); + letter-spacing: 1px; + color: var(--noble-gray-800); + transition: color 0.2s; + } + + label { + position: relative; + display: flex; + flex-direction: column; + font: var(--regular-font); + letter-spacing: 1px; + color: var(--noble-gray-800); + gap: calc(var(--extra-small-offset) / 2); + + button { + position: absolute; + right: 0; + top: 34px; + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 8); + width: 24px; + height: 24px; + background-color: transparent; + transform: translate(-12%, 0); + + svg { + width: 20px; + height: 20px; + stroke: var(--noble-gray-600); + transition: stroke 0.2s; + } + + &:focus { + background-color: var(--noble-gray-200); + + svg { + stroke: var(--steam-green-800); + } + } + + @media (hover: hover) { + &:hover { + background-color: var(--noble-gray-200); + + svg { + stroke: var(--steam-green-800); + } + } + } + } + + @media (max-width: 768px) { + button { + top: 24px; + } + } + } + + input { + border: 1px solid var(--noble-gray-200); + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 2) var(--extra-small-offset); + font: var(--regular-font); + letter-spacing: 1px; + color: var(--noble-gray-800); + transition: border 0.2s; + cursor: text; + + &::placeholder { + color: var(--noble-gray-600); + } + + &:focus { + border: 1px solid var(--steam-green-800); + } + + @media (hover: hover) { + &:hover { + border: 1px solid var(--steam-green-800); + } + } + + &[type='date'] { + -webkit-appearance: none; + appearance: none; + padding-right: 0; + } + + &[type='date']::-webkit-calendar-picker-indicator { + background-image: url('../../../shared/img/svg/calendar.svg'); + background-position: -3px 0; + cursor: pointer; + } + + &[type='date']::-webkit-inner-spin-button, + &[type='date']::-webkit-outer-spin-button { + display: none; + } + + &::-webkit-datetime-edit-day-field:focus, + &::-webkit-datetime-edit-month-field:focus, + &::-webkit-datetime-edit-year-field:focus { + outline: none; + border-radius: var(--small-br); + color: var(--steam-green-800); + background-color: var(--noble-gray-200); + } + } + + span { + font: var(--regular-font); + letter-spacing: 1px; + text-align: center; + color: var(--red-power-600); + } + + button { + display: flex; + align-items: center; + justify-content: center; + grid-column: 2 span; + grid-row: 5; + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 2) var(--small-offset); + max-height: 40px; + font: var(--bold-font); + letter-spacing: 1px; + color: var(--white); + background-color: var(--steam-green-800); + transition: + color 0.2s, + background-color 0.2s; + + @media (max-width: 768px) { + grid-column: 1; + } + + @media (hover: hover) { + &:hover { + background-color: var(--steam-green-700); + } + } + + &:disabled { + background-color: var(--noble-gray-300); + pointer-events: none; + } + } + + @media (max-width: 768px) { + grid-template-columns: repeat(1, 1fr); + } +} + +.credentialsWrapper, +.personalDataWrapper, +.shippingAddressWrapper, +.billingAddressWrapper { + display: grid; + grid-template-columns: repeat(2, 1fr); + border: 2px solid var(--noble-gray-200); + border-right: 0; + border-left: 0; + border-radius: var(--small-br); + padding: var(--extra-small-offset); + gap: var(--extra-small-offset); + + .title { + grid-column: 2 span; + font: var(--medium-font); + letter-spacing: 1px; + text-align: center; + color: var(--noble-gray-500); + + @media (max-width: 768px) { + grid-column: 1 span; + } + } + + @media (max-width: 768px) { + grid-column: 1 span; + grid-template-columns: repeat(1, 1fr); + } +} + +.credentialsWrapper { + grid-column: 2 span; + grid-row: 1; +} + +.personalDataWrapper { + grid-column: 2 span; + grid-row: 2; +} + +.shippingAddressWrapper { + grid-column: 2 span; + grid-row: 3; +} + +.billingAddressWrapper { + grid-column: 2 span; + grid-row: 4; + transition: transform 0.2s; + animation: show 0.5s ease-in forwards; +} + +.hidden { + animation: hide 0.5s ease-in forwards; +} + +@keyframes hide { + 0% { + transform: scale(1); + } + + 100% { + display: none; + transform: scale(0); + } +} + +@keyframes show { + 0% { + display: grid; + transform: scale(0); + } + + 100% { + transform: scale(1); + } +} + +.settingsAddressWrapper { + display: flex; + flex-direction: column; + align-items: end; +}