diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..66afe9f0 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +commitlint.config.js \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..2dd53c85 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,89 @@ +{ + "parser": "@typescript-eslint/parser", + "extends": [ + "eslint:recommended", + "plugin:solid/typescript", + "plugin:@typescript-eslint/recommended", + "prettier-standard" + ], + "parserOptions": { + "project": "tsconfig.eslint.json", + "sourceType": "module", + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": "latest" + }, + "plugins": ["@typescript-eslint", "prettier", "solid", "import"], + "env": { + "browser": true, + "es6": true, + "node": true, + "jest": true + }, + "rules": { + "no-redeclare": "off", + "camelcase": "off", + "no-use-before-define": "off", + "no-lone-blocks": "off", + "prettier/prettier": [ + "error", + { + "endOfLine": "auto" + } + ], + "import/no-anonymous-default-export": [ + "error", + { + "allowArrowFunction": true, + "allowAnonymousFunction": true + } + ], + "solid/reactivity": "off", + "no-unused-vars": "off", + "prefer-const": "off", + "@typescript-eslint/ban-ts-comment": "off", // отключили до разбирательства с типами (есть туду) + "@typescript-eslint/no-explicit-any": "off", // пока что отключил, чтоб не падал деплой + "@typescript-eslint/triple-slash-reference": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + "caughtErrorsIgnorePattern": "^_" + } + ], + "import/no-named-default": "off", + "no-implicit-globals": "error", + "max-len": [ + "warn", + { + "code": 140, + "ignoreComments": true + } + ], + "no-useless-escape": "off", + "no-unmodified-loop-condition": "off", + "import/export": "off" + }, + "overrides": [ + { + "files": ["src/**/*.js", "src/**/*.ts", "src/**/*.tsx"], + "rules": { + "import/newline-after-import": "error", + "import/no-internal-modules": ["off"], + "import/order": [ + "error", + { + "newlines-between": "always", + "groups": [["builtin", "external", "internal"]], + "pathGroupsExcludedImportTypes": [ + ["builtin", "external", "internal"] + ] + } + ] + } + } + ] +} diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 02388345..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "env": { - "browser": true, - "es2021": true, - "node": true - }, - "extends": ["eslint:recommended", "plugin:react/recommended", "plugin:@typescript-eslint/recommended", "prettier"], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": ["react", "@typescript-eslint"], - "rules": { - "@typescript-eslint/ban-types": [ - "warn", - { - "extendDefaults": true, - "types": { - "{}": false - } - } - ], - "@typescript-eslint/no-unused-vars": [ - "warn", - { - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_" - } - ] - }, - "settings": { - "react": { - "version": "detect" - } - } -} diff --git a/.github/workflows/backend-checks.yml b/.github/workflows/backend-checks.yml index 3274088f..ca52ccc0 100644 --- a/.github/workflows/backend-checks.yml +++ b/.github/workflows/backend-checks.yml @@ -58,4 +58,4 @@ jobs: with: name: clippy (${{ runner.os }}) token: ${{ secrets.GITHUB_TOKEN }} - args: --manifest-path ./src-tauri/Cargo.toml --no-default-features -- -D warnings + args: --manifest-path ./src-tauri/Cargo.toml --no-default-features diff --git a/.github/workflows/frontend-checks.yml b/.github/workflows/frontend-checks.yml index eb90bdfa..32302345 100644 --- a/.github/workflows/frontend-checks.yml +++ b/.github/workflows/frontend-checks.yml @@ -19,14 +19,44 @@ concurrency: jobs: prettier-tsc-eslint-checks: runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 + + - uses: pnpm/action-setup@v2 + name: Install pnpm + id: pnpm-install + with: + version: 7 + run_install: false + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'pnpm' + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v3 + name: Setup pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install - - name: Install modules - run: yarn - name: Run prettier - run: yarn prettier --check . + run: pnpm prettier --check . - name: Run tsc - run: yarn tsc --noEmit + run: pnpm tsc --noEmit - name: Run ESLint - run: yarn eslint src + run: pnpm eslint src diff --git a/.gitignore b/.gitignore index 3efbe5a1..de17ebdd 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ /.pnp .pnp.js +.idea + # testing /coverage diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 3ab2e13d..00000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - -yarn lint-staged --allow-empty diff --git a/.lefthook/commit-msg/commitlint.sh b/.lefthook/commit-msg/commitlint.sh new file mode 100755 index 00000000..5d84f50e --- /dev/null +++ b/.lefthook/commit-msg/commitlint.sh @@ -0,0 +1 @@ +echo $(head -n1 $1) | pnpx commitlint --color \ No newline at end of file diff --git a/.lintstagedrc.json b/.lintstagedrc.json deleted file mode 100644 index f03aec49..00000000 --- a/.lintstagedrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "src-tauri/**/*.rs": "rustfmt --edition 2021", - "*": "yarn prettier --write --ignore-unknown" -} diff --git a/.prettierignore b/.prettierignore index 76252dde..8437bb26 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,6 @@ node_modules/ src-tauri/resources/ src-tauri/target/ -src-tauri/WixTools/ \ No newline at end of file +src-tauri/WixTools/ +build/ +coverage/ \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000..eb5d6644 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,14 @@ +const prettierConfigStandard = require('prettier-config-standard'); + +const modifiedConfig = { + ...prettierConfigStandard, + semi: true, + parser: 'typescript', + singleQuote: true, + trailingComma: 'es5', + proseWrap: 'never', + arrowParens: 'always', + tabWidth: 2, +}; + +module.exports = modifiedConfig; diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index b2095be8..00000000 --- a/.prettierrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "semi": false, - "singleQuote": true -} diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 00000000..84dcb122 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], +}; diff --git a/public/index.html b/index.html similarity index 67% rename from public/index.html rename to index.html index 900bdf12..7611b7a0 100644 --- a/public/index.html +++ b/index.html @@ -2,16 +2,17 @@ - + - - + + Cultivation
+ diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 00000000..c62121a3 --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,18 @@ +pre-commit: + parallel: true + commands: + prettier-js: + glob: "*.{ts,js,tsx}" + run: prettier --write {staged_files} + prettier-json: + glob: "{*.json,.prettierrc,.lintstagedrc,.eslintrc}" + run: prettier --write --parser json {staged_files} + lint: + exclude: ".prettierrc.js|commitlint.config.js" + glob: "*.{ts,tsx}" + run: eslint --fix {staged_files} + +commit-msg: + scripts: + 'commitlint.sh': + runner: bash \ No newline at end of file diff --git a/package.json b/package.json index 4a13950d..fbe63686 100644 --- a/package.json +++ b/package.json @@ -3,48 +3,35 @@ "version": "1.0.10", "private": true, "dependencies": { - "@tauri-apps/api": "^1.0.0-rc.5", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^13.0.0", - "@testing-library/user-event": "^14.2.6", - "@types/jest": "^28.1.6", - "@types/node": "^18.0.6", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "react": "^18.1.0", - "react-dom": "^18.1.0", - "react-scripts": "5.0.1", - "typescript": "^4.4.2", - "web-vitals": "^2.1.0" + "@solid-devtools/overlay": "^0.3.1", + "@solid-primitives/timer": "^1.3.4", + "@tauri-apps/api": "^1.2.0", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/user-event": "^14.4.3", + "@types/jest": "^29.2.3", + "@types/node": "^18.11.9", + "classcat": "^5.0.4", + "typescript": "^4.9.3", + "web-vitals": "^3.1.0" }, "scripts": { - "start": "cross-env BROWSER=none react-scripts start", + "start": "cross-env BROWSER=none vite", "postbuild:windows": "xcopy /E /H /C /I /Y \".\\src-tauri\\lang\" \".\\src-tauri\\target\\release\\lang\"", "postbuild:linux": "cp -r \"./src-tauri/lang\" \"./lang\"", - "build:windows": "yarn tauri build", - "build:linux": "yarn tauri build", - "build": "react-scripts build && run-script-os", - "test": "react-scripts test", - "eject": "react-scripts eject", + "build:windows": "pnpm tauri build", + "build:linux": "pnpm tauri build", + "build": "vite build && run-script-os", + "test": "vitest", "tauri": "tauri", "start:dev": "tauri dev -- -- --no-admin", + "fe:lint:fix": "eslint src --fix", "format": "cargo fmt --manifest-path ./src-tauri/Cargo.toml --all && yarn prettier --write --cache --loglevel warn .", "lint": "cargo clippy --manifest-path ./src-tauri/Cargo.toml --no-default-features && yarn tsc --noEmit && yarn eslint src", "lint:fix": "cargo clippy --manifest-path ./src-tauri/Cargo.toml --no-default-features --fix --allow-dirty && yarn tsc --noEmit && yarn eslint --fix src", - "prepare": "husky install" - }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] + "prepare": "lefthook install" }, "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], + "production": [">0.2%", "not dead", "not op_mini all"], "development": [ "last 1 chrome version", "last 1 firefox version", @@ -52,16 +39,39 @@ ] }, "devDependencies": { - "@tauri-apps/cli": "^1.0.0-rc.11", - "@typescript-eslint/eslint-plugin": "^5.22.0", - "@typescript-eslint/parser": "^5.22.0", + "@commitlint/cli": "^17.3.0", + "@commitlint/config-conventional": "^17.3.0", + "@tauri-apps/cli": "^1.2.1", + "@typescript-eslint/eslint-plugin": "^5.44.0", + "@typescript-eslint/parser": "^5.44.0", + "commitizen": "^4.2.5", "cross-env": "^7.0.3", - "eslint": "^8.15.0", + "cz-conventional-changelog": "^3.3.0", + "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", - "eslint-plugin-react": "^7.29.4", - "husky": "^8.0.0", - "lint-staged": "^13.0.3", - "prettier": "^2.7.1", - "run-script-os": "^1.1.6" + "eslint-config-prettier-standard": "^4.0.1", + "eslint-config-standard": "^17.0.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-n": "^15.5.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-simple-import-sort": "^8.0.0", + "eslint-plugin-solid": "^0.8.0", + "lefthook": "^1.2.2", + "lint-staged": "^13.0.4", + "prettier": "^2.8.0", + "prettier-config-standard": "^5.0.0", + "run-script-os": "^1.1.6", + "solid-js": "^1.6.2", + "solid-testing-library": "^0.5.0", + "vite": "^3.2.4", + "vite-plugin-solid": "^2.4.0", + "vitest": "^0.25.3" + }, + "config": { + "commitizen": { + "path": "./node_modules/cz-conventional-changelog" + } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..5ca3c2d6 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,5148 @@ +lockfileVersion: 5.4 + +specifiers: + '@commitlint/cli': ^17.3.0 + '@commitlint/config-conventional': ^17.3.0 + '@solid-devtools/overlay': ^0.3.1 + '@solid-primitives/timer': ^1.3.4 + '@tauri-apps/api': ^1.2.0 + '@tauri-apps/cli': ^1.2.1 + '@testing-library/jest-dom': ^5.16.5 + '@testing-library/user-event': ^14.4.3 + '@types/jest': ^29.2.3 + '@types/node': ^18.11.9 + '@typescript-eslint/eslint-plugin': ^5.44.0 + '@typescript-eslint/parser': ^5.44.0 + classcat: ^5.0.4 + commitizen: ^4.2.5 + cross-env: ^7.0.3 + cz-conventional-changelog: ^3.3.0 + eslint: ^8.28.0 + eslint-config-prettier: ^8.5.0 + eslint-config-prettier-standard: ^4.0.1 + eslint-config-standard: ^17.0.0 + eslint-plugin-import: ^2.26.0 + eslint-plugin-n: ^15.5.1 + eslint-plugin-node: ^11.1.0 + eslint-plugin-prettier: ^4.2.1 + eslint-plugin-promise: ^6.1.1 + eslint-plugin-simple-import-sort: ^8.0.0 + eslint-plugin-solid: ^0.8.0 + lefthook: ^1.2.2 + lint-staged: ^13.0.4 + prettier: ^2.8.0 + prettier-config-standard: ^5.0.0 + run-script-os: ^1.1.6 + solid-js: ^1.6.2 + solid-testing-library: ^0.5.0 + typescript: ^4.9.3 + vite: ^3.2.4 + vite-plugin-solid: ^2.4.0 + vitest: ^0.25.3 + web-vitals: ^3.1.0 + +dependencies: + '@solid-devtools/overlay': 0.3.1_solid-js@1.6.2+vite@3.2.4 + '@solid-primitives/timer': 1.3.4_solid-js@1.6.2 + '@tauri-apps/api': 1.2.0 + '@testing-library/jest-dom': 5.16.5 + '@testing-library/user-event': 14.4.3 + '@types/jest': 29.2.3 + '@types/node': 18.11.9 + classcat: 5.0.4 + typescript: 4.9.3 + web-vitals: 3.1.0 + +devDependencies: + '@commitlint/cli': 17.3.0 + '@commitlint/config-conventional': 17.3.0 + '@tauri-apps/cli': 1.2.1 + '@typescript-eslint/eslint-plugin': 5.44.0_fnsv2sbzcckq65bwfk7a5xwslu + '@typescript-eslint/parser': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + commitizen: 4.2.5 + cross-env: 7.0.3 + cz-conventional-changelog: 3.3.0 + eslint: 8.28.0 + eslint-config-prettier: 8.5.0_eslint@8.28.0 + eslint-config-prettier-standard: 4.0.1_g564no6wknyfo5tdpgct3p2ko4 + eslint-config-standard: 17.0.0_5dakk4wnrkkieagghiqvu5yn4y + eslint-plugin-import: 2.26.0_vfrilbydaxalswvos6uuh4sxs4 + eslint-plugin-n: 15.5.1_eslint@8.28.0 + eslint-plugin-node: 11.1.0_eslint@8.28.0 + eslint-plugin-prettier: 4.2.1_cwlo2dingkvfydnaculr42urve + eslint-plugin-promise: 6.1.1_eslint@8.28.0 + eslint-plugin-simple-import-sort: 8.0.0_eslint@8.28.0 + eslint-plugin-solid: 0.8.0_hsf322ms6xhhd4b5ne6lb74y4a + lefthook: 1.2.2 + lint-staged: 13.0.4 + prettier: 2.8.0 + prettier-config-standard: 5.0.0_prettier@2.8.0 + run-script-os: 1.1.6 + solid-js: 1.6.2 + solid-testing-library: 0.5.0_solid-js@1.6.2 + vite: 3.2.4_@types+node@18.11.9 + vite-plugin-solid: 2.4.0_solid-js@1.6.2+vite@3.2.4 + vitest: 0.25.3 + +packages: + + /@adobe/css-tools/4.0.1: + resolution: {integrity: sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==} + dev: false + + /@ampproject/remapping/2.2.0: + resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.1.1 + '@jridgewell/trace-mapping': 0.3.17 + + /@babel/code-frame/7.18.6: + resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.18.6 + + /@babel/compat-data/7.20.1: + resolution: {integrity: sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==} + engines: {node: '>=6.9.0'} + + /@babel/core/7.20.2: + resolution: {integrity: sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.0 + '@babel/code-frame': 7.18.6 + '@babel/generator': 7.20.4 + '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.2 + '@babel/helper-module-transforms': 7.20.2 + '@babel/helpers': 7.20.1 + '@babel/parser': 7.20.3 + '@babel/template': 7.18.10 + '@babel/traverse': 7.20.1 + '@babel/types': 7.20.2 + convert-source-map: 1.9.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.1 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + + /@babel/generator/7.20.4: + resolution: {integrity: sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.20.2 + '@jridgewell/gen-mapping': 0.3.2 + jsesc: 2.5.2 + + /@babel/helper-annotate-as-pure/7.18.6: + resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.20.2 + dev: true + + /@babel/helper-compilation-targets/7.20.0_@babel+core@7.20.2: + resolution: {integrity: sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.20.1 + '@babel/core': 7.20.2 + '@babel/helper-validator-option': 7.18.6 + browserslist: 4.21.4 + semver: 6.3.0 + + /@babel/helper-create-class-features-plugin/7.20.2_@babel+core@7.20.2: + resolution: {integrity: sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.20.2 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.19.0 + '@babel/helper-member-expression-to-functions': 7.18.9 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-replace-supers': 7.19.1 + '@babel/helper-split-export-declaration': 7.18.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-environment-visitor/7.18.9: + resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} + engines: {node: '>=6.9.0'} + + /@babel/helper-function-name/7.19.0: + resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.18.10 + '@babel/types': 7.20.2 + + /@babel/helper-hoist-variables/7.18.6: + resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.20.2 + + /@babel/helper-member-expression-to-functions/7.18.9: + resolution: {integrity: sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.20.2 + dev: true + + /@babel/helper-module-imports/7.16.0: + resolution: {integrity: sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.20.2 + dev: true + + /@babel/helper-module-imports/7.18.6: + resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.20.2 + + /@babel/helper-module-transforms/7.20.2: + resolution: {integrity: sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-module-imports': 7.18.6 + '@babel/helper-simple-access': 7.20.2 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/helper-validator-identifier': 7.19.1 + '@babel/template': 7.18.10 + '@babel/traverse': 7.20.1 + '@babel/types': 7.20.2 + transitivePeerDependencies: + - supports-color + + /@babel/helper-optimise-call-expression/7.18.6: + resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.20.2 + dev: true + + /@babel/helper-plugin-utils/7.20.2: + resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} + engines: {node: '>=6.9.0'} + + /@babel/helper-replace-supers/7.19.1: + resolution: {integrity: sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-member-expression-to-functions': 7.18.9 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/traverse': 7.20.1 + '@babel/types': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-simple-access/7.20.2: + resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.20.2 + + /@babel/helper-split-export-declaration/7.18.6: + resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.20.2 + + /@babel/helper-string-parser/7.19.4: + resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-identifier/7.19.1: + resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-option/7.18.6: + resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} + engines: {node: '>=6.9.0'} + + /@babel/helpers/7.20.1: + resolution: {integrity: sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.18.10 + '@babel/traverse': 7.20.1 + '@babel/types': 7.20.2 + transitivePeerDependencies: + - supports-color + + /@babel/highlight/7.18.6: + resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.19.1 + chalk: 2.4.2 + js-tokens: 4.0.0 + + /@babel/parser/7.20.3: + resolution: {integrity: sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.20.2 + + /@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.20.2: + resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.2 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-typescript/7.20.0_@babel+core@7.20.2: + resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.2 + '@babel/helper-plugin-utils': 7.20.2 + + /@babel/plugin-transform-typescript/7.20.2_@babel+core@7.20.2: + resolution: {integrity: sha512-jvS+ngBfrnTUBfOQq8NfGnSbF9BrqlR6hjJ2yVxMkmO5nL/cdifNbI30EfjRlN4g5wYWNnMPyj5Sa6R1pbLeag==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.2 + '@babel/helper-create-class-features-plugin': 7.20.2_@babel+core@7.20.2 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-typescript/7.18.6_@babel+core@7.20.2: + resolution: {integrity: sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.2 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-validator-option': 7.18.6 + '@babel/plugin-transform-typescript': 7.20.2_@babel+core@7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/runtime/7.20.1: + resolution: {integrity: sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + + /@babel/template/7.18.10: + resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/parser': 7.20.3 + '@babel/types': 7.20.2 + + /@babel/traverse/7.20.1: + resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/generator': 7.20.4 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.19.0 + '@babel/helper-hoist-variables': 7.18.6 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/parser': 7.20.3 + '@babel/types': 7.20.2 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + /@babel/types/7.20.2: + resolution: {integrity: sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.19.4 + '@babel/helper-validator-identifier': 7.19.1 + to-fast-properties: 2.0.0 + + /@commitlint/cli/17.3.0: + resolution: {integrity: sha512-/H0md7TsKflKzVPz226VfXzVafJFO1f9+r2KcFvmBu08V0T56lZU1s8WL7/xlxqLMqBTVaBf7Ixtc4bskdEEZg==} + engines: {node: '>=v14'} + hasBin: true + dependencies: + '@commitlint/format': 17.0.0 + '@commitlint/lint': 17.3.0 + '@commitlint/load': 17.3.0 + '@commitlint/read': 17.2.0 + '@commitlint/types': 17.0.0 + execa: 5.1.1 + lodash.isfunction: 3.0.9 + resolve-from: 5.0.0 + resolve-global: 1.0.0 + yargs: 17.6.2 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + dev: true + + /@commitlint/config-conventional/17.3.0: + resolution: {integrity: sha512-hgI+fN5xF8nhS9uG/V06xyT0nlcyvHHMkq0kwRSr96vl5BFlRGaL2C0/YY4kQagfU087tmj01bJkG9Ek98Wllw==} + engines: {node: '>=v14'} + dependencies: + conventional-changelog-conventionalcommits: 5.0.0 + dev: true + + /@commitlint/config-validator/17.1.0: + resolution: {integrity: sha512-Q1rRRSU09ngrTgeTXHq6ePJs2KrI+axPTgkNYDWSJIuS1Op4w3J30vUfSXjwn5YEJHklK3fSqWNHmBhmTR7Vdg==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.0.0 + ajv: 8.11.2 + dev: true + + /@commitlint/ensure/17.3.0: + resolution: {integrity: sha512-kWbrQHDoW5veIUQx30gXoLOCjWvwC6OOEofhPCLl5ytRPBDAQObMbxTha1Bt2aSyNE/IrJ0s0xkdZ1Gi3wJwQg==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.0.0 + 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 + dev: true + + /@commitlint/execute-rule/17.0.0: + resolution: {integrity: sha512-nVjL/w/zuqjCqSJm8UfpNaw66V9WzuJtQvEnCrK4jDw6qKTmZB+1JQ8m6BQVZbNBcwfYdDNKnhIhqI0Rk7lgpQ==} + engines: {node: '>=v14'} + dev: true + + /@commitlint/format/17.0.0: + resolution: {integrity: sha512-MZzJv7rBp/r6ZQJDEodoZvdRM0vXu1PfQvMTNWFb8jFraxnISMTnPBWMMjr2G/puoMashwaNM//fl7j8gGV5lA==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.0.0 + chalk: 4.1.2 + dev: true + + /@commitlint/is-ignored/17.2.0: + resolution: {integrity: sha512-rgUPUQraHxoMLxiE8GK430HA7/R2vXyLcOT4fQooNrZq9ERutNrP6dw3gdKLkq22Nede3+gEHQYUzL4Wu75ndg==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.0.0 + semver: 7.3.7 + dev: true + + /@commitlint/lint/17.3.0: + resolution: {integrity: sha512-VilOTPg0i9A7CCWM49E9bl5jytfTvfTxf9iwbWAWNjxJ/A5mhPKbm3sHuAdwJ87tDk1k4j8vomYfH23iaY+1Rw==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/is-ignored': 17.2.0 + '@commitlint/parse': 17.2.0 + '@commitlint/rules': 17.3.0 + '@commitlint/types': 17.0.0 + dev: true + + /@commitlint/load/17.3.0: + resolution: {integrity: sha512-u/pV6rCAJrCUN+HylBHLzZ4qj1Ew3+eN9GBPhNi9otGxtOfA8b+8nJSxaNbcC23Ins/kcpjGf9zPSVW7628Umw==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/config-validator': 17.1.0 + '@commitlint/execute-rule': 17.0.0 + '@commitlint/resolve-extends': 17.3.0 + '@commitlint/types': 17.0.0 + '@types/node': 14.18.33 + chalk: 4.1.2 + cosmiconfig: 7.1.0 + cosmiconfig-typescript-loader: 4.2.0_qoh33be55smklb2oyrgdyddh4a + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + resolve-from: 5.0.0 + ts-node: 10.9.1_kluoused5zacjtflizwvdqgpom + typescript: 4.9.3 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + dev: true + + /@commitlint/message/17.2.0: + resolution: {integrity: sha512-/4l2KFKxBOuoEn1YAuuNNlAU05Zt7sNsC9H0mPdPm3chOrT4rcX0pOqrQcLtdMrMkJz0gC7b3SF80q2+LtdL9Q==} + engines: {node: '>=v14'} + dev: true + + /@commitlint/parse/17.2.0: + resolution: {integrity: sha512-vLzLznK9Y21zQ6F9hf8D6kcIJRb2haAK5T/Vt1uW2CbHYOIfNsR/hJs0XnF/J9ctM20Tfsqv4zBitbYvVw7F6Q==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.0.0 + conventional-changelog-angular: 5.0.13 + conventional-commits-parser: 3.2.4 + dev: true + + /@commitlint/read/17.2.0: + resolution: {integrity: sha512-bbblBhrHkjxra3ptJNm0abxu7yeAaxumQ8ZtD6GIVqzURCETCP7Dm0tlVvGRDyXBuqX6lIJxh3W7oyKqllDsHQ==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/top-level': 17.0.0 + '@commitlint/types': 17.0.0 + fs-extra: 10.1.0 + git-raw-commits: 2.0.11 + minimist: 1.2.7 + dev: true + + /@commitlint/resolve-extends/17.3.0: + resolution: {integrity: sha512-Lf3JufJlc5yVEtJWC8o4IAZaB8FQAUaVlhlAHRACd0TTFizV2Lk2VH70et23KgvbQNf7kQzHs/2B4QZalBv6Cg==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/config-validator': 17.1.0 + '@commitlint/types': 17.0.0 + import-fresh: 3.3.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + resolve-global: 1.0.0 + dev: true + + /@commitlint/rules/17.3.0: + resolution: {integrity: sha512-s2UhDjC5yP2utx3WWqsnZRzjgzAX8BMwr1nltC0u0p8T/nzpkx4TojEfhlsOUj1t7efxzZRjUAV0NxNwdJyk+g==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/ensure': 17.3.0 + '@commitlint/message': 17.2.0 + '@commitlint/to-lines': 17.0.0 + '@commitlint/types': 17.0.0 + execa: 5.1.1 + dev: true + + /@commitlint/to-lines/17.0.0: + resolution: {integrity: sha512-nEi4YEz04Rf2upFbpnEorG8iymyH7o9jYIVFBG1QdzebbIFET3ir+8kQvCZuBE5pKCtViE4XBUsRZz139uFrRQ==} + engines: {node: '>=v14'} + dev: true + + /@commitlint/top-level/17.0.0: + resolution: {integrity: sha512-dZrEP1PBJvodNWYPOYiLWf6XZergdksKQaT6i1KSROLdjf5Ai0brLOv5/P+CPxBeoj3vBxK4Ax8H1Pg9t7sHIQ==} + engines: {node: '>=v14'} + dependencies: + find-up: 5.0.0 + dev: true + + /@commitlint/types/17.0.0: + resolution: {integrity: sha512-hBAw6U+SkAT5h47zDMeOu3HSiD0SODw4Aq7rRNh1ceUmL7GyLKYhPbUvlRWqZ65XjBLPHZhFyQlRaPNz8qvUyQ==} + engines: {node: '>=v14'} + dependencies: + chalk: 4.1.2 + dev: true + + /@cspotcode/source-map-support/0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: true + + /@emotion/hash/0.9.0: + resolution: {integrity: sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==} + dev: false + + /@esbuild/android-arm/0.15.15: + resolution: {integrity: sha512-JJjZjJi2eBL01QJuWjfCdZxcIgot+VoK6Fq7eKF9w4YHm9hwl7nhBR1o2Wnt/WcANk5l9SkpvrldW1PLuXxcbw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/linux-loong64/0.15.15: + resolution: {integrity: sha512-lhz6UNPMDXUhtXSulw8XlFAtSYO26WmHQnCi2Lg2p+/TMiJKNLtZCYUxV4wG6rZMzXmr8InGpNwk+DLT2Hm0PA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + optional: true + + /@eslint/eslintrc/1.3.3: + resolution: {integrity: sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.4.1 + globals: 13.18.0 + ignore: 5.2.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/config-array/0.11.7: + resolution: {integrity: sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer/1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema/1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@jest/expect-utils/29.3.1: + resolution: {integrity: sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.2.0 + dev: false + + /@jest/schemas/29.0.0: + resolution: {integrity: sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.24.51 + dev: false + + /@jest/types/29.3.1: + resolution: {integrity: sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.0.0 + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 18.11.9 + '@types/yargs': 17.0.14 + chalk: 4.1.2 + dev: false + + /@jridgewell/gen-mapping/0.1.1: + resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.14 + + /@jridgewell/gen-mapping/0.3.2: + resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/trace-mapping': 0.3.17 + + /@jridgewell/resolve-uri/3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + engines: {node: '>=6.0.0'} + + /@jridgewell/set-array/1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + + /@jridgewell/sourcemap-codec/1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + + /@jridgewell/trace-mapping/0.3.17: + resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + + /@jridgewell/trace-mapping/0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk/1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.13.0 + dev: true + + /@sinclair/typebox/0.24.51: + resolution: {integrity: sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==} + dev: false + + /@solid-devtools/debugger/0.15.3_solid-js@1.6.2+vite@3.2.4: + resolution: {integrity: sha512-XWTd/eXnqJay7DJedpDh8CGtc33PSD9NffYkyYe+cFawj6u4pkbkm1XRZujxtmZKzyqT2oudRyRGgHx773MW9w==} + peerDependencies: + solid-js: ^1.6.2 + dependencies: + '@solid-devtools/shared': 0.10.1_solid-js@1.6.2 + '@solid-devtools/transform': 0.9.0_solid-js@1.6.2+vite@3.2.4 + '@solid-primitives/bounds': 0.0.105_solid-js@1.6.2 + '@solid-primitives/cursor': 0.0.103_solid-js@1.6.2 + '@solid-primitives/event-bus': 0.1.4_solid-js@1.6.2 + '@solid-primitives/event-listener': 2.2.4_solid-js@1.6.2 + '@solid-primitives/keyboard': 1.0.5_solid-js@1.6.2 + '@solid-primitives/platform': 0.0.102_solid-js@1.6.2 + '@solid-primitives/scheduled': 1.2.0_solid-js@1.6.2 + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + type-fest: 3.2.0 + transitivePeerDependencies: + - supports-color + - vite + dev: false + + /@solid-devtools/frontend/0.2.4_solid-js@1.6.2+vite@3.2.4: + resolution: {integrity: sha512-keoRKE3uwATlo7WsbQ7g81NzipoBjuoKqahNEa5fko0dWvfhlVwgd8B+w9bfW0kCzp/9th9FEcbbGGvvaysQMQ==} + peerDependencies: + solid-js: ^1.6.2 + dependencies: + '@solid-devtools/debugger': 0.15.3_solid-js@1.6.2+vite@3.2.4 + '@solid-devtools/shared': 0.10.1_solid-js@1.6.2 + '@solid-primitives/context': 0.1.2_solid-js@1.6.2 + '@solid-primitives/cursor': 0.0.103_solid-js@1.6.2 + '@solid-primitives/event-bus': 0.1.4_solid-js@1.6.2 + '@solid-primitives/event-listener': 2.2.4_solid-js@1.6.2 + '@solid-primitives/keyboard': 1.0.5_solid-js@1.6.2 + '@solid-primitives/keyed': 1.1.4_solid-js@1.6.2 + '@solid-primitives/media': 2.0.4_solid-js@1.6.2 + '@solid-primitives/mouse': 2.0.4_solid-js@1.6.2 + '@solid-primitives/props': 3.0.1_solid-js@1.6.2 + '@solid-primitives/range': 0.1.4_solid-js@1.6.2 + '@solid-primitives/resize-observer': 2.0.7_solid-js@1.6.2 + '@solid-primitives/scheduled': 1.2.0_solid-js@1.6.2 + '@solid-primitives/styles': 0.0.101_solid-js@1.6.2 + '@solid-primitives/timer': 1.3.4_solid-js@1.6.2 + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + '@vanilla-extract/css': 1.9.2 + '@vanilla-extract/dynamic': 2.0.3 + '@vanilla-extract/private': 1.0.3 + clsx: 1.2.1 + csstype: 3.1.1 + solid-headless: 0.13.0_solid-js@1.6.2 + solid-js: 1.6.2 + type-fest: 3.2.0 + transitivePeerDependencies: + - supports-color + - vite + dev: false + + /@solid-devtools/overlay/0.3.1_solid-js@1.6.2+vite@3.2.4: + resolution: {integrity: sha512-D8HRfAZ0SjKgLNiva0NE0GQDJe4+JcLYfqfoqNgBzY9azjIWiy9HRqRgx5cUQTnXd9MU9/6n792o75Rq8jbUCw==} + peerDependencies: + solid-js: ^1.6.2 + dependencies: + '@solid-devtools/debugger': 0.15.3_solid-js@1.6.2+vite@3.2.4 + '@solid-devtools/frontend': 0.2.4_solid-js@1.6.2+vite@3.2.4 + '@solid-devtools/shared': 0.10.1_solid-js@1.6.2 + '@solid-primitives/cursor': 0.0.103_solid-js@1.6.2 + '@solid-primitives/event-listener': 2.2.4_solid-js@1.6.2 + '@solid-primitives/media': 2.0.4_solid-js@1.6.2 + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + transitivePeerDependencies: + - supports-color + - vite + dev: false + + /@solid-devtools/shared/0.10.1_solid-js@1.6.2: + resolution: {integrity: sha512-RCa6Ev5ZGdOWIo34bqcZixlaV9tEuVMTxELjuzCg561Lbja2JSp3SwKCpxu9CQrJ21CZpgvu/PxsJ28YEHJ0TA==} + peerDependencies: + solid-js: ^1.6.2 + dependencies: + '@solid-primitives/event-bus': 0.1.4_solid-js@1.6.2 + '@solid-primitives/event-listener': 2.2.4_solid-js@1.6.2 + '@solid-primitives/media': 2.0.4_solid-js@1.6.2 + '@solid-primitives/rootless': 1.2.1_solid-js@1.6.2 + '@solid-primitives/scheduled': 1.2.0_solid-js@1.6.2 + '@solid-primitives/styles': 0.0.101_solid-js@1.6.2 + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + type-fest: 3.2.0 + dev: false + + /@solid-devtools/transform/0.9.0_solid-js@1.6.2+vite@3.2.4: + resolution: {integrity: sha512-68Fz80+lkUNTfePvjiv0jC02cPGsZTYl06F2N8Y2DxnujAGYEJbg5mpdC805Q5ykIWMDcibUP3vdGYmNq1JL9w==} + peerDependencies: + solid-js: ^1.6.2 + vite: ^2.2.3 || ^3.0.0 + dependencies: + '@babel/core': 7.20.2 + '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.2 + '@babel/types': 7.20.2 + '@solid-devtools/shared': 0.10.1_solid-js@1.6.2 + solid-js: 1.6.2 + vite: 3.2.4_@types+node@18.11.9 + transitivePeerDependencies: + - supports-color + dev: false + + /@solid-primitives/bounds/0.0.105_solid-js@1.6.2: + resolution: {integrity: sha512-a2ZRuZayXV1/kSKx8cEOR5pIs2zKAF9lS3Gj/r7uHmBQBmn25GYCYOwj4LbLQbqqbumZr2eJO+/wDyi4UOX5pw==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/event-listener': 2.2.4_solid-js@1.6.2 + '@solid-primitives/resize-observer': 2.0.7_solid-js@1.6.2 + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/context/0.1.2_solid-js@1.6.2: + resolution: {integrity: sha512-kYnP08rKHgZA7O9azK8Bqo7yzN+2Fh8PHsftsghSAN6MVbH0soTSaBz+Cwx7jsVOJ7X3FRNjTEGIlvq97vfGyw==} + peerDependencies: + solid-js: ^1.5.0 + dependencies: + solid-js: 1.6.2 + dev: false + + /@solid-primitives/cursor/0.0.103_solid-js@1.6.2: + resolution: {integrity: sha512-bb5x5lCimBf7R2VqrrMVcP2y/aGTMjNj7fjvY+RvTAC3/WtG/odqeYwka4lCBV27pX9TiJCKtNS6mVTigdfLMA==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/event-bus/0.1.4_solid-js@1.6.2: + resolution: {integrity: sha512-fpj5/b/x5EZGmey7iUm6d/oc52ff8HbTr7yO/+WJUheMSCyY6dQz7INth7ovx57a3SDKTqZJGY3wRZijdBVFdg==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/immutable': 0.1.4_solid-js@1.6.2 + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/event-listener/2.2.4_solid-js@1.6.2: + resolution: {integrity: sha512-O/ppM0SpXWtNC7AHv1bQA9Dy6pj3NUM06MhSV9xwVv4N06PmlNYhGLDSPT1Esesm6b0fDgCXB5V+AgCSEzQd/w==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/immutable/0.1.4_solid-js@1.6.2: + resolution: {integrity: sha512-9oLK8ihIjG5FZv74KoXXyKErxgGxGZsdevsIKB0ugTreBBmozHPcYTjoYFL/sHoqs2ZNMlmfNQ3kduvrvKG2RQ==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/keyboard/1.0.5_solid-js@1.6.2: + resolution: {integrity: sha512-rDgBRi/tKcsfGE5zM5JSStdGor0yL7X6idpbhwXRC9KUTQX1yCDtIf07uGugi9lmQYwCIriRetZT4UCLgn66EQ==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/event-listener': 2.2.4_solid-js@1.6.2 + '@solid-primitives/rootless': 1.2.1_solid-js@1.6.2 + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/keyed/1.1.4_solid-js@1.6.2: + resolution: {integrity: sha512-K4DR4qGYOh5pJXgKKWwPjBEsnEBF4Old3zo4ht9wGBEvv3UB82P+zExqJK1lFie+7dYLOkgKD+8iZle1wZSEzg==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + solid-js: 1.6.2 + dev: false + + /@solid-primitives/media/2.0.4_solid-js@1.6.2: + resolution: {integrity: sha512-MZkdUlV3qJQts4b7ZfAldbFGB1neH64rwHsnTmIeF2Zj8gWjYcYtJ36SwkRs3NjHQ53uQliZ+DtMXiCeapNw/g==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/event-listener': 2.2.4_solid-js@1.6.2 + '@solid-primitives/rootless': 1.2.1_solid-js@1.6.2 + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/mouse/2.0.4_solid-js@1.6.2: + resolution: {integrity: sha512-UmTSJ3Ry4ID/JtGyDMR15zbSnzLaWpES2Tx/mUhAlRRbOIFEwM6W252LH6Q4obi0oRhVQBzJ5yYADmCdFrvBkQ==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/event-listener': 2.2.4_solid-js@1.6.2 + '@solid-primitives/rootless': 1.2.1_solid-js@1.6.2 + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/platform/0.0.102_solid-js@1.6.2: + resolution: {integrity: sha512-1eZA1/HYOhmlZ9LrrGot+LUi/ypO2NXqfB+9F1WY98dGNDMz9pG9k+X7kg2YDJTUHDGbzY7WrsBRyAE8LurE7Q==} + peerDependencies: + solid-js: ^1.5.0 + dependencies: + solid-js: 1.6.2 + dev: false + + /@solid-primitives/props/3.0.1_solid-js@1.6.2: + resolution: {integrity: sha512-5v27ex4KxxnIbgze1lXPEXHO/ebbtEjL6idkhezH/7jHpjunl8PYabpDgoGO16tb8DawcZWOAXa7waWqWPAe/A==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/range/0.1.4_solid-js@1.6.2: + resolution: {integrity: sha512-tyGk2V3VTe22rmy+ArjSS3zIi91kNN0bJN8pp5riLXi+etWaKm1OJYSn+B4uCAG7wBKSrepfjCW4fRGXHBNhbw==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/resize-observer/2.0.7_solid-js@1.6.2: + resolution: {integrity: sha512-/RtCTs61ACdsCKJodNTgnKA05CI09dkg7usAb5jg14L6mzwTNWWdZbXtbYsUlD+kh1/1j+BKxp6VtkbpgJE5yQ==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/event-listener': 2.2.4_solid-js@1.6.2 + '@solid-primitives/rootless': 1.2.1_solid-js@1.6.2 + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/rootless/1.2.1_solid-js@1.6.2: + resolution: {integrity: sha512-8RpdyS1e58PQbDjgjpyCh+IGoX3QEs/2LauMfl94eXJ5d/o1y/c6P61z9XqQm+Bx1Otdgx4nbFCoF7HPqa0mwg==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + '@solid-primitives/utils': 4.0.0_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/scheduled/1.2.0_solid-js@1.6.2: + resolution: {integrity: sha512-59QbtGACZD8RIkD0jNQVUHRBF6uW7dKzDVFYSgogRdfxRO9kgXc6aGkLrCjd4k4g3kYe+XiBLcvYKyut4F7BHg==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + solid-js: 1.6.2 + dev: false + + /@solid-primitives/styles/0.0.101_solid-js@1.6.2: + resolution: {integrity: sha512-tHkeUMntlS/w+/zDzXJv82hhMy3J3q7tVV3ZTbahRo0hZienAM8ZJrCYZNK/fu2px8NHVSZFRufxv9qhIclPTw==} + peerDependencies: + solid-js: ^1.5.0 + dependencies: + '@solid-primitives/rootless': 1.2.1_solid-js@1.6.2 + solid-js: 1.6.2 + dev: false + + /@solid-primitives/timer/1.3.4_solid-js@1.6.2: + resolution: {integrity: sha512-hJbW93n9uY2vqeeS8W5a+vfY7EHQP4ru2vzCCOhuVFxPISk5d5H+3zMWx9KBq8IMYxuRRr3W8wPjIC9snfqIzw==} + peerDependencies: + solid-js: ^1.5.0 + dependencies: + solid-js: 1.6.2 + dev: false + + /@solid-primitives/utils/4.0.0_solid-js@1.6.2: + resolution: {integrity: sha512-fGsJy8Z8YiwogpiezD7TWjI62UCb0JAHJWdoXWGrggrn4bfToZotKkabiB0IVFMkWVE1ZcrkvZT3bkmqGnK0ng==} + peerDependencies: + solid-js: ^1.6.0 + dependencies: + solid-js: 1.6.2 + dev: false + + /@tauri-apps/api/1.2.0: + resolution: {integrity: sha512-lsI54KI6HGf7VImuf/T9pnoejfgkNoXveP14pVV7XarrQ46rOejIVJLFqHI9sRReJMGdh2YuCoI3cc/yCWCsrw==} + engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'} + dev: false + + /@tauri-apps/cli-darwin-arm64/1.2.1: + resolution: {integrity: sha512-WiAxSON52owFI65Whd3NjcKjXdO1zJfafBVZ3v+Y3F2zlXhRPiirXbtefAc3mvN56zDz/pfi018Qb4XesuVzHA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@tauri-apps/cli-darwin-x64/1.2.1: + resolution: {integrity: sha512-jfumnrn7RYKVtDmHgrQhImoxpqT51bDrO4KxgpIXaYSaf6MdG2JT72dwUovPrURw0JX2Z/Elihq+dYbrsKoV/w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@tauri-apps/cli-linux-arm-gnueabihf/1.2.1: + resolution: {integrity: sha512-n4p6Ekn6Wa9X/klUGevEGgoWAGApGGsLrJYE4c8bKTbAUfQ9Nyzjh8gK/GDii1dg9oRW0FdXDa6BJa7aEEj9sA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@tauri-apps/cli-linux-arm64-gnu/1.2.1: + resolution: {integrity: sha512-oAHkQQGfNCh8pQQHuDzzqt+S5sOj3tiUkySaquR2z/AQEHeDGAMrRGLZwOiDw9Xvu7qxFiF9H0e5OMK7BkncDw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@tauri-apps/cli-linux-arm64-musl/1.2.1: + resolution: {integrity: sha512-1dEZ5fdFYkMyB1U7ZkDJUlwYwCeqy9Y3vXmtZ6pCxrvgs844s8+RIFDuMU42pTN+lUxfFeQARmv0LpS4eF/QWQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@tauri-apps/cli-linux-x64-gnu/1.2.1: + resolution: {integrity: sha512-wkgCD3s5P6tgBPnn0/gDx7MXMx2Hx+jdA+JP8zdCq4cIeYXlxdZG/zXbHb5ldPadNh582lzHiGg+Pmc+wDg2fA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@tauri-apps/cli-linux-x64-musl/1.2.1: + resolution: {integrity: sha512-zD+a+5cSlYVU0ECOojWp71ok/9jE0DJufzb9oky17XIKV/oiOAG60z4OYRe+oqxYS1TcBt+pUa1/2zlu/6SRdA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@tauri-apps/cli-win32-ia32-msvc/1.2.1: + resolution: {integrity: sha512-nEgdRd8czaKL1RQfj946dsfzlk6atmD95Fm7NVTVOe77PFHTS3ztHeWK7X6jirCaOF3h/F7qpJVCU6JMnq2tfA==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@tauri-apps/cli-win32-x64-msvc/1.2.1: + resolution: {integrity: sha512-ceWiQkmNNRrnfgbLMnndT4QF1IyLK7aOJsMqS/HueshAwmVQWnC1DUE0C58Taetgq38Cavc4gGnZOCHuH6ZuTw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@tauri-apps/cli/1.2.1: + resolution: {integrity: sha512-JrFFT1/4V+AGSRjKdgszZwOr+/a1519LDhNxBkbsIg6D/kFK+3kk1qImaQBY9DvvIWK6IV4whc8OAkgxm+Sl3w==} + engines: {node: '>= 10'} + hasBin: true + optionalDependencies: + '@tauri-apps/cli-darwin-arm64': 1.2.1 + '@tauri-apps/cli-darwin-x64': 1.2.1 + '@tauri-apps/cli-linux-arm-gnueabihf': 1.2.1 + '@tauri-apps/cli-linux-arm64-gnu': 1.2.1 + '@tauri-apps/cli-linux-arm64-musl': 1.2.1 + '@tauri-apps/cli-linux-x64-gnu': 1.2.1 + '@tauri-apps/cli-linux-x64-musl': 1.2.1 + '@tauri-apps/cli-win32-ia32-msvc': 1.2.1 + '@tauri-apps/cli-win32-x64-msvc': 1.2.1 + dev: true + + /@testing-library/dom/8.19.0: + resolution: {integrity: sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==} + engines: {node: '>=12'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/runtime': 7.20.1 + '@types/aria-query': 4.2.2 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.14 + lz-string: 1.4.4 + pretty-format: 27.5.1 + dev: true + + /@testing-library/jest-dom/5.16.5: + resolution: {integrity: sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==} + engines: {node: '>=8', npm: '>=6', yarn: '>=1'} + dependencies: + '@adobe/css-tools': 4.0.1 + '@babel/runtime': 7.20.1 + '@types/testing-library__jest-dom': 5.14.5 + aria-query: 5.1.3 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.5.14 + lodash: 4.17.21 + redent: 3.0.0 + dev: false + + /@testing-library/user-event/14.4.3: + resolution: {integrity: sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + dev: false + + /@tsconfig/node10/1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + dev: true + + /@tsconfig/node12/1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: true + + /@tsconfig/node14/1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: true + + /@tsconfig/node16/1.0.3: + resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} + dev: true + + /@types/aria-query/4.2.2: + resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==} + dev: true + + /@types/chai-subset/1.3.3: + resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} + dependencies: + '@types/chai': 4.3.4 + dev: true + + /@types/chai/4.3.4: + resolution: {integrity: sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==} + dev: true + + /@types/istanbul-lib-coverage/2.0.4: + resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + dev: false + + /@types/istanbul-lib-report/3.0.0: + resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + dev: false + + /@types/istanbul-reports/3.0.1: + resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} + dependencies: + '@types/istanbul-lib-report': 3.0.0 + dev: false + + /@types/jest/29.2.3: + resolution: {integrity: sha512-6XwoEbmatfyoCjWRX7z0fKMmgYKe9+/HrviJ5k0X/tjJWHGAezZOfYaxqQKuzG/TvQyr+ktjm4jgbk0s4/oF2w==} + dependencies: + expect: 29.3.1 + pretty-format: 29.3.1 + dev: false + + /@types/json-schema/7.0.11: + resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} + dev: true + + /@types/json5/0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/minimist/1.2.2: + resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} + dev: true + + /@types/node/14.18.33: + resolution: {integrity: sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==} + dev: true + + /@types/node/18.11.9: + resolution: {integrity: sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==} + + /@types/normalize-package-data/2.4.1: + resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} + dev: true + + /@types/parse-json/4.0.0: + resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} + dev: true + + /@types/semver/7.3.13: + resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} + dev: true + + /@types/stack-utils/2.0.1: + resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} + dev: false + + /@types/testing-library__jest-dom/5.14.5: + resolution: {integrity: sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==} + dependencies: + '@types/jest': 29.2.3 + dev: false + + /@types/yargs-parser/21.0.0: + resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} + dev: false + + /@types/yargs/17.0.14: + resolution: {integrity: sha512-9Pj7abXoW1RSTcZaL2Hk6G2XyLMlp5ECdVC/Zf2p/KBjC3srijLGgRAXOBjtFrJoIrvxdTKyKDA14bEcbxBaWw==} + dependencies: + '@types/yargs-parser': 21.0.0 + dev: false + + /@typescript-eslint/eslint-plugin/5.44.0_fnsv2sbzcckq65bwfk7a5xwslu: + resolution: {integrity: sha512-j5ULd7FmmekcyWeArx+i8x7sdRHzAtXTkmDPthE4amxZOWKFK7bomoJ4r7PJ8K7PoMzD16U8MmuZFAonr1ERvw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/parser': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + '@typescript-eslint/scope-manager': 5.44.0 + '@typescript-eslint/type-utils': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + '@typescript-eslint/utils': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + debug: 4.3.4 + eslint: 8.28.0 + ignore: 5.2.0 + natural-compare-lite: 1.4.0 + regexpp: 3.2.0 + semver: 7.3.8 + tsutils: 3.21.0_typescript@4.9.3 + typescript: 4.9.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser/5.44.0_hsf322ms6xhhd4b5ne6lb74y4a: + resolution: {integrity: sha512-H7LCqbZnKqkkgQHaKLGC6KUjt3pjJDx8ETDqmwncyb6PuoigYajyAwBGz08VU/l86dZWZgI4zm5k2VaKqayYyA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.44.0 + '@typescript-eslint/types': 5.44.0 + '@typescript-eslint/typescript-estree': 5.44.0_typescript@4.9.3 + debug: 4.3.4 + eslint: 8.28.0 + typescript: 4.9.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager/5.44.0: + resolution: {integrity: sha512-2pKml57KusI0LAhgLKae9kwWeITZ7IsZs77YxyNyIVOwQ1kToyXRaJLl+uDEXzMN5hnobKUOo2gKntK9H1YL8g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.44.0 + '@typescript-eslint/visitor-keys': 5.44.0 + dev: true + + /@typescript-eslint/type-utils/5.44.0_hsf322ms6xhhd4b5ne6lb74y4a: + resolution: {integrity: sha512-A1u0Yo5wZxkXPQ7/noGkRhV4J9opcymcr31XQtOzcc5nO/IHN2E2TPMECKWYpM3e6olWEM63fq/BaL1wEYnt/w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.44.0_typescript@4.9.3 + '@typescript-eslint/utils': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + debug: 4.3.4 + eslint: 8.28.0 + tsutils: 3.21.0_typescript@4.9.3 + typescript: 4.9.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types/5.44.0: + resolution: {integrity: sha512-Tp+zDnHmGk4qKR1l+Y1rBvpjpm5tGXX339eAlRBDg+kgZkz9Bw+pqi4dyseOZMsGuSH69fYfPJCBKBrbPCxYFQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/typescript-estree/5.44.0_typescript@4.9.3: + resolution: {integrity: sha512-M6Jr+RM7M5zeRj2maSfsZK2660HKAJawv4Ud0xT+yauyvgrsHu276VtXlKDFnEmhG+nVEd0fYZNXGoAgxwDWJw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.44.0 + '@typescript-eslint/visitor-keys': 5.44.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.3.8 + tsutils: 3.21.0_typescript@4.9.3 + typescript: 4.9.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils/5.44.0_hsf322ms6xhhd4b5ne6lb74y4a: + resolution: {integrity: sha512-fMzA8LLQ189gaBjS0MZszw5HBdZgVwxVFShCO3QN+ws3GlPkcy9YuS3U4wkT6su0w+Byjq3mS3uamy9HE4Yfjw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@types/json-schema': 7.0.11 + '@types/semver': 7.3.13 + '@typescript-eslint/scope-manager': 5.44.0 + '@typescript-eslint/types': 5.44.0 + '@typescript-eslint/typescript-estree': 5.44.0_typescript@4.9.3 + eslint: 8.28.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0_eslint@8.28.0 + semver: 7.3.8 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys/5.44.0: + resolution: {integrity: sha512-a48tLG8/4m62gPFbJ27FxwCOqPKxsb8KC3HkmYoq2As/4YyjQl1jDbRr1s63+g4FS/iIehjmN3L5UjmKva1HzQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.44.0 + eslint-visitor-keys: 3.3.0 + dev: true + + /@vanilla-extract/css/1.9.2: + resolution: {integrity: sha512-CE5+R89LOl9XG5dRwEIvVyl/YcS2GkqjdE/XnGJ+p7Fp6Exu08fifv7tY87XxFeCIRAbc9psM+h4lF+wC3Y0fg==} + dependencies: + '@emotion/hash': 0.9.0 + '@vanilla-extract/private': 1.0.3 + ahocorasick: 1.0.2 + chalk: 4.1.2 + css-what: 5.1.0 + cssesc: 3.0.0 + csstype: 3.1.1 + deep-object-diff: 1.1.9 + deepmerge: 4.2.2 + media-query-parser: 2.0.2 + outdent: 0.8.0 + dev: false + + /@vanilla-extract/dynamic/2.0.3: + resolution: {integrity: sha512-Rglfw2gXAYiBzAQ4jgUG7rBgE2c88e/zcG27ZVoIqMHVq56wf2C1katGMm1yFMNBgzqM7oBNYzz4YOMzznydkg==} + dependencies: + '@vanilla-extract/private': 1.0.3 + dev: false + + /@vanilla-extract/private/1.0.3: + resolution: {integrity: sha512-17kVyLq3ePTKOkveHxXuIJZtGYs+cSoev7BlP+Lf4916qfDhk/HBjvlYDe8egrea7LNPHKwSZJK/bzZC+Q6AwQ==} + dev: false + + /JSONStream/1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + dev: true + + /acorn-jsx/5.3.2_acorn@8.8.1: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.8.1 + dev: true + + /acorn-walk/8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn/8.8.1: + resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /aggregate-error/3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: true + + /ahocorasick/1.0.2: + resolution: {integrity: sha512-hCOfMzbFx5IDutmWLAt6MZwOUjIfSM9G9FyVxytmE4Rs/5YDPWQrD/+IR1w+FweD9H2oOZEnv36TmkjhNURBVA==} + dev: false + + /ajv/6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ajv/8.11.2: + resolution: {integrity: sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /ansi-escapes/4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-regex/5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-regex/6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles/3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /ansi-styles/5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + /ansi-styles/6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /arg/4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /argparse/2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /aria-query/5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + dependencies: + deep-equal: 2.1.0 + + /array-ify/1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + dev: true + + /array-includes/3.1.6: + resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.4 + get-intrinsic: 1.1.3 + is-string: 1.0.7 + dev: true + + /array-union/2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.flat/1.3.1: + resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.4 + es-shim-unscopables: 1.0.0 + dev: true + + /arrify/1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + dev: true + + /assertion-error/1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + + /astral-regex/2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true + + /at-least-node/1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + dev: true + + /available-typed-arrays/1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + + /babel-plugin-jsx-dom-expressions/0.35.6_@babel+core@7.20.2: + resolution: {integrity: sha512-z8VBym+Scol38MiR97iqQGsANjhsDqscRRemk+po+z3TWKV/fb9kux/gdKOJJSC/ARyUL3HExBFVtr+Efd24uw==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.20.2 + '@babel/helper-module-imports': 7.16.0 + '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.20.2 + '@babel/types': 7.20.2 + html-entities: 2.3.2 + dev: true + + /babel-preset-solid/1.6.2_@babel+core@7.20.2: + resolution: {integrity: sha512-5sFI34g7Jtp4r04YFWkuC1o+gnekBdPXQTJb5/6lmxi5YwzazVgKAXRwEAToC3zRaPyIYJbZUVLpOi5mDzPEuw==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.20.2 + babel-plugin-jsx-dom-expressions: 0.35.6_@babel+core@7.20.2 + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /bl/4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: true + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + + /browserslist/4.21.4: + resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001434 + electron-to-chromium: 1.4.284 + node-releases: 2.0.6 + update-browserslist-db: 1.0.10_browserslist@4.21.4 + + /buffer/5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /builtins/5.0.1: + resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + dependencies: + semver: 7.3.8 + dev: true + + /cachedir/2.3.0: + resolution: {integrity: sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==} + engines: {node: '>=6'} + dev: true + + /call-bind/1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.1.3 + + /callsites/3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase-keys/6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + map-obj: 4.3.0 + quick-lru: 4.0.1 + dev: true + + /camelcase/5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /caniuse-lite/1.0.30001434: + resolution: {integrity: sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA==} + + /chai/4.3.7: + resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.2 + deep-eql: 4.1.2 + get-func-name: 2.0.0 + loupe: 2.3.6 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + + /chalk/2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + /chalk/3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false + + /chalk/4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /chardet/0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: true + + /check-error/1.0.2: + resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} + dev: true + + /ci-info/3.7.0: + resolution: {integrity: sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==} + engines: {node: '>=8'} + dev: false + + /classcat/5.0.4: + resolution: {integrity: sha512-sbpkOw6z413p+HDGcBENe498WM9woqWHiJxCq7nvmxe9WmrUmqfAcxpIwAiMtM5Q3AhYkzXcNQHqsWq0mND51g==} + dev: false + + /clean-stack/2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: true + + /cli-cursor/3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: true + + /cli-spinners/2.7.0: + resolution: {integrity: sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==} + engines: {node: '>=6'} + dev: true + + /cli-truncate/2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + dev: true + + /cli-truncate/3.1.0: + resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + slice-ansi: 5.0.0 + string-width: 5.1.2 + dev: true + + /cli-width/3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: true + + /cliui/8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /clone/1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: true + + /clsx/1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + dev: false + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + + /color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name/1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /colorette/2.0.19: + resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} + dev: true + + /commander/9.4.1: + resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==} + engines: {node: ^12.20.0 || >=14} + dev: true + + /commitizen/4.2.5: + resolution: {integrity: sha512-9sXju8Qrz1B4Tw7kC5KhnvwYQN88qs2zbiB8oyMsnXZyJ24PPGiNM3nHr73d32dnE3i8VJEXddBFIbOgYSEXtQ==} + engines: {node: '>= 12'} + hasBin: true + dependencies: + cachedir: 2.3.0 + cz-conventional-changelog: 3.3.0 + dedent: 0.7.0 + detect-indent: 6.1.0 + find-node-modules: 2.1.3 + find-root: 1.1.0 + fs-extra: 9.1.0 + glob: 7.2.3 + inquirer: 8.2.4 + is-utf8: 0.2.1 + lodash: 4.17.21 + minimist: 1.2.6 + strip-bom: 4.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + dev: true + + /compare-func/2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + dev: true + + /concat-map/0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + dev: true + + /conventional-changelog-angular/5.0.13: + resolution: {integrity: sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==} + engines: {node: '>=10'} + dependencies: + compare-func: 2.0.0 + q: 1.5.1 + dev: true + + /conventional-changelog-conventionalcommits/5.0.0: + resolution: {integrity: sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==} + engines: {node: '>=10'} + dependencies: + compare-func: 2.0.0 + lodash: 4.17.21 + q: 1.5.1 + dev: true + + /conventional-commit-types/3.0.0: + resolution: {integrity: sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==} + dev: true + + /conventional-commits-parser/3.2.4: + resolution: {integrity: sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==} + engines: {node: '>=10'} + hasBin: true + dependencies: + JSONStream: 1.3.5 + is-text-path: 1.0.1 + lodash: 4.17.21 + meow: 8.1.2 + split2: 3.2.2 + through2: 4.0.2 + dev: true + + /convert-source-map/1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + /cosmiconfig-typescript-loader/4.2.0_qoh33be55smklb2oyrgdyddh4a: + resolution: {integrity: sha512-NkANeMnaHrlaSSlpKGyvn2R4rqUDeE/9E5YHx+b4nwo0R8dZyAqcih8/gxpCZvqWP9Vf6xuLpMSzSgdVEIM78g==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=7' + ts-node: '>=10' + typescript: '>=3' + dependencies: + '@types/node': 14.18.33 + cosmiconfig: 7.1.0 + ts-node: 10.9.1_kluoused5zacjtflizwvdqgpom + typescript: 4.9.3 + dev: true + + /cosmiconfig/7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.0 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: true + + /create-require/1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /cross-env/7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + dependencies: + cross-spawn: 7.0.3 + dev: true + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /css-what/5.1.0: + resolution: {integrity: sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==} + engines: {node: '>= 6'} + dev: false + + /css.escape/1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + dev: false + + /cssesc/3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /csstype/3.1.1: + resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} + + /cz-conventional-changelog/3.3.0: + resolution: {integrity: sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==} + engines: {node: '>= 10'} + dependencies: + chalk: 2.4.2 + commitizen: 4.2.5 + conventional-commit-types: 3.0.0 + lodash.map: 4.6.0 + longest: 2.0.1 + word-wrap: 1.2.3 + optionalDependencies: + '@commitlint/load': 17.3.0 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + dev: true + + /dargs/7.0.0: + resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} + engines: {node: '>=8'} + dev: true + + /debug/2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + + /debug/3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + + /decamelize-keys/1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + dev: true + + /decamelize/1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /dedent/0.7.0: + resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + dev: true + + /deep-eql/4.1.2: + resolution: {integrity: sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.0.8 + dev: true + + /deep-equal/2.1.0: + resolution: {integrity: sha512-2pxgvWu3Alv1PoWEyVg7HS8YhGlUFUV7N5oOvfL6d+7xAmLSemMwv/c8Zv/i9KFzxV5Kt5CAvQc70fLwVuf4UA==} + dependencies: + call-bind: 1.0.2 + es-get-iterator: 1.1.2 + get-intrinsic: 1.1.3 + is-arguments: 1.1.1 + is-date-object: 1.0.5 + is-regex: 1.1.4 + isarray: 2.0.5 + object-is: 1.1.5 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.4.3 + side-channel: 1.0.4 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.1 + which-typed-array: 1.1.9 + + /deep-is/0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deep-object-diff/1.1.9: + resolution: {integrity: sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==} + dev: false + + /deepmerge/4.2.2: + resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} + engines: {node: '>=0.10.0'} + dev: false + + /defaults/1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: true + + /define-properties/1.1.4: + resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} + engines: {node: '>= 0.4'} + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + + /detect-file/1.0.0: + resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} + engines: {node: '>=0.10.0'} + dev: true + + /detect-indent/6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: true + + /diff-sequences/29.3.1: + resolution: {integrity: sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: false + + /diff/4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /dir-glob/3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine/2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine/3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dom-accessibility-api/0.5.14: + resolution: {integrity: sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==} + + /dot-prop/5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + dependencies: + is-obj: 2.0.0 + dev: true + + /eastasianwidth/0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /electron-to-chromium/1.4.284: + resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} + + /emoji-regex/8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex/9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /error-ex/1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-abstract/1.20.4: + resolution: {integrity: sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + es-to-primitive: 1.2.1 + function-bind: 1.1.1 + function.prototype.name: 1.1.5 + get-intrinsic: 1.1.3 + get-symbol-description: 1.0.0 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-symbols: 1.0.3 + internal-slot: 1.0.3 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-weakref: 1.0.2 + object-inspect: 1.12.2 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.4.3 + safe-regex-test: 1.0.0 + string.prototype.trimend: 1.0.6 + string.prototype.trimstart: 1.0.6 + unbox-primitive: 1.0.2 + dev: true + + /es-get-iterator/1.1.2: + resolution: {integrity: sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.3 + has-symbols: 1.0.3 + is-arguments: 1.1.1 + is-map: 2.0.2 + is-set: 2.0.2 + is-string: 1.0.7 + isarray: 2.0.5 + + /es-shim-unscopables/1.0.0: + resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + dependencies: + has: 1.0.3 + dev: true + + /es-to-primitive/1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /esbuild-android-64/0.15.15: + resolution: {integrity: sha512-F+WjjQxO+JQOva3tJWNdVjouFMLK6R6i5gjDvgUthLYJnIZJsp1HlF523k73hELY20WPyEO8xcz7aaYBVkeg5Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + + /esbuild-android-arm64/0.15.15: + resolution: {integrity: sha512-attlyhD6Y22jNyQ0fIIQ7mnPvDWKw7k6FKnsXlBvQE6s3z6s6cuEHcSgoirquQc7TmZgVCK5fD/2uxmRN+ZpcQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + /esbuild-darwin-64/0.15.15: + resolution: {integrity: sha512-ohZtF8W1SHJ4JWldsPVdk8st0r9ExbAOSrBOh5L+Mq47i696GVwv1ab/KlmbUoikSTNoXEhDzVpxUR/WIO19FQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /esbuild-darwin-arm64/0.15.15: + resolution: {integrity: sha512-P8jOZ5zshCNIuGn+9KehKs/cq5uIniC+BeCykvdVhx/rBXSxmtj3CUIKZz4sDCuESMbitK54drf/2QX9QHG5Ag==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /esbuild-freebsd-64/0.15.15: + resolution: {integrity: sha512-KkTg+AmDXz1IvA9S1gt8dE24C8Thx0X5oM0KGF322DuP+P3evwTL9YyusHAWNsh4qLsR80nvBr/EIYs29VSwuA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + /esbuild-freebsd-arm64/0.15.15: + resolution: {integrity: sha512-FUcML0DRsuyqCMfAC+HoeAqvWxMeq0qXvclZZ/lt2kLU6XBnDA5uKTLUd379WYEyVD4KKFctqWd9tTuk8C/96g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + + /esbuild-linux-32/0.15.15: + resolution: {integrity: sha512-q28Qn5pZgHNqug02aTkzw5sW9OklSo96b5nm17Mq0pDXrdTBcQ+M6Q9A1B+dalFeynunwh/pvfrNucjzwDXj+Q==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + optional: true + + /esbuild-linux-64/0.15.15: + resolution: {integrity: sha512-217KPmWMirkf8liO+fj2qrPwbIbhNTGNVtvqI1TnOWJgcMjUWvd677Gq3fTzXEjilkx2yWypVnTswM2KbXgoAg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /esbuild-linux-arm/0.15.15: + resolution: {integrity: sha512-RYVW9o2yN8yM7SB1yaWr378CwrjvGCyGybX3SdzPHpikUHkME2AP55Ma20uNwkNyY2eSYFX9D55kDrfQmQBR4w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /esbuild-linux-arm64/0.15.15: + resolution: {integrity: sha512-/ltmNFs0FivZkYsTzAsXIfLQX38lFnwJTWCJts0IbCqWZQe+jjj0vYBNbI0kmXLb3y5NljiM5USVAO1NVkdh2g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /esbuild-linux-mips64le/0.15.15: + resolution: {integrity: sha512-PksEPb321/28GFFxtvL33yVPfnMZihxkEv5zME2zapXGp7fA1X2jYeiTUK+9tJ/EGgcNWuwvtawPxJG7Mmn86A==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + optional: true + + /esbuild-linux-ppc64le/0.15.15: + resolution: {integrity: sha512-ek8gJBEIhcpGI327eAZigBOHl58QqrJrYYIZBWQCnH3UnXoeWMrMZLeeZL8BI2XMBhP+sQ6ERctD5X+ajL/AIA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + optional: true + + /esbuild-linux-riscv64/0.15.15: + resolution: {integrity: sha512-H5ilTZb33/GnUBrZMNJtBk7/OXzDHDXjIzoLXHSutwwsLxSNaLxzAaMoDGDd/keZoS+GDBqNVxdCkpuiRW4OSw==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + optional: true + + /esbuild-linux-s390x/0.15.15: + resolution: {integrity: sha512-jKaLUg78mua3rrtrkpv4Or2dNTJU7bgHN4bEjT4OX4GR7nLBSA9dfJezQouTxMmIW7opwEC5/iR9mpC18utnxQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + optional: true + + /esbuild-netbsd-64/0.15.15: + resolution: {integrity: sha512-aOvmF/UkjFuW6F36HbIlImJTTx45KUCHJndtKo+KdP8Dhq3mgLRKW9+6Ircpm8bX/RcS3zZMMmaBLkvGY06Gvw==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + /esbuild-openbsd-64/0.15.15: + resolution: {integrity: sha512-HFFX+WYedx1w2yJ1VyR1Dfo8zyYGQZf1cA69bLdrHzu9svj6KH6ZLK0k3A1/LFPhcEY9idSOhsB2UyU0tHPxgQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + optional: true + + /esbuild-sunos-64/0.15.15: + resolution: {integrity: sha512-jOPBudffG4HN8yJXcK9rib/ZTFoTA5pvIKbRrt3IKAGMq1EpBi4xoVoSRrq/0d4OgZLaQbmkHp8RO9eZIn5atA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + optional: true + + /esbuild-windows-32/0.15.15: + resolution: {integrity: sha512-MDkJ3QkjnCetKF0fKxCyYNBnOq6dmidcwstBVeMtXSgGYTy8XSwBeIE4+HuKiSsG6I/mXEb++px3IGSmTN0XiA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + /esbuild-windows-64/0.15.15: + resolution: {integrity: sha512-xaAUIB2qllE888SsMU3j9nrqyLbkqqkpQyWVkfwSil6BBPgcPk3zOFitTTncEKCLTQy3XV9RuH7PDj3aJDljWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + /esbuild-windows-arm64/0.15.15: + resolution: {integrity: sha512-ttuoCYCIJAFx4UUKKWYnFdrVpoXa3+3WWkXVI6s09U+YjhnyM5h96ewTq/WgQj9LFSIlABQvadHSOQyAVjW5xQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + /esbuild/0.15.15: + resolution: {integrity: sha512-TEw/lwK4Zzld9x3FedV6jy8onOUHqcEX3ADFk4k+gzPUwrxn8nWV62tH0udo8jOtjFodlEfc4ypsqX3e+WWO6w==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.15.15 + '@esbuild/linux-loong64': 0.15.15 + esbuild-android-64: 0.15.15 + esbuild-android-arm64: 0.15.15 + esbuild-darwin-64: 0.15.15 + esbuild-darwin-arm64: 0.15.15 + esbuild-freebsd-64: 0.15.15 + esbuild-freebsd-arm64: 0.15.15 + esbuild-linux-32: 0.15.15 + esbuild-linux-64: 0.15.15 + esbuild-linux-arm: 0.15.15 + esbuild-linux-arm64: 0.15.15 + esbuild-linux-mips64le: 0.15.15 + esbuild-linux-ppc64le: 0.15.15 + esbuild-linux-riscv64: 0.15.15 + esbuild-linux-s390x: 0.15.15 + esbuild-netbsd-64: 0.15.15 + esbuild-openbsd-64: 0.15.15 + esbuild-sunos-64: 0.15.15 + esbuild-windows-32: 0.15.15 + esbuild-windows-64: 0.15.15 + esbuild-windows-arm64: 0.15.15 + + /escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + /escape-string-regexp/2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: false + + /escape-string-regexp/4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-prettier-standard/4.0.1_g564no6wknyfo5tdpgct3p2ko4: + resolution: {integrity: sha512-l5IsZo387QArxPcRl6qcsQnc0hf66rrV5p3RvMDcHL9FGXRJ/s3/ZCES343gMGgyYN+XTJpBnwJHCnZegAMmfw==} + peerDependencies: + eslint-config-prettier: '>=5.0.0' + eslint-config-standard: '>=16.0.0' + eslint-plugin-prettier: '>=3.1.0' + prettier-config-standard: '>=1.0.0' + dependencies: + eslint-config-prettier: 8.5.0_eslint@8.28.0 + eslint-config-standard: 17.0.0_5dakk4wnrkkieagghiqvu5yn4y + eslint-plugin-prettier: 4.2.1_cwlo2dingkvfydnaculr42urve + prettier-config-standard: 5.0.0_prettier@2.8.0 + dev: true + + /eslint-config-prettier/8.5.0_eslint@8.28.0: + resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.28.0 + dev: true + + /eslint-config-standard/17.0.0_5dakk4wnrkkieagghiqvu5yn4y: + resolution: {integrity: sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==} + peerDependencies: + eslint: ^8.0.1 + eslint-plugin-import: ^2.25.2 + eslint-plugin-n: ^15.0.0 + eslint-plugin-promise: ^6.0.0 + dependencies: + eslint: 8.28.0 + eslint-plugin-import: 2.26.0_vfrilbydaxalswvos6uuh4sxs4 + eslint-plugin-n: 15.5.1_eslint@8.28.0 + eslint-plugin-promise: 6.1.1_eslint@8.28.0 + dev: true + + /eslint-import-resolver-node/0.3.6: + resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==} + dependencies: + debug: 3.2.7 + resolve: 1.22.1 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils/2.7.4_hohserqfhq4k7fjhuck6y26tu4: + resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + debug: 3.2.7 + eslint: 8.28.0 + eslint-import-resolver-node: 0.3.6 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-es/3.0.1_eslint@8.28.0: + resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + eslint: 8.28.0 + eslint-utils: 2.1.0 + regexpp: 3.2.0 + dev: true + + /eslint-plugin-es/4.1.0_eslint@8.28.0: + resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + eslint: 8.28.0 + eslint-utils: 2.1.0 + regexpp: 3.2.0 + dev: true + + /eslint-plugin-import/2.26.0_vfrilbydaxalswvos6uuh4sxs4: + resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + array-includes: 3.1.6 + array.prototype.flat: 1.3.1 + debug: 2.6.9 + doctrine: 2.1.0 + eslint: 8.28.0 + eslint-import-resolver-node: 0.3.6 + eslint-module-utils: 2.7.4_hohserqfhq4k7fjhuck6y26tu4 + has: 1.0.3 + is-core-module: 2.11.0 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.values: 1.1.6 + resolve: 1.22.1 + tsconfig-paths: 3.14.1 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-n/15.5.1_eslint@8.28.0: + resolution: {integrity: sha512-kAd+xhZm7brHoFLzKLB7/FGRFJNg/srmv67mqb7tto22rpr4wv/LV6RuXzAfv3jbab7+k1wi42PsIhGviywaaw==} + engines: {node: '>=12.22.0'} + peerDependencies: + eslint: '>=7.0.0' + dependencies: + builtins: 5.0.1 + eslint: 8.28.0 + eslint-plugin-es: 4.1.0_eslint@8.28.0 + eslint-utils: 3.0.0_eslint@8.28.0 + ignore: 5.2.0 + is-core-module: 2.11.0 + minimatch: 3.1.2 + resolve: 1.22.1 + semver: 7.3.8 + dev: true + + /eslint-plugin-node/11.1.0_eslint@8.28.0: + resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=5.16.0' + dependencies: + eslint: 8.28.0 + eslint-plugin-es: 3.0.1_eslint@8.28.0 + eslint-utils: 2.1.0 + ignore: 5.2.0 + minimatch: 3.1.2 + resolve: 1.22.1 + semver: 6.3.0 + dev: true + + /eslint-plugin-prettier/4.2.1_cwlo2dingkvfydnaculr42urve: + resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: '>=7.28.0' + eslint-config-prettier: '*' + prettier: '>=2.0.0' + peerDependenciesMeta: + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.28.0 + eslint-config-prettier: 8.5.0_eslint@8.28.0 + prettier: 2.8.0 + prettier-linter-helpers: 1.0.0 + dev: true + + /eslint-plugin-promise/6.1.1_eslint@8.28.0: + resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + eslint: 8.28.0 + dev: true + + /eslint-plugin-simple-import-sort/8.0.0_eslint@8.28.0: + resolution: {integrity: sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==} + peerDependencies: + eslint: '>=5.0.0' + dependencies: + eslint: 8.28.0 + dev: true + + /eslint-plugin-solid/0.8.0_hsf322ms6xhhd4b5ne6lb74y4a: + resolution: {integrity: sha512-yzTpqZ4+qGO14aM2rii9waonMNqSlpXHID2GMREYCOWpbIrkC5gILXpLl/+ZWFHSJDvsQN+/COobBkqizn7pkw==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@typescript-eslint/utils': 5.44.0_hsf322ms6xhhd4b5ne6lb74y4a + eslint: 8.28.0 + is-html: 2.0.0 + jsx-ast-utils: 3.3.3 + kebab-case: 1.0.2 + known-css-properties: 0.24.0 + style-to-object: 0.3.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-scope/5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope/7.1.1: + resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-utils/2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + dependencies: + eslint-visitor-keys: 1.3.0 + dev: true + + /eslint-utils/3.0.0_eslint@8.28.0: + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + dependencies: + eslint: 8.28.0 + eslint-visitor-keys: 2.1.0 + dev: true + + /eslint-visitor-keys/1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + dev: true + + /eslint-visitor-keys/2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true + + /eslint-visitor-keys/3.3.0: + resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint/8.28.0: + resolution: {integrity: sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint/eslintrc': 1.3.3 + '@humanwhocodes/config-array': 0.11.7 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.1.1 + eslint-utils: 3.0.0_eslint@8.28.0 + eslint-visitor-keys: 3.3.0 + espree: 9.4.1 + esquery: 1.4.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.18.0 + grapheme-splitter: 1.0.4 + ignore: 5.2.0 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-sdsl: 4.2.0 + 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.1 + regexpp: 3.2.0 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree/9.4.1: + resolution: {integrity: sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.8.1 + acorn-jsx: 5.3.2_acorn@8.8.1 + eslint-visitor-keys: 3.3.0 + dev: true + + /esquery/1.4.0: + resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse/4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse/4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse/5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils/2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /execa/5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /execa/6.1.0: + resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 3.0.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + dev: true + + /expand-tilde/2.0.2: + resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} + engines: {node: '>=0.10.0'} + dependencies: + homedir-polyfill: 1.0.3 + dev: true + + /expect/29.3.1: + resolution: {integrity: sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/expect-utils': 29.3.1 + jest-get-type: 29.2.0 + jest-matcher-utils: 29.3.1 + jest-message-util: 29.3.1 + jest-util: 29.3.1 + dev: false + + /external-editor/3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: true + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff/1.2.0: + resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} + dev: true + + /fast-glob/3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify/2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein/2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq/1.13.0: + resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + dependencies: + reusify: 1.0.4 + dev: true + + /figures/3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /file-entry-cache/6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.0.4 + dev: true + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + + /find-node-modules/2.1.3: + resolution: {integrity: sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==} + dependencies: + findup-sync: 4.0.0 + merge: 2.1.1 + dev: true + + /find-root/1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + dev: true + + /find-up/4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up/5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /findup-sync/4.0.0: + resolution: {integrity: sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==} + engines: {node: '>= 8'} + dependencies: + detect-file: 1.0.0 + is-glob: 4.0.3 + micromatch: 4.0.5 + resolve-dir: 1.0.1 + dev: true + + /flat-cache/3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.7 + rimraf: 3.0.2 + dev: true + + /flatted/3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + dev: true + + /for-each/0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + + /fs-extra/10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.10 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs-extra/9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.10 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + + /function.prototype.name/1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.4 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names/1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + /gensync/1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + /get-caller-file/2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-func-name/2.0.0: + resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} + dev: true + + /get-intrinsic/1.1.3: + resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 + + /get-stream/6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /get-symbol-description/1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.3 + dev: true + + /git-raw-commits/2.0.11: + resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + dargs: 7.0.0 + lodash: 4.17.21 + meow: 8.1.2 + split2: 3.2.2 + through2: 4.0.2 + dev: true + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent/6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /global-dirs/0.1.1: + resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} + engines: {node: '>=4'} + dependencies: + ini: 1.3.8 + dev: true + + /global-modules/1.0.0: + resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} + engines: {node: '>=0.10.0'} + dependencies: + global-prefix: 1.0.2 + is-windows: 1.0.2 + resolve-dir: 1.0.1 + dev: true + + /global-prefix/1.0.2: + resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} + engines: {node: '>=0.10.0'} + dependencies: + expand-tilde: 2.0.2 + homedir-polyfill: 1.0.3 + ini: 1.3.8 + is-windows: 1.0.2 + which: 1.3.1 + dev: true + + /globals/11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + /globals/13.18.0: + resolution: {integrity: sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globby/11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /gopd/1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.1.3 + + /graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + + /grapheme-splitter/1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + dev: true + + /hard-rejection/2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + dev: true + + /has-bigints/1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + /has-flag/3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + /has-property-descriptors/1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.1.3 + + /has-symbols/1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + /has-tostringtag/1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + + /homedir-polyfill/1.0.3: + resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} + engines: {node: '>=0.10.0'} + dependencies: + parse-passwd: 1.0.0 + dev: true + + /hosted-git-info/2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /hosted-git-info/4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + dependencies: + lru-cache: 6.0.0 + dev: true + + /html-entities/2.3.2: + resolution: {integrity: sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==} + dev: true + + /html-tags/3.2.0: + resolution: {integrity: sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==} + engines: {node: '>=8'} + dev: true + + /human-signals/2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /human-signals/3.0.1: + resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==} + engines: {node: '>=12.20.0'} + dev: true + + /iconv-lite/0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /ieee754/1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + + /ignore/5.2.0: + resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} + engines: {node: '>= 4'} + dev: true + + /import-fresh/3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash/0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string/4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /ini/1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /inline-style-parser/0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + dev: true + + /inquirer/8.2.4: + resolution: {integrity: sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==} + engines: {node: '>=12.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.5.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: true + + /internal-slot/1.0.3: + resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.1.3 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + + /is-arguments/1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + + /is-arrayish/0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-bigint/1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + + /is-boolean-object/1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + + /is-callable/1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + /is-core-module/2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + dependencies: + has: 1.0.3 + + /is-date-object/1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + + /is-extglob/2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point/3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-fullwidth-code-point/4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: true + + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-html/2.0.0: + resolution: {integrity: sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==} + engines: {node: '>=8'} + dependencies: + html-tags: 3.2.0 + dev: true + + /is-interactive/1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: true + + /is-map/2.0.2: + resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} + + /is-negative-zero/2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object/1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + /is-obj/2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + dev: true + + /is-path-inside/3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-plain-obj/1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-regex/1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + + /is-set/2.0.2: + resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} + + /is-shared-array-buffer/1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-stream/2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-stream/3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-string/1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + + /is-symbol/1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + + /is-text-path/1.0.1: + resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} + engines: {node: '>=0.10.0'} + dependencies: + text-extensions: 1.9.0 + dev: true + + /is-typed-array/1.1.10: + resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + + /is-unicode-supported/0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + + /is-utf8/0.2.1: + resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==} + dev: true + + /is-weakmap/2.0.1: + resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} + + /is-weakref/1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-weakset/2.0.2: + resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.3 + + /is-what/4.1.7: + resolution: {integrity: sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==} + engines: {node: '>=12.13'} + dev: true + + /is-windows/1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /isarray/2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /jest-diff/29.3.1: + resolution: {integrity: sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 29.3.1 + jest-get-type: 29.2.0 + pretty-format: 29.3.1 + dev: false + + /jest-get-type/29.2.0: + resolution: {integrity: sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: false + + /jest-matcher-utils/29.3.1: + resolution: {integrity: sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 29.3.1 + jest-get-type: 29.2.0 + pretty-format: 29.3.1 + dev: false + + /jest-message-util/29.3.1: + resolution: {integrity: sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/code-frame': 7.18.6 + '@jest/types': 29.3.1 + '@types/stack-utils': 2.0.1 + chalk: 4.1.2 + graceful-fs: 4.2.10 + micromatch: 4.0.5 + pretty-format: 29.3.1 + slash: 3.0.0 + stack-utils: 2.0.6 + dev: false + + /jest-util/29.3.1: + resolution: {integrity: sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.3.1 + '@types/node': 18.11.9 + chalk: 4.1.2 + ci-info: 3.7.0 + graceful-fs: 4.2.10 + picomatch: 2.3.1 + dev: false + + /js-sdsl/4.2.0: + resolution: {integrity: sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==} + dev: true + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + /js-yaml/4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsesc/2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse/0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse/1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-stable-stringify-without-jsonify/1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5/1.0.1: + resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} + hasBin: true + dependencies: + minimist: 1.2.7 + dev: true + + /json5/2.2.1: + resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} + engines: {node: '>=6'} + hasBin: true + + /jsonfile/6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.10 + dev: true + + /jsonparse/1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + dev: true + + /jsx-ast-utils/3.3.3: + resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==} + engines: {node: '>=4.0'} + dependencies: + array-includes: 3.1.6 + object.assign: 4.1.4 + dev: true + + /kebab-case/1.0.2: + resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==} + dev: true + + /kind-of/6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /known-css-properties/0.24.0: + resolution: {integrity: sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==} + dev: true + + /lefthook-darwin-arm64/1.2.2: + resolution: {integrity: sha512-dRC67p29yCKjI/A50tXKJwxRM1ko0mWzryc3ELHikZOwBjfJxh1MmifGGTLkXdJoaIlzLmtnsH58BMJ9SUiWDQ==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /lefthook-darwin-x64/1.2.2: + resolution: {integrity: sha512-vzEkP7ISTq99rO/awRkFIopjUOBrIYgm2qhpLV2BFU47YCq6972CUx5F4hNHpkrZG3iNbM1RnL0aHrAf8hoP4w==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /lefthook-freebsd-arm64/1.2.2: + resolution: {integrity: sha512-m2v7CFIt/DBfG2KpUE693xDHWyP+BNRuVzAMuWXxizwjqLDp8wOPyAWsBvsuG3lj6Al82ESzlAxov8aWMMWXDQ==} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /lefthook-freebsd-x64/1.2.2: + resolution: {integrity: sha512-v7Eat6/fDJyuSfmdjwg2mwR+bKQxwjB8su31tTW5HhDj+JFr6A3p26VHWPrlUEHAcepGsWdpcqCEzKU7IsOblA==} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /lefthook-linux-arm64/1.2.2: + resolution: {integrity: sha512-+FfRjzRKtW5J1Rv4EiLNRQRYwNjaaZBm4w5nThh4AMETbv3QC9pu0E+c/bIg/SqDU2Hn585XaTPqFnWamPIVNg==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /lefthook-linux-x64/1.2.2: + resolution: {integrity: sha512-IMen7XttJUgD+Pg4tX9qeknEGCDjtFEXlf8QMQpwjI999V6ZoQ+25msdFmxtZoEGYjVJ/qmfZblK7CaOKqjeIQ==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /lefthook-windows-arm64/1.2.2: + resolution: {integrity: sha512-x/YkDCOnmXnA7pLOm7JyC9mD6KnREUh9H1Y4aVWBdRblr0xV9RHknIIUV96/91d1ny14TSVNTr6tCfDLnvsSOw==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /lefthook-windows-x64/1.2.2: + resolution: {integrity: sha512-GEBIynskF6LvYUhmQaLNoPj/LeEhRZGUlRYQQD40tGp69Cp791eU3FEJZ0Rdkru98H2bL9itM5+nxMDlMnZi+g==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /lefthook/1.2.2: + resolution: {integrity: sha512-jSMBSkwy/2DXAD73Q9Xv8XY9rMKO9KeJNE15UcH7Is7UYTV/+5d7LnFm8pCFSa4fHEDiblL00FG9YC0FKdVwtQ==} + hasBin: true + requiresBuild: true + optionalDependencies: + lefthook-darwin-arm64: 1.2.2 + lefthook-darwin-x64: 1.2.2 + lefthook-freebsd-arm64: 1.2.2 + lefthook-freebsd-x64: 1.2.2 + lefthook-linux-arm64: 1.2.2 + lefthook-linux-x64: 1.2.2 + lefthook-windows-arm64: 1.2.2 + lefthook-windows-x64: 1.2.2 + dev: true + + /levn/0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lilconfig/2.0.6: + resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==} + engines: {node: '>=10'} + dev: true + + /lines-and-columns/1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /lint-staged/13.0.4: + resolution: {integrity: sha512-HxlHCXoYRsq9QCby5wFozmZW00hMs/9e3l+/dz6Qr8Kle4UH0kJTdABAbqhzG+3pcG6QjL9kz7NgGBfph+a5dw==} + engines: {node: ^14.13.1 || >=16.0.0} + hasBin: true + dependencies: + cli-truncate: 3.1.0 + colorette: 2.0.19 + commander: 9.4.1 + debug: 4.3.4 + execa: 6.1.0 + lilconfig: 2.0.6 + listr2: 5.0.5 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-inspect: 1.12.2 + pidtree: 0.6.0 + string-argv: 0.3.1 + yaml: 2.1.3 + transitivePeerDependencies: + - enquirer + - supports-color + dev: true + + /listr2/5.0.5: + resolution: {integrity: sha512-DpBel6fczu7oQKTXMekeprc0o3XDgGMkD7JNYyX+X0xbwK+xgrx9dcyKoXKqpLSUvAWfmoePS7kavniOcq3r4w==} + engines: {node: ^14.13.1 || >=16.0.0} + peerDependencies: + enquirer: '>= 2.3.0 < 3' + peerDependenciesMeta: + enquirer: + optional: true + dependencies: + cli-truncate: 2.1.0 + colorette: 2.0.19 + log-update: 4.0.0 + p-map: 4.0.0 + rfdc: 1.3.0 + rxjs: 7.5.7 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: true + + /local-pkg/0.4.2: + resolution: {integrity: sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==} + engines: {node: '>=14'} + dev: true + + /locate-path/5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path/6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.camelcase/4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: true + + /lodash.isfunction/3.0.9: + resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} + dev: true + + /lodash.isplainobject/4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: true + + /lodash.kebabcase/4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + dev: true + + /lodash.map/4.6.0: + resolution: {integrity: sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==} + dev: true + + /lodash.merge/4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.mergewith/4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + dev: true + + /lodash.snakecase/4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + dev: true + + /lodash.startcase/4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + dev: true + + /lodash.uniq/4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + dev: true + + /lodash.upperfirst/4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + dev: true + + /lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + /log-symbols/4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + + /log-update/4.0.0: + resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} + engines: {node: '>=10'} + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + dev: true + + /longest/2.0.1: + resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==} + engines: {node: '>=0.10.0'} + dev: true + + /loupe/2.3.6: + resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + dependencies: + get-func-name: 2.0.0 + dev: true + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /lz-string/1.4.4: + resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} + hasBin: true + dev: true + + /make-error/1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /map-obj/1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-obj/4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + dev: true + + /media-query-parser/2.0.2: + resolution: {integrity: sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==} + dependencies: + '@babel/runtime': 7.20.1 + dev: false + + /meow/8.1.2: + resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} + engines: {node: '>=10'} + dependencies: + '@types/minimist': 1.2.2 + camelcase-keys: 6.2.2 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 7.0.1 + redent: 3.0.0 + trim-newlines: 3.0.1 + type-fest: 0.18.1 + yargs-parser: 20.2.9 + dev: true + + /merge-anything/5.1.3: + resolution: {integrity: sha512-pMb85+QShjqye+99Dkrg9m6EbTjDXwZFQbPysx/lNkuwjT+UJZlQvpnOy0P8kgGXzUx8iWSoNQel5QJjoyWHmQ==} + engines: {node: '>=12.13'} + dependencies: + is-what: 4.1.7 + dev: true + + /merge-stream/2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge/2.1.1: + resolution: {integrity: sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==} + dev: true + + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + + /mimic-fn/2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-fn/4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + + /min-indent/1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist-options/4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + dev: true + + /minimist/1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + dev: true + + /minimist/1.2.7: + resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} + dev: true + + /ms/2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: true + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + /ms/2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /mute-stream/0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + dev: true + + /nanoid/3.3.4: + resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + /natural-compare-lite/1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + + /natural-compare/1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /node-releases/2.0.6: + resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} + + /normalize-package-data/2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.1 + semver: 5.7.1 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-package-data/3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + dependencies: + hosted-git-info: 4.1.0 + is-core-module: 2.11.0 + semver: 7.3.8 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-run-path/4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /npm-run-path/5.1.0: + resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + + /object-inspect/1.12.2: + resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} + + /object-is/1.1.5: + resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + + /object-keys/1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + /object.assign/4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + has-symbols: 1.0.3 + object-keys: 1.1.1 + + /object.values/1.1.6: + resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.4 + dev: true + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime/5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /onetime/6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + + /optionator/0.9.1: + resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.3 + dev: true + + /ora/5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.7.0 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: true + + /os-tmpdir/1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /outdent/0.8.0: + resolution: {integrity: sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==} + dev: false + + /p-limit/2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit/3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate/4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate/5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-map/4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: true + + /p-try/2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parent-module/1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json/5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.18.6 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse-passwd/1.0.0: + resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} + engines: {node: '>=0.10.0'} + dev: true + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-key/4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + /path-type/4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pathval/1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + /pidtree/0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + dev: true + + /postcss/8.4.19: + resolution: {integrity: sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.4 + picocolors: 1.0.0 + source-map-js: 1.0.2 + + /prelude-ls/1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-config-standard/5.0.0_prettier@2.8.0: + resolution: {integrity: sha512-QK252QwCxlsak8Zx+rPKZU31UdbRcu9iUk9X1ONYtLSO221OgvV9TlKoTf6iPDZtvF3vE2mkgzFIEgSUcGELSQ==} + peerDependencies: + prettier: ^2.4.0 + dependencies: + prettier: 2.8.0 + dev: true + + /prettier-linter-helpers/1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.2.0 + dev: true + + /prettier/2.8.0: + resolution: {integrity: sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /pretty-format/27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: true + + /pretty-format/29.3.1: + resolution: {integrity: sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.0.0 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: false + + /punycode/2.1.1: + resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + engines: {node: '>=6'} + dev: true + + /q/1.5.1: + resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} + engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + dev: true + + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /quick-lru/4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + dev: true + + /react-is/17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + dev: true + + /react-is/18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: false + + /read-pkg-up/7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg/5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.1 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /readable-stream/3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /redent/3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + /regenerator-runtime/0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + + /regexp.prototype.flags/1.4.3: + resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + functions-have-names: 1.2.3 + + /regexpp/3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + + /require-directory/2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-from-string/2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /resolve-dir/1.0.1: + resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} + engines: {node: '>=0.10.0'} + dependencies: + expand-tilde: 2.0.2 + global-modules: 1.0.0 + dev: true + + /resolve-from/4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from/5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve-global/1.0.0: + resolution: {integrity: sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==} + engines: {node: '>=8'} + dependencies: + global-dirs: 0.1.1 + dev: true + + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.11.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + /restore-cursor/3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rfdc/1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: true + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup/2.79.1: + resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + + /run-async/2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: true + + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /run-script-os/1.1.6: + resolution: {integrity: sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==} + hasBin: true + dev: true + + /rxjs/7.5.7: + resolution: {integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==} + dependencies: + tslib: 2.4.1 + dev: true + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /safe-regex-test/1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.3 + is-regex: 1.1.4 + dev: true + + /safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + + /semver/5.7.1: + resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + hasBin: true + dev: true + + /semver/6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + + /semver/7.3.7: + resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /semver/7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel/1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.3 + object-inspect: 1.12.2 + + /signal-exit/3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + /slice-ansi/3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /slice-ansi/4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /slice-ansi/5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + dev: true + + /solid-headless/0.13.0_solid-js@1.6.2: + resolution: {integrity: sha512-N118iPl7W5lyug4K+4c0cwM8YR2yEVJ/3H4wq6tVijATHfXfLnB1ACFI5GGHSXlwu70PUzaGSKwcVqLlloUMyA==} + engines: {node: '>=10'} + peerDependencies: + solid-js: ^1.2 + dependencies: + solid-js: 1.6.2 + solid-use: 0.5.0_solid-js@1.6.2 + dev: false + + /solid-js/1.6.2: + resolution: {integrity: sha512-AZBsj+Yn1xliniTTeuQKG9V7VQVkQ8lZmSKvBjpcVSoZeF7nvt/N5f7Kcsx6QSufioa2YgvBjkIiA0cM0qhotw==} + dependencies: + csstype: 3.1.1 + + /solid-refresh/0.4.1_solid-js@1.6.2: + resolution: {integrity: sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==} + peerDependencies: + solid-js: ^1.3 + dependencies: + '@babel/generator': 7.20.4 + '@babel/helper-module-imports': 7.18.6 + '@babel/types': 7.20.2 + solid-js: 1.6.2 + dev: true + + /solid-testing-library/0.5.0_solid-js@1.6.2: + resolution: {integrity: sha512-vr4Ke9Dq3bUFLaXOcN8/IVn2e9Q37w4vdmoIOmFBIPs7iCJX9IxuC0IdQqK8nzBZMQqceijkfyCE3Qc407KmaA==} + engines: {node: '>= 14'} + peerDependencies: + solid-js: '>=1.0.0' + dependencies: + '@testing-library/dom': 8.19.0 + solid-js: 1.6.2 + dev: true + + /solid-use/0.5.0_solid-js@1.6.2: + resolution: {integrity: sha512-z1AaS99SL3gNP70K4+XIVKGXDRI56m3Q6Q4X63bfgw0kaN6cwT4SAyFZAmIRjHcvf5rOMRQfNgUV4YVDha+LcQ==} + engines: {node: '>=10'} + peerDependencies: + solid-js: ^1.2 + dependencies: + solid-js: 1.6.2 + dev: false + + /source-map-js/1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dev: true + + /spdx-correct/3.1.1: + resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.12 + dev: true + + /spdx-exceptions/2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse/3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.12 + dev: true + + /spdx-license-ids/3.0.12: + resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} + dev: true + + /split2/3.2.2: + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + dependencies: + readable-stream: 3.6.0 + dev: true + + /stack-utils/2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + dev: false + + /string-argv/0.3.1: + resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==} + engines: {node: '>=0.6.19'} + dev: true + + /string-width/4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width/5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.0.1 + dev: true + + /string.prototype.trimend/1.0.6: + resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.4 + dev: true + + /string.prototype.trimstart/1.0.6: + resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.4 + dev: true + + /string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi/6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-ansi/7.0.1: + resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + + /strip-bom/3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-bom/4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + + /strip-final-newline/2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-final-newline/3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /strip-indent/3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + + /strip-json-comments/3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /strip-literal/0.4.2: + resolution: {integrity: sha512-pv48ybn4iE1O9RLgCAN0iU4Xv7RlBTiit6DKmMiErbs9x1wH6vXBs45tWc0H5wUIF6TLTrKweqkmYF/iraQKNw==} + dependencies: + acorn: 8.8.1 + dev: true + + /style-to-object/0.3.0: + resolution: {integrity: sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==} + dependencies: + inline-style-parser: 0.1.1 + dev: true + + /supports-color/5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + + /supports-color/7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + /text-extensions/1.9.0: + resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} + engines: {node: '>=0.10'} + dev: true + + /text-table/0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /through/2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /through2/4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + dependencies: + readable-stream: 3.6.0 + dev: true + + /tinybench/2.3.1: + resolution: {integrity: sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==} + dev: true + + /tinypool/0.3.0: + resolution: {integrity: sha512-NX5KeqHOBZU6Bc0xj9Vr5Szbb1j8tUHIeD18s41aDJaPeC5QTdEhK0SpdpUrZlj2nv5cctNcSjaKNanXlfcVEQ==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy/1.0.2: + resolution: {integrity: sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==} + engines: {node: '>=14.0.0'} + dev: true + + /tmp/0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: true + + /to-fast-properties/2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + + /trim-newlines/3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + dev: true + + /ts-node/10.9.1_kluoused5zacjtflizwvdqgpom: + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.3 + '@types/node': 14.18.33 + acorn: 8.8.1 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.9.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + + /tsconfig-paths/3.14.1: + resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.1 + minimist: 1.2.7 + strip-bom: 3.0.0 + dev: true + + /tslib/1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib/2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: true + + /tsutils/3.21.0_typescript@4.9.3: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 4.9.3 + dev: true + + /type-check/0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-detect/4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest/0.18.1: + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} + dev: true + + /type-fest/0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest/0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-fest/0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest/0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /type-fest/3.2.0: + resolution: {integrity: sha512-Il3wdLRzWvbAEtocgxGQA9YOoRVeVUGOMBtel5LdEpNeEAol6GJTLw8GbX6Z8EIMfvfhoOXs2bwOijtAZdK5og==} + engines: {node: '>=14.16'} + dev: false + + /typescript/4.9.3: + resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==} + engines: {node: '>=4.2.0'} + hasBin: true + + /unbox-primitive/1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /universalify/2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + dev: true + + /update-browserslist-db/1.0.10_browserslist@4.21.4: + resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.21.4 + escalade: 3.1.1 + picocolors: 1.0.0 + + /uri-js/4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.1.1 + dev: true + + /util-deprecate/1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /v8-compile-cache-lib/3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: true + + /validate-npm-package-license/3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.1.1 + spdx-expression-parse: 3.0.1 + dev: true + + /vite-plugin-solid/2.4.0_solid-js@1.6.2+vite@3.2.4: + resolution: {integrity: sha512-Rr+t2sr9TWIvH16yzBZzx6O9YSpYAvcwKUMPqbi/4iU3mRumXQ4O10i1XGtQIynC7U3XwJsMzAJigDFGbiJBiw==} + peerDependencies: + solid-js: ^1.3.17 + vite: ^3.0.0 + dependencies: + '@babel/core': 7.20.2 + '@babel/preset-typescript': 7.18.6_@babel+core@7.20.2 + babel-preset-solid: 1.6.2_@babel+core@7.20.2 + merge-anything: 5.1.3 + solid-js: 1.6.2 + solid-refresh: 0.4.1_solid-js@1.6.2 + vite: 3.2.4_@types+node@18.11.9 + vitefu: 0.1.1_vite@3.2.4 + transitivePeerDependencies: + - supports-color + dev: true + + /vite/3.2.4_@types+node@18.11.9: + resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.11.9 + esbuild: 0.15.15 + postcss: 8.4.19 + resolve: 1.22.1 + rollup: 2.79.1 + optionalDependencies: + fsevents: 2.3.2 + + /vitefu/0.1.1_vite@3.2.4: + resolution: {integrity: sha512-HClD14fjMJ+NQgXBqT3dC3RdO/+Chayil+cCPYZKY3kT+KcJomKzrdgzfCHJkIL2L0OAY+VPvrSW615iPtc7ag==} + peerDependencies: + vite: ^3.0.0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + vite: 3.2.4_@types+node@18.11.9 + dev: true + + /vitest/0.25.3: + resolution: {integrity: sha512-/UzHfXIKsELZhL7OaM2xFlRF8HRZgAHtPctacvNK8H4vOcbJJAMEgbWNGSAK7Y9b1NBe5SeM7VTuz2RsTHFJJA==} + engines: {node: '>=v14.16.0'} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@vitest/browser': '*' + '@vitest/ui': '*' + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/chai': 4.3.4 + '@types/chai-subset': 1.3.3 + '@types/node': 18.11.9 + acorn: 8.8.1 + acorn-walk: 8.2.0 + chai: 4.3.7 + debug: 4.3.4 + local-pkg: 0.4.2 + source-map: 0.6.1 + strip-literal: 0.4.2 + tinybench: 2.3.1 + tinypool: 0.3.0 + tinyspy: 1.0.2 + vite: 3.2.4_@types+node@18.11.9 + transitivePeerDependencies: + - less + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /wcwidth/1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: true + + /web-vitals/3.1.0: + resolution: {integrity: sha512-zCeQ+bOjWjJbXv5ZL0r8Py3XP2doCQMZXNKlBGfUjPAVZWokApdeF/kFlK1peuKlCt8sL9TFkKzyXE9/cmNJQA==} + dev: false + + /which-boxed-primitive/1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + + /which-collection/1.0.1: + resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} + dependencies: + is-map: 2.0.2 + is-set: 2.0.2 + is-weakmap: 2.0.1 + is-weakset: 2.0.2 + + /which-typed-array/1.1.9: + resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + is-typed-array: 1.1.10 + + /which/1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /word-wrap/1.2.3: + resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} + engines: {node: '>=0.10.0'} + dev: true + + /wrap-ansi/6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi/7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /y18n/5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yaml/1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: true + + /yaml/2.1.3: + resolution: {integrity: sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==} + engines: {node: '>= 14'} + dev: true + + /yargs-parser/20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: true + + /yargs-parser/21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs/17.6.2: + resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==} + engines: {node: '>=12'} + 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.8 + yargs-parser: 21.1.1 + dev: true + + /yn/3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true + + /yocto-queue/0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 110bff37..f8688fe4 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -61,6 +61,15 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.66" @@ -141,11 +150,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" dependencies = [ "brotli", + "bzip2", "flate2", "futures-core", "memchr", "pin-project-lite", "tokio", + "xz2", "zstd", "zstd-safe", ] @@ -191,6 +202,29 @@ dependencies = [ "syn", ] +[[package]] +name = "async_io_utilities" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b20cffc5590f4bf33f05f97a3ea587feba9c50d20325b401daa096b92ff7da0" +dependencies = [ + "tokio", +] + +[[package]] +name = "async_zip" +version = "0.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a36d43bdefc7215b2b3a97edd03b1553b7969ad76551025eedd3b913c645f6e" +dependencies = [ + "async-compression", + "async_io_utilities", + "chrono", + "crc32fast", + "thiserror", + "tokio", +] + [[package]] name = "atk" version = "0.15.1" @@ -473,6 +507,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits 0.2.15", + "time 0.1.43", + "wasm-bindgen", + "winapi", +] + [[package]] name = "cipher" version = "0.3.0" @@ -513,6 +562,16 @@ dependencies = [ "objc", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -719,8 +778,10 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" name = "cultivation" version = "0.1.0" dependencies = [ + "async_zip", "cc", "ctrlc", + "dashmap", "duct", "file_diff", "futures-util", @@ -735,21 +796,68 @@ dependencies = [ "reqwest", "rust-ini", "rustls-pemfile", + "sanitize-filename", "serde", "serde_json", "sudo", "sysinfo", "tauri", "tauri-build", + "thiserror", "tokio", "tokio-rustls", "tokio-tungstenite", + "tokio-util", "tracing", "unrar", "zip 0.6.3", "zip-extract", ] +[[package]] +name = "cxx" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "darling" version = "0.13.4" @@ -785,6 +893,20 @@ dependencies = [ "syn", ] +[[package]] +name = "dashmap" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", + "serde", +] + [[package]] name = "data-encoding" version = "2.3.2" @@ -1676,6 +1798,30 @@ dependencies = [ "tungstenite", ] +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "ico" version = "0.1.0" @@ -1911,6 +2057,15 @@ dependencies = [ "safemem", ] +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + [[package]] name = "lock_api" version = "0.4.9" @@ -1945,6 +2100,17 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lzma-sys" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "mac" version = "0.1.1" @@ -3346,6 +3512,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "sanitize-filename" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c502bdb638f1396509467cb0580ef3b29aa2a45c5d43e5d84928241280296c" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "schannel" version = "0.1.20" @@ -3377,6 +3553,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "sct" version = "0.7.0" @@ -4140,6 +4322,15 @@ dependencies = [ "utf-8", ] +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thin-slice" version = "0.1.1" @@ -4242,9 +4433,21 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "socket2", + "tokio-macros", "winapi", ] +[[package]] +name = "tokio-macros" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-native-tls" version = "0.3.0" @@ -4464,6 +4667,12 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "unicode-xid" version = "0.2.4" @@ -5227,6 +5436,15 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" +[[package]] +name = "xz2" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" +dependencies = [ + "lzma-sys", +] + [[package]] name = "yasna" version = "0.5.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5ab51066..6599bfd5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -50,7 +50,7 @@ hudsucker = "0.18.0" tracing = "0.1.37" tokio-rustls = "0.23.4" tokio-tungstenite = "0.17.2" -tokio = { version = "1.21.2", features = ["signal"] } +tokio = { version = "1.21.2", features = ["signal", "macros", "rt-multi-thread", "io-std", "fs"] } rustls-pemfile = "1.0.1" reqwest = { version = "0.11.13", features = ["stream"] } futures-util = "0.3.25" @@ -63,11 +63,16 @@ regex = "1" file_diff = "1.0.0" rust-ini = "0.18.0" ctrlc = "3.2.3" +thiserror = "1.0.37" +dashmap = { version = "5.4.0", features = ["serde"] } +tokio-util = "0.7.4" +async_zip = "0.0.9" +sanitize-filename = "0.4.0" [features] # by default Tauri runs in production mode # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL -default = [ "custom-protocol" ] +default = ["custom-protocol"] # this feature is used used for production builds where `devPath` points to the filesystem # DO NOT remove this -custom-protocol = [ "tauri/custom-protocol" ] +custom-protocol = ["tauri/custom-protocol"] diff --git a/src-tauri/lang/vi.json b/src-tauri/lang/vi.json index ad2387ce..5572533a 100644 --- a/src-tauri/lang/vi.json +++ b/src-tauri/lang/vi.json @@ -68,9 +68,9 @@ "gc_dev_data": "Tải xuống tệp dữ liệu phiên bản mới nhất của Grasscutter. Bản này không đi kèm với tập tin jar, hữu dụng khi muốn cập nhật.", "encryption": "Mục này nên được tắt.", "resources": "Tài nguyên được yêu cầu để chạy máy chủ Grasscutter. Nút này sẽ có màu xám nếu bạn đã có sẵn một thư mục tài nguyên (resources) có nội dung bên trong", - "emergency_metadata": "Trong trường hợp gặp vấn đề, khôi phục lại metadata về phiên bản chính thức mới nhất.", - "use_proxy": "Sử dụng proxy nội bộ của Cultivation. Nên bật tùy chọn này trừ khi bạn đang sử dụng một ứng dụng khác, như Fiddler", - "patch_metadata": "Tự động vá và sửa lại metadata của game. Tùy chọn này nên được bật trừ khi bạn đang sử dụng phiên bản cũ, phiên bản không chính thức hoặc bạn đã tự vá metadata rồi." + "emergency_metadata": "Trong trường hợp gặp vấn đề, khôi phục lại metadata về phiên bản chính thức mới nhất.", + "use_proxy": "Sử dụng proxy nội bộ của Cultivation. Nên bật tùy chọn này trừ khi bạn đang sử dụng một ứng dụng khác, như Fiddler", + "patch_metadata": "Tự động vá và sửa lại metadata của game. Tùy chọn này nên được bật trừ khi bạn đang sử dụng phiên bản cũ, phiên bản không chính thức hoặc bạn đã tự vá metadata rồi." }, "swag": { "akebi_name": "Akebi", diff --git a/src-tauri/rustfmt.toml b/src-tauri/rustfmt.toml index 28dc59ff..2b9d9660 100644 --- a/src-tauri/rustfmt.toml +++ b/src-tauri/rustfmt.toml @@ -2,3 +2,7 @@ newline_style = "Unix" tab_spaces = 2 use_field_init_shorthand = true use_try_shorthand = true +format_code_in_doc_comments = true +wrap_comments = true +format_strings = true +imports_granularity = "Crate" \ No newline at end of file diff --git a/src-tauri/src/admin.rs b/src-tauri/src/admin.rs index 66daa492..e473fab9 100644 --- a/src-tauri/src/admin.rs +++ b/src-tauri/src/admin.rs @@ -1,5 +1,7 @@ #[cfg(windows)] pub fn reopen_as_admin() { + use std::process::{exit, Command}; + let install = std::env::current_exe().unwrap(); println!("Opening as admin: {}", install.to_str().unwrap()); @@ -16,5 +18,6 @@ pub fn reopen_as_admin() { exit(0); } +#[allow(unused)] #[cfg(target_os = "linux")] pub fn reopen_as_admin() {} diff --git a/src-tauri/src/downloader.rs b/src-tauri/src/downloader.rs index ebf63013..d678f70f 100644 --- a/src-tauri/src/downloader.rs +++ b/src-tauri/src/downloader.rs @@ -1,117 +1,96 @@ -use once_cell::sync::Lazy; - +use dashmap::{mapref::entry::Entry, DashMap}; use std::cmp::min; -use std::fs::File; -use std::io::Write; -use std::sync::Mutex; +use tokio::fs::File; +use crate::{error::CultivationResult, Downloads}; use futures_util::StreamExt; +use reqwest::Client; +use tauri::State; +use tokio::io::AsyncWriteExt; +use tokio_util::sync::CancellationToken; -// This will create a downloads list that will be used to check if we should continue downloading the file -static DOWNLOADS: Lazy>> = Lazy::new(|| Mutex::new(Vec::new())); - -// Lots of help from: https://gist.github.com/giuliano-oliveira/4d11d6b3bb003dba3a1b53f43d81b30d -// and docs ofc #[tauri::command] -pub async fn download_file(window: tauri::Window, url: &str, path: &str) -> Result<(), String> { - // Reqwest setup - let res = match reqwest::get(url).await { - Ok(r) => r, - Err(_e) => { - emit_download_err(window, format!("Failed to request {}", url), path); - return Err(format!("Failed to request {}", url)); - } - }; - let total_size = res.content_length().unwrap_or(0); - - // Create file path - let mut file = match File::create(path) { - Ok(f) => f, - Err(_e) => { - emit_download_err(window, format!("Failed to create file '{}'", path), path); - return Err(format!("Failed to create file '{}'", path)); - } - }; - let mut downloaded: u64 = 0; - let mut total_downloaded: u64 = 0; +pub async fn download_file( + window: tauri::Window, + url: &str, + path: &str, + downloads: State<'_, Downloads>, + client: State<'_, Client>, +) -> CultivationResult<()> { + let token = CancellationToken::new(); + // Assuming all goes well, add to the downloads list + downloads.insert(path.to_string(), token.clone()); - // File stream - let mut stream = res.bytes_stream(); + let out = tokio::select! { + _ = token.cancelled() => { + println!("Cancelled {path}! Returning..."); + Ok(()) + }, + r = async move { + // Reqwest setup + let res = client.get(url).send().await?; + let total_size = res.content_length().unwrap_or(0); - // Assuming all goes well, add to the downloads list - DOWNLOADS.lock().unwrap().push(path.to_string()); + // Create file path + let mut file = File::create(path).await?; + let mut downloaded: u64 = 0; + let mut total_downloaded: u64 = 0; - // Await chunks - while let Some(item) = stream.next().await { - // Stop the loop if the download is removed from the list - if !DOWNLOADS.lock().unwrap().contains(&path.to_string()) { - break; - } + // File stream + let mut stream = res.bytes_stream(); - let chunk = match item { - Ok(itm) => itm, - Err(e) => { - emit_download_err(window, "Error while downloading file".to_string(), path); - return Err(format!("Error while downloading file: {}", e)); - } - }; - let vect = &chunk.to_vec()[..]; - - // Write bytes - match file.write_all(vect) { - Ok(x) => x, - Err(e) => { - emit_download_err(window, "Error while writing file".to_string(), path); - return Err(format!("Error while writing file: {}", e)); - } - } + // Await chunks + while let Some(item) = stream.next().await { + // Stop the loop if the download is removed from the list + if !downloads.contains_key(path) { + break; + } - // New progress - let new = min(downloaded + (chunk.len() as u64), total_size); - downloaded = new; + let chunk = item?; - total_downloaded += chunk.len() as u64; + // Write bytes + file.write_all(&chunk).await?; - let mut res_hash = std::collections::HashMap::new(); + // New progress + let new = min(downloaded + (chunk.len() as u64), total_size); + downloaded = new; - res_hash.insert("downloaded".to_string(), downloaded.to_string()); - res_hash.insert("total".to_string(), total_size.to_string()); - res_hash.insert("path".to_string(), path.to_string()); - res_hash.insert("total_downloaded".to_string(), total_downloaded.to_string()); + total_downloaded += chunk.len() as u64; - // Create event to send to frontend - window.emit("download_progress", &res_hash).unwrap(); - } + let res_hash = DashMap::with_capacity(4); - // One more "finish" event - window.emit("download_finished", &path).unwrap(); + res_hash.insert("downloaded".to_string(), downloaded.to_string()); + res_hash.insert("total".to_string(), total_size.to_string()); + res_hash.insert("path".to_string(), path.to_string()); + res_hash.insert("total_downloaded".to_string(), total_downloaded.to_string()); - // We are done - Ok(()) -} + // Create event to send to frontend + window.emit("download_progress", &res_hash)?; + } -pub fn emit_download_err(window: tauri::Window, msg: String, path: &str) { - let mut res_hash = std::collections::HashMap::new(); + // One more "finish" event + window.emit("download_finished", &path)?; - res_hash.insert("error".to_string(), msg); - res_hash.insert("path".to_string(), path.to_string()); + // We are done + Ok(()) + } => r + }; - window.emit("download_error", &res_hash).unwrap(); + out } #[tauri::command] -pub fn stop_download(path: String) { - // Check if the path is in the downloads list - let mut downloads = DOWNLOADS.lock().unwrap(); - let index = downloads.iter().position(|x| x == &path); - - // Remove from list - if let Some(i) = index { - downloads.remove(i); - } +pub async fn stop_download(path: String, downloads: State<'_, Downloads>) -> CultivationResult<()> { + match downloads.entry(path) { + Entry::Occupied(occupied) => { + let (path, token) = occupied.remove_entry(); + token.cancel(); - // Delete the file from disk - if let Err(_e) = std::fs::remove_file(&path) { - // Do nothing + // Delete the file from disk + tokio::fs::remove_file(&path).await?; + + Ok(()) + } + _ => Ok(()), } } diff --git a/src-tauri/src/error.rs b/src-tauri/src/error.rs new file mode 100644 index 00000000..4260ccbf --- /dev/null +++ b/src-tauri/src/error.rs @@ -0,0 +1,75 @@ +use serde::Serialize; +use thiserror::Error; + +/* +This will not have mutex lock error +because we are going to get rid of locking data structures so +we can leave unwraps `as is` for now + */ + +#[derive(Debug, Error)] +/// Error type to signal about different errors that could occur +/// while Cultivation is running. +pub enum CultivationError { + // We hide sensitive information in production + #[cfg_attr(debug_assertions, error("IO error has occured: {:?}", .0))] + #[cfg_attr(not(debug_assertions), error("IO error has occured."))] + IO(#[from] tokio::io::Error), + #[cfg_attr(debug_assertions, error("Tauri failed with an error: {}", .0))] + #[cfg_attr(not(debug_assertions), error("Tauri failed with an error"))] + Tauri(#[from] tauri::Error), + #[cfg_attr(debug_assertions, error("Failed to create zip archive: {}", .0))] + #[cfg_attr(not(debug_assertions), error("Zip related function has failed"))] + Zip(#[from] zip::result::ZipError), + #[cfg_attr(debug_assertions, error("Failed to unzip archive: {}", .0))] + #[cfg_attr(not(debug_assertions), error("Failed to unzip archive"))] + Unzip(#[from] zip_extract::ZipExtractError), + #[cfg_attr(debug_assertions, error("Failed to unrar: {}", .0))] + #[cfg_attr(not(debug_assertions), error("Failed to unrar"))] + Unrar(#[from] UnrarError), + #[cfg_attr(debug_assertions, error("HTTP request failed: {}", .0))] + #[cfg_attr(not(debug_assertions), error("HTTP request failed"))] + Reqwest(#[from] reqwest::Error), + #[cfg_attr(debug_assertions, error("Malformed language config: {}", .0))] + #[cfg_attr(not(debug_assertions), error("Malformed language config"))] + MalformedLangObject(#[from] serde_json::Error), + #[cfg_attr(debug_assertions, error("Ctrlc handler failed: {}", .0))] + #[cfg_attr( + not(debug_assertions), + error("Could not set graceful shutdown handler") + )] + CtrlCError(#[from] ctrlc::Error), + #[cfg_attr(debug_assertions, error("Certificate generation failed: {}", .0))] + #[cfg_attr(not(debug_assertions), error("Certificate generation has failed."))] + Certificate(#[from] rcgen::RcgenError), + #[cfg(windows)] + #[cfg_attr(debug_assertions, error("Registry error: {}", .0))] + #[cfg_attr(not(debug_assertions), error("Registry error has occured"))] + Registry(#[from] registry::Error), + #[cfg_attr(debug_assertions, error("Custom error: {}", .0))] + #[cfg_attr(not(debug_assertions), error("Something went wrong"))] + #[allow(unused)] + Custom(String), +} + +#[derive(Debug, Error)] +#[cfg_attr(debug_assertions, error("Failed to unrar: {}", .0))] +#[cfg_attr(not(debug_assertions), error("Failed to unrar"))] +pub struct UnrarError(String); + +impl From> for UnrarError { + fn from(value: unrar::error::UnrarError) -> Self { + Self(value.to_string()) + } +} + +impl Serialize for CultivationError { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.to_string().as_ref()) + } +} + +pub type CultivationResult = Result; diff --git a/src-tauri/src/file_helpers.rs b/src-tauri/src/file_helpers.rs index ee77b618..6d3708ab 100644 --- a/src-tauri/src/file_helpers.rs +++ b/src-tauri/src/file_helpers.rs @@ -1,15 +1,20 @@ +use crate::error::CultivationResult; use file_diff::diff; -use std::fs; -use std::io::{Read, Write}; -use std::path::PathBuf; +use std::{ + fs, + io::{Read, Write}, + path::PathBuf, +}; +// TODO: remove this file helper, already exists an api for this in tauri. #[tauri::command] -pub fn rename(path: String, new_name: String) { +#[deprecated = "file helper is redundant"] +pub fn rename(path: String, new_name: String) -> CultivationResult<()> { let mut new_path = path.clone(); // Check if file/folder to replace exists if fs::metadata(&path).is_err() { - return; + return Ok(()); } // Check if path uses forward or back slashes @@ -19,37 +24,38 @@ pub fn rename(path: String, new_name: String) { let path_replaced = &path.replace(new_path.split('/').last().unwrap(), &new_name); - match fs::rename(&path, path_replaced) { - Ok(_) => { - println!("Renamed {} to {}", &path, path_replaced); - } - Err(e) => { - println!("Error: {}", e); - } - }; + fs::rename(&path, path_replaced).map_err(Into::into) } +// TODO: remove this file helper, already exists an api for this in tauri. #[tauri::command] -pub fn dir_create(path: String) { - fs::create_dir_all(path).unwrap(); +#[deprecated = "file helper is redundant"] +pub fn dir_create(path: String) -> CultivationResult<()> { + fs::create_dir_all(path).map_err(Into::into) } +// TODO: remove this file helper, already exists an api for this in tauri. #[tauri::command] +#[deprecated = "file helper is redundant"] pub fn dir_exists(path: &str) -> bool { let path_buf = PathBuf::from(path); fs::metadata(path_buf).is_ok() } +// TODO: remove this file helper, already exists an api for this in tauri. #[tauri::command] -pub fn dir_is_empty(path: &str) -> bool { +#[deprecated = "file helper is redundant"] +pub fn dir_is_empty(path: &str) -> CultivationResult { let path_buf = PathBuf::from(path); - fs::read_dir(path_buf).unwrap().count() == 0 + Ok(fs::read_dir(path_buf)?.count() == 0) } +// TODO: remove this file helper, already exists an api for this in tauri. #[tauri::command] -pub fn dir_delete(path: &str) { +#[deprecated = "file helper is redundant"] +pub fn dir_delete(path: &str) -> CultivationResult<()> { let path_buf = PathBuf::from(path); - fs::remove_dir_all(path_buf).unwrap(); + fs::remove_dir_all(path_buf).map_err(Into::into) } #[tauri::command] @@ -57,109 +63,79 @@ pub fn are_files_identical(path1: &str, path2: &str) -> bool { diff(path1, path2) } +// TODO: remove this file helper, already exists an api for this in tauri. #[tauri::command] -pub fn copy_file(path: String, new_path: String) -> bool { +#[deprecated = "file helper is redundant"] +pub fn copy_file(path: String, new_path: String) -> CultivationResult<()> { let filename = &path.split('/').last().unwrap(); let path_buf = PathBuf::from(&path); // If the new path doesn't exist, create it. if !dir_exists(PathBuf::from(&new_path).pop().to_string().as_str()) { - std::fs::create_dir_all(&new_path).unwrap(); + std::fs::create_dir_all(&new_path)?; } // Copy old to new - match std::fs::copy(path_buf, format!("{}/{}", new_path, filename)) { - Ok(_) => true, - Err(e) => { - println!("Failed to copy file: {}", e); - println!("Path: {}", path); - println!("New Path: {}", new_path); - false - } - } + std::fs::copy(path_buf, format!("{}/{}", new_path, filename))?; + Ok(()) } +// TODO: remove this file helper, already exists an api for this in tauri. #[tauri::command] -pub fn copy_file_with_new_name(path: String, new_path: String, new_name: String) -> bool { +#[deprecated = "file helper is redundant"] +pub fn copy_file_with_new_name( + path: String, + new_path: String, + new_name: String, +) -> CultivationResult<()> { let mut new_path_buf = PathBuf::from(&new_path); let path_buf = PathBuf::from(&path); // If the new path doesn't exist, create it. if !dir_exists(PathBuf::from(&new_path).pop().to_string().as_str()) { - match std::fs::create_dir_all(&new_path) { - Ok(_) => {} - Err(e) => { - println!("Failed to create directory: {}", e); - return false; - } - }; + std::fs::create_dir_all(&new_path)?; } new_path_buf.push(new_name); // Copy old to new - match std::fs::copy(path_buf, &new_path_buf) { - Ok(_) => true, - Err(e) => { - println!("Failed to copy file: {}", e); - println!("Path: {}", path); - println!("New Path: {}", new_path); - false - } - } + std::fs::copy(path_buf, &new_path_buf)?; + + Ok(()) } +// TODO: remove this file helper, already exists an api for this in tauri. #[tauri::command] -pub fn delete_file(path: String) -> bool { +#[deprecated = "file helper is redundant"] +pub fn delete_file(path: String) -> CultivationResult<()> { let path_buf = PathBuf::from(&path); - match std::fs::remove_file(path_buf) { - Ok(_) => true, - Err(e) => { - println!("Failed to delete file: {}", e); - false - } - }; - - false + std::fs::remove_file(path_buf).map_err(Into::into) } +// TODO: remove this file helper, already exists an api for this in tauri. #[tauri::command] -pub fn read_file(path: String) -> String { +#[deprecated = "file helper is redundant"] +pub fn read_file(path: String) -> CultivationResult { let path_buf = PathBuf::from(&path); - let mut file = match fs::File::open(path_buf) { - Ok(file) => file, - Err(e) => { - println!("Failed to open file: {}", e); - return String::new(); - } - }; + let mut file = fs::File::open(path_buf)?; let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); - contents + Ok(contents) } +// TODO: remove this file helper, already exists an api for this in tauri. #[tauri::command] -pub fn write_file(path: String, contents: String) { +#[deprecated = "file helper is redundant"] +pub fn write_file(path: String, contents: String) -> CultivationResult<()> { let path_buf = PathBuf::from(&path); // Create file if it exists, otherwise just open and rewrite - let mut file = match fs::File::create(path_buf) { - Ok(file) => file, - Err(e) => { - println!("Failed to open file: {}", e); - return; - } - }; + let mut file = fs::File::create(path_buf)?; // Write contents to file - match file.write_all(contents.as_bytes()) { - Ok(_) => (), - Err(e) => { - println!("Failed to write to file: {}", e); - } - } + file.write_all(contents.as_bytes()).map_err(Into::into) } diff --git a/src-tauri/src/gamebanana.rs b/src-tauri/src/gamebanana.rs index f0aeef9c..f439a34b 100644 --- a/src-tauri/src/gamebanana.rs +++ b/src-tauri/src/gamebanana.rs @@ -1,19 +1,17 @@ -use crate::file_helpers; -use crate::web; -use std::collections::HashMap; -use std::fs::read_dir; -use std::io::Read; +use crate::{error::CultivationResult, file_helpers, web}; +use dashmap::DashMap; use std::path::PathBuf; +use tokio::{fs, io::AsyncReadExt}; static SITE_URL: &str = "https://gamebanana.com"; #[tauri::command] -pub async fn get_download_links(mod_id: String) -> String { +pub async fn get_download_links(mod_id: String) -> CultivationResult { web::query(format!("{}/apiv9/Mod/{}/DownloadPage", SITE_URL, mod_id).as_str()).await } #[tauri::command] -pub async fn list_submissions(mode: String, page: String) -> String { +pub async fn list_submissions(mode: String, page: String) -> CultivationResult { web::query( format!( "{}/apiv9/Util/Game/Submissions?_idGameRow=8552&_nPage={}&_nPerpage=50&_sMode={}", @@ -25,7 +23,7 @@ pub async fn list_submissions(mode: String, page: String) -> String { } #[tauri::command] -pub async fn list_mods(path: String) -> HashMap { +pub async fn list_mods(path: String) -> CultivationResult> { let mut path_buf = PathBuf::from(path); // If the path includes a file, remove it @@ -37,15 +35,16 @@ pub async fn list_mods(path: String) -> HashMap { path_buf.push("Mods"); // Check if dir is empty - if file_helpers::dir_is_empty(path_buf.to_str().unwrap()) { - return HashMap::new(); + if file_helpers::dir_is_empty(path_buf.to_str().unwrap())? { + return Ok(DashMap::new()); } let mut mod_info_files = vec![]; - let mut mod_info_strings = HashMap::new(); + let mod_info_strings = DashMap::new(); - for entry in read_dir(path_buf).unwrap() { - let entry = entry.unwrap(); + let mut dir_reader = fs::read_dir(path_buf).await?; + + while let Some(entry) = dir_reader.next_entry().await? { let path = entry.path(); // Check each dir for a modinfo.json file @@ -73,12 +72,12 @@ pub async fn list_mods(path: String) -> HashMap { let mut mod_info_string = String::new(); // It is safe to unwrap here since we *know* that the file exists - let mut file = std::fs::File::open(&mod_info_file).unwrap(); - file.read_to_string(&mut mod_info_string).unwrap(); + let mut file = fs::File::open(&mod_info_file).await?; + file.read_to_string(&mut mod_info_string).await?; // Push into hashmap using path as key mod_info_strings.insert(mod_info_file, mod_info_string); } - mod_info_strings + Ok(mod_info_strings) } diff --git a/src-tauri/src/lang.rs b/src-tauri/src/lang.rs index 08a9579f..7e2ee178 100644 --- a/src-tauri/src/lang.rs +++ b/src-tauri/src/lang.rs @@ -1,53 +1,35 @@ -use crate::system_helpers::*; +use crate::{error::CultivationResult, system_helpers::*}; +use dashmap::DashMap; use std::path::{Path, PathBuf}; +use tokio::fs; #[tauri::command] -pub async fn get_lang(window: tauri::Window, lang: String) -> String { +pub async fn get_lang(_window: tauri::Window, lang: String) -> CultivationResult { let lang = lang.to_lowercase(); // Send contents of language file back let lang_path: PathBuf = [&install_location(), "lang", &format!("{}.json", lang)] .iter() .collect(); - match std::fs::read_to_string(lang_path) { - Ok(x) => x, - Err(e) => { - emit_lang_err(window, format!("Failed to read language file: {}", e)); - "".to_string() - } - } + fs::read_to_string(lang_path).await.map_err(Into::into) } #[tauri::command] -pub async fn get_languages() -> std::collections::HashMap { - // for each lang file, set the key as the filename and the value as the lang_name contained in the file - let mut languages = std::collections::HashMap::new(); +pub async fn get_languages() -> CultivationResult> { + // for each lang file, set the key as the filename and the value as the + // lang_name contained in the file + let languages = DashMap::new(); - let lang_files = std::fs::read_dir(Path::new(&install_location()).join("lang")).unwrap(); + let mut lang_files = fs::read_dir(Path::new(&install_location()).join("lang")).await?; - for entry in lang_files { - let entry = entry.unwrap(); + while let Some(entry) = lang_files.next_entry().await? { let path = entry.path(); let filename = path.file_name().unwrap().to_str().unwrap(); - let content = match std::fs::read_to_string(&path) { - Ok(x) => x, - Err(e) => { - println!("Failed to read language file: {}", e); - break; - } - }; + let content = fs::read_to_string(&path).await?; languages.insert(filename.to_string(), content); } - languages -} - -pub fn emit_lang_err(window: tauri::Window, msg: String) { - let mut res_hash = std::collections::HashMap::new(); - - res_hash.insert("error".to_string(), msg); - - window.emit("lang_error", &res_hash).unwrap(); + Ok(languages) } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 05a33a35..1af74fa2 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,23 +4,26 @@ )] #![deny(clippy::all, unused)] -use file_helpers::dir_exists; +use dashmap::DashMap; use once_cell::sync::Lazy; -use std::fs; -use std::io::Write; -use std::{collections::HashMap, sync::Mutex}; +use reqwest::Client; +use std::{path::Path, sync::Mutex}; use system_helpers::is_elevated; use tauri::api::path::data_dir; -use tauri::async_runtime::block_on; -use std::thread; use sysinfo::{System, SystemExt}; +use tokio::{fs, io::AsyncWriteExt}; +use tokio_util::sync::CancellationToken; #[cfg(windows)] use crate::admin::reopen_as_admin; +use crate::error::CultivationResult; + +pub(crate) type Downloads = DashMap; mod admin; mod downloader; +mod error; mod file_helpers; mod gamebanana; mod lang; @@ -32,25 +35,32 @@ mod web; static WATCH_GAME_PROCESS: Lazy> = Lazy::new(|| Mutex::new(String::new())); -fn try_flush() { - std::io::stdout().flush().unwrap_or(()) +async fn try_flush() -> CultivationResult<()> { + tokio::io::stdout().flush().await.map_err(Into::into) } fn has_arg(args: &[String], arg: &str) -> bool { args.contains(&arg.to_string()) } -async fn arg_handler(args: &[String]) { +async fn arg_handler(args: &[String]) -> CultivationResult<()> { if has_arg(args, "--proxy") { let mut pathbuf = data_dir().unwrap(); pathbuf.push("cultivation"); pathbuf.push("ca"); - connect(8035, pathbuf.to_str().unwrap().to_string()).await; + connect(8035, pathbuf.to_str().unwrap().to_string()).await?; + + Ok(()) + } else { + Ok(()) } } -fn main() { +#[tokio::main] +async fn main() -> CultivationResult<()> { + let downloads = Downloads::with_capacity(4); + let args: Vec = std::env::args().collect(); if !is_elevated() && !has_arg(&args, "--no-admin") { @@ -62,27 +72,29 @@ fn main() { reopen_as_admin(); } - // Setup datadir/cultivation just in case something went funky and it wasn't made - if !dir_exists(data_dir().unwrap().join("cultivation").to_str().unwrap()) { - fs::create_dir_all(data_dir().unwrap().join("cultivation")).unwrap(); + // Setup datadir/cultivation just in case something went funky and it wasn't + // made + if !Path::exists(&data_dir().unwrap().join("cultivation")) { + fs::create_dir_all(data_dir().unwrap().join("cultivation")).await?; } // Always set CWD to the location of the executable. - let mut exe_path = std::env::current_exe().unwrap(); + let mut exe_path = std::env::current_exe()?; exe_path.pop(); - std::env::set_current_dir(&exe_path).unwrap(); + std::env::set_current_dir(&exe_path)?; - block_on(arg_handler(&args)); + arg_handler(&args).await?; // For disabled GUI ctrlc::set_handler(|| { disconnect(); std::process::exit(0); - }) - .unwrap_or(()); + })?; if !has_arg(&args, "--no-gui") { tauri::Builder::default() + .manage(downloads) + .manage(Client::new()) .invoke_handler(tauri::generate_handler![ enable_process_watcher, connect, @@ -125,16 +137,17 @@ fn main() { gamebanana::list_mods, metadata_patcher::patch_metadata ]) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); + .run(tauri::generate_context!())?; } else { - try_flush(); + try_flush().await?; println!("Press enter or CTRL-C twice to quit..."); - std::io::stdin().read_line(&mut String::new()).unwrap(); + std::io::stdin().read_line(&mut String::new())?; } // Always disconnect upon closing the program disconnect(); + + Ok(()) } #[tauri::command] @@ -146,23 +159,24 @@ fn is_game_running() -> bool { } #[tauri::command] -fn enable_process_watcher(window: tauri::Window, process: String) { +async fn enable_process_watcher(window: tauri::Window, process: String) -> CultivationResult<()> { *WATCH_GAME_PROCESS.lock().unwrap() = process; - window.listen("disable_process_watcher", |_e| { + let id = window.listen("disable_process_watcher", |_e| { *WATCH_GAME_PROCESS.lock().unwrap() = "".to_string(); }); println!("Starting process watcher..."); - thread::spawn(move || { - // Initial sleep for 8 seconds, since running 20 different injectors or whatever can take a while - std::thread::sleep(std::time::Duration::from_secs(10)); + tokio::spawn(async move { + // Initial sleep for 8 seconds, since running 20 different injectors or whatever + // can take a while + tokio::time::sleep(tokio::time::Duration::from_secs(10)).await; let mut system = System::new_all(); loop { - thread::sleep(std::time::Duration::from_secs(5)); + tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; // Refresh system info system.refresh_all(); @@ -177,6 +191,7 @@ fn enable_process_watcher(window: tauri::Window, process: String) { // If the game process closes, disable the proxy. if !exists { println!("Game closed"); + window.unlisten(id); *WATCH_GAME_PROCESS.lock().unwrap() = "".to_string(); disconnect(); @@ -187,18 +202,22 @@ fn enable_process_watcher(window: tauri::Window, process: String) { } } }); + + Ok(()) } #[tauri::command] -async fn connect(port: u16, certificate_path: String) { +async fn connect(port: u16, certificate_path: String) -> CultivationResult<()> { // Log message to console. println!("Connecting to proxy..."); // Change proxy settings. - proxy::connect_to_proxy(port); + proxy::connect_to_proxy(port)?; // Create and start a proxy. - proxy::create_proxy(port, certificate_path).await; + proxy::create_proxy(port, certificate_path).await?; + + Ok(()) } #[tauri::command] @@ -211,34 +230,37 @@ fn disconnect() { } #[tauri::command] -async fn req_get(url: String) -> String { - // Send a GET request to the specified URL and send the response body back to the client. +#[inline(always)] +async fn req_get(url: String) -> CultivationResult { + // Send a GET request to the specified URL and send the response body back to + // the client. web::query(&url.to_string()).await } #[tauri::command] -async fn get_theme_list(data_dir: String) -> Vec> { +async fn get_theme_list(data_dir: String) -> CultivationResult>> { let theme_loc = format!("{}/themes", data_dir); // Ensure folder exists - if !std::path::Path::new(&theme_loc).exists() { - std::fs::create_dir_all(&theme_loc).unwrap(); + if !Path::new(&theme_loc).exists() { + fs::create_dir_all(&theme_loc).await?; } // Read each index.json folder in each theme folder let mut themes = Vec::new(); - for entry in std::fs::read_dir(&theme_loc).unwrap() { - let entry = entry.unwrap(); + let mut dir_reader = fs::read_dir(&theme_loc).await?; + + while let Some(entry) = dir_reader.next_entry().await? { let path = entry.path(); if path.is_dir() { let index_path = format!("{}/index.json", path.to_str().unwrap()); - if std::path::Path::new(&index_path).exists() { - let theme_json = std::fs::read_to_string(&index_path).unwrap(); + if Path::new(&index_path).exists() { + let theme_json = fs::read_to_string(&index_path).await?; - let mut map = HashMap::new(); + let map = DashMap::with_capacity(2); map.insert("json".to_string(), theme_json); map.insert("path".to_string(), path.to_str().unwrap().to_string()); @@ -249,5 +271,5 @@ async fn get_theme_list(data_dir: String) -> Vec> { } } - themes + Ok(themes) } diff --git a/src-tauri/src/metadata_patcher.rs b/src-tauri/src/metadata_patcher.rs index e72c3a1f..b49cab79 100644 --- a/src-tauri/src/metadata_patcher.rs +++ b/src-tauri/src/metadata_patcher.rs @@ -1,5 +1,10 @@ use regex::Regex; -use std::{fs, fs::File, fs::OpenOptions, io::Read, io::Write, path::Path}; +use std::{ + fs, + fs::{File, OpenOptions}, + io::{Read, Write}, + path::Path, +}; // For these two functions, a non-zero return value indicates failure. extern "C" { diff --git a/src-tauri/src/proxy.rs b/src-tauri/src/proxy.rs index e844147a..a877a0cc 100644 --- a/src-tauri/src/proxy.rs +++ b/src-tauri/src/proxy.rs @@ -3,7 +3,6 @@ * https://github.com/omjadas/hudsucker/blob/main/examples/log.rs */ -#[cfg(target_os = "linux")] use crate::system_helpers::run_command; use once_cell::sync::Lazy; @@ -17,13 +16,13 @@ use hudsucker::{ }; use rcgen::*; -use std::fs; -use std::net::SocketAddr; -use std::path::Path; +use std::{net::SocketAddr, path::Path}; +use tokio::fs; use rustls_pemfile as pemfile; use tauri::{api::path::data_dir, http::Uri}; +use crate::error::CultivationResult; #[cfg(windows)] use registry::{Data, Hive, Security}; @@ -78,32 +77,35 @@ impl HttpHandler for ProxyHandler { /** * Starts an HTTP(S) proxy server. */ -pub async fn create_proxy(proxy_port: u16, certificate_path: String) { +pub async fn create_proxy(proxy_port: u16, certificate_path: String) -> CultivationResult<()> { let cert_path = PathBuf::from(certificate_path); let pk_path = cert_path.join("private.key"); let ca_path = cert_path.join("cert.crt"); + async fn regen_cert( + e: tokio::io::Error, + path: &PathBuf, + dir: &Path, + ) -> CultivationResult> { + println!("Encountered {}. Regenerating CA cert and retrying...", e); + generate_ca_files(dir).await?; + + fs::read(path).await.map_err(Into::into) + } + + let cultivation_dir = &data_dir().unwrap().join("cultivation"); + // Get the certificate and private key. - let mut private_key_bytes: &[u8] = &match fs::read(&pk_path) { + let mut private_key_bytes: &[u8] = &match fs::read(&pk_path).await { // Try regenerating the CA stuff and read it again. If that doesn't work, quit. Ok(b) => b, - Err(e) => { - println!("Encountered {}. Regenerating CA cert and retrying...", e); - generate_ca_files(&data_dir().unwrap().join("cultivation")); - - fs::read(&pk_path).expect("Could not read private key") - } + Err(e) => regen_cert(e, &pk_path, cultivation_dir).await?, }; - let mut ca_cert_bytes: &[u8] = &match fs::read(&ca_path) { + let mut ca_cert_bytes: &[u8] = &match fs::read(&ca_path).await { // Try regenerating the CA stuff and read it again. If that doesn't work, quit. Ok(b) => b, - Err(e) => { - println!("Encountered {}. Regenerating CA cert and retrying...", e); - generate_ca_files(&data_dir().unwrap().join("cultivation")); - - fs::read(&ca_path).expect("Could not read certificate") - } + Err(e) => regen_cert(e, &ca_path, cultivation_dir).await?, }; // Parse the private key and certificate. @@ -133,13 +135,15 @@ pub async fn create_proxy(proxy_port: u16, certificate_path: String) { // Start the proxy. tokio::spawn(proxy.start(shutdown_signal())); + + Ok(()) } /** * Connects to the local HTTP(S) proxy server. */ #[cfg(windows)] -pub fn connect_to_proxy(proxy_port: u16) { +pub fn connect_to_proxy(proxy_port: u16) -> CultivationResult<()> { // Create 'ProxyServer' string. let server_string: String = format!( "http=127.0.0.1:{};https=127.0.0.1:{}", @@ -147,40 +151,40 @@ pub fn connect_to_proxy(proxy_port: u16) { ); // Fetch the 'Internet Settings' registry key. - let settings = Hive::CurrentUser - .open( - r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", - Security::Write, - ) - .unwrap(); + let settings = Hive::CurrentUser.open( + r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", + Security::Write, + )?; // Set registry values. - settings - .set_value("ProxyServer", &Data::String(server_string.parse().unwrap())) - .unwrap(); - settings.set_value("ProxyEnable", &Data::U32(1)).unwrap(); + settings.set_value("ProxyServer", &Data::String(server_string.parse().unwrap()))?; + settings.set_value("ProxyEnable", &Data::U32(1))?; println!("Connected to the proxy."); + Ok(()) } #[cfg(unix)] -pub fn connect_to_proxy(proxy_port: u16) { +pub fn connect_to_proxy(proxy_port: u16) -> CultivationResult<()> { // Edit /etc/environment to set $http_proxy and $https_proxy - let mut env_file = match fs::read_to_string("/etc/environment") { + let mut env_file = match std::fs::read_to_string("/etc/environment") { Ok(f) => f, Err(e) => { println!("Error opening /etc/environment: {}", e); - return; + return Ok(()); } }; // Append the proxy configuration. - // We will not remove the current proxy config if it exists, so we can just remove these last lines when we disconnect + // We will not remove the current proxy config if it exists, so we can just + // remove these last lines when we disconnect env_file += format!("\nhttps_proxy=127.0.0.1:{}", proxy_port).as_str(); env_file += format!("\nhttp_proxy=127.0.0.1:{}", proxy_port).as_str(); // Save - fs::write("/etc/environment", env_file).unwrap(); + std::fs::write("/etc/environment", env_file)?; + + Ok(()) } #[cfg(target_od = "macos")] @@ -216,12 +220,13 @@ pub fn disconnect_from_proxy() { r"(https|http)_proxy=.*127.0.0.1:.*", ) .unwrap(); - let environment = &fs::read_to_string("/etc/environment").expect("Failed to open environment"); + let environment = + &std::fs::read_to_string("/etc/environment").expect("Failed to open environment"); let new_environment = regexp.replace_all(environment, "").to_string(); // Write new environment - fs::write("/etc/environment", new_environment.trim_end()).expect( + std::fs::write("/etc/environment", new_environment.trim_end()).expect( "Could not write environment, remove proxy declarations manually if they are still set", ); } @@ -231,11 +236,11 @@ pub fn disconnect_from_proxy() {} /* * Generates a private key and certificate used by the certificate authority. - * Additionally installs the certificate and private key in the Root CA store. - * Source: https://github.com/zu1k/good-mitm/raw/master/src/ca/gen.rs + * Additionally installs the certificate and private key in the Root CA + * store. Source: https://github.com/zu1k/good-mitm/raw/master/src/ca/gen.rs */ #[tauri::command] -pub fn generate_ca_files(path: &Path) { +pub async fn generate_ca_files(path: &Path) -> CultivationResult<()> { let mut params = CertificateParams::default(); let mut details = DistinguishedName::new(); @@ -256,54 +261,34 @@ pub fn generate_ca_files(path: &Path) { ]; // Create certificate. - let cert = Certificate::from_params(params).unwrap(); - let cert_crt = cert.serialize_pem().unwrap(); + let cert = Certificate::from_params(params)?; + let cert_crt = cert.serialize_pem()?; let private_key = cert.serialize_private_key_pem(); // Make certificate directory. let cert_dir = path.join("ca"); - match fs::create_dir(&cert_dir) { - Ok(_) => {} - Err(e) => { - println!("{}", e); - } - }; + fs::create_dir(&cert_dir).await?; // Write the certificate to a file. let cert_path = cert_dir.join("cert.crt"); - match fs::write(&cert_path, cert_crt) { - Ok(_) => println!("Wrote certificate to {}", cert_path.to_str().unwrap()), - Err(e) => println!( - "Error writing certificate to {}: {}", - cert_path.to_str().unwrap(), - e - ), - } + fs::write(&cert_path, cert_crt).await?; // Write the private key to a file. let private_key_path = cert_dir.join("private.key"); - match fs::write(&private_key_path, private_key) { - Ok(_) => println!( - "Wrote private key to {}", - private_key_path.to_str().unwrap() - ), - Err(e) => println!( - "Error writing private key to {}: {}", - private_key_path.to_str().unwrap(), - e - ), - } + fs::write(private_key_path, private_key).await?; // Install certificate into the system's Root CA store. install_ca_files(&cert_path); + Ok(()) } /* - * Attempts to install the certificate authority's certificate into the Root CA store. + * Attempts to install the certificate authority's certificate into the Root + * CA store. */ #[cfg(windows)] pub fn install_ca_files(cert_path: &Path) { - crate::system_helpers::run_command( + run_command( "certutil", vec!["-user", "-addstore", "Root", cert_path.to_str().unwrap()], None, @@ -313,7 +298,7 @@ pub fn install_ca_files(cert_path: &Path) { #[cfg(target_os = "macos")] pub fn install_ca_files(cert_path: &Path) { - crate::system_helpers::run_command( + run_command( "security", vec![ "add-trusted-cert", @@ -336,9 +321,10 @@ pub fn install_ca_files(cert_path: &Path) { let usr_cert_path = usr_certs.join("cultivation.crt"); // Create dir if it doesn't exist - fs::create_dir_all(&usr_certs).expect("Unable to create local certificate directory"); + std::fs::create_dir_all(&usr_certs).expect("Unable to create local certificate directory"); - fs::copy(cert_path, &usr_cert_path).expect("Unable to copy cert to local certificate directory"); + std::fs::copy(cert_path, &usr_cert_path) + .expect("Unable to copy cert to local certificate directory"); run_command("update-ca-certificates", vec![], None); println!("Installed certificate."); diff --git a/src-tauri/src/system_helpers.rs b/src-tauri/src/system_helpers.rs index 88b11333..1c2be89f 100644 --- a/src-tauri/src/system_helpers.rs +++ b/src-tauri/src/system_helpers.rs @@ -2,32 +2,33 @@ use duct::cmd; use ini::Ini; use std::path::PathBuf; +use crate::error::CultivationResult; #[cfg(windows)] use registry::{Data, Hive, Security}; #[tauri::command] -pub fn run_program(path: String, args: Option) { +pub fn run_program(path: String, args: Option) -> CultivationResult<()> { // Without unwrap_or, this can crash when UAC prompt is denied - open::that(format!("{} {}", &path, &args.unwrap_or_else(|| "".into()))).unwrap_or(()); + open::that(format!("{} {}", &path, &args.unwrap_or_else(|| "".into()))).map_err(Into::into) } #[tauri::command] -pub fn run_program_relative(path: String, args: Option) { +pub fn run_program_relative(path: String, args: Option) -> CultivationResult<()> { // Save the current working directory - let cwd = std::env::current_dir().unwrap(); + let cwd = std::env::current_dir()?; // Set the new working directory to the path before the executable let mut path_buf = std::path::PathBuf::from(&path); path_buf.pop(); // Set new working directory - std::env::set_current_dir(&path_buf).unwrap(); + std::env::set_current_dir(&path_buf)?; // Without unwrap_or, this can crash when UAC prompt is denied - open::that(format!("{} {}", &path, args.unwrap_or_else(|| "".into()))).unwrap_or(()); + open::that(format!("{} {}", &path, args.unwrap_or_else(|| "".into())))?; // Restore the original working directory - std::env::set_current_dir(cwd).unwrap(); + std::env::set_current_dir(cwd).map_err(Into::into) } #[tauri::command] @@ -65,6 +66,7 @@ pub fn run_jar(path: String, execute_in: String, java_path: String) { }; // Open the program from the specified path. + // TODO: incredibly niche (only windows) match open::with( format!("/k cd /D \"{}\" & {}", &execute_in, &command), "C:\\Windows\\System32\\cmd.exe", diff --git a/src-tauri/src/unzip.rs b/src-tauri/src/unzip.rs index 9a908c9e..aba8c009 100644 --- a/src-tauri/src/unzip.rs +++ b/src-tauri/src/unzip.rs @@ -1,130 +1,121 @@ -use std::fs::{read_dir, File}; -use std::path; -use std::thread; +use crate::{error::CultivationResult, Downloads}; +use dashmap::DashMap; +use std::{fs::File as StdFile, path, path::PathBuf}; +use tokio::fs::{create_dir_all, read_dir, remove_file, File, OpenOptions}; use unrar::archive::Archive; #[tauri::command] -pub fn unzip( +pub async fn unzip( window: tauri::Window, zipfile: String, destpath: String, top_level: Option, folder_if_loose: Option, -) { - // Read file TODO: replace test file - let f = match File::open(&zipfile) { - Ok(f) => f, - Err(e) => { - println!("Failed to open zip file: {}", e); - return; - } - }; - - let write_path = path::PathBuf::from(&destpath); + downloads: tauri::State<'_, Downloads>, +) -> CultivationResult<()> { + // SAFETY: contract says that we can't call unzip on a file that we haven't + // started downloading + let token = unsafe { downloads.get(&zipfile).unwrap_unchecked() }; + let path = zipfile.clone(); + let out = tokio::select! { + _ = token.cancelled() => { + println!("Cancelled unzip {path}"); + Ok(()) + }, + r = async move { + let tokio_f = File::open(&zipfile).await?; + let f = tokio_f.try_clone().await.unwrap().into_std().await; + + let write_path = path::PathBuf::from(&destpath); + + // Get a list of all current directories + let mut dir_reader = read_dir(&write_path).await?; + + let mut dirs: Vec = vec![]; + + while let Some(entry) = dir_reader.next_entry().await? { + let entry_path = entry.path(); + if entry_path.is_dir() { + dirs.push(entry_path); + } + } - // Get a list of all current directories - let mut dirs = vec![]; - for entry in read_dir(&write_path).unwrap() { - let entry = entry.unwrap(); - let entry_path = entry.path(); - if entry_path.is_dir() { - dirs.push(entry_path); - } - } + let mut full_path = write_path.clone(); - // Run extraction in seperate thread - thread::spawn(move || { - let mut full_path = write_path.clone(); - - window.emit("extract_start", &zipfile).unwrap(); - - if folder_if_loose.unwrap_or(false) { - // Create a new folder with the same name as the zip file - let mut file_name = path::Path::new(&zipfile) - .file_name() - .unwrap() - .to_str() - .unwrap(); - - // remove ".zip" from the end of the file name - file_name = &file_name[..file_name.len() - 4]; - - let new_path = full_path.join(file_name); - match std::fs::create_dir_all(&new_path) { - Ok(_) => {} - Err(e) => { - println!("Failed to create directory: {}", e); - return; - } - }; + window.emit("extract_start", &zipfile)?; - full_path = new_path; - } + if folder_if_loose.unwrap_or(false) { + // Create a new folder with the same name as the zip file + let file_name = path::Path::new(&zipfile).with_extension(""); - println!("Is rar file? {}", zipfile.ends_with(".rar")); + let new_path = full_path.join(file_name); + create_dir_all(&new_path).await?; - let name; - let success; + full_path = new_path; + } - // If file ends in zip, OR is unknown, extract as zip, otherwise extract as rar - if zipfile.ends_with(".rar") { - success = extract_rar(&zipfile, &f, &full_path, top_level.unwrap_or(true)); + println!("Is rar file? {}", zipfile.ends_with(".rar")); - let archive = Archive::new(zipfile.clone()); - name = archive.list().unwrap().next().unwrap().unwrap().filename; - } else { - success = extract_zip(&zipfile, &f, &full_path, top_level.unwrap_or(true)); + let name; + let success; - // Get the name of the inenr file in the zip file - let mut zip = zip::ZipArchive::new(&f).unwrap(); - let file = zip.by_index(0).unwrap(); - name = file.name().to_string(); - } + // If file ends in zip, OR is unknown, extract as zip, otherwise extract as rar + if zipfile.ends_with(".rar") { + success = extract_rar(&zipfile, &f, &full_path, top_level.unwrap_or(true)); - if !success { - let mut res_hash = std::collections::HashMap::new(); + let archive = Archive::new(zipfile.clone()); + name = archive.list().unwrap().next().unwrap().unwrap().filename; + } else { + success = extract_zip(tokio_f, &full_path).await; - res_hash.insert("path".to_string(), zipfile.to_string()); + // Get the name of the inenr file in the zip file + let mut zip = zip::ZipArchive::new(&f)?; + let file = zip.by_index(0)?; + name = file.name().to_string(); + } - window.emit("download_error", &res_hash).unwrap(); - } + if !success { + let res_hash = DashMap::with_capacity(1); - // If the contents is a jar file, emit that we have extracted a new jar file - if name.ends_with(".jar") { - window - .emit("jar_extracted", destpath.to_string() + name.as_str()) - .unwrap(); - } + res_hash.insert("path".to_string(), zipfile.to_string()); - // Delete zip file - match std::fs::remove_file(&zipfile) { - Ok(_) => { - println!("Deleted zip file: {}", zipfile); + window.emit("download_error", &res_hash)?; } - Err(e) => { - println!("Failed to delete zip file: {}", e); + + // If the contents is a jar file, emit that we have extracted a new jar file + if name.ends_with(".jar") { + window.emit("jar_extracted", destpath.to_string() + name.as_str())?; } - }; - - // Get any new directory that could have been created - let mut new_dir: String = String::new(); - for entry in read_dir(&write_path).unwrap() { - let entry = entry.unwrap(); - let entry_path = entry.path(); - if entry_path.is_dir() && !dirs.contains(&entry_path) { - new_dir = entry_path.to_str().unwrap().to_string(); + + // Delete zip file + remove_file(&zipfile).await?; + + // Get any new directory that could have been created + let mut new_dir: String = String::new(); + + let mut dir_reader = read_dir(&write_path).await?; + + while let Some(entry) = dir_reader.next_entry().await? { + let entry_path = entry.path(); + if entry_path.is_dir() && !dirs.contains(&entry_path) { + new_dir = entry_path.to_str().unwrap().to_string(); + } } - } - let mut res_hash = std::collections::HashMap::new(); - res_hash.insert("file", zipfile.to_string()); - res_hash.insert("new_folder", new_dir); + let res_hash = DashMap::with_capacity(2); + res_hash.insert("file", zipfile.to_string()); + res_hash.insert("new_folder", new_dir); + + window.emit("extract_end", &res_hash)?; + + Ok(()) + } => r + }; - window.emit("extract_end", &res_hash).unwrap(); - }); + out } -fn extract_rar(rarfile: &str, _f: &File, full_path: &path::Path, _top_level: bool) -> bool { +fn extract_rar(rarfile: &str, _f: &StdFile, full_path: &path::Path, _top_level: bool) -> bool { let archive = Archive::new(rarfile.to_string()); let mut open_archive = archive @@ -147,19 +138,55 @@ fn extract_rar(rarfile: &str, _f: &File, full_path: &path::Path, _top_level: boo } } -fn extract_zip(_zipfile: &str, f: &File, full_path: &path::Path, top_level: bool) -> bool { - match zip_extract::extract(f, full_path, top_level) { - Ok(_) => { - println!( - "Extracted zip file to: {}", - full_path.to_str().unwrap_or("Error") - ); +fn sanitize_file_path(path: &str) -> PathBuf { + path + .replace('\\', "/") + .split('/') + .map(sanitize_filename::sanitize) + .collect() +} - true - } - Err(e) => { - println!("Failed to extract zip file: {}", e); - false +async fn extract_zip(f: File, full_path: &path::Path) -> bool { + let mut reader = async_zip::read::seek::ZipFileReader::new(f).await.unwrap(); + + for index in 0..reader.entries().len() { + let entry = reader + .entry_reader(index) + .await + .expect("Failed to read ZipEntry"); + let path = full_path.join(sanitize_file_path(entry.entry().filename())); + let entry_is_dir = entry.entry().filename().ends_with('/'); + + if entry_is_dir { + if !path.exists() { + create_dir_all(&path) + .await + .expect("Failed to create extracted directory"); + } + } else { + let parent = path + .parent() + .expect("A file entry should have parent directories"); + if !parent.is_dir() { + create_dir_all(parent) + .await + .expect("Failed to create parent directories"); + } + if path.exists() { + tokio::fs::remove_file(&path).await.unwrap(); + } + let mut writer = OpenOptions::new() + .write(true) + .create_new(true) + .open(&path) + .await + .expect("Failed to create extracted file"); + entry + .copy_to_end_crc(&mut writer, 65536) + .await + .expect("Failed to copy to extracted file"); } } + + true } diff --git a/src-tauri/src/web.rs b/src-tauri/src/web.rs index 29193ee9..723134c4 100644 --- a/src-tauri/src/web.rs +++ b/src-tauri/src/web.rs @@ -1,6 +1,8 @@ +use crate::error::CultivationResult; use reqwest::header::{CONTENT_TYPE, USER_AGENT}; -pub(crate) async fn query(site: &str) -> String { +#[inline] +pub(crate) async fn query(site: &str) -> CultivationResult { let client = reqwest::Client::new(); let response = client @@ -8,13 +10,12 @@ pub(crate) async fn query(site: &str) -> String { .header(USER_AGENT, "cultivation") .header(CONTENT_TYPE, "application/json") .send() - .await - .unwrap(); - response.text().await.unwrap() + .await?; + response.text().await.map_err(Into::into) } #[tauri::command] -pub(crate) async fn valid_url(url: String) -> bool { +pub(crate) async fn valid_url(url: String) -> CultivationResult { // Check if we get a 200 response let client = reqwest::Client::new(); @@ -22,14 +23,15 @@ pub(crate) async fn valid_url(url: String) -> bool { .get(url) .header(USER_AGENT, "cultivation") .send() - .await - .unwrap(); + .await?; - response.status().as_str() == "200" + Ok(response.status().as_str() == "200") } #[tauri::command] -pub async fn web_get(url: String) -> String { - // Send a GET request to the specified URL and send the response body back to the client. +#[inline(always)] +pub async fn web_get(url: String) -> CultivationResult { + // Send a GET request to the specified URL and send the response body back to + // the client. query(&url).await } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index cc4b731c..7da1fc58 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,13 +1,13 @@ { "$schema": "..\\node_modules/@tauri-apps/cli\\schema.json", "build": { - "beforeDevCommand": "yarn start", - "devPath": "http://localhost:3000", + "beforeDevCommand": "pnpm start", + "devPath": "http://localhost:5173", "distDir": "../build" }, "package": { "productName": "Cultivation", - "version": "1.0.10" + "version": "2.0.0" }, "tauri": { "allowlist": { diff --git a/src/index.tsx b/src/index.tsx index f2aff33a..90500de4 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,21 +1,31 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' +import { Show } from 'solid-js'; +import { render } from 'solid-js/web'; +import { attachDevtoolsOverlay } from '@solid-devtools/overlay'; -import './index.css' -import App from './ui/App' -import Debug from './ui/Debug' +import App from './ui/App'; +import Debug from './ui/Debug'; +import { getConfigOption } from './utils/configuration'; +import reportWebVitals from './utils/reportWebVitals'; -import { getConfigOption } from './utils/configuration' +import './index.css'; -const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement) +attachDevtoolsOverlay({}); -let isDebug = false +const root = document.getElementById('root') as HTMLElement; -;async () => { - isDebug = await getConfigOption('debug_enabled') -} +let isDebug = false; -root.render({isDebug ? : }) +(async () => { + isDebug = await getConfigOption('debug_enabled'); +})(); -import reportWebVitals from './utils/reportWebVitals' -isDebug && reportWebVitals(console.log) +render( + () => ( + }> + + + ), + root +); + +isDebug && reportWebVitals(console.log); diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts deleted file mode 100644 index 6431bc5f..00000000 --- a/src/react-app-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/src/ui/App.tsx b/src/ui/App.tsx index 9e00a9bd..51244eea 100644 --- a/src/ui/App.tsx +++ b/src/ui/App.tsx @@ -1,102 +1,72 @@ -import React from 'react' -import './App.css' +import { createSignal, Match, onMount, Switch } from 'solid-js'; +import { convertFileSrc, invoke } from '@tauri-apps/api/tauri'; -import DownloadHandler from '../utils/download' -import { getConfigOption } from '../utils/configuration' -import { getTheme, loadTheme } from '../utils/themes' -import { convertFileSrc, invoke } from '@tauri-apps/api/tauri' -import { Main } from './Main' -import { Mods } from './Mods' +import { getConfigOption } from '../utils/configuration'; +import DownloadHandler from '../utils/download'; +import { getTheme, loadTheme } from '../utils/themes'; +import { Main } from './Main'; +import { Mods } from './Mods'; -interface IState { - page: string - bgFile: string -} - -const downloadHandler = new DownloadHandler() -const DEFAULT_BG = 'https://api.grasscutter.io/cultivation/bgfile' +import './App.css'; -class App extends React.Component, IState> { - constructor(props: Readonly) { - super(props) +const downloadHandler = new DownloadHandler(); +const DEFAULT_BG = 'https://api.grasscutter.io/cultivation/bgfile'; - this.state = { - page: 'main', - bgFile: DEFAULT_BG, - } - } +export default function App() { + const [page, setPage] = createSignal('main'); + const [bgFile, setBgFile] = createSignal(DEFAULT_BG); - async componentDidMount() { + onMount(async () => { // Load a theme if it exists - const theme = await getConfigOption('theme') + const theme = await getConfigOption('theme'); if (theme && theme !== 'default') { - const themeObj = await getTheme(theme) - await loadTheme(themeObj, document) + const themeObj = await getTheme(theme); + await loadTheme(themeObj, document); } // Get custom bg AFTER theme is loaded !! important !! - const custom_bg = await getConfigOption('customBackground') + const custom_bg = await getConfigOption('customBackground'); if (custom_bg) { - const isUrl = /^http(s)?:\/\//gm.test(custom_bg) + const isUrl = /^http(s)?:\/\//gm.test(custom_bg); if (!isUrl) { const isValid = await invoke('dir_exists', { path: custom_bg, - }) + }); - this.setState( - { - bgFile: isValid ? convertFileSrc(custom_bg) : DEFAULT_BG, - }, - this.forceUpdate - ) + setBgFile(isValid ? convertFileSrc(custom_bg) : DEFAULT_BG); } else { // Check if URL returns a valid image. const isValid = await invoke('valid_url', { url: custom_bg, - }) + }); - this.setState( - { - bgFile: isValid ? custom_bg : DEFAULT_BG, - }, - this.forceUpdate - ) + setBgFile(isValid ? custom_bg : DEFAULT_BG); } } window.addEventListener('changePage', (e) => { - this.setState({ - // @ts-expect-error - TS doesn't like our custom event - page: e.detail, - }) - }) - } + // @ts-expect-error - TS doesn't like our custom event + setPage(e.detail); + }); + }); - render() { - return ( -
- {(() => { - switch (this.state.page) { - case 'modding': - return - default: - return
- } - })()} -
- ) - } + return ( +
+ }> + + + + +
+ ); } - -export default App diff --git a/src/ui/Debug.tsx b/src/ui/Debug.tsx index 41ad966e..30bd7d4e 100644 --- a/src/ui/Debug.tsx +++ b/src/ui/Debug.tsx @@ -1,30 +1,34 @@ -import React from 'react' -import './App.css' +import { dataDir } from '@tauri-apps/api/path'; +import { invoke } from '@tauri-apps/api/tauri'; -import TopBar from './components/TopBar' +import TextInput from './components/common/TextInput'; +import TopBar from './components/TopBar'; -import { invoke } from '@tauri-apps/api/tauri' -import { dataDir } from '@tauri-apps/api/path' -import TextInput from './components/common/TextInput' +import './App.css'; -let proxyAddress = '' +let proxyAddress = ''; async function setProxyAddress(address: string) { - proxyAddress = address - await invoke('set_proxy_addr', { addr: address }) + proxyAddress = address; + await invoke('set_proxy_addr', { addr: address }); } async function startProxy() { - await invoke('connect', { port: 2222, certificatePath: (await dataDir()) + '\\cultivation\\ca' }) - await invoke('open_in_browser', { url: 'https://hoyoverse.com' }) + await invoke('connect', { + port: 2222, + certificatePath: (await dataDir()) + '\\cultivation\\ca', + }); + await invoke('open_in_browser', { url: 'https://hoyoverse.com' }); } async function stopProxy() { - await invoke('disconnect') + await invoke('disconnect'); } async function generateCertificates() { - await invoke('generate_ca_files', { path: (await dataDir()) + '\\cultivation' }) + await invoke('generate_ca_files', { + path: (await dataDir()) + '\\cultivation', + }); } async function generateInfo() { @@ -32,23 +36,23 @@ async function generateInfo() { certificatePath: (await dataDir()) + '\\cultivation\\ca', isAdmin: await invoke('is_elevated'), connectingTo: proxyAddress, - }) - alert('check your dev console and send that in #cultivation') + }); + alert('check your dev console and send that in #cultivation'); } -class Debug extends React.Component { - render() { - return ( -
- - - - - - -
- ) - } +export default function Debug() { + return ( +
+ + + + + + +
+ ); } - -export default Debug diff --git a/src/ui/Main.tsx b/src/ui/Main.tsx index 5a7dd9b4..116140f6 100644 --- a/src/ui/Main.tsx +++ b/src/ui/Main.tsx @@ -1,241 +1,231 @@ -import React from 'react' - // Major Components -import TopBar from './components/TopBar' -import ServerLaunchSection from './components/ServerLaunchSection' -import MainProgressBar from './components/common/MainProgressBar' -import Options from './components/menu/Options' -import MiniDialog from './components/MiniDialog' -import DownloadList from './components/common/DownloadList' -import Downloads from './components/menu/Downloads' -import NewsSection from './components/news/NewsSection' -import Game from './components/menu/Game' -import RightBar from './components/RightBar' - -import { getConfigOption, setConfigOption } from '../utils/configuration' -import { invoke } from '@tauri-apps/api' -import { listen } from '@tauri-apps/api/event' -import { dataDir } from '@tauri-apps/api/path' -import { appWindow } from '@tauri-apps/api/window' -import { unpatchGame } from '../utils/metadata' -import DownloadHandler from '../utils/download' +import { batch, onCleanup, onMount, Show } from 'solid-js'; +import { createMutable } from 'solid-js/store'; +import { invoke } from '@tauri-apps/api'; +import { listen, UnlistenFn } from '@tauri-apps/api/event'; +import { dataDir } from '@tauri-apps/api/path'; +import { appWindow } from '@tauri-apps/api/window'; // Graphics -import cogBtn from '../resources/icons/cog.svg' -import downBtn from '../resources/icons/download.svg' -import wrenchBtn from '../resources/icons/wrench.svg' -import { ExtrasMenu } from './components/menu/ExtrasMenu' +import cogBtn from '../resources/icons/cog.svg'; +import downBtn from '../resources/icons/download.svg'; +import wrenchBtn from '../resources/icons/wrench.svg'; +import { getConfigOption, setConfigOption } from '../utils/configuration'; +import DownloadHandler from '../utils/download'; +import { unpatchGame } from '../utils/metadata'; +import DownloadList from './components/common/DownloadList'; +import MainProgressBar from './components/common/MainProgressBar'; +import Downloads from './components/menu/Downloads'; +import { ExtrasMenu } from './components/menu/ExtrasMenu'; +import Game from './components/menu/Game'; +import Options from './components/menu/Options'; +import MiniDialog from './components/MiniDialog'; +import NewsSection from './components/news/NewsSection'; +import RightBar from './components/RightBar'; +import ServerLaunchSection from './components/ServerLaunchSection'; +import TopBar from './components/TopBar'; interface IProps { - downloadHandler: DownloadHandler + downloadHandler: DownloadHandler; } interface IState { - isDownloading: boolean - optionsOpen: boolean - miniDownloadsOpen: boolean - downloadsOpen: boolean - gameDownloadsOpen: boolean - extrasOpen: boolean - migotoSet: boolean - playGame: (exe?: string, proc_name?: string) => void + isDownloading: boolean; + optionsOpen: boolean; + miniDownloadsOpen: boolean; + downloadsOpen: boolean; + gameDownloadsOpen: boolean; + extrasOpen: boolean; + migotoSet: boolean; + playGame: (exe?: string, proc_name?: string) => void; } -export class Main extends React.Component { - constructor(props: IProps) { - super(props) - this.state = { - isDownloading: false, - optionsOpen: false, - miniDownloadsOpen: false, - downloadsOpen: false, - gameDownloadsOpen: false, - extrasOpen: false, - migotoSet: false, - playGame: () => { - alert('Error launching game') - }, - } - +export function Main(props: IProps) { + const unlisteners: Promise[] = []; + const state = createMutable({ + isDownloading: false, + optionsOpen: false, + miniDownloadsOpen: false, + downloadsOpen: false, + gameDownloadsOpen: false, + extrasOpen: false, + migotoSet: false, + playGame: () => { + alert('Error launching game'); + }, + }); + + unlisteners.push( listen('lang_error', (payload) => { - console.log(payload) + console.log(payload); }) + ); + unlisteners.push( listen('jar_extracted', ({ payload }: { payload: string }) => { - setConfigOption('grasscutter_path', payload) + setConfigOption('grasscutter_path', payload); }) + ); + unlisteners.push( // Emitted for metadata replacing-purposes listen('game_closed', async () => { - const wasPatched = await getConfigOption('patch_metadata') + const wasPatched = await getConfigOption('patch_metadata'); if (wasPatched) { - const unpatched = await unpatchGame() + const unpatched = await unpatchGame(); if (!unpatched) { alert( `Could not unpatch game! (You should be able to find your metadata backup in ${await dataDir()}\\cultivation\\)` - ) + ); } } }) + ); - let min = false + let min = false; - // periodically check if we need to min/max based on whether the game is open - setInterval(async () => { - const gameOpen = await invoke('is_game_running') + // periodically check if we need to min/max based on whether the game is open + const id = window.setInterval(async () => { + const gameOpen = await invoke('is_game_running'); - if (gameOpen && !min) { - appWindow.minimize() - min = true - } else if (!gameOpen && min) { - appWindow.unminimize() - min = false - } - }, 1000) + if (gameOpen && !min) { + appWindow.minimize(); + min = true; + } else if (!gameOpen && min) { + appWindow.unminimize(); + min = false; + } + }, 1000); - this.openExtrasMenu = this.openExtrasMenu.bind(this) - } + onCleanup(() => clearInterval(id)); + + onCleanup(async () => { + const uls = await Promise.all(unlisteners); + for (const ul of uls) { + ul(); + } + }); - async componentDidMount() { - const cert_generated = await getConfigOption('cert_generated') + onMount(async () => { + const cert_generated = await getConfigOption('cert_generated'); - this.setState({ - migotoSet: !!(await getConfigOption('migoto_path')), - }) + state.migotoSet = !!(await getConfigOption('migoto_path')); if (!cert_generated) { // Generate the certificate await invoke('generate_ca_files', { path: (await dataDir()) + 'cultivation', - }) + }); - await setConfigOption('cert_generated', true) + await setConfigOption('cert_generated', true); } // Period check to only show progress bar when downloading files setInterval(() => { - this.setState({ - isDownloading: this.props.downloadHandler.getDownloads().filter((d) => d.status !== 'finished')?.length > 0, - }) - }, 1000) + state.isDownloading = + props.downloadHandler + .getDownloads() + .filter((d) => d.status !== 'finished')?.length > 0; + }, 1000); + }); + + async function openExtrasMenu(playGame: () => void) { + batch(() => { + state.extrasOpen = true; + state.playGame = playGame; + }); } - async openExtrasMenu(playGame: () => void) { - this.setState({ - extrasOpen: true, - playGame, - }) - } - - render() { - return ( - <> - -
this.setState({ optionsOpen: !this.state.optionsOpen })} - className="TopButton" - > - settings -
+ return ( + <> + +
(state.optionsOpen = !state.optionsOpen)} + class="TopButton"> + settings +
+
(state.downloadsOpen = !state.downloadsOpen)}> + downloads +
+
this.setState({ downloadsOpen: !this.state.downloadsOpen })} - > - downloads + id="modsBtn" + onClick={() => { + // Create and dispatch a custom "openMods" event + const event = new CustomEvent('changePage', { + detail: 'modding', + }); + window.dispatchEvent(event); + }} + class="TopButton"> + mods
- {this.state.migotoSet && ( -
{ - // Create and dispatch a custom "openMods" event - const event = new CustomEvent('changePage', { detail: 'modding' }) - window.dispatchEvent(event) - }} - className="TopButton" - > - mods -
- )} - {/*
this.setState({ gameDownloadsOpen: !this.state.gameDownloadsOpen })}> + + {/*
this.setState({ gameDownloadsOpen: !this.state.gameDownloadsOpen })}> game
*/} - - - - - - - { - // Extras section - this.state.extrasOpen && ( - this.setState({ extrasOpen: false })} playGame={this.state.playGame}> - Yo - - ) - } - - { - // Mini downloads section - this.state.miniDownloadsOpen ? ( -
- { - this.setState({ miniDownloadsOpen: false }) - }} - > - - -
-
- ) : null - } - - { - // Download menu - this.state.downloadsOpen ? ( - this.setState({ downloadsOpen: false })} - /> - ) : null - } - - { - // Options menu - this.state.optionsOpen ? ( - this.setState({ optionsOpen: !this.state.optionsOpen })} - /> - ) : null - } - - { - // Game downloads menu - this.state.gameDownloadsOpen ? ( - this.setState({ gameDownloadsOpen: false })} - /> - ) : null - } - -
- - -
this.setState({ miniDownloadsOpen: !this.state.miniDownloadsOpen })} - > - {this.state.isDownloading ? : null} -
+ + + + + + + + (state.extrasOpen = false)} + playGame={state.playGame}> + Yo + + + + +
+ (state.miniDownloadsOpen = false)}> + + +
- - ) - } + + + + (state.downloadsOpen = false)} + /> + + + + (state.optionsOpen = !state.optionsOpen)} + downloadManager={props.downloadHandler} + /> + + + + (state.gameDownloadsOpen = false)} + /> + + +
+ +
(state.miniDownloadsOpen = !state.miniDownloadsOpen)}> + + + +
+
+ + ); } diff --git a/src/ui/Mods.tsx b/src/ui/Mods.tsx index 3129ebc8..195a2643 100644 --- a/src/ui/Mods.tsx +++ b/src/ui/Mods.tsx @@ -1,28 +1,23 @@ -import { invoke } from '@tauri-apps/api' -import React from 'react' -import DownloadHandler from '../utils/download' -import { getModDownload, ModData } from '../utils/gamebanana' -import { getModsFolder } from '../utils/mods' -import { unzip } from '../utils/zipUtils' -import ProgressBar from './components/common/MainProgressBar' -import { ModHeader } from './components/mods/ModHeader' -import { ModList } from './components/mods/ModList' -import TopBar from './components/TopBar' - -import './Mods.css' -import Back from '../resources/icons/back.svg' -import Menu from './components/menu/Menu' -import BigButton from './components/common/BigButton' -import Tr from '../utils/language' +import { createSignal, For, Show } from 'solid-js'; +import { invoke } from '@tauri-apps/api'; + +import Back from '../resources/icons/back.svg'; +import DownloadHandler from '../utils/download'; +import { getModDownload, ModData } from '../utils/gamebanana'; +import Tr from '../utils/language'; +import { getModsFolder } from '../utils/mods'; +import { unzip } from '../utils/zipUtils'; +import BigButton from './components/common/BigButton'; +import ProgressBar from './components/common/MainProgressBar'; +import Menu from './components/menu/Menu'; +import { ModHeader } from './components/mods/ModHeader'; +import { ModList } from './components/mods/ModList'; +import TopBar from './components/TopBar'; + +import './Mods.css'; interface IProps { - downloadHandler: DownloadHandler -} - -interface IState { - isDownloading: boolean - category: string - downloadList: { name: string; url: string; mod: ModData }[] | null + downloadHandler: DownloadHandler; } const headers = [ @@ -38,132 +33,121 @@ const headers = [ name: 'installed', title: 'Installed', }, -] +]; /** * Mods currently install into folder labelled with their GB ID * * @TODO Categorizaiton/sorting (by likes, views, etc) */ -export class Mods extends React.Component { - constructor(props: IProps) { - super(props) - - this.state = { - isDownloading: false, - category: '', - downloadList: null, - } - - this.setCategory = this.setCategory.bind(this) - this.addDownload = this.addDownload.bind(this) - } +export function Mods(props: IProps) { + const [category, setCategory] = createSignal(''); + const [downloadList, setDownloadList] = createSignal< + { name: string; url: string; mod: ModData }[] | null + >(null); - async addDownload(mod: ModData) { - const dlLinks = await getModDownload(String(mod.id)) + async function addDownload(mod: ModData) { + const dlLinks = await getModDownload(String(mod.id)); // Not gonna bother allowing sorting for now - const firstLink = dlLinks[0].downloadUrl - const fileExt = firstLink.split('.').pop() + const firstLink = dlLinks[0].downloadUrl; + const fileExt = firstLink.split('.').pop(); - const modName = `${mod.id}.${fileExt}` + const modName = `${mod.id}.${fileExt}`; - if (dlLinks.length === 0) return + if (dlLinks.length === 0) return; // If there is one download we don't care to choose if (dlLinks.length === 1) { - this.downloadMod(firstLink, modName, mod) - return + downloadMod(firstLink, modName, mod); + return; } - this.setState({ - downloadList: dlLinks.map((link) => ({ + setDownloadList( + dlLinks.map((link) => ({ name: link.filename, url: link.downloadUrl, - mod: mod, - })), - }) + mod, + })) + ); } - async downloadMod(link: string, modName: string, mod: ModData) { - const modFolder = await getModsFolder() - const path = `${modFolder}/${modName}` + async function downloadMod(link: string, modName: string, mod: ModData) { + const modFolder = await getModsFolder(); + const path = `${modFolder}/${modName}`; - if (!modFolder) return + if (!modFolder) return; - this.props.downloadHandler.addDownload(link, path, async () => { - const unzipRes = await unzip(path, modFolder, false, true) + props.downloadHandler.addDownload(link, path, async () => { + const unzipRes = await unzip(path, modFolder, false, true); // Write a modinfo.json file invoke('write_file', { path: `${unzipRes.new_folder}/modinfo.json`, contents: JSON.stringify(mod), - }) - }) - } - - async setCategory(value: string) { - this.setState( - { - category: value, - }, - this.forceUpdate - ) + }); + }); } - render() { - return ( -
- -
{ - // Create and dispatch a custom "changePage" event - const event = new CustomEvent('changePage', { detail: 'main' }) - window.dispatchEvent(event) - }} - > - back -
-
- - {this.state.downloadList && ( - this.setState({ downloadList: null })}> -
- {this.state.downloadList.map((o) => { + return ( +
+ +
{ + // Create and dispatch a custom "changePage" event + const event = new CustomEvent('changePage', { detail: 'main' }); + window.dispatchEvent(event); + }}> + back +
+
+ + + setDownloadList(null)}> +
+ + {(o) => { return ( -
-
{o.name}
+
+
{o.name}
{ - const fileExt = o.url.split('.').pop() - const modName = `${o.mod.id}.${fileExt}` - - this.downloadMod(o.url, modName, o.mod) - this.setState({ - downloadList: null, - }) - }} - > + const fileExt = o.url.split('.').pop(); + const modName = `${o.mod.id}.${fileExt}`; + + downloadMod(o.url, modName, o.mod); + setDownloadList(null); + }}>
- ) - })} -
-
- )} - -
- -
+ ); + }} + +
+
+ + +
+ +
- + - -
- ) - } + +
+ ); } diff --git a/src/ui/components/MiniDialog.tsx b/src/ui/components/MiniDialog.tsx index c27089d5..d5236ed3 100644 --- a/src/ui/components/MiniDialog.tsx +++ b/src/ui/components/MiniDialog.tsx @@ -1,49 +1,47 @@ -import React from 'react' +import { JSX, onCleanup, onMount, Show } from 'solid-js'; -import Close from '../../resources/icons/close.svg' -import './MiniDialog.css' +import Close from '../../resources/icons/close.svg'; + +import './MiniDialog.css'; interface IProps { - children: React.ReactNode[] | React.ReactNode - title?: string - closeable?: boolean - closeFn: () => void + children: JSX.Element; + title?: string; + closeable?: boolean; + closeFn: () => void; } -export default class MiniDialog extends React.Component { - constructor(props: IProps) { - super(props) - } - - componentDidMount() { - document.addEventListener('mousedown', (evt) => { - const tgt = evt.target as HTMLElement - const isInside = tgt.closest('.MiniDialog') !== null +export default function MiniDialog(props: IProps) { + function mouseDownHandler(evt: MouseEvent) { + const tgt = evt.target as HTMLElement; + const isInside = tgt.closest('.MiniDialog') !== null; - if (!isInside) { - this.props.closeFn() - } - }) + if (!isInside) { + props.closeFn(); + } } - componentWillUnmount() { - document.removeEventListener('mousedown', this.props.closeFn) - } - - render() { - return ( -
- {this.props.closeable !== undefined && this.props.closeable ? ( -
- {this.props?.title} - -
- ) : null} - -
- {this.props.children} + onMount(() => document.addEventListener('mousedown', mouseDownHandler)); + + onCleanup(() => document.removeEventListener('mousedown', mouseDownHandler)); + + return ( +
+ +
+ {props?.title} +
+
+ +
+ {props.children}
- ) - } +
+ ); } diff --git a/src/ui/components/RightBar.tsx b/src/ui/components/RightBar.tsx index 456fde40..c3154b81 100644 --- a/src/ui/components/RightBar.tsx +++ b/src/ui/components/RightBar.tsx @@ -1,31 +1,34 @@ -import { invoke } from '@tauri-apps/api' -import React from 'react' +import { invoke } from '@tauri-apps/api'; -import Discord from '../../resources/icons/discord.svg' -import Github from '../../resources/icons/github.svg' +import Discord from '../../resources/icons/discord.svg'; +import Github from '../../resources/icons/github.svg'; -import './RightBar.css' +import './RightBar.css'; -const DISCORD = 'https://discord.gg/T5vZU6UyeG' -const GITHUB = 'https://github.com/Grasscutters/Grasscutter' +const DISCORD = 'https://discord.gg/T5vZU6UyeG'; +const GITHUB = 'https://github.com/Grasscutters/Grasscutter'; -export default class RightBar extends React.Component { - openInBrowser(url: string) { - invoke('open_in_browser', { url }) +export default function RightBar() { + function openInBrowser(url: string) { + invoke('open_in_browser', { url }); } - render() { - return ( -
-
-
this.openInBrowser(DISCORD)}> - -
-
this.openInBrowser(GITHUB)}> - -
+ return ( +
+
+
openInBrowser(DISCORD)}> + +
+
openInBrowser(GITHUB)}> +
- ) - } +
+ ); } diff --git a/src/ui/components/ServerLaunchSection.tsx b/src/ui/components/ServerLaunchSection.tsx index 984c26f8..a0a6d3fb 100644 --- a/src/ui/components/ServerLaunchSection.tsx +++ b/src/ui/components/ServerLaunchSection.tsx @@ -1,75 +1,70 @@ -import React from 'react' -import Checkbox from './common/Checkbox' -import BigButton from './common/BigButton' -import TextInput from './common/TextInput' -import HelpButton from './common/HelpButton' -import { getConfig, saveConfig, setConfigOption } from '../../utils/configuration' -import { translate } from '../../utils/language' -import { invoke } from '@tauri-apps/api/tauri' - -import Server from '../../resources/icons/server.svg' -import Plus from '../../resources/icons/plus.svg' - -import './ServerLaunchSection.css' -import { dataDir } from '@tauri-apps/api/path' -import { getGameExecutable, getGameVersion } from '../../utils/game' -import { patchGame, unpatchGame } from '../../utils/metadata' +import { onMount, Show } from 'solid-js'; +import { createStore } from 'solid-js/store'; +import { dataDir } from '@tauri-apps/api/path'; +import { invoke } from '@tauri-apps/api/tauri'; + +import Plus from '../../resources/icons/plus.svg'; +import Server from '../../resources/icons/server.svg'; +import { + getConfig, + saveConfig, + setConfigOption, +} from '../../utils/configuration'; +import { getGameExecutable, getGameVersion } from '../../utils/game'; +import { translate } from '../../utils/language'; +import { patchGame, unpatchGame } from '../../utils/metadata'; +import BigButton from './common/BigButton'; +import Checkbox from './common/Checkbox'; +import HelpButton from './common/HelpButton'; +import TextInput from './common/TextInput'; + +import './ServerLaunchSection.css'; interface IProps { - openExtras: (playGame: () => void) => void + openExtras: (playGame: () => void) => void; } interface IState { - grasscutterEnabled: boolean - buttonLabel: string - checkboxLabel: string - ip: string - port: string + grasscutterEnabled: boolean; + buttonLabel: string; + checkboxLabel: string; + ip: string; + port: string; - ipPlaceholder: string - portPlaceholder: string + ipPlaceholder: string; + portPlaceholder: string; - portHelpText: string + portHelpText: string; - httpsLabel: string - httpsEnabled: boolean + httpsLabel: string; + httpsEnabled: boolean; - swag: boolean - akebiSet: boolean - migotoSet: boolean + swag: boolean; + akebiSet: boolean; + migotoSet: boolean; } -export default class ServerLaunchSection extends React.Component { - constructor(props: IProps) { - super(props) - - this.state = { - grasscutterEnabled: false, - buttonLabel: '', - checkboxLabel: '', - ip: '', - port: '', - ipPlaceholder: '', - portPlaceholder: '', - portHelpText: '', - httpsLabel: '', - httpsEnabled: false, - swag: false, - akebiSet: false, - migotoSet: false, - } - - this.toggleGrasscutter = this.toggleGrasscutter.bind(this) - this.playGame = this.playGame.bind(this) - this.setIp = this.setIp.bind(this) - this.setPort = this.setPort.bind(this) - this.toggleHttps = this.toggleHttps.bind(this) - } - - async componentDidMount() { - const config = await getConfig() - - this.setState({ +export default function ServerLaunchSection(props: IProps) { + const [state, setState] = createStore({ + grasscutterEnabled: false, + buttonLabel: '', + checkboxLabel: '', + ip: '', + port: '', + ipPlaceholder: '', + portPlaceholder: '', + portHelpText: '', + httpsLabel: '', + httpsEnabled: false, + swag: false, + akebiSet: false, + migotoSet: false, + }); + + onMount(async () => { + const config = await getConfig(); + + setState({ grasscutterEnabled: config.toggle_grasscutter || false, buttonLabel: await translate('main.launch_button'), checkboxLabel: await translate('main.gc_enable'), @@ -83,105 +78,117 @@ export default class ServerLaunchSection extends React.Component swag: config.swag_mode || false, akebiSet: config.akebi_path !== '', migotoSet: config.migoto_path !== '', - }) - } + }); + }); - async toggleGrasscutter() { - const config = await getConfig() + async function toggleGrasscutter() { + const config = await getConfig(); - config.toggle_grasscutter = !config.toggle_grasscutter + config.toggle_grasscutter = !config.toggle_grasscutter; // Set state as well - this.setState({ - grasscutterEnabled: config.toggle_grasscutter, - }) + setState('grasscutterEnabled', config.toggle_grasscutter); - await saveConfig(config) + await saveConfig(config); } - async playGame(exe?: string, proc_name?: string) { - const config = await getConfig() + async function playGame(exe?: string, proc_name?: string) { + const config = await getConfig(); if (!(await getGameExecutable())) { - alert('Game executable not set!') - return + alert('Game executable not set!'); + return; } // Connect to proxy if (config.toggle_grasscutter) { if (config.patch_metadata) { - const gameVersion = await getGameVersion() - console.log(gameVersion) + const gameVersion = await getGameVersion(); + console.log(gameVersion); if (gameVersion == null) { alert( 'Game version could not be determined. Please make sure you have the game correctly selected and try again.' - ) - return + ); + return; } - if (gameVersion?.major == 2 && gameVersion?.minor < 8) { + if (gameVersion?.major === 2 && gameVersion?.minor < 8) { alert( 'Game version is too old for metadata patching. Please disable metadata patching in the settings and try again.' - ) - return + ); + return; } - if (gameVersion?.major == 3 && gameVersion?.minor >= 1) { + if (gameVersion?.major === 3 && gameVersion?.minor >= 1) { alert( - 'Game version is too new for metadata patching. Please disable metadata patching in the settings to launch the game.\nNOTE: You will require a UA patch to play the game.' - ) - return + 'Game version is too new for metadata patching. ' + + 'Please disable metadata patching in the settings' + + ' to launch the game.\nNOTE: ' + + 'You will require a UA patch to play the game.' + ); + return; } - const patched = await patchGame() + const patched = await patchGame(); if (!patched) { - alert('Could not patch game!') - return + alert('Could not patch game!'); + return; } } - const game_exe = await getGameExecutable() + const game_exe = await getGameExecutable(); // Save last connected server and port - await setConfigOption('last_ip', this.state.ip) - await setConfigOption('last_port', this.state.port) + // TODO[perf]: could be batched + await setConfigOption('last_ip', state.ip); + await setConfigOption('last_port', state.port); await invoke('enable_process_watcher', { process: proc_name || game_exe, - }) + }); if (config.use_internal_proxy) { // Set IP await invoke('set_proxy_addr', { - addr: (this.state.httpsEnabled ? 'https' : 'http') + '://' + this.state.ip + ':' + this.state.port, - }) + addr: + (state.httpsEnabled ? 'https' : 'http') + + '://' + + state.ip + + ':' + + state.port, + }); // Connect to proxy - await invoke('connect', { port: 8365, certificatePath: (await dataDir()) + '\\cultivation\\ca' }) + await invoke('connect', { + port: 8365, + certificatePath: (await dataDir()) + '\\cultivation\\ca', + }); } // Open server as well if the options are set if (config.grasscutter_with_game) { - const jarFolderArr = config.grasscutter_path.replace(/\\/g, '/').split('/') - jarFolderArr.pop() + const jarFolderArr = config.grasscutter_path + .replace(/\\/g, '/') + .split('/'); + jarFolderArr.pop(); - const jarFolder = jarFolderArr.join('/') + const jarFolder = jarFolderArr.join('/'); await invoke('run_jar', { path: config.grasscutter_path, executeIn: jarFolder, javaPath: config.java_path || '', - }) + }); } } else { - const unpatched = await unpatchGame() + const unpatched = await unpatchGame(); if (!unpatched) { alert( `Could not unpatch game, aborting launch! (You can find your metadata backup in ${await dataDir()}\\cultivation\\)` - ) - return + ); + return; } } @@ -189,30 +196,42 @@ export default class ServerLaunchSection extends React.Component // First wipe registry if we have to await invoke('wipe_registry', { // The exe is always PascalCase so we can get the dir using regex - execName: (await getGameExecutable())?.split('.exe')[0].replace(/([a-z\d])([A-Z])/g, '$1 $2'), - }) + execName: (await getGameExecutable()) + ?.split('.exe')[0] + .replace(/([a-z\d])([A-Z])/g, '$1 $2'), + }); } // Launch the program const gameExists = await invoke('dir_exists', { path: exe || config.game_install_path, - }) + }); - if (gameExists) await invoke('run_program_relative', { path: exe || config.game_install_path }) - else alert('Game not found! At: ' + (exe || config.game_install_path)) + if (gameExists) + await invoke('run_program_relative', { + path: exe || config.game_install_path, + }); + else alert('Game not found! At: ' + (exe || config.game_install_path)); } - async launchServer() { - const config = await getConfig() + async function launchServer() { + const config = await getConfig(); - if (!config.grasscutter_path) return alert('Grasscutter not installed or set!') + if (!config.grasscutter_path) + return alert('Grasscutter not installed or set!'); - let jarFolder = config.grasscutter_path + let jarFolder = config.grasscutter_path; if (jarFolder.includes('/')) { - jarFolder = jarFolder.substring(0, config.grasscutter_path.lastIndexOf('/')) + jarFolder = jarFolder.substring( + 0, + config.grasscutter_path.lastIndexOf('/') + ); } else { - jarFolder = jarFolder.substring(0, config.grasscutter_path.lastIndexOf('\\')) + jarFolder = jarFolder.substring( + 0, + config.grasscutter_path.lastIndexOf('\\') + ); } // Launch the jar @@ -220,91 +239,83 @@ export default class ServerLaunchSection extends React.Component path: config.grasscutter_path, executeIn: jarFolder, javaPath: config.java_path || '', - }) + }); } - setIp(text: string) { - this.setState({ - ip: text, - }) + function setIp(text: string) { + setState('ip', text); } - setPort(text: string) { - this.setState({ - port: text, - }) + function setPort(text: string) { + setState('port', text); } - async toggleHttps() { - const config = await getConfig() + async function toggleHttps() { + const config = await getConfig(); - config.https_enabled = !config.https_enabled + config.https_enabled = !config.https_enabled; // Set state as well - this.setState({ - httpsEnabled: config.https_enabled, - }) + setState('httpsEnabled', config.https_enabled); - await saveConfig(config) + await saveConfig(config); } - render() { - return ( -
-
- -
+ return ( +
+
+ +
- {this.state.grasscutterEnabled && ( -
-
- - - - -
+ +
+
+ + + +
- )} - -
- - {this.state.buttonLabel} - - {this.state.swag && ( - this.props.openExtras(this.playGame)} id="ExtrasMenuButton"> - - - )} - - -
+ + +
+ + {state.buttonLabel} + + + props.openExtras(playGame)} + id="ExtrasMenuButton"> + + + + + +
- ) - } +
+ ); } diff --git a/src/ui/components/TopBar.tsx b/src/ui/components/TopBar.tsx index 42edddd0..2e38e35b 100644 --- a/src/ui/components/TopBar.tsx +++ b/src/ui/components/TopBar.tsx @@ -1,113 +1,103 @@ -import React from 'react' -import { app } from '@tauri-apps/api' -import { appWindow } from '@tauri-apps/api/window' -import { getConfig, setConfigOption } from '../../utils/configuration' -import Tr from '../../utils/language' +import { batch, createSignal, JSX, onCleanup, onMount } from 'solid-js'; +import { app } from '@tauri-apps/api'; +import { appWindow } from '@tauri-apps/api/window'; -import './TopBar.css' -import closeIcon from '../../resources/icons/close.svg' -import minIcon from '../../resources/icons/min.svg' +import closeIcon from '../../resources/icons/close.svg'; +import minIcon from '../../resources/icons/min.svg'; +import { getConfig, setConfigOption } from '../../utils/configuration'; +import Tr from '../../utils/language'; -interface IProps { - children?: React.ReactNode | React.ReactNode[] -} +import './TopBar.css'; -interface IState { - version: string - clicks: number - intv: NodeJS.Timeout | null +interface IProps { + children?: JSX.Element; } -export default class TopBar extends React.Component { - constructor(props: IProps) { - super(props) +export default function TopBar(props: IProps) { + const [version, setVersion] = createSignal('0.0.0'); + const [clicks, setClicks] = createSignal(0); + const [intv, setIntv] = createSignal(null); - this.state = { - version: '0.0.0', - clicks: 0, - intv: null, - } + onMount(async () => { + const version = await app.getVersion(); + setVersion(version); + }); - this.activateClick = this.activateClick.bind(this) - } + onCleanup(() => { + const handle = intv(); - async componentDidMount() { - const version = await app.getVersion() - this.setState({ version }) - } + handle && clearTimeout(handle); + }); - handleClose() { - appWindow.close() + function handleClose() { + appWindow.close(); } - handleMinimize() { - appWindow.minimize() + function handleMinimize() { + appWindow.minimize(); } - async activateClick() { - const config = await getConfig() + async function activateClick() { + const config = await getConfig(); // They already got it, no need to reactivate - if (config.swag_mode) return + if (config.swag_mode) return; - if (this.state.clicks === 2) { + if (clicks() === 2) { setTimeout(() => { - // Gotta clear it so it goes back to regular colors - this.setState({ - clicks: 0, - }) - }, 600) + // Have got to clear it, so it goes back to regular colors + setClicks(0); + }, 600); // Activate... SWAG MODE - await setConfigOption('swag_mode', true) + await setConfigOption('swag_mode', true); // Reload the window - window.location.reload() + window.location.reload(); - return + return; } - if (this.state.clicks < 3) { - this.setState({ - clicks: this.state.clicks + 1, - intv: setTimeout(() => this.setState({ clicks: 0 }), 1500), - }) - - return + if (clicks() < 3) { + batch(() => { + setClicks((clicks) => clicks + 1); + setIntv(window.setTimeout(() => setClicks(0), 1500)); + }); } } - render() { - return ( -
-
- - - - - {this.state?.version} - -
- {/** - * HEY YOU - * - * If you're looking at the source code to find the swag mode thing, that's okay! If you're not, move along... - * Just do me a favor and don't go telling everyone about how you found it. If you are just helping someone who - * for some reason needs it, that's fine, but not EVERYONE needs it, which is why it exists in the first place. - */} -
- ? + return ( +
+
+ + + + + {version()} + +
+ {/** + * HEY YOU + * + * If you're looking at the source code to find the swag mode thing, that's okay! If you're not, move along... + * Just do me a favor and don't go telling everyone about how you found it. If you are just helping someone who + * for some reason needs it, that's fine, but not EVERYONE needs it, which is why it exists in the first place. + */} +
+ ? +
+
+
+ close
-
-
- close -
-
- minimize -
- {this.props.children} +
+ minimize
+ {props.children}
- ) - } +
+ ); } diff --git a/src/ui/components/common/BigButton.tsx b/src/ui/components/common/BigButton.tsx index 6fa10bd4..fc1f860a 100644 --- a/src/ui/components/common/BigButton.tsx +++ b/src/ui/components/common/BigButton.tsx @@ -1,49 +1,33 @@ -import React from 'react' -import './BigButton.css' +import { JSX } from 'solid-js'; +import cc from 'classcat'; -interface IProps { - children: React.ReactNode - onClick: () => unknown - id: string - disabled?: boolean -} +import './BigButton.css'; -interface IState { - disabled?: boolean +interface IProps { + children: JSX.Element; + onClick: () => unknown; + id: string; + disabled?: boolean; } -export default class BigButton extends React.Component { - constructor(props: IProps) { - super(props) - - this.state = { - disabled: this.props.disabled, - } - - this.handleClick = this.handleClick.bind(this) - } +export default function BigButton(props: IProps) { + function handleClick() { + if (props.disabled) return; - static getDerivedStateFromProps(props: IProps, _state: IState) { - return { - disabled: props.disabled, - } + props.onClick(); } - handleClick() { - if (this.state.disabled) return - - this.props.onClick() - } - - render() { - return ( -
-
{this.props.children}
-
- ) - } + return ( +
+
{props.children}
+
+ ); } diff --git a/src/ui/components/common/Checkbox.tsx b/src/ui/components/common/Checkbox.tsx index c3b938ee..75cfee97 100644 --- a/src/ui/components/common/Checkbox.tsx +++ b/src/ui/components/common/Checkbox.tsx @@ -1,52 +1,44 @@ -import React from 'react' -import checkmark from '../../../resources/icons/check.svg' +import { createEffect, createSignal, Show } from 'solid-js'; -import './Checkbox.css' +import checkmark from '../../../resources/icons/check.svg'; -interface IProps { - label?: string - checked: boolean - onChange: () => void - id?: string -} +import './Checkbox.css'; -interface IState { - checked: boolean +interface IProps { + label?: string; + checked: boolean; + onChange: () => void; + id?: string; } -export default class Checkbox extends React.Component { - constructor(props: IProps) { - super(props) - - this.state = { - checked: props.checked, - } - } - - static getDerivedStateFromProps(props: IProps, state: IState) { - if (props.checked !== state.checked) { - return { - checked: props.checked, - } - } +export default function Checkbox(props: IProps) { + const [checked, setChecked] = createSignal(props.checked); - return { checked: props.checked } - } + createEffect(() => { + if (props.checked !== checked()) setChecked(props.checked); + }); - handleChange = () => { - this.setState({ checked: !this.state.checked }) - this.props.onChange() + function handleChange() { + setChecked((c) => !c); + props.onChange(); } - render() { - return ( -
- - -
- ) - } + return ( +
+ + +
+ ); } diff --git a/src/ui/components/common/DirInput.tsx b/src/ui/components/common/DirInput.tsx index 1bcbc519..c9a9b1ab 100644 --- a/src/ui/components/common/DirInput.tsx +++ b/src/ui/components/common/DirInput.tsx @@ -1,109 +1,85 @@ -import React from 'react' -import { open } from '@tauri-apps/api/dialog' -import { translate } from '../../../utils/language' -import TextInput from './TextInput' -import File from '../../../resources/icons/folder.svg' +import { createEffect, createSignal, onMount } from 'solid-js'; +import { open } from '@tauri-apps/api/dialog'; -import './DirInput.css' +import File from '../../../resources/icons/folder.svg'; +import { translate } from '../../../utils/language'; +import TextInput from './TextInput'; -interface IProps { - value?: string - clearable?: boolean - onChange?: (value: string) => void - extensions?: string[] - readonly?: boolean - placeholder?: string - folder?: boolean - customClearBehaviour?: () => void - openFolder?: string -} +import './DirInput.css'; -interface IState { - value: string - placeholder: string - folder: boolean +interface IProps { + value?: string; + clearable?: boolean; + onChange?: (value: string) => void; + extensions?: string[]; + readonly?: boolean; + placeholder?: string; + folder?: boolean; + customClearBehaviour?: () => void; + openFolder?: string; } -export default class DirInput extends React.Component { - constructor(props: IProps) { - super(props) - - this.state = { - value: props.value || '', - placeholder: this.props.placeholder || 'Select file or folder...', - folder: this.props.folder || false, - } - - this.handleIconClick = this.handleIconClick.bind(this) - } - - static getDerivedStateFromProps(props: IProps, state: IState) { - const newState = state - - if (props.value && state.value === '') { - newState.value = props.value || '' +export default function DirInput(props: IProps) { + const [value, setValue] = createSignal(props.value); + const [placeholder, setPlaceholder] = createSignal( + props.placeholder || 'Select file or folder...' + ); + const [folder, _setFolder] = createSignal(props.folder || false); + + createEffect(() => { + if (props.value && value() === '') setValue(props.value || ''); + }); + + createEffect(() => { + if (props.placeholder) setPlaceholder(props.placeholder); + }); + + onMount(async () => { + if (!props.placeholder) { + const translation = await translate('components.select_file'); + setPlaceholder(translation); } + }); - if (props.placeholder) { - newState.placeholder = props.placeholder - } - - return newState - } + async function handleIconClick() { + let path; - async componentDidMount() { - if (!this.props.placeholder) { - const translation = await translate('components.select_file') - this.setState({ - placeholder: translation, - }) - } - } - - async handleIconClick() { - let path - - if (this.state.folder) { + if (folder()) { path = await open({ directory: true, - }) + }); } else { path = await open({ - filters: [{ name: 'Files', extensions: this.props.extensions || ['*'] }], - defaultPath: this.props.openFolder, - }) + filters: [{ name: 'Files', extensions: props.extensions || ['*'] }], + defaultPath: props.openFolder, + }); } - if (Array.isArray(path)) path = path[0] - if (!path) return + if (Array.isArray(path)) path = path[0]; + if (!path) return; - this.setState({ - value: path, - }) + setValue(path); - if (this.props.onChange) this.props.onChange(path) + if (props.onChange) props.onChange(path); } - render() { - return ( -
- { - this.setState({ value: text }) - - if (this.props.onChange) this.props.onChange(text) - this.forceUpdate() - }} - customClearBehaviour={this.props.customClearBehaviour} - /> -
- -
+ return ( +
+ { + setValue(text); + + props.onChange?.(text); + }} + customClearBehaviour={props.customClearBehaviour} + /> +
+
- ) - } +
+ ); } diff --git a/src/ui/components/common/DownloadList.tsx b/src/ui/components/common/DownloadList.tsx index 6bbd9065..19a83bfe 100644 --- a/src/ui/components/common/DownloadList.tsx +++ b/src/ui/components/common/DownloadList.tsx @@ -1,29 +1,31 @@ -import React from 'react' -import DownloadHandler from '../../../utils/download' -import DownloadSection from './DownloadSection' +import { createMemo, For, Show } from 'solid-js'; -import './DownloadList.css' +import DownloadHandler from '../../../utils/download'; +import DownloadSection from './DownloadSection'; + +import './DownloadList.css'; interface IProps { - downloadManager: DownloadHandler + downloadManager: DownloadHandler; } -export default class DownloadList extends React.Component { - constructor(props: IProps) { - super(props) - } - - render() { - const list = this.props.downloadManager.getDownloads().map((download) => { - return ( - - ) - }) - - return
{list.length > 0 ? list : 'No downloads present'}
- } +export default function DownloadList(props: IProps) { + const list = createMemo(() => props.downloadManager.getDownloads()); + return ( +
+ 0} + keyed={false} + fallback="No downloads present"> + + {(download) => ( + + )} + + +
+ ); } diff --git a/src/ui/components/common/DownloadSection.tsx b/src/ui/components/common/DownloadSection.tsx index 0b9b4ac7..bfe39dd4 100644 --- a/src/ui/components/common/DownloadSection.tsx +++ b/src/ui/components/common/DownloadSection.tsx @@ -1,35 +1,34 @@ -import React from 'react' -import DownloadHandler from '../../../utils/download' -import ProgressBar from './ProgressBar' +import DownloadHandler from '../../../utils/download'; +import ProgressBar from './ProgressBar'; -import './DownloadSection.css' +import './DownloadSection.css'; interface IProps { - downloadManager: DownloadHandler - downloadName: string + downloadManager: DownloadHandler; + downloadName: string; } -export default class DownloadSection extends React.Component { - constructor(props: IProps) { - super(props) +export default function DownloadSection(props: IProps) { + function getFilenameFromPath() { + const name = props.downloadName.replace(/\\/g, '/'); + return name.split('/').pop(); } - getFilenameFromPath() { - const name = this.props.downloadName.replace(/\\/g, '/') - return name.split('/').pop() - } - - render() { - return ( -
-
-
{this.getFilenameFromPath()}
-
- {this.props.downloadManager.getDownloadSize(this.props.downloadName)}
-
-
- + return ( +
+
+
{getFilenameFromPath()}
+
+ {' '} + - {props.downloadManager.getDownloadSize(props.downloadName)}
- ) - } +
+ +
+
+ ); } diff --git a/src/ui/components/common/HelpButton.tsx b/src/ui/components/common/HelpButton.tsx index fb388e7f..686b43b5 100644 --- a/src/ui/components/common/HelpButton.tsx +++ b/src/ui/components/common/HelpButton.tsx @@ -1,33 +1,26 @@ -import React from 'react' +import { JSX } from 'solid-js'; -import './HelpButton.css' -import Help from '../../../resources/icons/help.svg' -import { translate } from '../../../utils/language' +import Help from '../../../resources/icons/help.svg'; +import { translate } from '../../../utils/language'; + +import './HelpButton.css'; interface IProps { - children?: React.ReactNode[] | React.ReactNode - contents?: string - id?: string + children?: JSX.Element; + contents?: string; + id?: string; } -export default class HelpButton extends React.Component { - constructor(props: IProps) { - super(props) - - this.showAlert = this.showAlert.bind(this) +export default function HelpButton(props: IProps) { + async function showAlert() { + if (props.contents) alert(await translate(props.contents)); } - async showAlert() { - if (this.props.contents) alert(await translate(this.props.contents)) - } - - render() { - return ( -
-
- -
+ return ( +
+
+
- ) - } +
+ ); } diff --git a/src/ui/components/common/MainProgressBar.tsx b/src/ui/components/common/MainProgressBar.tsx index 27e3df06..7857d908 100644 --- a/src/ui/components/common/MainProgressBar.tsx +++ b/src/ui/components/common/MainProgressBar.tsx @@ -1,84 +1,83 @@ -import React from 'react' -import DownloadHandler from '../../../utils/download' -import Tr from '../../../utils/language' -import './ProgressBar.css' +import { onCleanup, Show } from 'solid-js'; +import { createStore } from 'solid-js/store'; + +import DownloadHandler from '../../../utils/download'; +import Tr from '../../../utils/language'; + +import './ProgressBar.css'; interface IProps { - downloadManager: DownloadHandler - withStats?: boolean + downloadManager: DownloadHandler; + withStats?: boolean; } interface IState { - average: number - files: number - extracting: number - total: number - speed: string + average: number; + files: number; + extracting: number; + total: number; + speed: string; } /** * This component differes because it averages all downloads together */ -export default class ProgressBar extends React.Component { - constructor(props: IProps) { - super(props) - - const { average, files, extracting, totalSize } = this.props.downloadManager.getTotalAverage() +export default function ProgressBar(props: IProps) { + const { average, files, extracting, totalSize } = + props.downloadManager.getTotalAverage(); - this.state = { - average, - files, - extracting, - total: totalSize, - speed: '0 B/s', - } - } + const [state, setState] = createStore({ + average, + files, + extracting, + total: totalSize, + speed: '0 B/s', + }); - componentDidMount() { - // Periodically check the progress of passed file path - setInterval(() => { - const prog = this.props.downloadManager.getTotalAverage() - this.setState({ - average: prog?.average || 0, - files: prog?.files, - extracting: prog?.extracting, - total: prog?.totalSize || 0, - speed: prog?.speed || '0 B/s', - }) - }, 200) - } + const interval = window.setInterval(() => { + const prog = props.downloadManager.getTotalAverage(); + setState({ + average: prog?.average || 0, + files: prog?.files, + extracting: prog?.extracting, + total: prog?.totalSize || 0, + speed: prog?.speed || '0 B/s', + }); + }, 200); - render() { - return ( -
-
-
{ - // Handles no files downloading - if (this.state.files === 0 || this.state.average >= 100) { - return '100' - } + onCleanup(() => window.clearInterval(interval)); - if (this.state.total <= 0) { - return '0' - } + return ( +
+
+
{ + // Handles no files downloading + if (state.files === 0 || state.average >= 100) { + return '100'; + } - return this.state.average - })()}%`, - }} - >
-
+ if (state.total <= 0) { + return '0'; + } - {(this.props.withStats === undefined || this.props.withStats) && ( -
- {this.state.files} ({this.state.speed}) -
- {this.state.extracting} -
- )} + return state.average; + })()}%`, + }} + />
- ) - } + + +
+ {state.files} ({state.speed}) +
+ {state.extracting} +
+
+
+ ); } diff --git a/src/ui/components/common/ProgressBar.tsx b/src/ui/components/common/ProgressBar.tsx index 650dd22c..9d1384c8 100644 --- a/src/ui/components/common/ProgressBar.tsx +++ b/src/ui/components/common/ProgressBar.tsx @@ -1,92 +1,88 @@ -import React from 'react' -import { capitalize } from '../../../utils/string' +import { createStore } from 'solid-js/store'; +import { makeTimer } from '@solid-primitives/timer'; -import Stop from '../../../resources/icons/close.svg' -import './ProgressBar.css' -import DownloadHandler from '../../../utils/download' -import { translate } from '../../../utils/language' +import Stop from '../../../resources/icons/close.svg'; +import DownloadHandler from '../../../utils/download'; +import { translate } from '../../../utils/language'; +import { capitalize } from '../../../utils/string'; + +import './ProgressBar.css'; interface IProps { - path: string - downloadManager: DownloadHandler + path: string; + downloadManager: DownloadHandler; } interface IState { - progress: number - status: string - total: number + progress: number; + status: string; + total: number; } -export default class ProgressBar extends React.Component { - constructor(props: IProps) { - super(props) - - this.state = { - progress: 0, - status: '', - total: this.props.downloadManager.getDownloadProgress(this.props.path)?.total || 0, - } +export default function ProgressBar(props: IProps) { + const [state, setState] = createStore({ + progress: 0, + status: '', + total: props.downloadManager.getDownloadProgress(props.path)?.total || 0, + }); - this.stopDownload = this.stopDownload.bind(this) - } - - componentDidMount() { - // Periodically check the progress of passed file path - const intv = setInterval(async () => { - const prog = this.props.downloadManager.getDownloadProgress(this.props.path) - this.setState({ + const disposeTimer = makeTimer( + async () => { + const prog = props.downloadManager.getDownloadProgress(props.path); + setState({ progress: prog?.progress || 0, - status: (await translate(`download_status.${prog?.status || 'stopped'}`)) || 'stopped', + status: + (await translate(`download_status.${prog?.status || 'stopped'}`)) || + 'stopped', total: prog?.total || 0, - }) + }); - if (this.state.status === 'finished' || this.state.status === 'error') { + if (state.status === 'finished' || state.status === 'error') { // Ensure progress is 100% - clearInterval(intv) + disposeTimer(); } - }, 500) - } + }, + 500, + setInterval + ); - stopDownload() { - this.props.downloadManager.stopDownload(this.props.path) + function stopDownload() { + props.downloadManager.stopDownload(props.path); } - render() { - return ( -
-
-
-
{ - // Handles files with content-lengths of 0 - if (this.state.status === 'finished') { - return '100' - } + return ( +
+
+
+
{ + // Handles files with content-lengths of 0 + if (state.status === 'finished') { + return '100'; + } - if (this.state.total <= 0) { - return '0' - } + if (state.total <= 0) { + return '0'; + } - return (this.state.progress / this.state.total) * 100 - })()}%`, - }} - >
-
-
-
- -
+ return (state.progress / state.total) * 100; + })()}%`, + }} + /> +
+
+
+
- -
{capitalize(this.state.status) || 'Waiting'}
- ) - } + +
{capitalize(state.status) || 'Waiting'}
+
+ ); } diff --git a/src/ui/components/common/TextInput.tsx b/src/ui/components/common/TextInput.tsx index 22996f9e..e382b7b3 100644 --- a/src/ui/components/common/TextInput.tsx +++ b/src/ui/components/common/TextInput.tsx @@ -1,77 +1,55 @@ -import React from 'react' +import { createSignal, JSX, onMount, Show } from 'solid-js'; -import './TextInput.css' -import Close from '../../../resources/icons/close.svg' +import Close from '../../../resources/icons/close.svg'; -interface IProps { - value?: string - initalValue?: string - placeholder?: string - onChange?: (value: string) => void - readOnly?: boolean - id?: string - clearable?: boolean - customClearBehaviour?: () => void - style?: React.CSSProperties -} +import './TextInput.css'; -interface IState { - value: string +interface IProps { + value?: string; + initalValue?: string; + placeholder?: string; + onChange?: (value: string) => void; + readOnly?: boolean; + id?: string; + clearable?: boolean; + customClearBehaviour?: () => void; + style?: JSX.CSSProperties; } -export default class TextInput extends React.Component { - constructor(props: IProps) { - super(props) - - this.state = { - value: props.value || '', - } - } - - async componentDidMount() { - if (this.props.initalValue) { - this.setState({ - value: this.props.initalValue, - }) - } - } - - static getDerivedStateFromProps(props: IProps, state: IState) { - return { value: props.value || state.value } - } - - render() { - return ( -
- { - this.setState({ value: e.target.value }) - if (this.props.onChange) this.props.onChange(e.target.value) - }} - /> - {this.props.clearable ? ( -
{ - // Run custom behaviour first - if (this.props.customClearBehaviour) return this.props.customClearBehaviour() - - this.setState({ value: '' }) - - if (this.props.onChange) this.props.onChange('') - - this.forceUpdate() - }} - > - -
- ) : null} -
- ) - } +export default function TextInput(props: IProps) { + const [value, setValue] = createSignal(props.value || ''); + + onMount(() => { + if (props.initalValue) setValue(props.initalValue); + }); + + return ( +
+ { + setValue(e.currentTarget.value); + if (props.onChange) props.onChange(e.currentTarget.value); + }} + /> + +
{ + // Run custom behaviour first + if (props.customClearBehaviour) return props.customClearBehaviour(); + + setValue(''); + + if (props.onChange) props.onChange(''); + }}> + +
+
+
+ ); } diff --git a/src/ui/components/menu/Divider.tsx b/src/ui/components/menu/Divider.tsx index c516e6fb..a7d0889d 100644 --- a/src/ui/components/menu/Divider.tsx +++ b/src/ui/components/menu/Divider.tsx @@ -1,13 +1,9 @@ -import React from 'react' +import './Divider.css'; -import './Divider.css' - -export default class Divider extends React.Component { - render() { - return ( -
-
-
- ) - } +export default function Divider() { + return ( +
+
+
+ ); } diff --git a/src/ui/components/menu/Downloads.tsx b/src/ui/components/menu/Downloads.tsx index ebbffa60..b9c83f7d 100644 --- a/src/ui/components/menu/Downloads.tsx +++ b/src/ui/components/menu/Downloads.tsx @@ -1,75 +1,72 @@ -import React from 'react' -import Menu from './Menu' -import Tr from '../../../utils/language' -import DownloadHandler from '../../../utils/download' -import { unzip } from '../../../utils/zipUtils' -import BigButton from '../common/BigButton' -import { dataDir } from '@tauri-apps/api/path' - -import './Downloads.css' -import Divider from './Divider' -import { getConfigOption } from '../../../utils/configuration' -import { invoke } from '@tauri-apps/api' -import { listen } from '@tauri-apps/api/event' -import HelpButton from '../common/HelpButton' - -const STABLE_REPO_DOWNLOAD = 'https://github.com/Grasscutters/Grasscutter/archive/refs/heads/stable.zip' -const DEV_REPO_DOWNLOAD = 'https://github.com/Grasscutters/Grasscutter/archive/refs/heads/development.zip' -const STABLE_DOWNLOAD = 'https://nightly.link/Grasscutters/Grasscutter/workflows/build/stable/Grasscutter.zip' -const DEV_DOWNLOAD = 'https://nightly.link/Grasscutters/Grasscutter/workflows/build/development/Grasscutter.zip' -const RESOURCES_DOWNLOAD = 'https://github.com/tamilpp25/Grasscutter_Resources/archive/refs/heads/3.0.zip' +import { onCleanup, onMount } from 'solid-js'; +import { createStore } from 'solid-js/store'; +import { invoke } from '@tauri-apps/api'; +import { listen } from '@tauri-apps/api/event'; +import { dataDir } from '@tauri-apps/api/path'; + +import { getConfigOption } from '../../../utils/configuration'; +import DownloadHandler from '../../../utils/download'; +import Tr from '../../../utils/language'; +import { unzip } from '../../../utils/zipUtils'; +import BigButton from '../common/BigButton'; +import HelpButton from '../common/HelpButton'; +import Divider from './Divider'; +import Menu from './Menu'; + +import './Downloads.css'; + +const STABLE_REPO_DOWNLOAD = + 'https://github.com/Grasscutters/Grasscutter/archive/refs/heads/stable.zip'; +const DEV_REPO_DOWNLOAD = + 'https://github.com/Grasscutters/Grasscutter/archive/refs/heads/development.zip'; +const STABLE_DOWNLOAD = + 'https://nightly.link/Grasscutters/Grasscutter/workflows/build/stable/Grasscutter.zip'; +const DEV_DOWNLOAD = + 'https://nightly.link/Grasscutters/Grasscutter/workflows/build/development/Grasscutter.zip'; +const RESOURCES_DOWNLOAD = + 'https://github.com/tamilpp25/Grasscutter_Resources/archive/refs/heads/3.0.zip'; interface IProps { - closeFn: () => void - downloadManager: DownloadHandler + closeFn: () => void; + downloadManager: DownloadHandler; } interface IState { - grasscutter_downloading: boolean - resources_downloading: boolean - repo_downloading: boolean - grasscutter_set: boolean - resources_exist: boolean + grasscutter_downloading: boolean; + resources_downloading: boolean; + repo_downloading: boolean; + grasscutter_set: boolean; + resources_exist: boolean; } -export default class Downloads extends React.Component { - constructor(props: IProps) { - super(props) +export default function Downloads(props: IProps) { + const [state, setState] = createStore({ + grasscutter_downloading: props.downloadManager.downloadingJar(), + resources_downloading: props.downloadManager.downloadingResources(), + repo_downloading: props.downloadManager.downloadingRepo(), + grasscutter_set: false, + resources_exist: false, + }); - this.state = { - grasscutter_downloading: this.props.downloadManager.downloadingJar(), - resources_downloading: this.props.downloadManager.downloadingResources(), - repo_downloading: this.props.downloadManager.downloadingRepo(), - grasscutter_set: false, - resources_exist: false, - } - - this.getGrasscutterFolder = this.getGrasscutterFolder.bind(this) - this.downloadGrasscutterStableRepo = this.downloadGrasscutterStableRepo.bind(this) - this.downloadGrasscutterDevRepo = this.downloadGrasscutterDevRepo.bind(this) - this.downloadGrasscutterStable = this.downloadGrasscutterStable.bind(this) - this.downloadGrasscutterLatest = this.downloadGrasscutterLatest.bind(this) - this.downloadResources = this.downloadResources.bind(this) - this.toggleButtons = this.toggleButtons.bind(this) - } + const unlisten = listen('jar_extracted', () => { + setState('grasscutter_set', true); + }); - async componentDidMount() { - const gc_path = await getConfigOption('grasscutter_path') + onCleanup(() => unlisten.then((ul) => ul())); - listen('jar_extracted', () => { - this.setState({ grasscutter_set: true }, this.forceUpdate) - }) + onMount(async () => { + const gc_path = await getConfigOption('grasscutter_path'); if (!gc_path || gc_path === '') { - this.setState({ + setState({ grasscutter_set: false, resources_exist: false, - }) + }); - return + return; } - const path = gc_path.substring(0, gc_path.lastIndexOf('\\')) + const path = gc_path.substring(0, gc_path.lastIndexOf('\\')); if (gc_path) { const resources_exist: boolean = @@ -78,223 +75,248 @@ export default class Downloads extends React.Component { })) as boolean) && (!(await invoke('dir_is_empty', { path: path + '\\resources', - })) as boolean) + })) as boolean); - this.setState({ + setState({ grasscutter_set: gc_path !== '', resources_exist, - }) + }); } - } + }); - async getGrasscutterFolder() { - const path = await getConfigOption('grasscutter_path') - let folderPath + async function getGrasscutterFolder() { + const path = await getConfigOption('grasscutter_path'); + let folderPath; // Set to default if not set if (!path || path === '') { - const appdata = await dataDir() - folderPath = appdata + 'cultivation\\grasscutter' + const appdata = await dataDir(); + folderPath = appdata + 'cultivation\\grasscutter'; // Early return since its formatted properly - return folderPath + return folderPath; } if (path.includes('/')) { - folderPath = path.substring(0, path.lastIndexOf('/')) + folderPath = path.substring(0, path.lastIndexOf('/')); } else { - folderPath = path.substring(0, path.lastIndexOf('\\')) + folderPath = path.substring(0, path.lastIndexOf('\\')); } - return folderPath + return folderPath; } - async downloadGrasscutterStableRepo() { - const folder = await this.getGrasscutterFolder() - this.props.downloadManager.addDownload(STABLE_REPO_DOWNLOAD, folder + '\\grasscutter_repo.zip', async () => { - await unzip(folder + '\\grasscutter_repo.zip', folder + '\\', true) - this.toggleButtons() - }) + async function downloadGrasscutterStableRepo() { + const folder = await getGrasscutterFolder(); + props.downloadManager.addDownload( + STABLE_REPO_DOWNLOAD, + folder + '\\grasscutter_repo.zip', + async () => { + await unzip(folder + '\\grasscutter_repo.zip', folder + '\\', true); + toggleButtons(); + } + ); - this.toggleButtons() + toggleButtons(); } - async downloadGrasscutterDevRepo() { - const folder = await this.getGrasscutterFolder() - this.props.downloadManager.addDownload(DEV_REPO_DOWNLOAD, folder + '\\grasscutter_repo.zip', async () => { - await unzip(folder + '\\grasscutter_repo.zip', folder + '\\', true) - this.toggleButtons() - }) + async function downloadGrasscutterDevRepo() { + const folder = await getGrasscutterFolder(); + props.downloadManager.addDownload( + DEV_REPO_DOWNLOAD, + folder + '\\grasscutter_repo.zip', + async () => { + await unzip(folder + '\\grasscutter_repo.zip', folder + '\\', true); + toggleButtons(); + } + ); - this.toggleButtons() + toggleButtons(); } - async downloadGrasscutterStable() { - const folder = await this.getGrasscutterFolder() - this.props.downloadManager.addDownload(STABLE_DOWNLOAD, folder + '\\grasscutter.zip', async () => { - await unzip(folder + '\\grasscutter.zip', folder + '\\', true) - this.toggleButtons - }) + async function downloadGrasscutterStable() { + const folder = await getGrasscutterFolder(); + props.downloadManager.addDownload( + STABLE_DOWNLOAD, + folder + '\\grasscutter.zip', + async () => { + await unzip(folder + '\\grasscutter.zip', folder + '\\', true); + toggleButtons(); + } + ); // Also add repo download - this.downloadGrasscutterStableRepo() + downloadGrasscutterStableRepo(); - this.toggleButtons() + toggleButtons(); } - async downloadGrasscutterLatest() { - const folder = await this.getGrasscutterFolder() - this.props.downloadManager.addDownload(DEV_DOWNLOAD, folder + '\\grasscutter.zip', async () => { - await unzip(folder + '\\grasscutter.zip', folder + '\\', true) - this.toggleButtons() - }) + async function downloadGrasscutterLatest() { + const folder = await getGrasscutterFolder(); + props.downloadManager.addDownload( + DEV_DOWNLOAD, + folder + '\\grasscutter.zip', + async () => { + await unzip(folder + '\\grasscutter.zip', folder + '\\', true); + toggleButtons(); + } + ); // Also add repo download - this.downloadGrasscutterDevRepo() + downloadGrasscutterDevRepo(); - this.toggleButtons() + toggleButtons(); } - async downloadResources() { - const folder = await this.getGrasscutterFolder() - this.props.downloadManager.addDownload(RESOURCES_DOWNLOAD, folder + '\\resources.zip', async () => { - // Delete the existing folder if it exists - if ( - await invoke('dir_exists', { - path: folder + '\\resources', - }) - ) { - await invoke('dir_delete', { - path: folder + '\\resources', - }) + async function downloadResources() { + const folder = await getGrasscutterFolder(); + props.downloadManager.addDownload( + RESOURCES_DOWNLOAD, + folder + '\\resources.zip', + async () => { + // Delete the existing folder if it exists + if ( + await invoke('dir_exists', { + path: folder + '\\resources', + }) + ) { + await invoke('dir_delete', { + path: folder + '\\resources', + }); + } + + await unzip(folder + '\\resources.zip', folder + '\\', true); + // Rename folder to resources + invoke('rename', { + path: folder + '\\Resources', + newName: 'resources', + }); + + toggleButtons(); } + ); - await unzip(folder + '\\resources.zip', folder + '\\', true) - // Rename folder to resources - invoke('rename', { - path: folder + '\\Resources', - newName: 'resources', - }) - - this.toggleButtons() - }) - - this.toggleButtons() + toggleButtons(); } - async toggleButtons() { - const gc_path = await getConfigOption('grasscutter_path') + async function toggleButtons() { + const gc_path = await getConfigOption('grasscutter_path'); // Set states since we know we are downloading something if this is called - this.setState({ - grasscutter_downloading: this.props.downloadManager.downloadingJar(), - resources_downloading: this.props.downloadManager.downloadingResources(), - repo_downloading: this.props.downloadManager.downloadingRepo(), + setState({ + grasscutter_downloading: props.downloadManager.downloadingJar(), + resources_downloading: props.downloadManager.downloadingResources(), + repo_downloading: props.downloadManager.downloadingRepo(), grasscutter_set: gc_path !== '', - }) + }); } - render() { - return ( - -
-
- - -
-
- - - -
+ return ( + +
+
+ +
-
-
- - -
-
- - - -
+
+ + +
- - - -
-
- - -
-
- - - -
+
+
+
+ + +
+
+ + + +
+
+ + + +
+
+ + +
+
+ + +
-
-
- - -
-
- - - -
+
+
+
+ +
+
+ + + +
+
+ + - - -
-
- - -
-
- - - -
+
+
+ +
-
- ) - } +
+ + + +
+
+
+ ); } diff --git a/src/ui/components/menu/ExtrasMenu.tsx b/src/ui/components/menu/ExtrasMenu.tsx index 900b3044..5a1622ce 100644 --- a/src/ui/components/menu/ExtrasMenu.tsx +++ b/src/ui/components/menu/ExtrasMenu.tsx @@ -1,179 +1,176 @@ -import React from 'react' -import { getConfig, saveConfig } from '../../../utils/configuration' -import Checkbox from '../common/Checkbox' -import Menu from './Menu' +import { JSX, onMount, Show } from 'solid-js'; +import { createStore } from 'solid-js/store'; +import { invoke } from '@tauri-apps/api'; -import './ExtrasMenu.css' -import BigButton from '../common/BigButton' -import { invoke } from '@tauri-apps/api' -import Tr from '../../../utils/language' -import { getGameExecutable } from '../../../utils/game' +import { getConfig, saveConfig } from '../../../utils/configuration'; +import { getGameExecutable } from '../../../utils/game'; +import Tr from '../../../utils/language'; +import BigButton from '../common/BigButton'; +import Checkbox from '../common/Checkbox'; +import Menu from './Menu'; + +import './ExtrasMenu.css'; interface IProps { - children: React.ReactNode | React.ReactNode[] - closeFn: () => void - playGame: (exe?: string, proc_name?: string) => void + children: JSX.Element; + closeFn: () => void; + playGame: (exe?: string, proc_name?: string) => void; } interface IState { - migoto?: string - akebi?: string - reshade?: string - launch_migoto: boolean - launch_akebi: boolean - launch_reshade: boolean + migoto?: string; + akebi?: string; + reshade?: string; + launch_migoto: boolean; + launch_akebi: boolean; + launch_reshade: boolean; } -export class ExtrasMenu extends React.Component { - constructor(props: IProps) { - super(props) - - this.state = { - launch_migoto: false, - launch_akebi: false, - launch_reshade: false, - } - - this.launchPreprograms = this.launchPreprograms.bind(this) - this.toggleMigoto = this.toggleMigoto.bind(this) - this.toggleAkebi = this.toggleAkebi.bind(this) - this.toggleReshade = this.toggleReshade.bind(this) - } +export function ExtrasMenu(props: IProps) { + const [state, setState] = createStore({ + launch_migoto: false, + launch_akebi: false, + launch_reshade: false, + }); - async componentDidMount() { - const config = await getConfig() + onMount(async () => { + const config = await getConfig(); - this.setState({ + setState({ migoto: config.migoto_path, akebi: config.akebi_path, reshade: config.reshade_path, launch_akebi: config?.last_extras?.akebi ?? false, launch_migoto: config?.last_extras?.migoto ?? false, launch_reshade: config?.last_extras?.reshade ?? false, - }) - } + }); + }); - async launchPreprograms() { - const config = await getConfig() + async function launchPreprograms() { + const config = await getConfig(); config.last_extras = { - migoto: this.state.launch_migoto, - akebi: this.state.launch_akebi, - reshade: this.state.launch_reshade, - } + migoto: state.launch_migoto, + akebi: state.launch_akebi, + reshade: state.launch_reshade, + }; - await saveConfig(config) + await saveConfig(config); // Close menu - this.props.closeFn() + props.closeFn(); // This injects independent of the game - if (this.state.launch_migoto) { - await this.launchMigoto() + if (state.launch_migoto) { + await launchMigoto(); } // This injects independent of the game - if (this.state.launch_reshade) { - await this.launchReshade() + if (state.launch_reshade) { + await launchReshade(); } // This will launch the game - if (this.state.launch_akebi) { - await this.launchAkebi() + if (state.launch_akebi) { + await launchAkebi(); // This already launches the game - return + return; } // Launch the game - await this.props.playGame() + await props.playGame(); } - async launchAkebi() { - const config = await getConfig() + async function launchAkebi() { + const config = await getConfig(); // Get game exe from game path, so we can watch it - const pathArr = config.game_install_path.replace(/\\/g, '/').split('/') - const gameExec = pathArr[pathArr.length - 1] + const pathArr = config.game_install_path.replace(/\\/g, '/').split('/'); + const gameExec = pathArr[pathArr.length - 1]; - await this.props.playGame(config.akebi_path, gameExec) + await props.playGame(config.akebi_path, gameExec); } - async launchMigoto() { - const config = await getConfig() + async function launchMigoto() { + const config = await getConfig(); - if (!config.migoto_path) return alert('Migoto not installed or set!') + if (!config.migoto_path) return alert('Migoto not installed or set!'); - await invoke('run_program_relative', { path: config.migoto_path }) + await invoke('run_program_relative', { path: config.migoto_path }); } - async launchReshade() { - const config = await getConfig() + async function launchReshade() { + const config = await getConfig(); - if (!config.reshade_path) return alert('Reshade not installed or set!') + if (!config.reshade_path) return alert('Reshade not installed or set!'); await invoke('run_command', { program: config.reshade_path, args: [await getGameExecutable()], relative: true, - }) + }); } - toggleMigoto() { - this.setState({ - launch_migoto: !this.state.launch_migoto, - }) + function toggleMigoto() { + setState('launch_migoto', (l) => !l); } - toggleAkebi() { - this.setState({ - launch_akebi: !this.state.launch_akebi, - }) + function toggleAkebi() { + setState('launch_akebi', (l) => !l); } - toggleReshade() { - this.setState({ - launch_reshade: !this.state.launch_reshade, - }) + function toggleReshade() { + setState('launch_reshade', (l) => !l); } - render() { - return ( - -
- {this.state.migoto && ( -
-
- -
- + return ( + +
+ +
+
+
- )} - - {this.state.akebi && ( -
-
- -
- + +
+ + + +
+
+
- )} - - {this.state.reshade && ( -
-
- -
- + +
+ + + +
+
+
- )} -
-
- - - -
-
- ) - } + +
+ +
+
+ + + +
+
+ ); } diff --git a/src/ui/components/menu/Game.tsx b/src/ui/components/menu/Game.tsx index c623ba58..7424b2fb 100644 --- a/src/ui/components/menu/Game.tsx +++ b/src/ui/components/menu/Game.tsx @@ -1,92 +1,75 @@ -import React from 'react' -import Menu from './Menu' -import { translate } from '../../../utils/language' -import DownloadHandler from '../../../utils/download' +import { createSignal, onMount, Show } from 'solid-js'; -import './Game.css' -import DirInput from '../common/DirInput' -import BigButton from '../common/BigButton' -import HelpButton from '../common/HelpButton' -import { unzip } from '../../../utils/zipUtils' +import DownloadHandler from '../../../utils/download'; +import { translate } from '../../../utils/language'; +import { unzip } from '../../../utils/zipUtils'; +import BigButton from '../common/BigButton'; +import DirInput from '../common/DirInput'; +import HelpButton from '../common/HelpButton'; +import Menu from './Menu'; -const GAME_DOWNLOAD = '' +import './Game.css'; -interface IProps { - closeFn: () => void - downloadManager: DownloadHandler -} +const GAME_DOWNLOAD = ''; -interface IState { - gameDownloading: boolean - gameDownloadFolder: string - dirPlaceholder: string +interface IProps { + closeFn: () => void; + downloadManager: DownloadHandler; } -export default class Downloads extends React.Component { - constructor(props: IProps) { - super(props) +export default function Downloads(props: IProps) { + const [gameDownloading, setGameDownloading] = createSignal(false); + const [gameDownloadFolder, setGameDownloadFolder] = createSignal(''); + const [dirPlaceholder, setDirPlaceholder] = createSignal(''); - this.state = { - gameDownloading: false, - gameDownloadFolder: '', - dirPlaceholder: '', - } + onMount(async () => + setDirPlaceholder(await translate('components.select_folder')) + ); - this.downloadGame = this.downloadGame.bind(this) - } - - async componentDidMount() { - this.setState({ - dirPlaceholder: await translate('components.select_folder'), - }) + async function downloadGame() { + const folder = gameDownloadFolder(); + props.downloadManager.addDownload( + GAME_DOWNLOAD, + folder + '\\game.zip', + async () => { + await unzip(folder + '\\game.zip', folder + '\\', true); + setGameDownloading(false); + } + ); - console.log(this.state) + setGameDownloading(true); } - async downloadGame() { - const folder = this.state.gameDownloadFolder - this.props.downloadManager.addDownload(GAME_DOWNLOAD, folder + '\\game.zip', async () => { - await unzip(folder + '\\game.zip', folder + '\\', true) - this.setState({ - gameDownloading: false, - }) - }) - - this.setState({ - gameDownloading: true, - }) - } - - render() { - return ( - -
- {this.state.gameDownloadFolder !== '' && !this.state.gameDownloading ? ( - - Download Game - - ) : ( + return ( + +
+ null} disabled> Download Game - )} - -
+ }> + + Download Game + + + +
-
- - this.setState({ - gameDownloadFolder: value, - }) - } - /> -
-
- ) - } +
+ +
+ + ); } diff --git a/src/ui/components/menu/Menu.tsx b/src/ui/components/menu/Menu.tsx index f57f3e77..d776865e 100644 --- a/src/ui/components/menu/Menu.tsx +++ b/src/ui/components/menu/Menu.tsx @@ -1,35 +1,33 @@ -import React from 'react' -import './Menu.css' +import { JSX } from 'solid-js'; -import Close from '../../../resources/icons/close.svg' +import Close from '../../../resources/icons/close.svg'; + +import './Menu.css'; interface IProps { - children: React.ReactNode[] | React.ReactNode - className?: string - heading: string - closeFn: () => void + children: JSX.Element; + class?: string; + heading: string; + closeFn: () => void; } -export default class Menu extends React.Component { - constructor(props: IProps) { - super(props) - } - - render() { - return ( -