diff --git a/.github/workflows/dev_release.yml b/.github/workflows/dev_release.yml index e68ac55b4..bb97b1863 100644 --- a/.github/workflows/dev_release.yml +++ b/.github/workflows/dev_release.yml @@ -77,3 +77,23 @@ jobs: files: | CHANGELOG_LATEST.md ./build/firmware/*.* + + - name: Update version in Cloudflare KV store + if: github.repository == 'emsesp/EMS-ESP32' + env: + CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} + CF_NAMESPACE_ID: ${{ secrets.CF_NAMESPACE_ID }} + CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }} + VERSION: ${{ steps.build_info.outputs.VERSION }} + run: | + JSON_DATA=$(jq -n \ + --arg version "$VERSION" \ + --arg date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + '{version: $version, date: $date}') + echo "JSON_DATA: $JSON_DATA" + curl -sS --fail-with-body \ + -X PUT "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/storage/kv/namespaces/${CF_NAMESPACE_ID}/values/dev" \ + -H "Authorization: Bearer ${CF_API_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$JSON_DATA" + echo diff --git a/.github/workflows/stable_release.yml b/.github/workflows/stable_release.yml index 6286e6ea3..93f45ad3d 100644 --- a/.github/workflows/stable_release.yml +++ b/.github/workflows/stable_release.yml @@ -27,10 +27,17 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 - + - name: Enable Corepack run: corepack enable pnpm + + - name: Get the EMS-ESP version + id: build_info + run: | + version=`grep -E '^#define EMSESP_APP_VERSION' ./src/emsesp_version.h | awk -F'"' '{print $2}'` + echo "VERSION=$version" >> $GITHUB_OUTPUT + - name: Install PlatformIO run: | python -m pip install --upgrade pip @@ -61,3 +68,23 @@ jobs: files: | CHANGELOG.md ./build/firmware/*.* + + - name: Update version in Cloudflare KV store + if: github.repository == 'emsesp/EMS-ESP32' + env: + CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} + CF_NAMESPACE_ID: ${{ secrets.CF_NAMESPACE_ID }} + CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }} + VERSION: ${{ steps.build_info.outputs.VERSION }} + run: | + JSON_DATA=$(jq -n \ + --arg version "$VERSION" \ + --arg date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + '{version: $version, date: $date}') + echo "JSON_DATA: $JSON_DATA" + curl -sS --fail-with-body \ + -X PUT "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/storage/kv/namespaces/${CF_NAMESPACE_ID}/values/stable" \ + -H "Authorization: Bearer ${CF_API_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$JSON_DATA" + echo diff --git a/.github/workflows/update_versions.yml b/.github/workflows/update_versions.yml new file mode 100644 index 000000000..e246f84c2 --- /dev/null +++ b/.github/workflows/update_versions.yml @@ -0,0 +1,40 @@ +name: 'Update versions' + +on: + workflow_dispatch: + +permissions: + contents: write + +jobs: + update-version: + name: 'Update versions in Cloudflare KV store' + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Get and Send EMS-ESP version to Cloudflare + env: + CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} + CF_NAMESPACE_ID: ${{ secrets.CF_NAMESPACE_ID }} + CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }} + run: | + version=$(grep -E '^#define EMSESP_APP_VERSION' ./src/emsesp_version.h | awk -F'"' '{print $2}') + if [ "$GITHUB_REF" = "refs/heads/main" ]; then + KV_ENV="stable" + else + KV_ENV="dev" + fi + JSON_DATA=$(jq -n \ + --arg version "$version" \ + --arg date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + '{version: $version, date: $date}') + echo "KV_ENV: $KV_ENV" + echo "JSON_DATA: $JSON_DATA" + curl -sS --fail-with-body \ + -X PUT "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/storage/kv/namespaces/${CF_NAMESPACE_ID}/values/${KV_ENV}" \ + -H "Authorization: Bearer ${CF_API_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$JSON_DATA" + echo diff --git a/.gitignore b/.gitignore index 1de26422a..15466ba7c 100644 --- a/.gitignore +++ b/.gitignore @@ -64,7 +64,7 @@ words-found-verbose.txt # sonarlint compile_commands.json -# pioarduino + hybrid +# other files managed_components dependencies.lock CMakeLists.txt diff --git a/interface/package.json b/interface/package.json index b7108bd2a..80f1bf7cd 100644 --- a/interface/package.json +++ b/interface/package.json @@ -3,7 +3,7 @@ "version": "3.8.2", "description": "EMS-ESP WebUI", "homepage": "https://emsesp.org", - "author": "proddy, emsesp.org", + "author": "emsesp.org", "license": "MIT", "private": true, "type": "module", @@ -28,14 +28,11 @@ "@emotion/styled": "^11.14.1", "@mui/icons-material": "^9.0.0", "@mui/material": "^9.0.0", - "@preact/compat": "^18.3.2", "@table-library/react-table-library": "4.1.15", "alova": "^3.5.1", "async-validator": "^4.2.5", "etag": "^1.8.1", - "formidable": "^3.5.4", "jwt-decode": "^4.0.0", - "magic-string": "^0.30.21", "mime-types": "^3.0.2", "preact": "^10.29.1", "react": "^19.2.5", @@ -47,24 +44,21 @@ "typescript": "^6.0.3" }, "devDependencies": { - "@babel/core": "^7.29.0", "@eslint/js": "^10.0.1", - "@preact/compat": "^18.3.2", "@preact/preset-vite": "^2.10.5", "@trivago/prettier-plugin-sort-imports": "^6.0.2", "@types/node": "^25.6.0", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", - "axe-core": "^4.11.3", "concurrently": "^9.2.1", "eslint": "^10.2.1", "eslint-config-prettier": "^10.1.8", "prettier": "^3.8.3", "rollup-plugin-visualizer": "^7.0.1", - "terser": "^5.46.1", - "typescript-eslint": "^8.59.0", - "vite": "^8.0.9", + "terser": "^5.46.2", + "typescript-eslint": "^8.59.1", + "vite": "^8.0.10", "vite-plugin-imagemin": "^0.6.1" }, - "packageManager": "pnpm@10.33.1+sha512.05ba3c1d5d1c18f68df06470d74055e62d41fc110a0c660db1b2dfb2785327f04cf0f68345d4609bc52089e7fa0343c31593b2f9594e2c5d5da426230acc9820" + "packageManager": "pnpm@10.33.2+sha512.a90faf6feeab71ad6c6e57f94e0fe1a12f5dcc22cd754db40ae9593eb6a3e0b6b12e3540218bb37ae083404b1f2ce6db2a4121e979829b4aff94b99f49da1cf8" } diff --git a/interface/pnpm-lock.yaml b/interface/pnpm-lock.yaml index d73652f4f..5c26d35cd 100644 --- a/interface/pnpm-lock.yaml +++ b/interface/pnpm-lock.yaml @@ -5,7 +5,6 @@ settings: excludeLinksFromLockfile: false importers: - .: dependencies: '@alova/adapter-xhr': @@ -23,9 +22,6 @@ importers: '@mui/material': specifier: ^9.0.0 version: 9.0.0(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - '@preact/compat': - specifier: ^18.3.2 - version: 18.3.2(preact@10.29.1) '@table-library/react-table-library': specifier: 4.1.15 version: 4.1.15(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) @@ -38,15 +34,9 @@ importers: etag: specifier: ^1.8.1 version: 1.8.1 - formidable: - specifier: ^3.5.4 - version: 3.5.4 jwt-decode: specifier: ^4.0.0 version: 4.0.0 - magic-string: - specifier: ^0.30.21 - version: 0.30.21 mime-types: specifier: ^3.0.2 version: 3.0.2 @@ -75,15 +65,12 @@ importers: specifier: ^6.0.3 version: 6.0.3 devDependencies: - '@babel/core': - specifier: ^7.29.0 - version: 7.29.0 '@eslint/js': specifier: ^10.0.1 version: 10.0.1(eslint@10.2.1) '@preact/preset-vite': specifier: ^2.10.5 - version: 2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.59.0)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1)) + version: 2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.59.0)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2)) '@trivago/prettier-plugin-sort-imports': specifier: ^6.0.2 version: 6.0.2(prettier@3.8.3) @@ -96,9 +83,6 @@ importers: '@types/react-dom': specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.14) - axe-core: - specifier: ^4.11.3 - version: 4.11.3 concurrently: specifier: ^9.2.1 version: 9.2.1 @@ -113,153 +97,251 @@ importers: version: 3.8.3 rollup-plugin-visualizer: specifier: ^7.0.1 - version: 7.0.1(rolldown@1.0.0-rc.16)(rollup@4.59.0) + version: 7.0.1(rolldown@1.0.0-rc.17)(rollup@4.59.0) terser: - specifier: ^5.46.1 - version: 5.46.1 + specifier: ^5.46.2 + version: 5.46.2 typescript-eslint: - specifier: ^8.59.0 - version: 8.59.0(eslint@10.2.1)(typescript@6.0.3) + specifier: ^8.59.1 + version: 8.59.1(eslint@10.2.1)(typescript@6.0.3) vite: - specifier: ^8.0.9 - version: 8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1) + specifier: ^8.0.10 + version: 8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2) vite-plugin-imagemin: specifier: ^0.6.1 - version: 0.6.1(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1)) + version: 0.6.1(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2)) packages: - '@alova/adapter-xhr@2.3.1': - resolution: {integrity: sha512-mhViueeSJ6yfyEUvHIWyZlb6V8+9GJCzwU1hUsvjXSZHpkzGCeNUefxjjFC++K9UBsvUzJ5KGeyeqoToUQg3gg==} + resolution: + { + integrity: sha512-mhViueeSJ6yfyEUvHIWyZlb6V8+9GJCzwU1hUsvjXSZHpkzGCeNUefxjjFC++K9UBsvUzJ5KGeyeqoToUQg3gg== + } peerDependencies: alova: ^3.0.20 '@alova/shared@1.3.2': - resolution: {integrity: sha512-1XvDLWgYpVZ99MmLl1f3Fw4T6S6pPYk5afz5cwRVjuq8JXEGsDn9IygDKfvRyWqkqCBx7Jif07LIct1O+MVEow==} + resolution: + { + integrity: sha512-1XvDLWgYpVZ99MmLl1f3Fw4T6S6pPYk5afz5cwRVjuq8JXEGsDn9IygDKfvRyWqkqCBx7Jif07LIct1O+MVEow== + } '@babel/code-frame@7.29.0': - resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw== + } + engines: { node: '>=6.9.0' } '@babel/compat-data@7.29.0': - resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg== + } + engines: { node: '>=6.9.0' } '@babel/core@7.29.0': - resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA== + } + engines: { node: '>=6.9.0' } '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw== + } + engines: { node: '>=6.9.0' } '@babel/helper-annotate-as-pure@7.27.3': - resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg== + } + engines: { node: '>=6.9.0' } '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== + } + engines: { node: '>=6.9.0' } '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + } + engines: { node: '>=6.9.0' } '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== + } + engines: { node: '>=6.9.0' } '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== + } + engines: { node: '>=6.9.0' } peerDependencies: '@babel/core': ^7.0.0 '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug== + } + engines: { node: '>=6.9.0' } '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + } + engines: { node: '>=6.9.0' } '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + } + engines: { node: '>=6.9.0' } '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + } + engines: { node: '>=6.9.0' } '@babel/helpers@7.29.2': - resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw== + } + engines: { node: '>=6.9.0' } '@babel/parser@7.29.2': - resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} - engines: {node: '>=6.0.0'} + resolution: + { + integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA== + } + engines: { node: '>=6.0.0' } hasBin: true '@babel/plugin-syntax-jsx@7.28.6': - resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w== + } + engines: { node: '>=6.9.0' } peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-transform-react-jsx-development@7.27.1': - resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q== + } + engines: { node: '>=6.9.0' } peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-transform-react-jsx@7.28.6': - resolution: {integrity: sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow== + } + engines: { node: '>=6.9.0' } peerDependencies: '@babel/core': ^7.0.0-0 '@babel/runtime@7.29.2': - resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g== + } + engines: { node: '>=6.9.0' } '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== + } + engines: { node: '>=6.9.0' } '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA== + } + engines: { node: '>=6.9.0' } '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A== + } + engines: { node: '>=6.9.0' } - '@emnapi/core@1.9.2': - resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} + '@emnapi/core@1.10.0': + resolution: + { + integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw== + } - '@emnapi/runtime@1.9.2': - resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} + '@emnapi/runtime@1.10.0': + resolution: + { + integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA== + } '@emnapi/wasi-threads@1.2.1': - resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + resolution: + { + integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w== + } '@emotion/babel-plugin@11.13.5': - resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} + resolution: + { + integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ== + } '@emotion/cache@11.14.0': - resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} + resolution: + { + integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA== + } '@emotion/hash@0.9.2': - resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + resolution: + { + integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== + } '@emotion/is-prop-valid@1.4.0': - resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==} + resolution: + { + integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw== + } '@emotion/memoize@0.9.0': - resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} + resolution: + { + integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== + } '@emotion/react@11.14.0': - resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} + resolution: + { + integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA== + } peerDependencies: '@types/react': '*' react: '>=16.8.0' @@ -268,13 +350,22 @@ packages: optional: true '@emotion/serialize@1.3.3': - resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} + resolution: + { + integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA== + } '@emotion/sheet@1.4.0': - resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} + resolution: + { + integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== + } '@emotion/styled@11.14.1': - resolution: {integrity: sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==} + resolution: + { + integrity: sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw== + } peerDependencies: '@emotion/react': ^11.0.0-rc.0 '@types/react': '*' @@ -284,206 +375,317 @@ packages: optional: true '@emotion/unitless@0.10.0': - resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} + resolution: + { + integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg== + } '@emotion/use-insertion-effect-with-fallbacks@1.2.0': - resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} + resolution: + { + integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg== + } peerDependencies: react: '>=16.8.0' '@emotion/utils@1.4.2': - resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} + resolution: + { + integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA== + } '@emotion/weak-memoize@0.4.0': - resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} + resolution: + { + integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg== + } '@esbuild/aix-ppc64@0.27.4': - resolution: {integrity: sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q== + } + engines: { node: '>=18' } cpu: [ppc64] os: [aix] '@esbuild/android-arm64@0.27.4': - resolution: {integrity: sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw== + } + engines: { node: '>=18' } cpu: [arm64] os: [android] '@esbuild/android-arm@0.27.4': - resolution: {integrity: sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ== + } + engines: { node: '>=18' } cpu: [arm] os: [android] '@esbuild/android-x64@0.27.4': - resolution: {integrity: sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw== + } + engines: { node: '>=18' } cpu: [x64] os: [android] '@esbuild/darwin-arm64@0.27.4': - resolution: {integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ== + } + engines: { node: '>=18' } cpu: [arm64] os: [darwin] '@esbuild/darwin-x64@0.27.4': - resolution: {integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw== + } + engines: { node: '>=18' } cpu: [x64] os: [darwin] '@esbuild/freebsd-arm64@0.27.4': - resolution: {integrity: sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw== + } + engines: { node: '>=18' } cpu: [arm64] os: [freebsd] '@esbuild/freebsd-x64@0.27.4': - resolution: {integrity: sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ== + } + engines: { node: '>=18' } cpu: [x64] os: [freebsd] '@esbuild/linux-arm64@0.27.4': - resolution: {integrity: sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA== + } + engines: { node: '>=18' } cpu: [arm64] os: [linux] '@esbuild/linux-arm@0.27.4': - resolution: {integrity: sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg== + } + engines: { node: '>=18' } cpu: [arm] os: [linux] '@esbuild/linux-ia32@0.27.4': - resolution: {integrity: sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA== + } + engines: { node: '>=18' } cpu: [ia32] os: [linux] '@esbuild/linux-loong64@0.14.54': - resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw== + } + engines: { node: '>=12' } cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.27.4': - resolution: {integrity: sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA== + } + engines: { node: '>=18' } cpu: [loong64] os: [linux] '@esbuild/linux-mips64el@0.27.4': - resolution: {integrity: sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw== + } + engines: { node: '>=18' } cpu: [mips64el] os: [linux] '@esbuild/linux-ppc64@0.27.4': - resolution: {integrity: sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA== + } + engines: { node: '>=18' } cpu: [ppc64] os: [linux] '@esbuild/linux-riscv64@0.27.4': - resolution: {integrity: sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw== + } + engines: { node: '>=18' } cpu: [riscv64] os: [linux] '@esbuild/linux-s390x@0.27.4': - resolution: {integrity: sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA== + } + engines: { node: '>=18' } cpu: [s390x] os: [linux] '@esbuild/linux-x64@0.27.4': - resolution: {integrity: sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA== + } + engines: { node: '>=18' } cpu: [x64] os: [linux] '@esbuild/netbsd-arm64@0.27.4': - resolution: {integrity: sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q== + } + engines: { node: '>=18' } cpu: [arm64] os: [netbsd] '@esbuild/netbsd-x64@0.27.4': - resolution: {integrity: sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg== + } + engines: { node: '>=18' } cpu: [x64] os: [netbsd] '@esbuild/openbsd-arm64@0.27.4': - resolution: {integrity: sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow== + } + engines: { node: '>=18' } cpu: [arm64] os: [openbsd] '@esbuild/openbsd-x64@0.27.4': - resolution: {integrity: sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ== + } + engines: { node: '>=18' } cpu: [x64] os: [openbsd] '@esbuild/openharmony-arm64@0.27.4': - resolution: {integrity: sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg== + } + engines: { node: '>=18' } cpu: [arm64] os: [openharmony] '@esbuild/sunos-x64@0.27.4': - resolution: {integrity: sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g== + } + engines: { node: '>=18' } cpu: [x64] os: [sunos] '@esbuild/win32-arm64@0.27.4': - resolution: {integrity: sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg== + } + engines: { node: '>=18' } cpu: [arm64] os: [win32] '@esbuild/win32-ia32@0.27.4': - resolution: {integrity: sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw== + } + engines: { node: '>=18' } cpu: [ia32] os: [win32] '@esbuild/win32-x64@0.27.4': - resolution: {integrity: sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg== + } + engines: { node: '>=18' } cpu: [x64] os: [win32] '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + resolution: + { + integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + resolution: + { + integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== + } + engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } '@eslint/config-array@0.23.5': - resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA== + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } '@eslint/config-helpers@0.5.5': - resolution: {integrity: sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w== + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } '@eslint/core@1.2.1': - resolution: {integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ== + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } '@eslint/js@10.0.1': - resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA== + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } peerDependencies: eslint: ^10.0.0 peerDependenciesMeta: @@ -491,58 +693,103 @@ packages: optional: true '@eslint/object-schema@3.0.5': - resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw== + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } '@eslint/plugin-kit@0.7.1': - resolution: {integrity: sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ== + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } '@humanfs/core@0.19.2': - resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} - engines: {node: '>=18.18.0'} + resolution: + { + integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA== + } + engines: { node: '>=18.18.0' } '@humanfs/node@0.16.8': - resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} - engines: {node: '>=18.18.0'} + resolution: + { + integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ== + } + engines: { node: '>=18.18.0' } '@humanfs/types@0.15.0': - resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} - engines: {node: '>=18.18.0'} + resolution: + { + integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q== + } + engines: { node: '>=18.18.0' } '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} + resolution: + { + integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + } + engines: { node: '>=12.22' } '@humanwhocodes/retry@0.4.3': - resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} - engines: {node: '>=18.18'} + resolution: + { + integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== + } + engines: { node: '>=18.18' } '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + resolution: + { + integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + } '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + resolution: + { + integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + } '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} + resolution: + { + integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + } + engines: { node: '>=6.0.0' } '@jridgewell/source-map@0.3.11': - resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + resolution: + { + integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA== + } '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + resolution: + { + integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + } '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + resolution: + { + integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + } '@mui/core-downloads-tracker@9.0.0': - resolution: {integrity: sha512-uwQNGkhv0lf7ufxw6QXev77BW6pWbW+7uxYjU5+rfp4lBkFtMEgJCsarTM3Tn+i0lGx6+Ol2u88JdGXr0GDskA==} + resolution: + { + integrity: sha512-uwQNGkhv0lf7ufxw6QXev77BW6pWbW+7uxYjU5+rfp4lBkFtMEgJCsarTM3Tn+i0lGx6+Ol2u88JdGXr0GDskA== + } '@mui/icons-material@9.0.0': - resolution: {integrity: sha512-oDwyvI6LgjWRC9MBcSGvLkPud9S9ELgSBQFYxa1rYcZn6Br55dn22SyvsPDMsn0G8OndFk53iMT45W5mNqrogw==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-oDwyvI6LgjWRC9MBcSGvLkPud9S9ELgSBQFYxa1rYcZn6Br55dn22SyvsPDMsn0G8OndFk53iMT45W5mNqrogw== + } + engines: { node: '>=14.0.0' } peerDependencies: '@mui/material': ^9.0.0 '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -552,8 +799,11 @@ packages: optional: true '@mui/material@9.0.0': - resolution: {integrity: sha512-+VP/oQCDhDR87NQQgXnNBG8dwy6GNuQLnenS1pZvkbn2dKFSxRSRMybTpH9xUxXP+316mlYDy5CSbYtusnCWtw==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-+VP/oQCDhDR87NQQgXnNBG8dwy6GNuQLnenS1pZvkbn2dKFSxRSRMybTpH9xUxXP+316mlYDy5CSbYtusnCWtw== + } + engines: { node: '>=14.0.0' } peerDependencies: '@emotion/react': ^11.5.0 '@emotion/styled': ^11.3.0 @@ -572,8 +822,11 @@ packages: optional: true '@mui/private-theming@9.0.0': - resolution: {integrity: sha512-JtuZoaiCqwD6vjgYu6Xp3T7DZkrxJlgtDz5yESzhI34fEX5hHMh2VJUbuL9UOg8xrfIFMrq6dcYoH/7Zi4G0RA==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-JtuZoaiCqwD6vjgYu6Xp3T7DZkrxJlgtDz5yESzhI34fEX5hHMh2VJUbuL9UOg8xrfIFMrq6dcYoH/7Zi4G0RA== + } + engines: { node: '>=14.0.0' } peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -582,8 +835,11 @@ packages: optional: true '@mui/styled-engine@9.0.0': - resolution: {integrity: sha512-9RLGdX4Jg0aQPRuvqh/OLzYSPlgd5zyEw5/1HIRfdavSiOd03WtUaGZH9/w1RoTYuRKwpgy0hpIFaMHIqPVIWg==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-9RLGdX4Jg0aQPRuvqh/OLzYSPlgd5zyEw5/1HIRfdavSiOd03WtUaGZH9/w1RoTYuRKwpgy0hpIFaMHIqPVIWg== + } + engines: { node: '>=14.0.0' } peerDependencies: '@emotion/react': ^11.4.1 '@emotion/styled': ^11.3.0 @@ -595,8 +851,11 @@ packages: optional: true '@mui/system@9.0.0': - resolution: {integrity: sha512-YnC5Zg6j04IxiLc/boAKs0464jfZlLFVa7mf5E8lF0XOtZVUvG6R6gJK50lgUYdaaLdyLfxF6xR7LaPuEpeT/g==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-YnC5Zg6j04IxiLc/boAKs0464jfZlLFVa7mf5E8lF0XOtZVUvG6R6gJK50lgUYdaaLdyLfxF6xR7LaPuEpeT/g== + } + engines: { node: '>=14.0.0' } peerDependencies: '@emotion/react': ^11.5.0 '@emotion/styled': ^11.3.0 @@ -611,7 +870,10 @@ packages: optional: true '@mui/types@9.0.0': - resolution: {integrity: sha512-i1cuFCAWN44b3AJWO7mh7tuh1sqbQSeVr/94oG0TX5uXivac8XalgE4/6fQZcmGZigzbQ35IXxj/4jLpRIBYZg==} + resolution: + { + integrity: sha512-i1cuFCAWN44b3AJWO7mh7tuh1sqbQSeVr/94oG0TX5uXivac8XalgE4/6fQZcmGZigzbQ35IXxj/4jLpRIBYZg== + } peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: @@ -619,8 +881,11 @@ packages: optional: true '@mui/utils@9.0.0': - resolution: {integrity: sha512-bQcqyg/gjULUqTuyUjSAFr6LQGLvtkNtDbJerAtoUn9kGZ0hg5QJiN1PLHMLbeFpe3te1831uq7GFl2ITokGdg==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-bQcqyg/gjULUqTuyUjSAFr6LQGLvtkNtDbJerAtoUn9kGZ0hg5QJiN1PLHMLbeFpe3te1831uq7GFl2ITokGdg== + } + engines: { node: '>=14.0.0' } peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -629,169 +894,244 @@ packages: optional: true '@napi-rs/wasm-runtime@1.1.4': - resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} + resolution: + { + integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow== + } peerDependencies: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 - '@noble/hashes@1.8.0': - resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} - engines: {node: ^14.21.3 || >=16} - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + } + engines: { node: '>= 8' } '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + } + engines: { node: '>= 8' } '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + } + engines: { node: '>= 8' } - '@oxc-project/types@0.126.0': - resolution: {integrity: sha512-oGfVtjAgwQVVpfBrbtk4e1XDyWHRFta6BS3GWVzrF8xYBT2VGQAk39yJS/wFSMrZqoiCU4oghT3Ch0HaHGIHcQ==} - - '@paralleldrive/cuid2@2.3.1': - resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} + '@oxc-project/types@0.127.0': + resolution: + { + integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ== + } '@popperjs/core@2.11.8': - resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - - '@preact/compat@18.3.2': - resolution: {integrity: sha512-5vSl55K5yLMvocT7PBKxDOHGgYPjMrKQqqr6roSNjIXcJOtSgDDMjpiCAF3s7klRdmGrN75b/Przmjw8gmlg/w==} - peerDependencies: - preact: '*' + resolution: + { + integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== + } '@preact/preset-vite@2.10.5': - resolution: {integrity: sha512-p0vJpxiVO7KWWazWny3LUZ+saXyZKWv6Ju0bYMWNJRp2YveufRPgSUB1C4MTqGJfz07EehMgfN+AJNwQy+w6Iw==} + resolution: + { + integrity: sha512-p0vJpxiVO7KWWazWny3LUZ+saXyZKWv6Ju0bYMWNJRp2YveufRPgSUB1C4MTqGJfz07EehMgfN+AJNwQy+w6Iw== + } peerDependencies: '@babel/core': 7.x vite: 2.x || 3.x || 4.x || 5.x || 6.x || 7.x || 8.x '@prefresh/babel-plugin@0.5.3': - resolution: {integrity: sha512-57LX2SHs4BX2s1IwCjNzTE2OJeEepRCNf1VTEpbNcUyHfMO68eeOWGDIt4ob9aYlW6PEWZ1SuwNikuoIXANDtQ==} + resolution: + { + integrity: sha512-57LX2SHs4BX2s1IwCjNzTE2OJeEepRCNf1VTEpbNcUyHfMO68eeOWGDIt4ob9aYlW6PEWZ1SuwNikuoIXANDtQ== + } '@prefresh/core@1.5.9': - resolution: {integrity: sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ==} + resolution: + { + integrity: sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ== + } peerDependencies: preact: ^10.0.0 || ^11.0.0-0 '@prefresh/utils@1.2.1': - resolution: {integrity: sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==} + resolution: + { + integrity: sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw== + } '@prefresh/vite@2.4.12': - resolution: {integrity: sha512-FY1fzXpUjiuosznMV0YM7XAOPZjB5FIdWS0W24+XnlxYkt9hNAwwsiKYn+cuTEoMtD/ZVazS5QVssBr9YhpCQA==} + resolution: + { + integrity: sha512-FY1fzXpUjiuosznMV0YM7XAOPZjB5FIdWS0W24+XnlxYkt9hNAwwsiKYn+cuTEoMtD/ZVazS5QVssBr9YhpCQA== + } peerDependencies: preact: ^10.4.0 || ^11.0.0-0 vite: '>=2.0.0' - '@rolldown/binding-android-arm64@1.0.0-rc.16': - resolution: {integrity: sha512-rhY3k7Bsae9qQfOtph2Pm2jZEA+s8Gmjoz4hhmx70K9iMQ/ddeae+xhRQcM5IuVx5ry1+bGfkvMn7D6MJggVSA==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-android-arm64@1.0.0-rc.17': + resolution: + { + integrity: sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-rc.16': - resolution: {integrity: sha512-rNz0yK078yrNn3DrdgN+PKiMOW8HfQ92jQiXxwX8yW899ayV00MLVdaCNeVBhG/TbH3ouYVObo8/yrkiectkcQ==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-darwin-arm64@1.0.0-rc.17': + resolution: + { + integrity: sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.16': - resolution: {integrity: sha512-r/OmdR00HmD4i79Z//xO06uEPOq5hRXdhw7nzkxQxwSavs3PSHa1ijntdpOiZ2mzOQ3fVVu8C1M19FoNM+dMUQ==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-darwin-x64@1.0.0-rc.17': + resolution: + { + integrity: sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-rc.16': - resolution: {integrity: sha512-KcRE5w8h0OnjUatG8pldyD14/CQ5Phs1oxfR+3pKDjboHRo9+MkqQaiIZlZRpsxC15paeXme/I127tUa9TXJ6g==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-freebsd-x64@1.0.0-rc.17': + resolution: + { + integrity: sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.16': - resolution: {integrity: sha512-bT0guA1bpxEJ/ZhTRniQf7rNF8ybvXOuWbNIeLABaV5NGjx4EtOWBTSRGWFU9ZWVkPOZ+HNFP8RMcBokBiZ0Kg==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': + resolution: + { + integrity: sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.16': - resolution: {integrity: sha512-+tHktCHWV8BDQSjemUqm/Jl/TPk3QObCTIjmdDy/nlupcujZghmKK2962LYrqFpWu+ai01AN/REOH3NEpqvYQg==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': + resolution: + { + integrity: sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.16': - resolution: {integrity: sha512-3fPzdREH806oRLxpTWW1Gt4tQHs0TitZFOECB2xzCFLPKnSOy90gwA7P29cksYilFO6XVRY1kzga0cL2nRjKPg==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': + resolution: + { + integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.16': - resolution: {integrity: sha512-EKwI1tSrLs7YVw+JPJT/G2dJQ1jl9qlTTTEG0V2Ok/RdOenRfBw2PQdLPyjhIu58ocdBfP7vIRN/pvMsPxs/AQ==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': + resolution: + { + integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.16': - resolution: {integrity: sha512-Uknladnb3Sxqu6SEcqBldQyJUpk8NleooZEc0MbRBJ4inEhRYWZX0NJu12vNf2mqAq7gsofAxHrGghiUYjhaLQ==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': + resolution: + { + integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.16': - resolution: {integrity: sha512-FIb8+uG49sZBtLTn+zt1AJ20TqVcqWeSIyoVt0or7uAWesgKaHbiBh6OpA/k9v0LTt+PTrb1Lao133kP4uVxkg==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': + resolution: + { + integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.0-rc.16': - resolution: {integrity: sha512-RuERhF9/EgWxZEXYWCOaViUWHIboceK4/ivdtQ3R0T44NjLkIIlGIAVAuCddFxsZ7vnRHtNQUrt2vR2n2slB2w==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': + resolution: + { + integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.16': - resolution: {integrity: sha512-mXcXnvd9GpazCxeUCCnZ2+YF7nut+ZOEbE4GtaiPtyY6AkhZWbK70y1KK3j+RDhjVq5+U8FySkKRb/+w0EeUwA==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': + resolution: + { + integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.16': - resolution: {integrity: sha512-3Q2KQxnC8IJOLqXmUMoYwyIPZU9hzRbnHaoV3Euz+VVnjZKcY8ktnNP8T9R4/GGQtb27C/UYKABxesKWb8lsvQ==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': + resolution: + { + integrity: sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.16': - resolution: {integrity: sha512-tj7XRemQcOcFwv7qhpUxMTBbI5mWMlE4c1Omhg5+h8GuLXzyj8HviYgR+bB2DMDgRqUE+jiDleqSCRjx4aYk/Q==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': + resolution: + { + integrity: sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.16': - resolution: {integrity: sha512-PH5DRZT+F4f2PTXRXR8uJxnBq2po/xFtddyabTJVJs/ZYVHqXPEgNIr35IHTEa6bpa0Q8Awg+ymkTaGnKITw4g==} - engines: {node: ^20.19.0 || >=22.12.0} + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': + resolution: + { + integrity: sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg== + } + engines: { node: ^20.19.0 || >=22.12.0 } cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-rc.16': - resolution: {integrity: sha512-45+YtqxLYKDWQouLKCrpIZhke+nXxhsw+qAHVzHDVwttyBlHNBVs2K25rDXrZzhpTp9w1FlAlvweV1H++fdZoA==} + '@rolldown/pluginutils@1.0.0-rc.17': + resolution: + { + integrity: sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg== + } '@rollup/pluginutils@4.2.1': - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} + resolution: + { + integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== + } + engines: { node: '>= 8.0.0' } '@rollup/pluginutils@5.3.0': - resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q== + } + engines: { node: '>=14.0.0' } peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: @@ -799,157 +1139,241 @@ packages: optional: true '@rollup/rollup-android-arm-eabi@4.59.0': - resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} + resolution: + { + integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg== + } cpu: [arm] os: [android] '@rollup/rollup-android-arm64@4.59.0': - resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + resolution: + { + integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q== + } cpu: [arm64] os: [android] '@rollup/rollup-darwin-arm64@4.59.0': - resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + resolution: + { + integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg== + } cpu: [arm64] os: [darwin] '@rollup/rollup-darwin-x64@4.59.0': - resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + resolution: + { + integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w== + } cpu: [x64] os: [darwin] '@rollup/rollup-freebsd-arm64@4.59.0': - resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} + resolution: + { + integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA== + } cpu: [arm64] os: [freebsd] '@rollup/rollup-freebsd-x64@4.59.0': - resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + resolution: + { + integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg== + } cpu: [x64] os: [freebsd] '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + resolution: + { + integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw== + } cpu: [arm] os: [linux] libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.59.0': - resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} + resolution: + { + integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA== + } cpu: [arm] os: [linux] libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.59.0': - resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + resolution: + { + integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA== + } cpu: [arm64] os: [linux] libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.59.0': - resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + resolution: + { + integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA== + } cpu: [arm64] os: [linux] libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.59.0': - resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} + resolution: + { + integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg== + } cpu: [loong64] os: [linux] libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.59.0': - resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} + resolution: + { + integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q== + } cpu: [loong64] os: [linux] libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.59.0': - resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + resolution: + { + integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA== + } cpu: [ppc64] os: [linux] libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.59.0': - resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} + resolution: + { + integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA== + } cpu: [ppc64] os: [linux] libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.59.0': - resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} + resolution: + { + integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg== + } cpu: [riscv64] os: [linux] libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.59.0': - resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} + resolution: + { + integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg== + } cpu: [riscv64] os: [linux] libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.59.0': - resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + resolution: + { + integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w== + } cpu: [s390x] os: [linux] libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.59.0': - resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} + resolution: + { + integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg== + } cpu: [x64] os: [linux] libc: [glibc] '@rollup/rollup-linux-x64-musl@4.59.0': - resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + resolution: + { + integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg== + } cpu: [x64] os: [linux] libc: [musl] '@rollup/rollup-openbsd-x64@4.59.0': - resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} + resolution: + { + integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ== + } cpu: [x64] os: [openbsd] '@rollup/rollup-openharmony-arm64@4.59.0': - resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + resolution: + { + integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA== + } cpu: [arm64] os: [openharmony] '@rollup/rollup-win32-arm64-msvc@4.59.0': - resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} + resolution: + { + integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A== + } cpu: [arm64] os: [win32] '@rollup/rollup-win32-ia32-msvc@4.59.0': - resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} + resolution: + { + integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA== + } cpu: [ia32] os: [win32] '@rollup/rollup-win32-x64-gnu@4.59.0': - resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + resolution: + { + integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA== + } cpu: [x64] os: [win32] '@rollup/rollup-win32-x64-msvc@4.59.0': - resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + resolution: + { + integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA== + } cpu: [x64] os: [win32] '@sindresorhus/is@0.7.0': - resolution: {integrity: sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== + } + engines: { node: '>=4' } '@table-library/react-table-library@4.1.15': - resolution: {integrity: sha512-c/FY88KbPhAqt+eFy+TnLsFVn9ntAdQrosZ08/T6QpoCUrESlaBFbMOeWvNSV1F4KyUo0RccSJAoSVbJYL5QlA==} + resolution: + { + integrity: sha512-c/FY88KbPhAqt+eFy+TnLsFVn9ntAdQrosZ08/T6QpoCUrESlaBFbMOeWvNSV1F4KyUo0RccSJAoSVbJYL5QlA== + } peerDependencies: '@emotion/react': '>= 11' react: '>=16.8.0' react-dom: '>=16.8.0' '@trivago/prettier-plugin-sort-imports@6.0.2': - resolution: {integrity: sha512-3DgfkukFyC/sE/VuYjaUUWoFfuVjPK55vOFDsxD56XXynFMCZDYFogH2l/hDfOsQAm1myoU/1xByJ3tWqtulXA==} - engines: {node: '>= 20'} + resolution: + { + integrity: sha512-3DgfkukFyC/sE/VuYjaUUWoFfuVjPK55vOFDsxD56XXynFMCZDYFogH2l/hDfOsQAm1myoU/1xByJ3tWqtulXA== + } + engines: { node: '>= 20' } peerDependencies: '@vue/compiler-sfc': 3.x prettier: 2.x - 3.x @@ -967,450 +1391,788 @@ packages: optional: true '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + resolution: + { + integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== + } '@types/esrecurse@4.3.1': - resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + resolution: + { + integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw== + } '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + resolution: + { + integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + } '@types/glob@7.2.0': - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + resolution: + { + integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + } '@types/imagemin-gifsicle@7.0.4': - resolution: {integrity: sha512-ZghMBd/Jgqg5utTJNPmvf6DkuHzMhscJ8vgf/7MUGCpO+G+cLrhYltL+5d+h3A1B4W73S2SrmJZ1jS5LACpX+A==} + resolution: + { + integrity: sha512-ZghMBd/Jgqg5utTJNPmvf6DkuHzMhscJ8vgf/7MUGCpO+G+cLrhYltL+5d+h3A1B4W73S2SrmJZ1jS5LACpX+A== + } '@types/imagemin-jpegtran@5.0.4': - resolution: {integrity: sha512-PSMxOeJa8q94Y+qx8Yriw+qj1+vH5xWpvar63o6SGO0Xi5RlKuwHHfJmN2GRUngPrlhe394jOUmpVq8jQlVmFA==} + resolution: + { + integrity: sha512-PSMxOeJa8q94Y+qx8Yriw+qj1+vH5xWpvar63o6SGO0Xi5RlKuwHHfJmN2GRUngPrlhe394jOUmpVq8jQlVmFA== + } '@types/imagemin-mozjpeg@8.0.4': - resolution: {integrity: sha512-ZCAxV8SYJB8ehwHpnbRpHjg5Wc4HcyuAMiDhXbkgC7gujDoOTyHO3dhDkUtZ1oK1DLBRZapqG9etdLVhUml7yQ==} + resolution: + { + integrity: sha512-ZCAxV8SYJB8ehwHpnbRpHjg5Wc4HcyuAMiDhXbkgC7gujDoOTyHO3dhDkUtZ1oK1DLBRZapqG9etdLVhUml7yQ== + } '@types/imagemin-optipng@5.2.4': - resolution: {integrity: sha512-mvKnDMC8eCYZetAQudjs1DbgpR84WhsTx1wgvdiXnpuUEti3oJ+MaMYBRWPY0JlQ4+y4TXKOfa7+LOuT8daegQ==} + resolution: + { + integrity: sha512-mvKnDMC8eCYZetAQudjs1DbgpR84WhsTx1wgvdiXnpuUEti3oJ+MaMYBRWPY0JlQ4+y4TXKOfa7+LOuT8daegQ== + } '@types/imagemin-svgo@10.0.5': - resolution: {integrity: sha512-9U2Rf7vWBHeqJvzmWNP3vYAKqR0208QqQ9Mkrq9OLIL5AeoF/dRVRou6iUYCufBSim57BpBpCJhZLrTgfS3k1g==} + resolution: + { + integrity: sha512-9U2Rf7vWBHeqJvzmWNP3vYAKqR0208QqQ9Mkrq9OLIL5AeoF/dRVRou6iUYCufBSim57BpBpCJhZLrTgfS3k1g== + } '@types/imagemin-webp@7.0.3': - resolution: {integrity: sha512-C2/EMohS4bzsvY5VJvdzHFdcfmnZoui54DmM/9bFtK57/CgGmKkc+p6n49euPGmMFDDvwm4yVl60nwxcZOmH5A==} + resolution: + { + integrity: sha512-C2/EMohS4bzsvY5VJvdzHFdcfmnZoui54DmM/9bFtK57/CgGmKkc+p6n49euPGmMFDDvwm4yVl60nwxcZOmH5A== + } '@types/imagemin@7.0.1': - resolution: {integrity: sha512-xEn5+M3lDBtI3JxLy6eU3ksoVurygnlG7OYhTqJfGGP4PcvYnfn+IABCmMve7ziM/SneHDm5xgJFKC8hCYPicw==} + resolution: + { + integrity: sha512-xEn5+M3lDBtI3JxLy6eU3ksoVurygnlG7OYhTqJfGGP4PcvYnfn+IABCmMve7ziM/SneHDm5xgJFKC8hCYPicw== + } '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + resolution: + { + integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + } '@types/keyv@3.1.4': - resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + resolution: + { + integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== + } '@types/minimatch@6.0.0': - resolution: {integrity: sha512-zmPitbQ8+6zNutpwgcQuLcsEpn/Cj54Kbn7L5pX0Os5kdWplB7xPgEh/g+SWOB/qmows2gpuCaPyduq8ZZRnxA==} + resolution: + { + integrity: sha512-zmPitbQ8+6zNutpwgcQuLcsEpn/Cj54Kbn7L5pX0Os5kdWplB7xPgEh/g+SWOB/qmows2gpuCaPyduq8ZZRnxA== + } deprecated: This is a stub types definition. minimatch provides its own type definitions, so you do not need this installed. '@types/node@25.6.0': - resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==} + resolution: + { + integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ== + } '@types/parse-json@4.0.2': - resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + resolution: + { + integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== + } '@types/prop-types@15.7.15': - resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} + resolution: + { + integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw== + } '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + resolution: + { + integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ== + } peerDependencies: '@types/react': ^19.2.0 '@types/react-transition-group@4.4.12': - resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==} + resolution: + { + integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w== + } peerDependencies: '@types/react': '*' '@types/react@19.2.14': - resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + resolution: + { + integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w== + } '@types/responselike@1.0.3': - resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + resolution: + { + integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw== + } '@types/svgo@2.6.4': - resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} + resolution: + { + integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng== + } - '@typescript-eslint/eslint-plugin@8.59.0': - resolution: {integrity: sha512-HyAZtpdkgZwpq8Sz3FSUvCR4c+ScbuWa9AksK2Jweub7w4M3yTz4O11AqVJzLYjy/B9ZWPyc81I+mOdJU/bDQw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/eslint-plugin@8.59.1': + resolution: + { + integrity: sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: - '@typescript-eslint/parser': ^8.59.0 + '@typescript-eslint/parser': ^8.59.1 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.59.0': - resolution: {integrity: sha512-TI1XGwKbDpo9tRW8UDIXCOeLk55qe9ZFGs8MTKU6/M08HWTw52DD/IYhfQtOEhEdPhLMT26Ka/x7p70nd3dzDg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/parser@8.59.1': + resolution: + { + integrity: sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.59.0': - resolution: {integrity: sha512-Lw5ITrR5s5TbC19YSvlr63ZfLaJoU6vtKTHyB0GQOpX0W7d5/Ir6vUahWi/8Sps/nOukZQ0IB3SmlxZnjaKVnw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/project-service@8.59.1': + resolution: + { + integrity: sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.59.0': - resolution: {integrity: sha512-UzR16Ut8IpA3Mc4DbgAShlPPkVm8xXMWafXxB0BocaVRHs8ZGakAxGRskF7FId3sdk9lgGD73GSFaWmWFDE4dg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.59.1': + resolution: + { + integrity: sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - '@typescript-eslint/tsconfig-utils@8.59.0': - resolution: {integrity: sha512-91Sbl3s4Kb3SybliIY6muFBmHVv+pYXfybC4Oolp3dvk8BvIE3wOPc+403CWIT7mJNkfQRGtdqghzs2+Z91Tqg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.59.1': + resolution: + { + integrity: sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.59.0': - resolution: {integrity: sha512-3TRiZaQSltGqGeNrJzzr1+8YcEobKH9rHnqIp/1psfKFmhRQDNMGP5hBufanYTGznwShzVLs3Mz+gDN7HkWfXg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/type-utils@8.59.1': + resolution: + { + integrity: sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.59.0': - resolution: {integrity: sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.59.1': + resolution: + { + integrity: sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - '@typescript-eslint/typescript-estree@8.59.0': - resolution: {integrity: sha512-O9Re9P1BmBLFJyikRbQpLku/QA3/AueZNO9WePLBwQrvkixTmDe8u76B6CYUAITRl/rHawggEqUGn5QIkVRLMw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.59.1': + resolution: + { + integrity: sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.59.0': - resolution: {integrity: sha512-I1R/K7V07XsMJ12Oaxg/O9GfrysGTmCRhvZJBv0RE0NcULMzjqVpR5kRRQjHsz3J/bElU7HwCO7zkqL+MSUz+g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/utils@8.59.1': + resolution: + { + integrity: sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.59.0': - resolution: {integrity: sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.59.1': + resolution: + { + integrity: sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + resolution: + { + integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + } peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 acorn@8.16.0: - resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} - engines: {node: '>=0.4.0'} + resolution: + { + integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== + } + engines: { node: '>=0.4.0' } hasBin: true - ajv@6.14.0: - resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} + ajv@6.15.0: + resolution: + { + integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw== + } alova@3.5.1: - resolution: {integrity: sha512-avrWPyFFWW51YLoy0S3OleNw1BV0GqNI+DSdWHfFbAoKZp80cXCCc7OtjA6OWeyhCOMglUMwo9O8j5huwnzFtQ==} - engines: {node: '>= 18.0.0'} + resolution: + { + integrity: sha512-avrWPyFFWW51YLoy0S3OleNw1BV0GqNI+DSdWHfFbAoKZp80cXCCc7OtjA6OWeyhCOMglUMwo9O8j5huwnzFtQ== + } + engines: { node: '>= 18.0.0' } ansi-regex@2.1.1: - resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + } + engines: { node: '>=0.10.0' } ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + } + engines: { node: '>=8' } ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + } + engines: { node: '>=12' } ansi-styles@2.2.1: - resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + } + engines: { node: '>=0.10.0' } ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + } + engines: { node: '>=8' } ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + } + engines: { node: '>=12' } arch@2.2.0: - resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + resolution: + { + integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== + } archive-type@4.0.0: - resolution: {integrity: sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA== + } + engines: { node: '>=4' } array-find-index@1.0.2: - resolution: {integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw== + } + engines: { node: '>=0.10.0' } array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - - asap@2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + resolution: + { + integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + } + engines: { node: '>=8' } async-validator@4.2.5: - resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + resolution: + { + integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg== + } available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - axe-core@4.11.3: - resolution: {integrity: sha512-zBQouZixDTbo3jMGqHKyePxYxr1e5W8UdTmBQ7sNtaA9M2bE32daxxPLS/jojhKOHxQ7LWwPjfiwf/fhaJWzlg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + } + engines: { node: '>= 0.4' } babel-plugin-macros@3.1.0: - resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} - engines: {node: '>=10', npm: '>=6'} + resolution: + { + integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== + } + engines: { node: '>=10', npm: '>=6' } babel-plugin-transform-hook-names@1.0.2: - resolution: {integrity: sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==} + resolution: + { + integrity: sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw== + } peerDependencies: '@babel/core': ^7.12.10 balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + resolution: + { + integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + } balanced-match@4.0.4: - resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} - engines: {node: 18 || 20 || >=22} + resolution: + { + integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA== + } + engines: { node: 18 || 20 || >=22 } base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + resolution: + { + integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + } - baseline-browser-mapping@2.10.20: - resolution: {integrity: sha512-1AaXxEPfXT+GvTBJFuy4yXVHWJBXa4OdbIebGN/wX5DlsIkU0+wzGnd2lOzokSk51d5LUmqjgBLRLlypLUqInQ==} - engines: {node: '>=6.0.0'} + baseline-browser-mapping@2.10.24: + resolution: + { + integrity: sha512-I2NkZOOrj2XuguvWCK6OVh9GavsNjZjK908Rq3mIBK25+GD8vPX5w2WdxVqnQ7xx3SrZJiCiZFu+/Oz50oSYSA== + } + engines: { node: '>=6.0.0' } hasBin: true bin-build@3.0.0: - resolution: {integrity: sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA== + } + engines: { node: '>=4' } bin-check@4.1.0: - resolution: {integrity: sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA== + } + engines: { node: '>=4' } bin-version-check@4.0.0: - resolution: {integrity: sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ== + } + engines: { node: '>=6' } bin-version@3.1.0: - resolution: {integrity: sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ== + } + engines: { node: '>=6' } bin-wrapper@4.1.0: - resolution: {integrity: sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q== + } + engines: { node: '>=6' } bl@1.2.3: - resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} + resolution: + { + integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + } boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + resolution: + { + integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + } brace-expansion@1.1.14: - resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==} + resolution: + { + integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g== + } brace-expansion@2.1.0: - resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==} + resolution: + { + integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== + } brace-expansion@5.0.5: - resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} - engines: {node: 18 || 20 || >=22} + resolution: + { + integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ== + } + engines: { node: 18 || 20 || >=22 } braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + } + engines: { node: '>=8' } browserslist@4.28.2: - resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + resolution: + { + integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg== + } + engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } hasBin: true buffer-alloc-unsafe@1.1.0: - resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} + resolution: + { + integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + } buffer-alloc@1.2.0: - resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==} + resolution: + { + integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + } buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + resolution: + { + integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + } buffer-fill@1.0.0: - resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} + resolution: + { + integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== + } buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + resolution: + { + integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + } buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + resolution: + { + integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + } bundle-name@4.1.0: - resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== + } + engines: { node: '>=18' } cacheable-request@2.1.4: - resolution: {integrity: sha512-vag0O2LKZ/najSoUwDbVlnlCFvhBE/7mGTY2B5FgCBDcRD+oVV1HYTOwM6JZfMg/hIcM6IwnTZ1uQQL5/X3xIQ==} + resolution: + { + integrity: sha512-vag0O2LKZ/najSoUwDbVlnlCFvhBE/7mGTY2B5FgCBDcRD+oVV1HYTOwM6JZfMg/hIcM6IwnTZ1uQQL5/X3xIQ== + } call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + } + engines: { node: '>= 0.4' } call-bind@1.0.9: - resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ== + } + engines: { node: '>= 0.4' } call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + } + engines: { node: '>= 0.4' } callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + } + engines: { node: '>=6' } camelcase-keys@2.1.0: - resolution: {integrity: sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ== + } + engines: { node: '>=0.10.0' } camelcase@2.1.1: - resolution: {integrity: sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw== + } + engines: { node: '>=0.10.0' } - caniuse-lite@1.0.30001790: - resolution: {integrity: sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw==} + caniuse-lite@1.0.30001791: + resolution: + { + integrity: sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ== + } caw@2.0.1: - resolution: {integrity: sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA== + } + engines: { node: '>=4' } chalk@1.1.3: - resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + } + engines: { node: '>=0.10.0' } chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + } + engines: { node: '>=10' } cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + } + engines: { node: '>=12' } cliui@9.0.1: - resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} - engines: {node: '>=20'} + resolution: + { + integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w== + } + engines: { node: '>=20' } clone-response@1.0.2: - resolution: {integrity: sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==} + resolution: + { + integrity: sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q== + } clsx@1.1.1: - resolution: {integrity: sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== + } + engines: { node: '>=6' } clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + } + engines: { node: '>=6' } color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + resolution: + { + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + } + engines: { node: '>=7.0.0' } color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + resolution: + { + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + } commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + resolution: + { + integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + } commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} + resolution: + { + integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + } + engines: { node: '>= 10' } concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + resolution: + { + integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + } concurrently@9.2.1: - resolution: {integrity: sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng== + } + engines: { node: '>=18' } hasBin: true config-chain@1.1.13: - resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + resolution: + { + integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== + } console-stream@0.1.1: - resolution: {integrity: sha512-QC/8l9e6ofi6nqZ5PawlDgzmMw3OxIXtvolBzap/F4UDBJlDaZRSNbL/lb41C29FcbSJncBFlJFj2WJoNyZRfQ==} + resolution: + { + integrity: sha512-QC/8l9e6ofi6nqZ5PawlDgzmMw3OxIXtvolBzap/F4UDBJlDaZRSNbL/lb41C29FcbSJncBFlJFj2WJoNyZRfQ== + } content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + } + engines: { node: '>= 0.6' } convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + resolution: + { + integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + } convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + resolution: + { + integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + } cookie@1.1.1: - resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ== + } + engines: { node: '>=18' } core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + resolution: + { + integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + } cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== + } + engines: { node: '>=10' } cross-spawn@5.1.0: - resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + resolution: + { + integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A== + } cross-spawn@6.0.6: - resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} - engines: {node: '>=4.8'} + resolution: + { + integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw== + } + engines: { node: '>=4.8' } cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + } + engines: { node: '>= 8' } css-select@4.3.0: - resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + resolution: + { + integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== + } css-select@5.2.2: - resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + resolution: + { + integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw== + } css-tree@1.1.3: - resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} - engines: {node: '>=8.0.0'} + resolution: + { + integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + } + engines: { node: '>=8.0.0' } css-what@6.2.2: - resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA== + } + engines: { node: '>= 6' } csso@4.2.0: - resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} - engines: {node: '>=8.0.0'} + resolution: + { + integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== + } + engines: { node: '>=8.0.0' } csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + resolution: + { + integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ== + } currently-unhandled@0.4.1: - resolution: {integrity: sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng== + } + engines: { node: '>=0.10.0' } cwebp-bin@6.1.2: - resolution: {integrity: sha512-NLEZ/BVAl9g426hwUX/qrQ7b/EfQH7BS1tr+CzPo2EgDQbcdzmUVE+fIfsi64lsL638lWgzTEViMAL4pxV1GOg==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-NLEZ/BVAl9g426hwUX/qrQ7b/EfQH7BS1tr+CzPo2EgDQbcdzmUVE+fIfsi64lsL638lWgzTEViMAL4pxV1GOg== + } + engines: { node: '>=10' } hasBin: true debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} + resolution: + { + integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + } + engines: { node: '>=6.0' } peerDependencies: supports-color: '*' peerDependenciesMeta: @@ -1418,305 +2180,503 @@ packages: optional: true decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + } + engines: { node: '>=0.10.0' } decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} + resolution: + { + integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + } + engines: { node: '>=0.10' } decompress-response@3.3.0: - resolution: {integrity: sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== + } + engines: { node: '>=4' } decompress-tar@4.1.1: - resolution: {integrity: sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== + } + engines: { node: '>=4' } decompress-tarbz2@4.1.1: - resolution: {integrity: sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== + } + engines: { node: '>=4' } decompress-targz@4.1.1: - resolution: {integrity: sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== + } + engines: { node: '>=4' } decompress-unzip@4.0.1: - resolution: {integrity: sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw== + } + engines: { node: '>=4' } decompress@4.2.1: - resolution: {integrity: sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== + } + engines: { node: '>=4' } deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + resolution: + { + integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + } default-browser-id@5.0.1: - resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q== + } + engines: { node: '>=18' } default-browser@5.5.0: - resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw== + } + engines: { node: '>=18' } define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + } + engines: { node: '>= 0.4' } define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + } + engines: { node: '>=12' } detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - - dezalgo@1.0.4: - resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + resolution: + { + integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + } + engines: { node: '>=8' } dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + } + engines: { node: '>=8' } dom-helpers@5.2.1: - resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + resolution: + { + integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + } dom-serializer@1.4.1: - resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + resolution: + { + integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== + } dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + resolution: + { + integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + } domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + resolution: + { + integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + } domhandler@4.3.1: - resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + } + engines: { node: '>= 4' } domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + } + engines: { node: '>= 4' } domutils@2.8.0: - resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + resolution: + { + integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + } domutils@3.2.2: - resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + resolution: + { + integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== + } download@6.2.5: - resolution: {integrity: sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA== + } + engines: { node: '>=4' } download@7.1.0: - resolution: {integrity: sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ== + } + engines: { node: '>=6' } dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + } + engines: { node: '>= 0.4' } duplexer3@0.1.5: - resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==} + resolution: + { + integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== + } - electron-to-chromium@1.5.343: - resolution: {integrity: sha512-YHnQ3MXI08icvL9ZKnEBy05F2EQ8ob01UaMOuMbM8l+4UcAq6MPPbBTJBbsBUg3H8JeZNt+O4fjsoWth3p6IFg==} + electron-to-chromium@1.5.344: + resolution: + { + integrity: sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg== + } emoji-regex@10.6.0: - resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + resolution: + { + integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A== + } emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + resolution: + { + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + } end-of-stream@1.4.5: - resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + resolution: + { + integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + } entities@2.2.0: - resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + resolution: + { + integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + } entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} + resolution: + { + integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + } + engines: { node: '>=0.12' } error-ex@1.3.4: - resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + resolution: + { + integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== + } es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + } + engines: { node: '>= 0.4' } es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + } + engines: { node: '>= 0.4' } es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + } + engines: { node: '>= 0.4' } esbuild-android-64@0.14.54: - resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ== + } + engines: { node: '>=12' } cpu: [x64] os: [android] esbuild-android-arm64@0.14.54: - resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg== + } + engines: { node: '>=12' } cpu: [arm64] os: [android] esbuild-darwin-64@0.14.54: - resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug== + } + engines: { node: '>=12' } cpu: [x64] os: [darwin] esbuild-darwin-arm64@0.14.54: - resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw== + } + engines: { node: '>=12' } cpu: [arm64] os: [darwin] esbuild-freebsd-64@0.14.54: - resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg== + } + engines: { node: '>=12' } cpu: [x64] os: [freebsd] esbuild-freebsd-arm64@0.14.54: - resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q== + } + engines: { node: '>=12' } cpu: [arm64] os: [freebsd] esbuild-linux-32@0.14.54: - resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw== + } + engines: { node: '>=12' } cpu: [ia32] os: [linux] esbuild-linux-64@0.14.54: - resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg== + } + engines: { node: '>=12' } cpu: [x64] os: [linux] esbuild-linux-arm64@0.14.54: - resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig== + } + engines: { node: '>=12' } cpu: [arm64] os: [linux] esbuild-linux-arm@0.14.54: - resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw== + } + engines: { node: '>=12' } cpu: [arm] os: [linux] esbuild-linux-mips64le@0.14.54: - resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw== + } + engines: { node: '>=12' } cpu: [mips64el] os: [linux] esbuild-linux-ppc64le@0.14.54: - resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ== + } + engines: { node: '>=12' } cpu: [ppc64] os: [linux] esbuild-linux-riscv64@0.14.54: - resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg== + } + engines: { node: '>=12' } cpu: [riscv64] os: [linux] esbuild-linux-s390x@0.14.54: - resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA== + } + engines: { node: '>=12' } cpu: [s390x] os: [linux] esbuild-netbsd-64@0.14.54: - resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w== + } + engines: { node: '>=12' } cpu: [x64] os: [netbsd] esbuild-openbsd-64@0.14.54: - resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw== + } + engines: { node: '>=12' } cpu: [x64] os: [openbsd] esbuild-sunos-64@0.14.54: - resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw== + } + engines: { node: '>=12' } cpu: [x64] os: [sunos] esbuild-windows-32@0.14.54: - resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w== + } + engines: { node: '>=12' } cpu: [ia32] os: [win32] esbuild-windows-64@0.14.54: - resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ== + } + engines: { node: '>=12' } cpu: [x64] os: [win32] esbuild-windows-arm64@0.14.54: - resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg== + } + engines: { node: '>=12' } cpu: [arm64] os: [win32] esbuild@0.14.54: - resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA== + } + engines: { node: '>=12' } hasBin: true esbuild@0.27.4: - resolution: {integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ== + } + engines: { node: '>=18' } hasBin: true escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + } + engines: { node: '>=6' } escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} + resolution: + { + integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + } + engines: { node: '>=0.8.0' } escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + } + engines: { node: '>=10' } eslint-config-prettier@10.1.8: - resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + resolution: + { + integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w== + } hasBin: true peerDependencies: eslint: '>=7.0.0' eslint-scope@9.1.2: - resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ== + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + resolution: + { + integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } eslint-visitor-keys@5.0.1: - resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA== + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } eslint@10.2.1: - resolution: {integrity: sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q== + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } hasBin: true peerDependencies: jiti: '*' @@ -1725,90 +2685,159 @@ packages: optional: true espree@11.2.0: - resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw== + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } esquery@1.7.0: - resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} - engines: {node: '>=0.10'} + resolution: + { + integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== + } + engines: { node: '>=0.10' } esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} + resolution: + { + integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + } + engines: { node: '>=4.0' } estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} + resolution: + { + integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + } + engines: { node: '>=4.0' } estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + resolution: + { + integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + } esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + } + engines: { node: '>=0.10.0' } etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + } + engines: { node: '>= 0.6' } exec-buffer@3.2.0: - resolution: {integrity: sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA== + } + engines: { node: '>=4' } execa@0.7.0: - resolution: {integrity: sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw== + } + engines: { node: '>=4' } execa@1.0.0: - resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + } + engines: { node: '>=6' } execa@4.1.0: - resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + } + engines: { node: '>=10' } execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + } + engines: { node: '>=10' } executable@4.1.1: - resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== + } + engines: { node: '>=4' } ext-list@2.2.2: - resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA== + } + engines: { node: '>=0.10.0' } ext-name@5.0.0: - resolution: {integrity: sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ== + } + engines: { node: '>=4' } fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + resolution: + { + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + } fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} + resolution: + { + integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + } + engines: { node: '>=8.6.0' } fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + resolution: + { + integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + } fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + resolution: + { + integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + } fast-xml-parser@4.5.6: - resolution: {integrity: sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A==} + resolution: + { + integrity: sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A== + } hasBin: true fastq@1.20.1: - resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + resolution: + { + integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw== + } fd-slicer@1.1.0: - resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + resolution: + { + integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== + } fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} + resolution: + { + integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + } + engines: { node: '>=12.0.0' } peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -1816,981 +2845,1727 @@ packages: optional: true figures@1.7.0: - resolution: {integrity: sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ== + } + engines: { node: '>=0.10.0' } file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} + resolution: + { + integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + } + engines: { node: '>=16.0.0' } file-type@10.11.0: - resolution: {integrity: sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw== + } + engines: { node: '>=6' } file-type@12.4.2: - resolution: {integrity: sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg== + } + engines: { node: '>=8' } file-type@3.9.0: - resolution: {integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA== + } + engines: { node: '>=0.10.0' } file-type@4.4.0: - resolution: {integrity: sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ== + } + engines: { node: '>=4' } file-type@5.2.0: - resolution: {integrity: sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ== + } + engines: { node: '>=4' } file-type@6.2.0: - resolution: {integrity: sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== + } + engines: { node: '>=4' } file-type@8.1.0: - resolution: {integrity: sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ== + } + engines: { node: '>=6' } filename-reserved-regex@2.0.0: - resolution: {integrity: sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ== + } + engines: { node: '>=4' } filenamify@2.1.0: - resolution: {integrity: sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA== + } + engines: { node: '>=4' } fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + } + engines: { node: '>=8' } find-root@1.1.0: - resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + resolution: + { + integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + } find-up@1.1.2: - resolution: {integrity: sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== + } + engines: { node: '>=0.10.0' } find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + } + engines: { node: '>=10' } find-versions@3.2.0: - resolution: {integrity: sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== + } + engines: { node: '>=6' } flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} + resolution: + { + integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + } + engines: { node: '>=16' } flatted@3.4.2: - resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + resolution: + { + integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA== + } for-each@0.3.5: - resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} - engines: {node: '>= 0.4'} - - formidable@3.5.4: - resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + } + engines: { node: '>= 0.4' } from2@2.3.0: - resolution: {integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==} + resolution: + { + integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g== + } fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + resolution: + { + integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + } fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + } + engines: { node: '>=12' } fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + resolution: + { + integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + } fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + resolution: + { + integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } os: [darwin] function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + resolution: + { + integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + } gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} + 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.*} + resolution: + { + integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + } + engines: { node: 6.* || 8.* || >= 10.* } get-east-asian-width@1.5.0: - resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA== + } + engines: { node: '>=18' } get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + } + engines: { node: '>= 0.4' } get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + } + engines: { node: '>= 0.4' } get-proxy@2.1.0: - resolution: {integrity: sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw== + } + engines: { node: '>=4' } get-stdin@4.0.1: - resolution: {integrity: sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw== + } + engines: { node: '>=0.10.0' } get-stream@2.3.1: - resolution: {integrity: sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA== + } + engines: { node: '>=0.10.0' } get-stream@3.0.0: - resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== + } + engines: { node: '>=4' } get-stream@4.1.0: - resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + } + engines: { node: '>=6' } get-stream@5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + } + engines: { node: '>=8' } get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + } + engines: { node: '>=10' } gifsicle@5.2.0: - resolution: {integrity: sha512-vOIS3j0XoTCxq9pkGj43gEix82RkI5FveNgaFZutjbaui/HH+4fR8Y56dwXDuxYo8hR4xOo6/j2h1WHoQW6XLw==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-vOIS3j0XoTCxq9pkGj43gEix82RkI5FveNgaFZutjbaui/HH+4fR8Y56dwXDuxYo8hR4xOo6/j2h1WHoQW6XLw== + } + engines: { node: '>=10' } hasBin: true glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + } + engines: { node: '>= 6' } glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} + resolution: + { + integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + } + engines: { node: '>=10.13.0' } glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + resolution: + { + integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + } deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me globby@10.0.2: - resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + } + engines: { node: '>=8' } gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + } + engines: { node: '>= 0.4' } got@7.1.0: - resolution: {integrity: sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== + } + engines: { node: '>=4' } got@8.3.2: - resolution: {integrity: sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw== + } + engines: { node: '>=4' } graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + resolution: + { + integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + } has-ansi@2.0.0: - resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + } + engines: { node: '>=0.10.0' } has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + } + engines: { node: '>=8' } has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + resolution: + { + integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + } has-symbol-support-x@1.4.2: - resolution: {integrity: sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==} + resolution: + { + integrity: sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== + } has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + } + engines: { node: '>= 0.4' } has-to-string-tag-x@1.4.1: - resolution: {integrity: sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==} + resolution: + { + integrity: sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== + } has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + } + engines: { node: '>= 0.4' } hasown@2.0.3: - resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg== + } + engines: { node: '>= 0.4' } he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + resolution: + { + integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + } hasBin: true hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + resolution: + { + integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + } hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + resolution: + { + integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + } http-cache-semantics@3.8.1: - resolution: {integrity: sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==} + resolution: + { + integrity: sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + } human-signals@1.1.1: - resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} - engines: {node: '>=8.12.0'} + resolution: + { + integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + } + engines: { node: '>=8.12.0' } human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} + resolution: + { + integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + } + engines: { node: '>=10.17.0' } ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + resolution: + { + integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + } ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + } + engines: { node: '>= 4' } ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + } + engines: { node: '>= 4' } imagemin-gifsicle@7.0.0: - resolution: {integrity: sha512-LaP38xhxAwS3W8PFh4y5iQ6feoTSF+dTAXFRUEYQWYst6Xd+9L/iPk34QGgK/VO/objmIlmq9TStGfVY2IcHIA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-LaP38xhxAwS3W8PFh4y5iQ6feoTSF+dTAXFRUEYQWYst6Xd+9L/iPk34QGgK/VO/objmIlmq9TStGfVY2IcHIA== + } + engines: { node: '>=10' } imagemin-jpegtran@7.0.0: - resolution: {integrity: sha512-MJoyTCW8YjMJf56NorFE41SR/WkaGA3IYk4JgvMlRwguJEEd3PnP9UxA8Y2UWjquz8d+On3Ds/03ZfiiLS8xTQ==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-MJoyTCW8YjMJf56NorFE41SR/WkaGA3IYk4JgvMlRwguJEEd3PnP9UxA8Y2UWjquz8d+On3Ds/03ZfiiLS8xTQ== + } + engines: { node: '>=10' } imagemin-mozjpeg@9.0.0: - resolution: {integrity: sha512-TwOjTzYqCFRgROTWpVSt5UTT0JeCuzF1jswPLKALDd89+PmrJ2PdMMYeDLYZ1fs9cTovI9GJd68mRSnuVt691w==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-TwOjTzYqCFRgROTWpVSt5UTT0JeCuzF1jswPLKALDd89+PmrJ2PdMMYeDLYZ1fs9cTovI9GJd68mRSnuVt691w== + } + engines: { node: '>=10' } imagemin-optipng@8.0.0: - resolution: {integrity: sha512-CUGfhfwqlPjAC0rm8Fy+R2DJDBGjzy2SkfyT09L8rasnF9jSoHFqJ1xxSZWK6HVPZBMhGPMxCTL70OgTHlLF5A==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-CUGfhfwqlPjAC0rm8Fy+R2DJDBGjzy2SkfyT09L8rasnF9jSoHFqJ1xxSZWK6HVPZBMhGPMxCTL70OgTHlLF5A== + } + engines: { node: '>=10' } imagemin-pngquant@9.0.2: - resolution: {integrity: sha512-cj//bKo8+Frd/DM8l6Pg9pws1pnDUjgb7ae++sUX1kUVdv2nrngPykhiUOgFeE0LGY/LmUbCf4egCHC4YUcZSg==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-cj//bKo8+Frd/DM8l6Pg9pws1pnDUjgb7ae++sUX1kUVdv2nrngPykhiUOgFeE0LGY/LmUbCf4egCHC4YUcZSg== + } + engines: { node: '>=10' } imagemin-svgo@9.0.0: - resolution: {integrity: sha512-uNgXpKHd99C0WODkrJ8OO/3zW3qjgS4pW7hcuII0RcHN3tnKxDjJWcitdVC/TZyfIqSricU8WfrHn26bdSW62g==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-uNgXpKHd99C0WODkrJ8OO/3zW3qjgS4pW7hcuII0RcHN3tnKxDjJWcitdVC/TZyfIqSricU8WfrHn26bdSW62g== + } + engines: { node: '>=10' } imagemin-webp@6.1.0: - resolution: {integrity: sha512-i8ZluZV1pfQX9aVzmZ/VZh9KBSdPwUlp5VruAa9c30GZnX/nMl5n7h+oUMnI7Mg7+SUpu9mYBsw2nsYGUEllWQ==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-i8ZluZV1pfQX9aVzmZ/VZh9KBSdPwUlp5VruAa9c30GZnX/nMl5n7h+oUMnI7Mg7+SUpu9mYBsw2nsYGUEllWQ== + } + engines: { node: '>=10' } imagemin@7.0.1: - resolution: {integrity: sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w== + } + engines: { node: '>=8' } import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + } + engines: { node: '>=6' } import-lazy@3.1.0: - resolution: {integrity: sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ== + } + engines: { node: '>=6' } imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} + resolution: + { + integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + } + engines: { node: '>=0.8.19' } indent-string@2.1.0: - resolution: {integrity: sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg== + } + engines: { node: '>=0.10.0' } inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + resolution: + { + integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + } deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + resolution: + { + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + } ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + resolution: + { + integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + } into-stream@3.1.0: - resolution: {integrity: sha512-TcdjPibTksa1NQximqep2r17ISRiNE9fwlfbg3F8ANdvP5/yrFTew86VcO//jk4QTaMlbjypPBq76HN2zaKfZQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-TcdjPibTksa1NQximqep2r17ISRiNE9fwlfbg3F8ANdvP5/yrFTew86VcO//jk4QTaMlbjypPBq76HN2zaKfZQ== + } + engines: { node: '>=4' } is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + resolution: + { + integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + } is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + } + engines: { node: '>= 0.4' } is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + } + engines: { node: '>= 0.4' } is-cwebp-readable@3.0.0: - resolution: {integrity: sha512-bpELc7/Q1/U5MWHn4NdHI44R3jxk0h9ew9ljzabiRl70/UIjL/ZAqRMb52F5+eke/VC8yTiv4Ewryo1fPWidvA==} + resolution: + { + integrity: sha512-bpELc7/Q1/U5MWHn4NdHI44R3jxk0h9ew9ljzabiRl70/UIjL/ZAqRMb52F5+eke/VC8yTiv4Ewryo1fPWidvA== + } is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } hasBin: true is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + } + engines: { node: '>=0.10.0' } is-finite@1.1.0: - resolution: {integrity: sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + } + engines: { node: '>=0.10.0' } is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + } + engines: { node: '>=8' } is-gif@3.0.0: - resolution: {integrity: sha512-IqJ/jlbw5WJSNfwQ/lHEDXF8rxhRgF6ythk2oiEvhpG29F704eX9NO6TvPfMiq9DrbwgcEDnETYNcZDPewQoVw==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-IqJ/jlbw5WJSNfwQ/lHEDXF8rxhRgF6ythk2oiEvhpG29F704eX9NO6TvPfMiq9DrbwgcEDnETYNcZDPewQoVw== + } + engines: { node: '>=6' } is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + } + engines: { node: '>=0.10.0' } is-in-ssh@1.0.0: - resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==} - engines: {node: '>=20'} + resolution: + { + integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw== + } + engines: { node: '>=20' } is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + } + engines: { node: '>=14.16' } hasBin: true is-jpg@2.0.0: - resolution: {integrity: sha512-ODlO0ruzhkzD3sdynIainVP5eoOFNN85rxA1+cwwnPe4dKyX0r5+hxNO5XpCrxlHcmb9vkOit9mhRD2JVuimHg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-ODlO0ruzhkzD3sdynIainVP5eoOFNN85rxA1+cwwnPe4dKyX0r5+hxNO5XpCrxlHcmb9vkOit9mhRD2JVuimHg== + } + engines: { node: '>=6' } is-natural-number@4.0.1: - resolution: {integrity: sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==} + resolution: + { + integrity: sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ== + } is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} + resolution: + { + integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + } + engines: { node: '>=0.12.0' } is-object@1.0.2: - resolution: {integrity: sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==} + resolution: + { + integrity: sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== + } is-plain-obj@1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + } + engines: { node: '>=0.10.0' } is-png@2.0.0: - resolution: {integrity: sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g== + } + engines: { node: '>=8' } is-retry-allowed@1.2.0: - resolution: {integrity: sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== + } + engines: { node: '>=0.10.0' } is-stream@1.1.0: - resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + } + engines: { node: '>=0.10.0' } is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + } + engines: { node: '>=8' } is-svg@4.4.0: - resolution: {integrity: sha512-v+AgVwiK5DsGtT9ng+m4mClp6zDAmwrW8nZi6Gg15qzvBnRWWdfWA1TGaXyCDnWq5g5asofIgMVl3PjKxvk1ug==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-v+AgVwiK5DsGtT9ng+m4mClp6zDAmwrW8nZi6Gg15qzvBnRWWdfWA1TGaXyCDnWq5g5asofIgMVl3PjKxvk1ug== + } + engines: { node: '>=6' } is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + } + engines: { node: '>= 0.4' } is-utf8@0.2.1: - resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==} + resolution: + { + integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== + } is-wsl@3.1.1: - resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} - engines: {node: '>=16'} + resolution: + { + integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw== + } + engines: { node: '>=16' } isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + resolution: + { + integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + } isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + resolution: + { + integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + } isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + resolution: + { + integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + } isurl@1.0.0: - resolution: {integrity: sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== + } + engines: { node: '>= 4' } javascript-natural-sort@0.7.1: - resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} + resolution: + { + integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== + } jpegtran-bin@5.0.2: - resolution: {integrity: sha512-4FSmgIcr8d5+V6T1+dHbPZjaFH0ogVyP4UVsE+zri7S9YLO4qAT2our4IN3sW3STVgNTbqPermdIgt2XuAJ4EA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-4FSmgIcr8d5+V6T1+dHbPZjaFH0ogVyP4UVsE+zri7S9YLO4qAT2our4IN3sW3STVgNTbqPermdIgt2XuAJ4EA== + } + engines: { node: '>=10' } hasBin: true jpegtran-bin@6.0.1: - resolution: {integrity: sha512-WohhhHhqe22de7PU8hXs6Sr5d4BAvkrfA93NR5tGlHyPnFLgvEW/bH+q7fv65JgoiQDsd7SBwwQ/OGRBivU3Mw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-WohhhHhqe22de7PU8hXs6Sr5d4BAvkrfA93NR5tGlHyPnFLgvEW/bH+q7fv65JgoiQDsd7SBwwQ/OGRBivU3Mw== + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } hasBin: true js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + resolution: + { + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + } jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + } + engines: { node: '>=6' } hasBin: true json-buffer@3.0.0: - resolution: {integrity: sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==} + resolution: + { + integrity: sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== + } json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + resolution: + { + integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + } json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + resolution: + { + integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + } json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + resolution: + { + integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + } json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + resolution: + { + integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + } json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + } + engines: { node: '>=6' } hasBin: true jsonfile@6.2.1: - resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + resolution: + { + integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q== + } junk@3.1.0: - resolution: {integrity: sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== + } + engines: { node: '>=8' } jwt-decode@4.0.0: - resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA== + } + engines: { node: '>=18' } keyv@3.0.0: - resolution: {integrity: sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==} + resolution: + { + integrity: sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA== + } keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + resolution: + { + integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + } kolorist@1.8.0: - resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + resolution: + { + integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + } levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} + resolution: + { + integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + } + engines: { node: '>= 0.8.0' } lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg== + } + engines: { node: '>= 12.0.0' } cpu: [arm64] os: [android] lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ== + } + engines: { node: '>= 12.0.0' } cpu: [arm64] os: [darwin] lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w== + } + engines: { node: '>= 12.0.0' } cpu: [x64] os: [darwin] lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig== + } + engines: { node: '>= 12.0.0' } cpu: [x64] os: [freebsd] lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw== + } + engines: { node: '>= 12.0.0' } cpu: [arm] os: [linux] lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ== + } + engines: { node: '>= 12.0.0' } cpu: [arm64] os: [linux] libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg== + } + engines: { node: '>= 12.0.0' } cpu: [arm64] os: [linux] libc: [musl] lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA== + } + engines: { node: '>= 12.0.0' } cpu: [x64] os: [linux] libc: [glibc] lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg== + } + engines: { node: '>= 12.0.0' } cpu: [x64] os: [linux] libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw== + } + engines: { node: '>= 12.0.0' } cpu: [arm64] os: [win32] lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q== + } + engines: { node: '>= 12.0.0' } cpu: [x64] os: [win32] lightningcss@1.32.0: - resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ== + } + engines: { node: '>= 12.0.0' } lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + resolution: + { + integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + } load-json-file@1.1.0: - resolution: {integrity: sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== + } + engines: { node: '>=0.10.0' } locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + } + engines: { node: '>=10' } lodash-es@4.18.1: - resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + resolution: + { + integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A== + } logalot@2.1.0: - resolution: {integrity: sha512-Ah4CgdSRfeCJagxQhcVNMi9BfGYyEKLa6d7OA6xSbld/Hg3Cf2QiOa1mDpmG7Ve8LOH6DN3mdttzjQAvWTyVkw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-Ah4CgdSRfeCJagxQhcVNMi9BfGYyEKLa6d7OA6xSbld/Hg3Cf2QiOa1mDpmG7Ve8LOH6DN3mdttzjQAvWTyVkw== + } + engines: { node: '>=0.10.0' } longest@1.0.1: - resolution: {integrity: sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg== + } + engines: { node: '>=0.10.0' } loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + resolution: + { + integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + } hasBin: true loud-rejection@1.6.0: - resolution: {integrity: sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ== + } + engines: { node: '>=0.10.0' } lowercase-keys@1.0.0: - resolution: {integrity: sha512-RPlX0+PHuvxVDZ7xX+EBVAp4RsVxP/TdDSN2mJYdiq1Lc4Hz7EUSjUI7RZrKKlmrIzVhf6Jo2stj7++gVarS0A==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-RPlX0+PHuvxVDZ7xX+EBVAp4RsVxP/TdDSN2mJYdiq1Lc4Hz7EUSjUI7RZrKKlmrIzVhf6Jo2stj7++gVarS0A== + } + engines: { node: '>=0.10.0' } lowercase-keys@1.0.1: - resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + } + engines: { node: '>=0.10.0' } lpad-align@1.1.2: - resolution: {integrity: sha512-MMIcFmmR9zlGZtBcFOows6c2COMekHCIFJz3ew/rRpKZ1wR4mXDPzvcVqLarux8M33X4TPSq2Jdw8WJj0q0KbQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-MMIcFmmR9zlGZtBcFOows6c2COMekHCIFJz3ew/rRpKZ1wR4mXDPzvcVqLarux8M33X4TPSq2Jdw8WJj0q0KbQ== + } + engines: { node: '>=0.10.0' } hasBin: true lru-cache@4.1.5: - resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + resolution: + { + integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + } lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + resolution: + { + integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + } magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + resolution: + { + integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + } make-dir@1.3.0: - resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + } + engines: { node: '>=4' } make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + } + engines: { node: '>=8' } map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== + } + engines: { node: '>=0.10.0' } math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + } + engines: { node: '>= 0.4' } mdn-data@2.0.14: - resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + resolution: + { + integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + } memoize-one@5.2.1: - resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} + resolution: + { + integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + } meow@3.7.0: - resolution: {integrity: sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA== + } + engines: { node: '>=0.10.0' } merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + resolution: + { + integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + } merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + } + engines: { node: '>= 8' } micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} + resolution: + { + integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + } + engines: { node: '>=8.6' } mime-db@1.54.0: - resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== + } + engines: { node: '>= 0.6' } mime-types@3.0.2: - resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A== + } + engines: { node: '>=18' } mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + } + engines: { node: '>=6' } mimic-response@1.0.1: - resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + } + engines: { node: '>=4' } minimatch@10.2.5: - resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} - engines: {node: 18 || 20 || >=22} + resolution: + { + integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg== + } + engines: { node: 18 || 20 || >=22 } minimatch@3.1.5: - resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + resolution: + { + integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== + } minimatch@9.0.9: - resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} - engines: {node: '>=16 || 14 >=14.17'} + resolution: + { + integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== + } + engines: { node: '>=16 || 14 >=14.17' } minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + resolution: + { + integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + } mozjpeg@7.1.1: - resolution: {integrity: sha512-iIDxWvzhWvLC9mcRJ1uSkiKaj4drF58oCqK2bITm5c2Jt6cJ8qQjSSru2PCaysG+hLIinryj8mgz5ZJzOYTv1A==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-iIDxWvzhWvLC9mcRJ1uSkiKaj4drF58oCqK2bITm5c2Jt6cJ8qQjSSru2PCaysG+hLIinryj8mgz5ZJzOYTv1A== + } + engines: { node: '>=10' } hasBin: true ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + resolution: + { + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + } nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + resolution: + { + integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + } + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } hasBin: true natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + resolution: + { + integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + } nice-try@1.0.5: - resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + resolution: + { + integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + } node-html-parser@6.1.13: - resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==} + resolution: + { + integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg== + } node-releases@2.0.38: - resolution: {integrity: sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==} + resolution: + { + integrity: sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw== + } normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + resolution: + { + integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + } normalize-url@2.0.1: - resolution: {integrity: sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== + } + engines: { node: '>=4' } npm-conf@1.1.3: - resolution: {integrity: sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== + } + engines: { node: '>=4' } npm-run-path@2.0.2: - resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== + } + engines: { node: '>=4' } npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + } + engines: { node: '>=8' } nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + resolution: + { + integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + } object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + } + engines: { node: '>=0.10.0' } once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + resolution: + { + integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + } onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + } + engines: { node: '>=6' } open@11.0.0: - resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==} - engines: {node: '>=20'} + resolution: + { + integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw== + } + engines: { node: '>=20' } optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} + resolution: + { + integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + } + engines: { node: '>= 0.8.0' } optipng-bin@7.0.1: - resolution: {integrity: sha512-W99mpdW7Nt2PpFiaO+74pkht7KEqkXkeRomdWXfEz3SALZ6hns81y/pm1dsGZ6ItUIfchiNIP6ORDr1zETU1jA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-W99mpdW7Nt2PpFiaO+74pkht7KEqkXkeRomdWXfEz3SALZ6hns81y/pm1dsGZ6ItUIfchiNIP6ORDr1zETU1jA== + } + engines: { node: '>=10' } hasBin: true os-filter-obj@2.0.0: - resolution: {integrity: sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg== + } + engines: { node: '>=4' } ow@0.17.0: - resolution: {integrity: sha512-i3keDzDQP5lWIe4oODyDFey1qVrq2hXKTuTH2VpqwpYtzPiKZt2ziRI4NBQmgW40AnV5Euz17OyWweCb+bNEQA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-i3keDzDQP5lWIe4oODyDFey1qVrq2hXKTuTH2VpqwpYtzPiKZt2ziRI4NBQmgW40AnV5Euz17OyWweCb+bNEQA== + } + engines: { node: '>=10' } p-cancelable@0.3.0: - resolution: {integrity: sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== + } + engines: { node: '>=4' } p-cancelable@0.4.1: - resolution: {integrity: sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== + } + engines: { node: '>=4' } p-event@1.3.0: - resolution: {integrity: sha512-hV1zbA7gwqPVFcapfeATaNjQ3J0NuzorHPyG8GPL9g/Y/TplWVBVoCKCXL6Ej2zscrCEv195QNWJXuBH6XZuzA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-hV1zbA7gwqPVFcapfeATaNjQ3J0NuzorHPyG8GPL9g/Y/TplWVBVoCKCXL6Ej2zscrCEv195QNWJXuBH6XZuzA== + } + engines: { node: '>=4' } p-event@2.3.1: - resolution: {integrity: sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA== + } + engines: { node: '>=6' } p-finally@1.0.0: - resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + } + engines: { node: '>=4' } p-is-promise@1.1.0: - resolution: {integrity: sha512-zL7VE4JVS2IFSkR2GQKDSPEVxkoH43/p7oEnwpdCndKYJO0HVeRB7fA8TJwuLOTBREtK0ea8eHaxdwcpob5dmg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-zL7VE4JVS2IFSkR2GQKDSPEVxkoH43/p7oEnwpdCndKYJO0HVeRB7fA8TJwuLOTBREtK0ea8eHaxdwcpob5dmg== + } + engines: { node: '>=4' } p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + } + engines: { node: '>=10' } p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + } + engines: { node: '>=10' } p-map-series@1.0.0: - resolution: {integrity: sha512-4k9LlvY6Bo/1FcIdV33wqZQES0Py+iKISU9Uc8p8AjWoZPnFKMpVIVD3s0EYn4jzLh1I+WeUZkJ0Yoa4Qfw3Kg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-4k9LlvY6Bo/1FcIdV33wqZQES0Py+iKISU9Uc8p8AjWoZPnFKMpVIVD3s0EYn4jzLh1I+WeUZkJ0Yoa4Qfw3Kg== + } + engines: { node: '>=4' } p-pipe@3.1.0: - resolution: {integrity: sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw== + } + engines: { node: '>=8' } p-reduce@1.0.0: - resolution: {integrity: sha512-3Tx1T3oM1xO/Y8Gj0sWyE78EIJZ+t+aEmXUdvQgvGmSMri7aPTHoovbXEreWKkL5j21Er60XAWLTzKbAKYOujQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-3Tx1T3oM1xO/Y8Gj0sWyE78EIJZ+t+aEmXUdvQgvGmSMri7aPTHoovbXEreWKkL5j21Er60XAWLTzKbAKYOujQ== + } + engines: { node: '>=4' } p-timeout@1.2.1: - resolution: {integrity: sha512-gb0ryzr+K2qFqFv6qi3khoeqMZF/+ajxQipEF6NteZVnvz9tzdsfAVj3lYtn1gAXvH5lfLwfxEII799gt/mRIA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-gb0ryzr+K2qFqFv6qi3khoeqMZF/+ajxQipEF6NteZVnvz9tzdsfAVj3lYtn1gAXvH5lfLwfxEII799gt/mRIA== + } + engines: { node: '>=4' } p-timeout@2.0.1: - resolution: {integrity: sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA== + } + engines: { node: '>=4' } parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + } + engines: { node: '>=6' } parse-imports-exports@0.2.4: - resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==} + resolution: + { + integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ== + } parse-json@2.2.0: - resolution: {integrity: sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== + } + engines: { node: '>=0.10.0' } parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + } + engines: { node: '>=8' } parse-statements@1.0.11: - resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} + resolution: + { + integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA== + } path-exists@2.1.0: - resolution: {integrity: sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== + } + engines: { node: '>=0.10.0' } path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + } + engines: { node: '>=8' } path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + } + engines: { node: '>=0.10.0' } path-key@2.0.1: - resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + } + engines: { node: '>=4' } path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + } + engines: { node: '>=8' } path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + resolution: + { + integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + } path-type@1.1.0: - resolution: {integrity: sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== + } + engines: { node: '>=0.10.0' } path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + } + engines: { node: '>=8' } pathe@0.2.0: - resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} + resolution: + { + integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw== + } pend@1.2.0: - resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + resolution: + { + integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== + } picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + resolution: + { + integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + } picomatch@2.3.2: - resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} - engines: {node: '>=8.6'} + resolution: + { + integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== + } + engines: { node: '>=8.6' } picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== + } + engines: { node: '>=12' } pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + } + engines: { node: '>=0.10.0' } pify@3.0.0: - resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== + } + engines: { node: '>=4' } pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + } + engines: { node: '>=6' } pinkie-promise@2.0.1: - resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== + } + engines: { node: '>=0.10.0' } pinkie@2.0.4: - resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== + } + engines: { node: '>=0.10.0' } pngquant-bin@6.0.1: - resolution: {integrity: sha512-Q3PUyolfktf+hYio6wsg3SanQzEU/v8aICg/WpzxXcuCMRb7H2Q81okfpcEztbMvw25ILjd3a87doj2N9kvbpQ==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-Q3PUyolfktf+hYio6wsg3SanQzEU/v8aICg/WpzxXcuCMRb7H2Q81okfpcEztbMvw25ILjd3a87doj2N9kvbpQ== + } + engines: { node: '>=10' } hasBin: true possible-typed-array-names@1.1.0: - resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + } + engines: { node: '>= 0.4' } - postcss@8.5.10: - resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==} - engines: {node: ^10 || ^12 || >=14} + postcss@8.5.12: + resolution: + { + integrity: sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA== + } + engines: { node: ^10 || ^12 || >=14 } powershell-utils@0.1.0: - resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} - engines: {node: '>=20'} + resolution: + { + integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A== + } + engines: { node: '>=20' } preact@10.29.1: - resolution: {integrity: sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==} + resolution: + { + integrity: sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg== + } prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} + resolution: + { + integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + } + engines: { node: '>= 0.8.0' } prepend-http@1.0.4: - resolution: {integrity: sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg== + } + engines: { node: '>=0.10.0' } prepend-http@2.0.0: - resolution: {integrity: sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== + } + engines: { node: '>=4' } prettier@3.8.3: - resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==} - engines: {node: '>=14'} + resolution: + { + integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw== + } + engines: { node: '>=14' } hasBin: true process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + resolution: + { + integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + } prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + resolution: + { + integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + } proto-list@1.2.4: - resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + resolution: + { + integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== + } pseudomap@1.0.2: - resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + resolution: + { + integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + } pump@3.0.4: - resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + resolution: + { + integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA== + } punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + } + engines: { node: '>=6' } query-string@5.1.1: - resolution: {integrity: sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + } + engines: { node: '>=0.10.0' } queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + resolution: + { + integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + } rate-limiter-flexible@5.0.5: - resolution: {integrity: sha512-+/dSQfo+3FYwYygUs/V2BBdwGa9nFtakDwKt4l0bnvNB53TNT++QSFewwHX9qXrZJuMe9j+TUaU21lm5ARgqdQ==} + resolution: + { + integrity: sha512-+/dSQfo+3FYwYygUs/V2BBdwGa9nFtakDwKt4l0bnvNB53TNT++QSFewwHX9qXrZJuMe9j+TUaU21lm5ARgqdQ== + } react-dom@19.2.5: - resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==} + resolution: + { + integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag== + } peerDependencies: react: ^19.2.5 react-icons@5.6.0: - resolution: {integrity: sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA==} + resolution: + { + integrity: sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA== + } peerDependencies: react: '*' react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + resolution: + { + integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + } react-is@19.2.5: - resolution: {integrity: sha512-Dn0t8IQhCmeIT3wu+Apm1/YVsJXsGWi6k4sPdnBIdqMVtHtv0IGi6dcpNpNkNac0zB2uUAqNX3MHzN8c+z2rwQ==} + resolution: + { + integrity: sha512-Dn0t8IQhCmeIT3wu+Apm1/YVsJXsGWi6k4sPdnBIdqMVtHtv0IGi6dcpNpNkNac0zB2uUAqNX3MHzN8c+z2rwQ== + } react-router@7.14.2: - resolution: {integrity: sha512-yCqNne6I8IB6rVCH7XUvlBK7/QKyqypBFGv+8dj4QBFJiiRX+FG7/nkdAvGElyvVZ/HQP5N19wzteuTARXi5Gw==} - engines: {node: '>=20.0.0'} + resolution: + { + integrity: sha512-yCqNne6I8IB6rVCH7XUvlBK7/QKyqypBFGv+8dj4QBFJiiRX+FG7/nkdAvGElyvVZ/HQP5N19wzteuTARXi5Gw== + } + engines: { node: '>=20.0.0' } peerDependencies: react: '>=18' react-dom: '>=18' @@ -2799,90 +4574,147 @@ packages: optional: true react-toastify@11.1.0: - resolution: {integrity: sha512-e9h23x3phN0wbFeB6yovmWp7lobzV4CaCH0LO8nVP6H7Y+3GbcLpIzMm9dJhcp1RXbpyfvjgpfXqO80QAmn7sg==} + resolution: + { + integrity: sha512-e9h23x3phN0wbFeB6yovmWp7lobzV4CaCH0LO8nVP6H7Y+3GbcLpIzMm9dJhcp1RXbpyfvjgpfXqO80QAmn7sg== + } peerDependencies: react: ^18 || ^19 react-dom: ^18 || ^19 react-transition-group@4.4.5: - resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + resolution: + { + integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + } peerDependencies: react: '>=16.6.0' react-dom: '>=16.6.0' react-virtualized-auto-sizer@1.0.26: - resolution: {integrity: sha512-CblNyiNVw2o+hsa5/49NH2ogGxZ+t+3aweRvNSq7TVjDIlwk7ir4lencEg5HxHeSzwNarSkNkiu0qJSOXtxm5A==} + resolution: + { + integrity: sha512-CblNyiNVw2o+hsa5/49NH2ogGxZ+t+3aweRvNSq7TVjDIlwk7ir4lencEg5HxHeSzwNarSkNkiu0qJSOXtxm5A== + } peerDependencies: react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0 react-window@1.8.11: - resolution: {integrity: sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ==} - engines: {node: '>8.0.0'} + resolution: + { + integrity: sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ== + } + engines: { node: '>8.0.0' } peerDependencies: react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react@19.2.5: - resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA== + } + engines: { node: '>=0.10.0' } read-pkg-up@1.0.1: - resolution: {integrity: sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== + } + engines: { node: '>=0.10.0' } read-pkg@1.1.0: - resolution: {integrity: sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== + } + engines: { node: '>=0.10.0' } readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + resolution: + { + integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + } redent@1.0.0: - resolution: {integrity: sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g== + } + engines: { node: '>=0.10.0' } repeating@2.0.1: - resolution: {integrity: sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== + } + engines: { node: '>=0.10.0' } replace-ext@1.0.1: - resolution: {integrity: sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== + } + engines: { node: '>= 0.10' } require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + } + engines: { node: '>=0.10.0' } resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + } + engines: { node: '>=4' } resolve@1.22.12: - resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA== + } + engines: { node: '>= 0.4' } hasBin: true responselike@1.0.2: - resolution: {integrity: sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==} + resolution: + { + integrity: sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== + } reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + resolution: + { + integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + } + engines: { iojs: '>=1.0.0', node: '>=0.10.0' } rimraf@2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + resolution: + { + integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + } deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rolldown@1.0.0-rc.16: - resolution: {integrity: sha512-rzi5WqKzEZw3SooTt7cgm4eqIoujPIyGcJNGFL7iPEuajQw7vxMHUkXylu4/vhCkJGXsgRmxqMKXUpT6FEgl0g==} - engines: {node: ^20.19.0 || >=22.12.0} + rolldown@1.0.0-rc.17: + resolution: + { + integrity: sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA== + } + engines: { node: ^20.19.0 || >=22.12.0 } hasBin: true rollup-plugin-visualizer@7.0.1: - resolution: {integrity: sha512-UJUT4+1Ho4OcWmPYU3sYXgUqI8B8Ayfe06MX7y0qCJ1K8aGoKtR/NDd/2nZqM7ADkrzny+I99Ul7GgyoiVNAgg==} - engines: {node: '>=22'} + resolution: + { + integrity: sha512-UJUT4+1Ho4OcWmPYU3sYXgUqI8B8Ayfe06MX7y0qCJ1K8aGoKtR/NDd/2nZqM7ADkrzny+I99Ul7GgyoiVNAgg== + } + engines: { node: '>=22' } hasBin: true peerDependencies: rolldown: 1.x || ^1.0.0-beta || ^1.0.0-rc @@ -2894,373 +4726,655 @@ packages: optional: true rollup@4.59.0: - resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} + resolution: + { + integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg== + } + engines: { node: '>=18.0.0', npm: '>=8.0.0' } hasBin: true run-applescript@7.1.0: - resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q== + } + engines: { node: '>=18' } run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + resolution: + { + integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + } rxjs@7.8.2: - resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + resolution: + { + integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== + } safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + resolution: + { + integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + } safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + resolution: + { + integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + } sax@1.6.0: - resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} - engines: {node: '>=11.0.0'} + resolution: + { + integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA== + } + engines: { node: '>=11.0.0' } scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + resolution: + { + integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q== + } seek-bzip@1.0.6: - resolution: {integrity: sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==} + resolution: + { + integrity: sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ== + } hasBin: true semver-regex@2.0.0: - resolution: {integrity: sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== + } + engines: { node: '>=6' } semver-truncate@1.1.2: - resolution: {integrity: sha512-V1fGg9i4CL3qesB6U0L6XAm4xOJiHmt4QAacazumuasc03BvtFGIMCduv01JWQ69Nv+JST9TqhSCiJoxoY031w==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-V1fGg9i4CL3qesB6U0L6XAm4xOJiHmt4QAacazumuasc03BvtFGIMCduv01JWQ69Nv+JST9TqhSCiJoxoY031w== + } + engines: { node: '>=0.10.0' } semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + resolution: + { + integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + } hasBin: true semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + resolution: + { + integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + } hasBin: true semver@7.7.4: - resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== + } + engines: { node: '>=10' } hasBin: true set-cookie-parser@2.7.2: - resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + resolution: + { + integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw== + } set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + } + engines: { node: '>= 0.4' } shebang-command@1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + } + engines: { node: '>=0.10.0' } shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + } + engines: { node: '>=8' } shebang-regex@1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + } + engines: { node: '>=0.10.0' } shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + } + engines: { node: '>=8' } shell-quote@1.8.3: - resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw== + } + engines: { node: '>= 0.4' } signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + resolution: + { + integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + } simple-code-frame@1.3.0: - resolution: {integrity: sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w==} + resolution: + { + integrity: sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w== + } slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + } + engines: { node: '>=8' } sort-keys-length@1.0.1: - resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw== + } + engines: { node: '>=0.10.0' } sort-keys@1.1.2: - resolution: {integrity: sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg== + } + engines: { node: '>=0.10.0' } sort-keys@2.0.0: - resolution: {integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg== + } + engines: { node: '>=4' } source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + } + engines: { node: '>=0.10.0' } source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + resolution: + { + integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + } source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + } + engines: { node: '>=0.10.0' } source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + } + engines: { node: '>=0.10.0' } source-map@0.7.6: - resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} - engines: {node: '>= 12'} + resolution: + { + integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ== + } + engines: { node: '>= 12' } spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + resolution: + { + integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + } spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + resolution: + { + integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== + } spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + resolution: + { + integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + } spdx-license-ids@3.0.23: - resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} + resolution: + { + integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw== + } squeak@1.3.0: - resolution: {integrity: sha512-YQL1ulInM+ev8nXX7vfXsCsDh6IqXlrremc1hzi77776BtpWgYJUMto3UM05GSAaGzJgWekszjoKDrVNB5XG+A==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-YQL1ulInM+ev8nXX7vfXsCsDh6IqXlrremc1hzi77776BtpWgYJUMto3UM05GSAaGzJgWekszjoKDrVNB5XG+A== + } + engines: { node: '>=0.10.0' } stable@0.1.8: - resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + resolution: + { + integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + } deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' stack-trace@1.0.0-pre2: - resolution: {integrity: sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A==} - engines: {node: '>=16'} + resolution: + { + integrity: sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A== + } + engines: { node: '>=16' } strict-uri-encode@1.1.0: - resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== + } + engines: { node: '>=0.10.0' } string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + } + engines: { node: '>=8' } string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + } + engines: { node: '>=18' } string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + resolution: + { + integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + } strip-ansi@3.0.1: - resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + } + engines: { node: '>=0.10.0' } strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + } + engines: { node: '>=8' } strip-ansi@7.2.0: - resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w== + } + engines: { node: '>=12' } strip-bom@2.0.0: - resolution: {integrity: sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== + } + engines: { node: '>=0.10.0' } strip-dirs@2.1.0: - resolution: {integrity: sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==} + resolution: + { + integrity: sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== + } strip-eof@1.0.0: - resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== + } + engines: { node: '>=0.10.0' } strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + } + engines: { node: '>=6' } strip-indent@1.0.1: - resolution: {integrity: sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA== + } + engines: { node: '>=0.10.0' } hasBin: true strip-outer@1.0.1: - resolution: {integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== + } + engines: { node: '>=0.10.0' } strnum@1.1.2: - resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} + resolution: + { + integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA== + } stylis@4.2.0: - resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + resolution: + { + integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + } supports-color@2.0.0: - resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} - engines: {node: '>=0.8.0'} + resolution: + { + integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + } + engines: { node: '>=0.8.0' } supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + } + engines: { node: '>=8' } supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + } + engines: { node: '>=10' } supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + } + engines: { node: '>= 0.4' } svgo@2.8.2: - resolution: {integrity: sha512-TyzE4NVGLUFy+H/Uy4N6c3G0HEeprsVfge6Lmq+0FdQQ/zqoVYB62IsBZORsiL+o96s6ff/V6/3UQo/C0cgCAA==} - engines: {node: '>=10.13.0'} + resolution: + { + integrity: sha512-TyzE4NVGLUFy+H/Uy4N6c3G0HEeprsVfge6Lmq+0FdQQ/zqoVYB62IsBZORsiL+o96s6ff/V6/3UQo/C0cgCAA== + } + engines: { node: '>=10.13.0' } hasBin: true tar-stream@1.6.2: - resolution: {integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==} - engines: {node: '>= 0.8.0'} + resolution: + { + integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + } + engines: { node: '>= 0.8.0' } temp-dir@1.0.0: - resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ== + } + engines: { node: '>=4' } tempfile@2.0.0: - resolution: {integrity: sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA== + } + engines: { node: '>=4' } - terser@5.46.1: - resolution: {integrity: sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==} - engines: {node: '>=10'} + terser@5.46.2: + resolution: + { + integrity: sha512-uxfo9fPcSgLDYob/w1FuL0c99MWiJDnv+5qXSQc5+Ki5NjVNsYi66INnMFBjf6uFz6OnX12piJQPF4IpjJTNTw== + } + engines: { node: '>=10' } hasBin: true through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + resolution: + { + integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + } timed-out@4.0.1: - resolution: {integrity: sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== + } + engines: { node: '>=0.10.0' } tinyglobby@0.2.16: - resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} - engines: {node: '>=12.0.0'} + resolution: + { + integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg== + } + engines: { node: '>=12.0.0' } to-buffer@1.2.2: - resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw== + } + engines: { node: '>= 0.4' } to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + resolution: + { + integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + } + engines: { node: '>=8.0' } tree-kill@1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + resolution: + { + integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + } hasBin: true trim-newlines@1.0.0: - resolution: {integrity: sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw== + } + engines: { node: '>=0.10.0' } trim-repeated@1.0.0: - resolution: {integrity: sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg== + } + engines: { node: '>=0.10.0' } ts-api-utils@2.5.0: - resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} - engines: {node: '>=18.12'} + resolution: + { + integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA== + } + engines: { node: '>=18.12' } peerDependencies: typescript: '>=4.8.4' tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + resolution: + { + integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + } tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + resolution: + { + integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + } type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} + resolution: + { + integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + } + engines: { node: '>= 0.8.0' } type-fest@0.11.0: - resolution: {integrity: sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== + } + engines: { node: '>=8' } typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== + } + engines: { node: '>= 0.4' } typesafe-i18n@5.27.1: - resolution: {integrity: sha512-749uWo2ZXETT//kWjVYPm8QPYR8xLh8G0wLfoAyCAtAmysX67uCaAyLjAjAWojL6fuJpE5B6yIjwvO9orXzUPg==} + resolution: + { + integrity: sha512-749uWo2ZXETT//kWjVYPm8QPYR8xLh8G0wLfoAyCAtAmysX67uCaAyLjAjAWojL6fuJpE5B6yIjwvO9orXzUPg== + } hasBin: true peerDependencies: typescript: '>=3.5.1' - typescript-eslint@8.59.0: - resolution: {integrity: sha512-BU3ONW9X+v90EcCH9ZS6LMackcVtxRLlI3XrYyqZIwVSHIk7Qf7bFw1z0M9Q0IUxhTMZCf8piY9hTYaNEIASrw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + typescript-eslint@8.59.1: + resolution: + { + integrity: sha512-xqDcFVBmlrltH64lklOVp1wYxgJr6LVdg3NamBgH2OOQDLFdTKfIZXF5PfghrnXQKXZGTQs8tr1vL7fJvq8CTQ== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' typescript@6.0.3: - resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} - engines: {node: '>=14.17'} + resolution: + { + integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw== + } + engines: { node: '>=14.17' } hasBin: true unbzip2-stream@1.4.3: - resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + resolution: + { + integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== + } undici-types@7.19.2: - resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} + resolution: + { + integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg== + } universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} + resolution: + { + integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + } + engines: { node: '>= 10.0.0' } update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + resolution: + { + integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== + } hasBin: true peerDependencies: browserslist: '>= 4.21.0' uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + resolution: + { + integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + } url-parse-lax@1.0.0: - resolution: {integrity: sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA== + } + engines: { node: '>=0.10.0' } url-parse-lax@3.0.0: - resolution: {integrity: sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== + } + engines: { node: '>=4' } url-to-options@1.0.1: - resolution: {integrity: sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A== + } + engines: { node: '>= 4' } util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + resolution: + { + integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + } uuid@3.4.0: - resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + resolution: + { + integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + } deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. hasBin: true validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + resolution: + { + integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + } vite-plugin-imagemin@0.6.1: - resolution: {integrity: sha512-cP7LDn8euPrji7WYtDoNQpJEB9nkMxJHm/A+QZnvMrrCSuyo/clpMy/T1v7suDXPBavsDiDdFdVQB5p7VGD2cg==} + resolution: + { + integrity: sha512-cP7LDn8euPrji7WYtDoNQpJEB9nkMxJHm/A+QZnvMrrCSuyo/clpMy/T1v7suDXPBavsDiDdFdVQB5p7VGD2cg== + } peerDependencies: vite: '>=2.0.0' vite-prerender-plugin@0.5.13: - resolution: {integrity: sha512-IKSpYkzDBsKAxa05naRbj7GvNVMSdww/Z/E89oO3xndz+gWnOBOKOAbEXv7qDhktY/j3vHgJmoV1pPzqU2tx9g==} + resolution: + { + integrity: sha512-IKSpYkzDBsKAxa05naRbj7GvNVMSdww/Z/E89oO3xndz+gWnOBOKOAbEXv7qDhktY/j3vHgJmoV1pPzqU2tx9g== + } peerDependencies: vite: 5.x || 6.x || 7.x || 8.x - vite@8.0.9: - resolution: {integrity: sha512-t7g7GVRpMXjNpa67HaVWI/8BWtdVIQPCL2WoozXXA7LBGEFK4AkkKkHx2hAQf5x1GZSlcmEDPkVLSGahxnEEZw==} - engines: {node: ^20.19.0 || >=22.12.0} + vite@8.0.10: + resolution: + { + integrity: sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw== + } + engines: { node: ^20.19.0 || >=22.12.0 } hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 @@ -3302,83 +5416,142 @@ packages: optional: true which-typed-array@1.1.20: - resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg== + } + engines: { node: '>= 0.4' } which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + resolution: + { + integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + } hasBin: true which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + } + engines: { node: '>= 8' } hasBin: true word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + } + engines: { node: '>=0.10.0' } wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + } + engines: { node: '>=10' } wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww== + } + engines: { node: '>=18' } wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + resolution: + { + integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + } wsl-utils@0.3.1: - resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} - engines: {node: '>=20'} + resolution: + { + integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg== + } + engines: { node: '>=20' } xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} + resolution: + { + integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + } + engines: { node: '>=0.4' } y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + } + engines: { node: '>=10' } yallist@2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + resolution: + { + integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== + } yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + resolution: + { + integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + } yaml@1.10.3: - resolution: {integrity: sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA== + } + engines: { node: '>= 6' } yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + } + engines: { node: '>=12' } yargs-parser@22.0.0: - resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} + resolution: + { + integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw== + } + engines: { node: ^20.19.0 || ^22.12.0 || >=23 } yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + } + engines: { node: '>=12' } yargs@18.0.0: - resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} + resolution: + { + integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg== + } + engines: { node: ^20.19.0 || ^22.12.0 || >=23 } yauzl@2.10.0: - resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + resolution: + { + integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== + } yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + } + engines: { node: '>=10' } zimmerframe@1.1.4: - resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + resolution: + { + integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ== + } snapshots: - '@alova/adapter-xhr@2.3.1(alova@3.5.1)': dependencies: '@alova/shared': 1.3.2 @@ -3517,13 +5690,13 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@emnapi/core@1.9.2': + '@emnapi/core@1.10.0': dependencies: '@emnapi/wasi-threads': 1.2.1 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.9.2': + '@emnapi/runtime@1.10.0': dependencies: tslib: 2.8.1 optional: true @@ -3858,15 +6031,13 @@ snapshots: optionalDependencies: '@types/react': 19.2.14 - '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: - '@emnapi/core': 1.9.2 - '@emnapi/runtime': 1.9.2 + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 '@tybys/wasm-util': 0.10.1 optional: true - '@noble/hashes@1.8.0': {} - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -3879,31 +6050,23 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@oxc-project/types@0.126.0': {} - - '@paralleldrive/cuid2@2.3.1': - dependencies: - '@noble/hashes': 1.8.0 + '@oxc-project/types@0.127.0': {} '@popperjs/core@2.11.8': {} - '@preact/compat@18.3.2(preact@10.29.1)': - dependencies: - preact: 10.29.1 - - '@preact/preset-vite@2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.59.0)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1))': + '@preact/preset-vite@2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.59.0)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.29.0) - '@prefresh/vite': 2.4.12(preact@10.29.1)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1)) + '@prefresh/vite': 2.4.12(preact@10.29.1)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2)) '@rollup/pluginutils': 5.3.0(rollup@4.59.0) babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.29.0) debug: 4.4.3 magic-string: 0.30.21 picocolors: 1.1.1 - vite: 8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1) - vite-prerender-plugin: 0.5.13(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1)) + vite: 8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2) + vite-prerender-plugin: 0.5.13(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2)) zimmerframe: 1.1.4 transitivePeerDependencies: - preact @@ -3918,7 +6081,7 @@ snapshots: '@prefresh/utils@1.2.1': {} - '@prefresh/vite@2.4.12(preact@10.29.1)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1))': + '@prefresh/vite@2.4.12(preact@10.29.1)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2))': dependencies: '@babel/core': 7.29.0 '@prefresh/babel-plugin': 0.5.3 @@ -3926,60 +6089,60 @@ snapshots: '@prefresh/utils': 1.2.1 '@rollup/pluginutils': 4.2.1 preact: 10.29.1 - vite: 8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1) + vite: 8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2) transitivePeerDependencies: - supports-color - '@rolldown/binding-android-arm64@1.0.0-rc.16': + '@rolldown/binding-android-arm64@1.0.0-rc.17': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.16': + '@rolldown/binding-darwin-arm64@1.0.0-rc.17': optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.16': + '@rolldown/binding-darwin-x64@1.0.0-rc.17': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.16': + '@rolldown/binding-freebsd-x64@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.16': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.16': + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.16': + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.16': + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.16': + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.16': + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.16': + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.16': + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.16': + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': dependencies: - '@emnapi/core': 1.9.2 - '@emnapi/runtime': 1.9.2 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.16': + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.16': + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': optional: true - '@rolldown/pluginutils@1.0.0-rc.16': {} + '@rolldown/pluginutils@1.0.0-rc.17': {} '@rollup/pluginutils@4.2.1': dependencies: @@ -4175,14 +6338,14 @@ snapshots: dependencies: '@types/node': 25.6.0 - '@typescript-eslint/eslint-plugin@8.59.0(@typescript-eslint/parser@8.59.0(eslint@10.2.1)(typescript@6.0.3))(eslint@10.2.1)(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.2.1)(typescript@6.0.3))(eslint@10.2.1)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.59.0(eslint@10.2.1)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.59.0 - '@typescript-eslint/type-utils': 8.59.0(eslint@10.2.1)(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.0(eslint@10.2.1)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.59.0 + '@typescript-eslint/parser': 8.59.1(eslint@10.2.1)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.59.1 + '@typescript-eslint/type-utils': 8.59.1(eslint@10.2.1)(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.1(eslint@10.2.1)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.59.1 eslint: 10.2.1 ignore: 7.0.5 natural-compare: 1.4.0 @@ -4191,41 +6354,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.59.0(eslint@10.2.1)(typescript@6.0.3)': + '@typescript-eslint/parser@8.59.1(eslint@10.2.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.59.0 - '@typescript-eslint/types': 8.59.0 - '@typescript-eslint/typescript-estree': 8.59.0(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.59.0 + '@typescript-eslint/scope-manager': 8.59.1 + '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.59.1 debug: 4.4.3 eslint: 10.2.1 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.59.0(typescript@6.0.3)': + '@typescript-eslint/project-service@8.59.1(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.59.0(typescript@6.0.3) - '@typescript-eslint/types': 8.59.0 + '@typescript-eslint/tsconfig-utils': 8.59.1(typescript@6.0.3) + '@typescript-eslint/types': 8.59.1 debug: 4.4.3 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.59.0': + '@typescript-eslint/scope-manager@8.59.1': dependencies: - '@typescript-eslint/types': 8.59.0 - '@typescript-eslint/visitor-keys': 8.59.0 + '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/visitor-keys': 8.59.1 - '@typescript-eslint/tsconfig-utils@8.59.0(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.59.1(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.59.0(eslint@10.2.1)(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.59.1(eslint@10.2.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.59.0 - '@typescript-eslint/typescript-estree': 8.59.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.0(eslint@10.2.1)(typescript@6.0.3) + '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.1(eslint@10.2.1)(typescript@6.0.3) debug: 4.4.3 eslint: 10.2.1 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -4233,14 +6396,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.59.0': {} + '@typescript-eslint/types@8.59.1': {} - '@typescript-eslint/typescript-estree@8.59.0(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.59.1(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.59.0(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.59.0(typescript@6.0.3) - '@typescript-eslint/types': 8.59.0 - '@typescript-eslint/visitor-keys': 8.59.0 + '@typescript-eslint/project-service': 8.59.1(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.59.1(typescript@6.0.3) + '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/visitor-keys': 8.59.1 debug: 4.4.3 minimatch: 10.2.5 semver: 7.7.4 @@ -4250,20 +6413,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.59.0(eslint@10.2.1)(typescript@6.0.3)': + '@typescript-eslint/utils@8.59.1(eslint@10.2.1)(typescript@6.0.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1) - '@typescript-eslint/scope-manager': 8.59.0 - '@typescript-eslint/types': 8.59.0 - '@typescript-eslint/typescript-estree': 8.59.0(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.59.1 + '@typescript-eslint/types': 8.59.1 + '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) eslint: 10.2.1 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.59.0': + '@typescript-eslint/visitor-keys@8.59.1': dependencies: - '@typescript-eslint/types': 8.59.0 + '@typescript-eslint/types': 8.59.1 eslint-visitor-keys: 5.0.1 acorn-jsx@5.3.2(acorn@8.16.0): @@ -4272,7 +6435,7 @@ snapshots: acorn@8.16.0: {} - ajv@6.14.0: + ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 @@ -4308,16 +6471,12 @@ snapshots: array-union@2.1.0: {} - asap@2.0.6: {} - async-validator@4.2.5: {} available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 - axe-core@4.11.3: {} - babel-plugin-macros@3.1.0: dependencies: '@babel/runtime': 7.29.2 @@ -4334,7 +6493,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.10.20: {} + baseline-browser-mapping@2.10.24: {} bin-build@3.0.0: dependencies: @@ -4395,9 +6554,9 @@ snapshots: browserslist@4.28.2: dependencies: - baseline-browser-mapping: 2.10.20 - caniuse-lite: 1.0.30001790 - electron-to-chromium: 1.5.343 + baseline-browser-mapping: 2.10.24 + caniuse-lite: 1.0.30001791 + electron-to-chromium: 1.5.344 node-releases: 2.0.38 update-browserslist-db: 1.2.3(browserslist@4.28.2) @@ -4459,7 +6618,7 @@ snapshots: camelcase@2.1.1: {} - caniuse-lite@1.0.30001790: {} + caniuse-lite@1.0.30001791: {} caw@2.0.1: dependencies: @@ -4676,11 +6835,6 @@ snapshots: detect-libc@2.1.2: {} - dezalgo@1.0.4: - dependencies: - asap: 2.0.6 - wrappy: 1.0.2 - dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -4761,7 +6915,7 @@ snapshots: duplexer3@0.1.5: {} - electron-to-chromium@1.5.343: {} + electron-to-chromium@1.5.344: {} emoji-regex@10.6.0: {} @@ -4934,7 +7088,7 @@ snapshots: '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.8 - ajv: 6.14.0 + ajv: 6.15.0 cross-spawn: 7.0.6 debug: 4.4.3 escape-string-regexp: 4.0.0 @@ -5136,12 +7290,6 @@ snapshots: dependencies: is-callable: 1.2.7 - formidable@3.5.4: - dependencies: - '@paralleldrive/cuid2': 2.3.1 - dezalgo: 1.0.4 - once: 1.4.0 - from2@2.3.0: dependencies: inherits: 2.0.4 @@ -5917,7 +8065,7 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss@8.5.10: + postcss@8.5.12: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -6067,35 +8215,35 @@ snapshots: dependencies: glob: 7.2.3 - rolldown@1.0.0-rc.16: + rolldown@1.0.0-rc.17: dependencies: - '@oxc-project/types': 0.126.0 - '@rolldown/pluginutils': 1.0.0-rc.16 + '@oxc-project/types': 0.127.0 + '@rolldown/pluginutils': 1.0.0-rc.17 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.16 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.16 - '@rolldown/binding-darwin-x64': 1.0.0-rc.16 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.16 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.16 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.16 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.16 - '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.16 - '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.16 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.16 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.16 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.16 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.16 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.16 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.16 + '@rolldown/binding-android-arm64': 1.0.0-rc.17 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.17 + '@rolldown/binding-darwin-x64': 1.0.0-rc.17 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.17 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.17 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.17 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.17 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.17 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.17 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.17 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.17 - rollup-plugin-visualizer@7.0.1(rolldown@1.0.0-rc.16)(rollup@4.59.0): + rollup-plugin-visualizer@7.0.1(rolldown@1.0.0-rc.17)(rollup@4.59.0): dependencies: open: 11.0.0 picomatch: 4.0.4 source-map: 0.7.6 yargs: 18.0.0 optionalDependencies: - rolldown: 1.0.0-rc.16 + rolldown: 1.0.0-rc.17 rollup: 4.59.0 rollup@4.59.0: @@ -6339,7 +8487,7 @@ snapshots: temp-dir: 1.0.0 uuid: 3.4.0 - terser@5.46.1: + terser@5.46.2: dependencies: '@jridgewell/source-map': 0.3.11 acorn: 8.16.0 @@ -6399,12 +8547,12 @@ snapshots: dependencies: typescript: 6.0.3 - typescript-eslint@8.59.0(eslint@10.2.1)(typescript@6.0.3): + typescript-eslint@8.59.1(eslint@10.2.1)(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.59.0(@typescript-eslint/parser@8.59.0(eslint@10.2.1)(typescript@6.0.3))(eslint@10.2.1)(typescript@6.0.3) - '@typescript-eslint/parser': 8.59.0(eslint@10.2.1)(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.59.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.0(eslint@10.2.1)(typescript@6.0.3) + '@typescript-eslint/eslint-plugin': 8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.2.1)(typescript@6.0.3))(eslint@10.2.1)(typescript@6.0.3) + '@typescript-eslint/parser': 8.59.1(eslint@10.2.1)(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.1(eslint@10.2.1)(typescript@6.0.3) eslint: 10.2.1 typescript: 6.0.3 transitivePeerDependencies: @@ -6450,7 +8598,7 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - vite-plugin-imagemin@0.6.1(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1)): + vite-plugin-imagemin@0.6.1(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2)): dependencies: '@types/imagemin': 7.0.1 '@types/imagemin-gifsicle': 7.0.4 @@ -6475,11 +8623,11 @@ snapshots: imagemin-webp: 6.1.0 jpegtran-bin: 6.0.1 pathe: 0.2.0 - vite: 8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1) + vite: 8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2) transitivePeerDependencies: - supports-color - vite-prerender-plugin@0.5.13(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1)): + vite-prerender-plugin@0.5.13(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2)): dependencies: kolorist: 1.8.0 magic-string: 0.30.21 @@ -6487,20 +8635,20 @@ snapshots: simple-code-frame: 1.3.0 source-map: 0.7.6 stack-trace: 1.0.0-pre2 - vite: 8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1) + vite: 8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2) - vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.1): + vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.4)(terser@5.46.2): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.10 - rolldown: 1.0.0-rc.16 + postcss: 8.5.12 + rolldown: 1.0.0-rc.17 tinyglobby: 0.2.16 optionalDependencies: '@types/node': 25.6.0 esbuild: 0.27.4 fsevents: 2.3.3 - terser: 5.46.1 + terser: 5.46.2 which-typed-array@1.1.20: dependencies: diff --git a/interface/src/App.tsx b/interface/src/App.tsx index c92e5f9cd..b2fc2749e 100644 --- a/interface/src/App.tsx +++ b/interface/src/App.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useEffect, useState } from 'react'; +import { memo, useEffect, useState } from 'react'; import { ToastContainer, Zoom } from 'react-toastify'; import AppRouting from 'AppRouting'; @@ -46,19 +46,17 @@ const App = memo(() => { const [wasLoaded, setWasLoaded] = useState(false); const [locale, setLocale] = useState('en'); - // Memoize locale initialization to prevent unnecessary re-runs - const initializeLocale = useCallback(async () => { - const browserLocale = detectLocale('en', AVAILABLE_LOCALES, navigatorDetector); - const newLocale = (localStorage.getItem('lang') || browserLocale) as Locales; - localStorage.setItem('lang', newLocale); - setLocale(newLocale); - await loadLocaleAsync(newLocale); - setWasLoaded(true); - }, []); - useEffect(() => { + const initializeLocale = async () => { + const browserLocale = detectLocale('en', AVAILABLE_LOCALES, navigatorDetector); + const newLocale = (localStorage.getItem('lang') || browserLocale) as Locales; + localStorage.setItem('lang', newLocale); + setLocale(newLocale); + await loadLocaleAsync(newLocale); + setWasLoaded(true); + }; void initializeLocale(); - }, [initializeLocale]); + }, []); if (!wasLoaded) return null; diff --git a/interface/src/AuthenticatedRouting.tsx b/interface/src/AuthenticatedRouting.tsx index 8ace232aa..1bab479ae 100644 --- a/interface/src/AuthenticatedRouting.tsx +++ b/interface/src/AuthenticatedRouting.tsx @@ -16,6 +16,7 @@ import DownloadUpload from 'app/settings/DownloadUpload'; import MqttSettings from 'app/settings/MqttSettings'; import NTPSettings from 'app/settings/NTPSettings'; import Settings from 'app/settings/Settings'; +import Version from 'app/settings/Version'; import Network from 'app/settings/network/Network'; import Security from 'app/settings/security/Security'; import APStatus from 'app/status/APStatus'; @@ -26,7 +27,6 @@ import NTPStatus from 'app/status/NTPStatus'; import NetworkStatus from 'app/status/NetworkStatus'; import Status from 'app/status/Status'; import SystemLog from 'app/status/SystemLog'; -import Version from 'app/status/Version'; import { Layout } from 'components'; import { AuthenticatedContext } from 'contexts/authentication'; @@ -49,11 +49,11 @@ const AuthenticatedRouting = memo(() => { } /> } /> } /> - } /> {me.admin && ( <> } /> + } /> } /> } /> } /> diff --git a/interface/src/SignIn.tsx b/interface/src/SignIn.tsx index c3955d286..0b59d9d70 100644 --- a/interface/src/SignIn.tsx +++ b/interface/src/SignIn.tsx @@ -43,7 +43,6 @@ const SignIn = memo(() => { } }); - // Memoize callback to prevent recreation on every render const updateLoginRequestValue = useMemo( () => updateValue((updater) => @@ -65,7 +64,7 @@ const SignIn = memo(() => { }); }, [callSignIn, signInRequest, LL]); - const validateAndSignIn = useCallback(async () => { + const validateAndSignIn = async () => { setProcessing(true); SIGN_IN_REQUEST_VALIDATOR.messages({ required: LL.IS_REQUIRED('%s') @@ -77,7 +76,7 @@ const SignIn = memo(() => { setFieldErrors((error as ValidationError).fieldErrors); setProcessing(false); } - }, [signInRequest, signIn, LL]); + }; const submitOnEnter = useMemo(() => onEnterCallback(signIn), [signIn]); diff --git a/interface/src/api/endpoints.ts b/interface/src/api/endpoints.ts index 95d462689..db867385a 100644 --- a/interface/src/api/endpoints.ts +++ b/interface/src/api/endpoints.ts @@ -57,12 +57,3 @@ export const alovaInstance = createAlova({ onSuccess: handleResponse } }); - -export const alovaInstanceGH = createAlova({ - baseURL: - process.env.NODE_ENV === 'development' - ? '/gh' - : 'https://api.github.com/repos/emsesp/EMS-ESP32/releases', - statesHook: ReactHook, - requestAdapter: xhrRequestAdapter() -}); diff --git a/interface/src/api/system.ts b/interface/src/api/system.ts index 1b9d1a37a..43829025a 100644 --- a/interface/src/api/system.ts +++ b/interface/src/api/system.ts @@ -1,6 +1,6 @@ import type { LogSettings, SystemStatus } from 'types'; -import { alovaInstance, alovaInstanceGH } from './endpoints'; +import { alovaInstance } from './endpoints'; // systemStatus - also used to ping in System Monitor for pinging export const readSystemStatus = () => @@ -13,29 +13,6 @@ export const updateLogSettings = (data: LogSettings) => alovaInstance.Post('/rest/logSettings', data); export const fetchLogES = () => alovaInstance.Get('/es/log'); -// Get versions from GitHub -// cache for 10 minutes to stop getting the IP blocked by GitHub -export const getStableVersion = () => - alovaInstanceGH.Get('latest', { - cacheFor: 60 * 10 * 1000, - transform(response: { data: { name: string; published_at: string } }) { - return { - name: response.data.name.substring(1), - published_at: response.data.published_at - }; - } - }); -export const getDevVersion = () => - alovaInstanceGH.Get('tags/latest', { - cacheFor: 60 * 10 * 1000, - transform(response: { data: { name: string; published_at: string } }) { - return { - name: response.data.name.split(/\s+/).splice(-1)[0]?.substring(1) || '', - published_at: response.data.published_at - }; - } - }); - const UPLOAD_TIMEOUT = 60000; // 1 minute export const uploadFile = (file: File) => { diff --git a/interface/src/app/main/CustomEntities.tsx b/interface/src/app/main/CustomEntities.tsx index 8359132ec..4e394ba7b 100644 --- a/interface/src/app/main/CustomEntities.tsx +++ b/interface/src/app/main/CustomEntities.tsx @@ -1,4 +1,4 @@ -import { useCallback, useMemo, useState } from 'react'; +import { useState } from 'react'; import { useBlocker } from 'react-router'; import { toast } from 'react-toastify'; @@ -57,20 +57,18 @@ const CustomEntities = () => { initialData: [] }); - const intervalCallback = useCallback(() => { + useInterval(() => { if (!dialogOpen && !numChanges) { void fetchEntities(); } - }, [dialogOpen, numChanges, fetchEntities]); - - useInterval(intervalCallback); + }); const { send: writeEntities } = useRequest( (data: Entities) => writeCustomEntities(data), { immediate: false } ); - const hasEntityChanged = useCallback((ei: EntityItem) => { + const hasEntityChanged = (ei: EntityItem) => { return ( ei.id !== ei.o_id || ei.ram !== ei.o_ram || @@ -86,21 +84,19 @@ const CustomEntities = () => { ei.deleted !== ei.o_deleted || (ei.value || '') !== (ei.o_value || '') ); - }, []); + }; - const entity_theme = useMemo( - () => - useTheme({ - Table: ` + const entity_theme = useTheme({ + Table: ` --data-table-library_grid-template-columns: repeat(1, minmax(60px, 1fr)) minmax(80px, auto) 80px 80px 80px 120px; `, - BaseRow: ` + BaseRow: ` font-size: 14px; .td { height: 32px; } `, - BaseCell: ` + BaseCell: ` &:nth-of-type(1) { padding: 8px; } @@ -120,7 +116,7 @@ const CustomEntities = () => { text-align: center; } `, - HeaderRow: ` + HeaderRow: ` text-transform: uppercase; background-color: black; color: #90CAF9; @@ -129,7 +125,7 @@ const CustomEntities = () => { height: 36px; } `, - Row: ` + Row: ` background-color: #1e1e1e; position: relative; cursor: pointer; @@ -140,11 +136,9 @@ const CustomEntities = () => { background-color: #177ac9; } ` - }), - [] - ); + }); - const saveEntities = useCallback(async () => { + const saveEntities = async () => { await writeEntities({ entities: entities .filter((ei: EntityItem) => !ei.deleted) @@ -173,44 +167,41 @@ const CustomEntities = () => { await fetchEntities(); setNumChanges(0); }); - }, [entities, writeEntities, LL, fetchEntities]); + }; - const editEntityItem = useCallback((ei: EntityItem) => { + const editEntityItem = (ei: EntityItem) => { setCreating(false); setSelectedEntityItem(ei); setDialogOpen(true); - }, []); + }; - const onDialogClose = useCallback(() => { + const onDialogClose = () => { setDialogOpen(false); - }, []); + }; - const onDialogCancel = useCallback(async () => { + const onDialogCancel = async () => { await fetchEntities().then(() => { setNumChanges(0); }); - }, [fetchEntities]); + }; - const onDialogSave = useCallback( - (updatedItem: EntityItem) => { - setDialogOpen(false); - void updateState(readCustomEntities(), (data: EntityItem[]) => { - const new_data = creating - ? [ - ...data.filter((ei) => creating || ei.o_id !== updatedItem.o_id), - updatedItem - ] - : data.map((ei) => - ei.id === updatedItem.id ? { ...ei, ...updatedItem } : ei - ); - setNumChanges(new_data.filter((ei) => hasEntityChanged(ei)).length); - return new_data; - }); - }, - [creating, hasEntityChanged] - ); + const onDialogSave = (updatedItem: EntityItem) => { + setDialogOpen(false); + void updateState(readCustomEntities(), (data: EntityItem[]) => { + const new_data = creating + ? [ + ...data.filter((ei) => creating || ei.o_id !== updatedItem.o_id), + updatedItem + ] + : data.map((ei) => + ei.id === updatedItem.id ? { ...ei, ...updatedItem } : ei + ); + setNumChanges(new_data.filter((ei) => hasEntityChanged(ei)).length); + return new_data; + }); + }; - const onDialogDup = useCallback((item: EntityItem) => { + const onDialogDup = (item: EntityItem) => { setCreating(true); setSelectedEntityItem({ id: Math.floor(Math.random() * (MAX_ID - MIN_ID) + MIN_ID), @@ -228,9 +219,9 @@ const CustomEntities = () => { value: item.value }); setDialogOpen(true); - }, []); + }; - const addEntityItem = useCallback(() => { + const addEntityItem = () => { setCreating(true); setSelectedEntityItem({ id: Math.floor(Math.random() * (MAX_ID - MIN_ID) + MIN_ID), @@ -248,30 +239,27 @@ const CustomEntities = () => { value: '' }); setDialogOpen(true); - }, []); + }; - const formatValue = useCallback((value: unknown, uom: number) => { + const formatValue = (value: unknown, uom: number) => { return value === undefined ? '' : typeof value === 'number' ? new Intl.NumberFormat().format(value) + (uom === 0 ? '' : ` ${DeviceValueUOM_s[uom]}`) : `${value as string}${uom === 0 ? '' : ` ${DeviceValueUOM_s[uom]}`}`; - }, []); + }; - const showHex = useCallback((value: number, digit: number) => { + const showHex = (value: number, digit: number) => { return `0x${value.toString(16).toUpperCase().padStart(digit, '0')}`; - }, []); + }; - const filteredAndSortedEntities = useMemo( - () => - entities - ?.filter((ei: EntityItem) => !ei.deleted) - .sort((a: EntityItem, b: EntityItem) => a.name.localeCompare(b.name)) ?? [], - [entities] - ); + const filteredAndSortedEntities = + entities + ?.filter((ei: EntityItem) => !ei.deleted) + .sort((a: EntityItem, b: EntityItem) => a.name.localeCompare(b.name)) ?? []; - const renderEntity = useCallback(() => { + const renderEntity = () => { if (!entities) { return ( @@ -328,17 +316,7 @@ const CustomEntities = () => { )} ); - }, [ - entities, - error, - fetchEntities, - entity_theme, - editEntityItem, - LL, - filteredAndSortedEntities, - showHex, - formatValue - ]); + }; return ( diff --git a/interface/src/app/main/CustomEntitiesDialog.tsx b/interface/src/app/main/CustomEntitiesDialog.tsx index b40e4aa25..8ede016b4 100644 --- a/interface/src/app/main/CustomEntitiesDialog.tsx +++ b/interface/src/app/main/CustomEntitiesDialog.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useEffect, useState } from 'react'; import AddIcon from '@mui/icons-material/Add'; import CancelIcon from '@mui/icons-material/Cancel'; @@ -68,14 +68,10 @@ const CustomEntitiesDialog = ({ const { LL } = useI18nContext(); const [editItem, setEditItem] = useState(selectedItem); const [fieldErrors, setFieldErrors] = useState(); - const updateFormValue = useMemo( - () => - updateValue( - setEditItem as unknown as React.Dispatch< - React.SetStateAction> - > - ), - [] + const updateFormValue = updateValue( + setEditItem as unknown as React.Dispatch< + React.SetStateAction> + > ); useEffect(() => { @@ -105,16 +101,16 @@ const CustomEntitiesDialog = ({ } }, [open, selectedItem]); - const handleClose = useCallback( - (_event: React.SyntheticEvent, reason: 'backdropClick' | 'escapeKeyDown') => { - if (reason !== 'backdropClick') { - onClose(); - } - }, - [onClose] - ); + const handleClose = ( + _event: React.SyntheticEvent, + reason: 'backdropClick' | 'escapeKeyDown' + ) => { + if (reason !== 'backdropClick') { + onClose(); + } + }; - const save = useCallback(async () => { + const save = async () => { try { setFieldErrors(undefined); await validate(validator, editItem); @@ -138,27 +134,21 @@ const CustomEntitiesDialog = ({ } catch (error) { setFieldErrors((error as ValidationError).fieldErrors); } - }, [validator, editItem, onSave]); + }; - const remove = useCallback(() => { - const itemWithDeleted = { ...editItem, deleted: true }; - onSave(itemWithDeleted); - }, [editItem, onSave]); + const remove = () => { + onSave({ ...editItem, deleted: true }); + }; - const dup = useCallback(() => { + const dup = () => { onDup(editItem); - }, [editItem, onDup]); + }; - // Memoize UOM menu items to avoid recreating on every render - const uomMenuItems = useMemo( - () => - DeviceValueUOM_s.map((val, i) => ( - - {val} - - )), - [] - ); + const uomMenuItems = DeviceValueUOM_s.map((val, i) => ( + + {val} + + )); return ( diff --git a/interface/src/app/main/Customizations.tsx b/interface/src/app/main/Customizations.tsx index 435c333bb..a127f9a04 100644 --- a/interface/src/app/main/Customizations.tsx +++ b/interface/src/app/main/Customizations.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useEffect, useState } from 'react'; import { useBlocker, useLocation } from 'react-router'; import { toast } from 'react-toastify'; @@ -171,19 +171,17 @@ const Customizations = () => { ); }; - const entities_theme = useMemo( - () => - useTheme({ - Table: ` + const entities_theme = useTheme({ + Table: ` --data-table-library_grid-template-columns: 156px repeat(1, minmax(80px, 1fr)) 45px minmax(45px, auto) minmax(120px, auto); `, - BaseRow: ` + BaseRow: ` font-size: 14px; .td { height: 32px; } `, - BaseCell: ` + BaseCell: ` &:nth-of-type(3) { text-align: right; } @@ -194,7 +192,7 @@ const Customizations = () => { text-align: right; } `, - HeaderRow: ` + HeaderRow: ` text-transform: uppercase; background-color: black; color: #90CAF9; @@ -206,7 +204,7 @@ const Customizations = () => { text-align: center; } `, - Row: ` + Row: ` background-color: #1e1e1e; position: relative; cursor: pointer; @@ -222,7 +220,7 @@ const Customizations = () => { background-color: #177ac9; } `, - Cell: ` + Cell: ` &:nth-of-type(2) { padding: 8px; } @@ -236,9 +234,7 @@ const Customizations = () => { padding-right: 8px; } ` - }), - [] - ); + }); function hasEntityChanged(de: DeviceEntity) { return ( @@ -287,26 +283,23 @@ const Customizations = () => { return value as string; } - const isCommand = useCallback((de: DeviceEntity) => { + const isCommand = (de: DeviceEntity) => { return de.n && de.n[0] === '!'; - }, []); + }; - const formatName = useCallback( - (de: DeviceEntity, withShortname: boolean) => { - let name: string; - if (isCommand(de)) { - name = de.t - ? `${LL.COMMAND(1)}: ${de.t} ${de.n?.slice(1)}` - : `${LL.COMMAND(1)}: ${de.n?.slice(1)}`; - } else if (de.cn && de.cn !== '') { - name = de.t ? `${de.t} ${de.cn}` : de.cn; - } else { - name = de.t ? `${de.t} ${de.n}` : de.n || ''; - } - return withShortname ? `${name} ${de.id}` : name; - }, - [LL] - ); + const formatName = (de: DeviceEntity, withShortname: boolean) => { + let name: string; + if (isCommand(de)) { + name = de.t + ? `${LL.COMMAND(1)}: ${de.t} ${de.n?.slice(1)}` + : `${LL.COMMAND(1)}: ${de.n?.slice(1)}`; + } else if (de.cn && de.cn !== '') { + name = de.t ? `${de.t} ${de.cn}` : de.cn; + } else { + name = de.t ? `${de.t} ${de.n}` : de.n || ''; + } + return withShortname ? `${name} ${de.id}` : name; + }; const getMaskNumber = (newMask: string[]) => { let new_mask = 0; @@ -336,33 +329,27 @@ const Customizations = () => { return new_masks; }; - const filter_entity = useCallback( - (de: DeviceEntity) => - (de.m & selectedFilters || !selectedFilters) && - formatName(de, true).toLowerCase().includes(search.toLowerCase()), - [selectedFilters, search, formatName] - ); + const filter_entity = (de: DeviceEntity) => + (de.m & selectedFilters || !selectedFilters) && + formatName(de, true).toLowerCase().includes(search.toLowerCase()); - const maskDisabled = useCallback( - (set: boolean) => { - setDeviceEntities((prev) => - prev.map((de) => { - if (filter_entity(de)) { - const excludeMask = - DeviceEntityMask.DV_API_MQTT_EXCLUDE | DeviceEntityMask.DV_WEB_EXCLUDE; - return { - ...de, - m: set ? de.m | excludeMask : de.m & ~excludeMask - }; - } - return de; - }) - ); - }, - [filter_entity] - ); + const maskDisabled = (set: boolean) => { + setDeviceEntities((prev) => + prev.map((de) => { + if (filter_entity(de)) { + const excludeMask = + DeviceEntityMask.DV_API_MQTT_EXCLUDE | DeviceEntityMask.DV_WEB_EXCLUDE; + return { + ...de, + m: set ? de.m | excludeMask : de.m & ~excludeMask + }; + } + return de; + }) + ); + }; - const resetCustomization = useCallback(async () => { + const resetCustomization = async () => { try { await sendResetCustomizations(); toast.info(LL.CUSTOMIZATIONS_RESTART()); @@ -372,30 +359,27 @@ const Customizations = () => { setConfirmReset(false); setRestarting(true); } - }, [sendResetCustomizations, LL]); + }; const onDialogClose = () => { setDialogOpen(false); }; - const updateDeviceEntity = useCallback((updatedItem: DeviceEntity) => { + const updateDeviceEntity = (updatedItem: DeviceEntity) => { setDeviceEntities( (prev) => prev?.map((de) => de.id === updatedItem.id ? { ...de, ...updatedItem } : de ) ?? [] ); - }, []); + }; - const onDialogSave = useCallback( - (updatedItem: DeviceEntity) => { - setDialogOpen(false); - updateDeviceEntity(updatedItem); - }, - [updateDeviceEntity] - ); + const onDialogSave = (updatedItem: DeviceEntity) => { + setDialogOpen(false); + updateDeviceEntity(updatedItem); + }; - const editDeviceEntity = useCallback((de: DeviceEntity) => { + const editDeviceEntity = (de: DeviceEntity) => { if (de.n === undefined || (de.n && de.n[0] === '!')) { return; } @@ -406,9 +390,9 @@ const Customizations = () => { setSelectedDeviceEntity(de); setDialogOpen(true); - }, []); + }; - const saveCustomization = useCallback(async () => { + const saveCustomization = async () => { if (!devices || !deviceEntities || selectedDevice === -1) { return; } @@ -441,9 +425,9 @@ const Customizations = () => { .finally(() => { setOriginalSettings(deviceEntities); }); - }, [devices, deviceEntities, selectedDevice, sendCustomizationEntities, LL]); + }; - const renameDevice = useCallback(async () => { + const renameDevice = async () => { await sendDeviceName({ id: selectedDevice, name: selectedDeviceName, @@ -459,14 +443,7 @@ const Customizations = () => { setRename(false); await fetchCoreData(); }); - }, [ - selectedDevice, - selectedDeviceName, - selectedDeviceBrand, - sendDeviceName, - LL, - fetchCoreData - ]); + }; const renderDeviceList = () => ( <> @@ -562,10 +539,7 @@ const Customizations = () => { ); - const filteredEntities = useMemo( - () => deviceEntities.filter((de) => filter_entity(de)), - [deviceEntities, filter_entity] - ); + const filteredEntities = deviceEntities.filter((de) => filter_entity(de)); const renderDeviceData = () => { return ( diff --git a/interface/src/app/main/CustomizationsDialog.tsx b/interface/src/app/main/CustomizationsDialog.tsx index 95615ab56..9e5d68ca9 100644 --- a/interface/src/app/main/CustomizationsDialog.tsx +++ b/interface/src/app/main/CustomizationsDialog.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useEffect, useMemo, useState } from 'react'; +import { memo, useEffect, useState } from 'react'; import CancelIcon from '@mui/icons-material/Cancel'; import CloseIcon from '@mui/icons-material/Close'; @@ -57,23 +57,16 @@ const CustomizationsDialog = ({ const [editItem, setEditItem] = useState(selectedItem); const [error, setError] = useState(false); - const updateFormValue = useMemo( - () => - updateValue( - setEditItem as unknown as React.Dispatch< - React.SetStateAction> - > - ), - [] + const updateFormValue = updateValue( + setEditItem as unknown as React.Dispatch< + React.SetStateAction> + > ); - const isWriteableNumber = useMemo( - () => - typeof editItem.v === 'number' && - editItem.w && - !(editItem.m & DeviceEntityMask.DV_READONLY), - [editItem.v, editItem.w, editItem.m] - ); + const isWriteableNumber = + typeof editItem.v === 'number' && + editItem.w && + !(editItem.m & DeviceEntityMask.DV_READONLY); useEffect(() => { if (open) { @@ -82,16 +75,16 @@ const CustomizationsDialog = ({ } }, [open, selectedItem]); - const handleClose = useCallback( - (_event: React.SyntheticEvent, reason: 'backdropClick' | 'escapeKeyDown') => { - if (reason !== 'backdropClick') { - onClose(); - } - }, - [onClose] - ); + const handleClose = ( + _event: React.SyntheticEvent, + reason: 'backdropClick' | 'escapeKeyDown' + ) => { + if (reason !== 'backdropClick') { + onClose(); + } + }; - const save = useCallback(() => { + const save = () => { if ( isWriteableNumber && editItem.mi && @@ -102,34 +95,31 @@ const CustomizationsDialog = ({ } else { onSave(editItem); } - }, [isWriteableNumber, editItem, onSave]); + }; - const updateDeviceEntity = useCallback((updatedItem: DeviceEntity) => { + const updateDeviceEntity = (updatedItem: DeviceEntity) => { setEditItem((prev) => ({ ...prev, m: updatedItem.m })); - }, []); - - const dialogTitle = useMemo(() => `${LL.EDIT()} ${LL.ENTITY()}`, [LL]); - - const writeableIcon = useMemo( - () => - editItem.w ? ( - - ) : ( - - ), - [editItem.w] - ); + }; return ( - {dialogTitle} + {`${LL.EDIT()} ${LL.ENTITY()}`} - + + ) : ( + + ) + } + /> diff --git a/interface/src/app/main/Dashboard.tsx b/interface/src/app/main/Dashboard.tsx index b2aff1090..964f68e43 100644 --- a/interface/src/app/main/Dashboard.tsx +++ b/interface/src/app/main/Dashboard.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useContext, useEffect, useMemo, useState } from 'react'; +import { memo, useContext, useEffect, useState } from 'react'; import { IconContext } from 'react-icons/lib'; import { Link } from 'react-router'; import { toast } from 'react-toastify'; @@ -77,40 +77,35 @@ const Dashboard = memo(() => { } ); - const deviceValueDialogSave = useCallback( - async (devicevalue: DeviceValue) => { - if (!selectedDashboardItem) { - return; - } - const id = selectedDashboardItem.parentNode.id; // this is the parent ID - await sendDeviceValue({ id, c: devicevalue.c ?? '', v: devicevalue.v }) - .then(() => { - toast.success(LL.WRITE_CMD_SENT()); - }) - .catch((error: Error) => { - toast.error(error.message); - }) - .finally(() => { - setDeviceValueDialogOpen(false); - setSelectedDashboardItem(undefined); - }); - }, - [selectedDashboardItem, sendDeviceValue, LL] - ); + const deviceValueDialogSave = async (devicevalue: DeviceValue) => { + if (!selectedDashboardItem) { + return; + } + const id = selectedDashboardItem.parentNode.id; // this is the parent ID + await sendDeviceValue({ id, c: devicevalue.c ?? '', v: devicevalue.v }) + .then(() => { + toast.success(LL.WRITE_CMD_SENT()); + }) + .catch((error: Error) => { + toast.error(error.message); + }) + .finally(() => { + setDeviceValueDialogOpen(false); + setSelectedDashboardItem(undefined); + }); + }; - const dashboard_theme = useMemo( - () => - useTheme({ - Table: ` + const dashboard_theme = useTheme({ + Table: ` --data-table-library_grid-template-columns: minmax(80px, auto) 120px 32px; `, - BaseRow: ` + BaseRow: ` font-size: 14px; .td { height: 28px; } `, - Row: ` + Row: ` cursor: pointer; background-color: #1e1e1e; &:nth-of-type(odd) .td { @@ -120,7 +115,7 @@ const Dashboard = memo(() => { background-color: #177ac9; }, `, - BaseCell: ` + BaseCell: ` &:nth-of-type(2) { text-align: right; } @@ -128,9 +123,7 @@ const Dashboard = memo(() => { text-align: right; } ` - }), - [] - ); + }); const tree = useTree( { nodes: [...data.nodes] }, @@ -164,79 +157,64 @@ const Dashboard = memo(() => { } }); - const nodeIds = useMemo( - () => data.nodes.map((item: DashboardItem) => item.id), - [data.nodes] - ); - useEffect(() => { + const nodeIds = data.nodes.map((item: DashboardItem) => item.id); showAll ? tree.fns.onAddAll(nodeIds) // expand tree : tree.fns.onRemoveAll(); // collapse tree }, [parentNodes]); - const showType = useCallback( - (n?: string, t?: number) => { - // if we have a name show it - if (n) { - return n; + const showType = (n?: string, t?: number) => { + // if we have a name show it + if (n) { + return n; + } + if (t) { + // otherwise pick translation based on type + switch (t) { + case DeviceType.CUSTOM: + return LL.CUSTOM_ENTITIES(0); + case DeviceType.ANALOGSENSOR: + return LL.ANALOG_SENSORS(); + case DeviceType.TEMPERATURESENSOR: + return LL.TEMP_SENSORS(); + case DeviceType.SCHEDULER: + return LL.SCHEDULER(); + default: + break; } - if (t) { - // otherwise pick translation based on type - switch (t) { - case DeviceType.CUSTOM: - return LL.CUSTOM_ENTITIES(0); - case DeviceType.ANALOGSENSOR: - return LL.ANALOG_SENSORS(); - case DeviceType.TEMPERATURESENSOR: - return LL.TEMP_SENSORS(); - case DeviceType.SCHEDULER: - return LL.SCHEDULER(); - default: - break; - } - } - return ''; - }, - [LL] - ); + } + return ''; + }; - const showName = useCallback( - (di: DashboardItem) => { - if (di.id < 100) { - // if its a device (parent node) and has entities - if (di.nodes?.length) { - return ( - - -   {showType(di.n, di.t)} -  ({di.nodes?.length}) - - ); - } + const showName = (di: DashboardItem) => { + if (di.id < 100) { + // if its a device (parent node) and has entities + if (di.nodes?.length) { + return ( + + +   {showType(di.n, di.t)} +  ({di.nodes?.length}) + + ); } - if (di.dv) { - return {di.dv.id.slice(2)}; - } - return null; - }, - [showType] - ); + } + if (di.dv) { + return {di.dv.id.slice(2)}; + } + return null; + }; - const hasMask = useCallback( - (id: string, mask: number) => (parseInt(id.slice(0, 2), 16) & mask) === mask, - [] - ); + const hasMask = (id: string, mask: number) => + (parseInt(id.slice(0, 2), 16) & mask) === mask; - const editDashboardValue = useCallback( - (di: DashboardItem) => { - if (me.admin && di.dv?.c) { - setSelectedDashboardItem(di); - setDeviceValueDialogOpen(true); - } - }, - [me.admin] - ); + const editDashboardValue = (di: DashboardItem) => { + if (me.admin && di.dv?.c) { + setSelectedDashboardItem(di); + setDeviceValueDialogOpen(true); + } + }; const handleShowAll = ( _event: React.MouseEvent, @@ -248,10 +226,9 @@ const Dashboard = memo(() => { } }; - const hasFavEntities = useMemo( - () => data.nodes.filter((item: DashboardItem) => item.id <= 90).length, - [data.nodes] - ); + const hasFavEntities = data.nodes.filter( + (item: DashboardItem) => item.id <= 90 + ).length; const renderContent = () => { if (!data) { diff --git a/interface/src/app/main/Devices.tsx b/interface/src/app/main/Devices.tsx index f21729b0e..08cd73524 100644 --- a/interface/src/app/main/Devices.tsx +++ b/interface/src/app/main/Devices.tsx @@ -4,7 +4,6 @@ import { useContext, useEffect, useLayoutEffect, - useMemo, useState } from 'react'; import { IconContext } from 'react-icons'; @@ -133,21 +132,19 @@ const Devices = memo(() => { }; }, []); - const leftOffset = useCallback(() => { + const leftOffset = () => { const devicesWindow = document.getElementById('devices-window'); if (!devicesWindow) return 0; const { left, right } = devicesWindow.getBoundingClientRect(); if (!left || !right) return 0; return left + (right - left < 400 ? 0 : 200); - }, []); + }; - const common_theme = useMemo( - () => - useTheme({ - BaseRow: ` + const common_theme = useTheme({ + BaseRow: ` font-size: 14px; `, - HeaderRow: ` + HeaderRow: ` text-transform: uppercase; background-color: black; color: #90CAF9; @@ -155,7 +152,7 @@ const Devices = memo(() => { border-bottom: 1px solid #565656; } `, - Row: ` + Row: ` cursor: pointer; background-color: #1E1E1E; .td { @@ -165,88 +162,78 @@ const Devices = memo(() => { background-color: #177ac9; } ` - }), - [] - ); + }); - const device_theme = useMemo( - () => - useTheme([ - common_theme, - { - BaseRow: ` - font-size: 15px; - .td { - height: 28px; - } - `, - Table: ` - --data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 130px; - `, - HeaderRow: ` - .th { - padding: 8px; - `, - Row: ` - &:nth-of-type(odd) .td { - background-color: #303030; - }, - &:hover .td { - background-color: #177ac9; - }, - ` - } - ]), - [common_theme] - ); - - const data_theme = useMemo( - () => - useTheme([ - common_theme, - { - Table: ` - --data-table-library_grid-template-columns: minmax(200px, auto) minmax(150px, auto) 40px; - height: auto; - max-height: 100%; - overflow-y: scroll; - ::-webkit-scrollbar { - display:none; + const device_theme = useTheme([ + common_theme, + { + BaseRow: ` + font-size: 15px; + .td { + height: 28px; } `, - BaseRow: ` - .td { - height: 32px; - } - `, - BaseCell: ` - &:nth-of-type(1) { - border-left: 1px solid #177ac9; - }, - &:nth-of-type(2) { - text-align: right; - }, - &:nth-of-type(3) { - border-right: 1px solid #177ac9; - } - `, - HeaderRow: ` - .th { - border-top: 1px solid #565656; - } - `, - Row: ` - &:nth-of-type(odd) .td { + Table: ` + --data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 130px; + `, + HeaderRow: ` + .th { + padding: 8px; + `, + Row: ` + &:nth-of-type(odd) .td { background-color: #303030; - }, - &:hover .td { - background-color: #177ac9; + }, + &:hover .td { + background-color: #177ac9; + }, + ` + } + ]); + + const data_theme = useTheme([ + common_theme, + { + Table: ` + --data-table-library_grid-template-columns: minmax(200px, auto) minmax(150px, auto) 40px; + height: auto; + max-height: 100%; + overflow-y: scroll; + ::-webkit-scrollbar { + display:none; } - ` - } - ]), - [common_theme] - ); + `, + BaseRow: ` + .td { + height: 32px; + } + `, + BaseCell: ` + &:nth-of-type(1) { + border-left: 1px solid #177ac9; + }, + &:nth-of-type(2) { + text-align: right; + }, + &:nth-of-type(3) { + border-right: 1px solid #177ac9; + } + `, + HeaderRow: ` + .th { + border-top: 1px solid #565656; + } + `, + Row: ` + &:nth-of-type(odd) .td { + background-color: #303030; + }, + &:hover .td { + background-color: #177ac9; + } + ` + } + ]); const getSortIcon = (state: State, sortKey: unknown) => { if (state.sortKey === sortKey && state.reverse) { @@ -345,10 +332,8 @@ const Devices = memo(() => { return sc; }; - const hasMask = useCallback( - (id: string, mask: number) => (parseInt(id.slice(0, 2), 16) & mask) === mask, - [] - ); + const hasMask = (id: string, mask: number) => + (parseInt(id.slice(0, 2), 16) & mask) === mask; const handleDownloadCsv = () => { const deviceIndex = coreData.devices.findIndex( @@ -607,41 +592,35 @@ const Devices = memo(() => { return; } - const showDeviceValue = useCallback((dv: DeviceValue) => { + const showDeviceValue = (dv: DeviceValue) => { setSelectedDeviceValue(dv); setDeviceValueDialogOpen(true); - }, []); + }; - const renderNameCell = useCallback( - (dv: DeviceValue) => ( - <> - {dv.id.slice(2)}  - {hasMask(dv.id, DeviceEntityMask.DV_FAVORITE) && ( - - )} - {hasMask(dv.id, DeviceEntityMask.DV_READONLY) && ( - - )} - {hasMask(dv.id, DeviceEntityMask.DV_API_MQTT_EXCLUDE) && ( - - )} - - ), - [hasMask] + const renderNameCell = (dv: DeviceValue) => ( + <> + {dv.id.slice(2)}  + {hasMask(dv.id, DeviceEntityMask.DV_FAVORITE) && ( + + )} + {hasMask(dv.id, DeviceEntityMask.DV_READONLY) && ( + + )} + {hasMask(dv.id, DeviceEntityMask.DV_API_MQTT_EXCLUDE) && ( + + )} + ); - const shown_data = useMemo(() => { - if (onlyFav) { - return deviceData.nodes.filter( + const shown_data = onlyFav + ? deviceData.nodes.filter( (dv: DeviceValue) => hasMask(dv.id, DeviceEntityMask.DV_FAVORITE) && dv.id.slice(2).toLowerCase().includes(search.toLowerCase()) + ) + : deviceData.nodes.filter((dv: DeviceValue) => + dv.id.slice(2).toLowerCase().includes(search.toLowerCase()) ); - } - return deviceData.nodes.filter((dv: DeviceValue) => - dv.id.slice(2).toLowerCase().includes(search.toLowerCase()) - ); - }, [deviceData.nodes, onlyFav, search]); const deviceIndex = coreData.devices.findIndex( (d: Device) => d.id === device_select.state.id diff --git a/interface/src/app/main/DevicesDialog.tsx b/interface/src/app/main/DevicesDialog.tsx index fd2770e7d..706c2d608 100644 --- a/interface/src/app/main/DevicesDialog.tsx +++ b/interface/src/app/main/DevicesDialog.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useEffect, useState } from 'react'; import CancelIcon from '@mui/icons-material/Cancel'; import WarningIcon from '@mui/icons-material/Warning'; @@ -52,7 +52,7 @@ const DevicesDialog = ({ const [editItem, setEditItem] = useState(selectedItem); const [fieldErrors, setFieldErrors] = useState(); - const updateFormValue = useMemo(() => updateValue(setEditItem), [setEditItem]); + const updateFormValue = updateValue(setEditItem); useEffect(() => { if (open) { @@ -61,7 +61,7 @@ const DevicesDialog = ({ } }, [open, selectedItem]); - const save = useCallback(async () => { + const save = async () => { try { setFieldErrors(undefined); await validate(validator, editItem); @@ -69,28 +69,25 @@ const DevicesDialog = ({ } catch (error) { setFieldErrors((error as ValidationError).fieldErrors); } - }, [validator, editItem, onSave]); + }; - const setUom = useCallback( - (uom?: DeviceValueUOM) => { - if (uom === undefined) { - return; - } - switch (uom) { - case DeviceValueUOM.HOURS: - return LL.HOURS(); - case DeviceValueUOM.MINUTES: - return LL.MINUTES(); - case DeviceValueUOM.SECONDS: - return LL.SECONDS(); - default: - return DeviceValueUOM_s[uom]; - } - }, - [LL] - ); + const setUom = (uom?: DeviceValueUOM) => { + if (uom === undefined) { + return; + } + switch (uom) { + case DeviceValueUOM.HOURS: + return LL.HOURS(); + case DeviceValueUOM.MINUTES: + return LL.MINUTES(); + case DeviceValueUOM.SECONDS: + return LL.SECONDS(); + default: + return DeviceValueUOM_s[uom]; + } + }; - const showHelperText = useCallback((dv: DeviceValue) => { + const showHelperText = (dv: DeviceValue) => { if (dv.h) return dv.h; if (dv.l) return dv.l.join(' | '); if (dv.m !== undefined && dv.x !== undefined) { @@ -101,26 +98,16 @@ const DevicesDialog = ({ ); } return undefined; - }, []); + }; - const isCommand = useMemo( - () => selectedItem.v === '' && selectedItem.c, - [selectedItem.v, selectedItem.c] - ); - - const dialogTitle = useMemo(() => { - if (isCommand) return LL.RUN_COMMAND(); - return writeable ? LL.CHANGE_VALUE() : LL.VALUE(0); - }, [isCommand, writeable, LL]); - - const buttonLabel = useMemo(() => { - return isCommand ? LL.EXECUTE() : LL.UPDATE(); - }, [isCommand, LL]); - - const helperText = useMemo( - () => showHelperText(editItem), - [editItem, showHelperText] - ); + const isCommand = selectedItem.v === '' && selectedItem.c; + const dialogTitle = isCommand + ? LL.RUN_COMMAND() + : writeable + ? LL.CHANGE_VALUE() + : LL.VALUE(0); + const buttonLabel = isCommand ? LL.EXECUTE() : LL.UPDATE(); + const helperText = showHelperText(editItem); const valueLabel = LL.VALUE(0); diff --git a/interface/src/app/main/EntityMaskToggle.tsx b/interface/src/app/main/EntityMaskToggle.tsx index d2304d6f1..e4bbe6176 100644 --- a/interface/src/app/main/EntityMaskToggle.tsx +++ b/interface/src/app/main/EntityMaskToggle.tsx @@ -1,5 +1,3 @@ -import { useCallback, useMemo } from 'react'; - import { ToggleButton, ToggleButtonGroup } from '@mui/material'; import OptionIcon from './OptionIcon'; @@ -11,7 +9,6 @@ interface EntityMaskToggleProps { de: DeviceEntity; } -// Available mask values const MASK_VALUES = [ DeviceEntityMask.DV_WEB_EXCLUDE, // 1 DeviceEntityMask.DV_API_MQTT_EXCLUDE, // 2 @@ -20,123 +17,95 @@ const MASK_VALUES = [ DeviceEntityMask.DV_DELETED // 128 ]; -/** - * Converts an array of mask strings to a bitmask number - */ -const getMaskNumber = (newMask: string[]): number => { - return newMask.reduce((mask, entry) => mask | Number(entry), 0); -}; +const getMaskNumber = (newMask: string[]): number => + newMask.reduce((mask, entry) => mask | Number(entry), 0); -/** - * Converts a bitmask number to an array of mask strings - */ -const getMaskString = (mask: number): string[] => { - return MASK_VALUES.filter((value) => (mask & value) === value).map((value) => +const getMaskString = (mask: number): string[] => + MASK_VALUES.filter((value) => (mask & value) === value).map((value) => String(value) ); -}; -/** - * Checks if a specific mask bit is set - */ const hasMask = (mask: number, flag: number): boolean => (mask & flag) === flag; const EntityMaskToggle = ({ onUpdate, de }: EntityMaskToggleProps) => { - const handleChange = useCallback( - (_event: unknown, mask: string[]) => { - // Convert selected masks to a number - const newMask = getMaskNumber(mask); - const updatedDe = { ...de }; + const handleChange = (_event: unknown, mask: string[]) => { + const newMask = getMaskNumber(mask); + const updatedDe = { ...de }; - // Apply business logic for mask interactions - // If entity has no name and is set to readonly, also exclude from web - if (updatedDe.n === '' && hasMask(newMask, DeviceEntityMask.DV_READONLY)) { - updatedDe.m = newMask | DeviceEntityMask.DV_WEB_EXCLUDE; - } else { - updatedDe.m = newMask; - } + // If entity has no name and is set to readonly, also exclude from web + if (updatedDe.n === '' && hasMask(newMask, DeviceEntityMask.DV_READONLY)) { + updatedDe.m = newMask | DeviceEntityMask.DV_WEB_EXCLUDE; + } else { + updatedDe.m = newMask; + } - // If excluded from web, cannot be favorite - if (hasMask(updatedDe.m, DeviceEntityMask.DV_WEB_EXCLUDE)) { - updatedDe.m = updatedDe.m & ~DeviceEntityMask.DV_FAVORITE; - } + // If excluded from web, cannot be favorite + if (hasMask(updatedDe.m, DeviceEntityMask.DV_WEB_EXCLUDE)) { + updatedDe.m = updatedDe.m & ~DeviceEntityMask.DV_FAVORITE; + } - onUpdate(updatedDe); - }, - [de, onUpdate] - ); - - // Memoize mask string value - const maskStringValue = useMemo(() => getMaskString(de.m), [de.m]); - - // Memoize disabled states - const isFavoriteDisabled = useMemo( - () => - hasMask(de.m, DeviceEntityMask.DV_WEB_EXCLUDE | DeviceEntityMask.DV_DELETED) || - de.n === undefined, - [de.m, de.n] - ); - - const isReadonlyDisabled = useMemo( - () => - !de.w || - hasMask(de.m, DeviceEntityMask.DV_WEB_EXCLUDE | DeviceEntityMask.DV_FAVORITE), - [de.w, de.m] - ); - - const isApiMqttExcludeDisabled = useMemo( - () => de.n === '' || hasMask(de.m, DeviceEntityMask.DV_DELETED), - [de.n, de.m] - ); - - const isWebExcludeDisabled = useMemo( - () => de.n === undefined || hasMask(de.m, DeviceEntityMask.DV_DELETED), - [de.n, de.m] - ); - - // Memoize mask flag checks - const isFavoriteSet = useMemo( - () => hasMask(de.m, DeviceEntityMask.DV_FAVORITE), - [de.m] - ); - const isReadonlySet = useMemo( - () => hasMask(de.m, DeviceEntityMask.DV_READONLY), - [de.m] - ); - const isApiMqttExcludeSet = useMemo( - () => hasMask(de.m, DeviceEntityMask.DV_API_MQTT_EXCLUDE), - [de.m] - ); - const isWebExcludeSet = useMemo( - () => hasMask(de.m, DeviceEntityMask.DV_WEB_EXCLUDE), - [de.m] - ); - const isDeletedSet = useMemo( - () => hasMask(de.m, DeviceEntityMask.DV_DELETED), - [de.m] - ); + onUpdate(updatedDe); + }; return ( - - + + - - + + - - + + - - + + - + ); diff --git a/interface/src/app/main/Help.tsx b/interface/src/app/main/Help.tsx index d68ffa591..ff1fe6a56 100644 --- a/interface/src/app/main/Help.tsx +++ b/interface/src/app/main/Help.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useContext, useMemo, useState } from 'react'; +import { memo, useContext, useState } from 'react'; import type { ReactElement } from 'react'; import { toast } from 'react-toastify'; @@ -60,6 +60,8 @@ const AVATAR_STYLES: SxProps = { bgcolor: '#72caf9' }; +const SYSTEM_INFO_API: APIcall = { device: 'system', cmd: 'info', id: 0 }; + const HelpComponent = () => { const { LL } = useI18nContext(); useLayoutTitle(LL.HELP()); @@ -72,12 +74,7 @@ const HelpComponent = () => { }); const [imgError, setImgError] = useState(false); - const getCustomSupportMethod = useMemo( - () => callAction({ action: 'getCustomSupport' }), - [] - ); - - useRequest(getCustomSupportMethod).onSuccess((event) => { + useRequest(callAction({ action: 'getCustomSupport' })).onSuccess((event) => { if (event?.data && Object.keys(event.data).length !== 0) { const { Support } = event.data as { Support: { img_url?: string; html?: string[] }; @@ -100,47 +97,26 @@ const HelpComponent = () => { toast.error(String(error.error?.message || 'An error occurred')); }); - // Optimize API call memoization - const apiCall = useMemo(() => ({ device: 'system', cmd: 'info', id: 0 }), []); + const helpLinks: HelpLink[] = [ + { + href: 'https://emsesp.org', + icon: , + label: () => LL.HELP_INFORMATION_1() + }, + { + href: 'https://discord.gg/GP9DPSgeJq', + icon: , + label: () => LL.HELP_INFORMATION_2() + }, + { + href: 'https://github.com/emsesp/EMS-ESP32/issues/new/choose', + icon: , + label: () => LL.HELP_INFORMATION_3() + } + ]; - const handleDownloadSystemInfo = useCallback(() => { - void sendAPI(apiCall); - }, [sendAPI, apiCall]); - - const handleImageError = useCallback(() => { - setImgError(true); - }, []); - - // Memoize help links to prevent recreation on every render - const helpLinks: HelpLink[] = useMemo( - () => [ - { - href: 'https://emsesp.org', - icon: , - label: () => LL.HELP_INFORMATION_1() - }, - { - href: 'https://discord.gg/GP9DPSgeJq', - icon: , - label: () => LL.HELP_INFORMATION_2() - }, - { - href: 'https://github.com/emsesp/EMS-ESP32/issues/new/choose', - icon: , - label: () => LL.HELP_INFORMATION_3() - } - ], - [LL] - ); - - const isAdmin = useMemo(() => me?.admin ?? false, [me?.admin]); - - // Memoize image source computation - const imageSrc = useMemo( - () => - imgError || !customSupport.img_url ? DEFAULT_IMAGE_URL : customSupport.img_url, - [imgError, customSupport.img_url] - ); + const imageSrc = + imgError || !customSupport.img_url ? DEFAULT_IMAGE_URL : customSupport.img_url; return ( @@ -157,13 +133,13 @@ const HelpComponent = () => { component="img" referrerPolicy="no-referrer" sx={IMAGE_STYLES} - onError={handleImageError} + onError={() => setImgError(true)} src={imageSrc} /> )} - {isAdmin && ( + {me?.admin && ( {helpLinks.map(({ href, icon, label }) => ( @@ -191,7 +167,7 @@ const HelpComponent = () => { startIcon={} variant="outlined" color="primary" - onClick={handleDownloadSystemInfo} + onClick={() => void sendAPI(SYSTEM_INFO_API)} > {LL.SUPPORT_INFORMATION(0)} @@ -214,7 +190,6 @@ const HelpComponent = () => { ); }; -// Memoize the component to prevent unnecessary re-renders const Help = memo(HelpComponent); export default Help; diff --git a/interface/src/app/main/Modules.tsx b/interface/src/app/main/Modules.tsx index 91d126f5a..82ea16079 100644 --- a/interface/src/app/main/Modules.tsx +++ b/interface/src/app/main/Modules.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useMemo, useState } from 'react'; +import { memo, useState } from 'react'; import { useBlocker } from 'react-router'; import { toast } from 'react-toastify'; @@ -69,58 +69,53 @@ const Modules = () => { } ); - const modules_theme = useTheme( - useMemo( - () => ({ - Table: ` - --data-table-library_grid-template-columns: 48px 180px 120px 100px repeat(1, minmax(160px, 1fr)) 180px; - `, - BaseRow: ` - font-size: 14px; - .td { - height: 32px; - } - `, - BaseCell: ` - &:nth-of-type(1) { - text-align: center; - } - `, - HeaderRow: ` - text-transform: uppercase; - background-color: black; - color: #90CAF9; - .th { - border-bottom: 1px solid #565656; - height: 36px; - } - `, - Row: ` - background-color: #1e1e1e; - position: relative; - cursor: pointer; - .td { - border-top: 1px solid #565656; - border-bottom: 1px solid #565656; - } - &:hover .td { - border-top: 1px solid #177ac9; - border-bottom: 1px solid #177ac9; - } - &:nth-of-type(odd) .td { - background-color: #303030; - } - ` - }), - [] - ) - ); + const modules_theme = useTheme({ + Table: ` + --data-table-library_grid-template-columns: 48px 180px 120px 100px repeat(1, minmax(160px, 1fr)) 180px; + `, + BaseRow: ` + font-size: 14px; + .td { + height: 32px; + } + `, + BaseCell: ` + &:nth-of-type(1) { + text-align: center; + } + `, + HeaderRow: ` + text-transform: uppercase; + background-color: black; + color: #90CAF9; + .th { + border-bottom: 1px solid #565656; + height: 36px; + } + `, + Row: ` + background-color: #1e1e1e; + position: relative; + cursor: pointer; + .td { + border-top: 1px solid #565656; + border-bottom: 1px solid #565656; + } + &:hover .td { + border-top: 1px solid #177ac9; + border-bottom: 1px solid #177ac9; + } + &:nth-of-type(odd) .td { + background-color: #303030; + } + ` + }); - const onDialogClose = useCallback(() => { + const onDialogClose = () => { setDialogOpen(false); - }, []); + }; - const updateModuleItem = useCallback((updatedItem: ModuleItem) => { + const updateModuleItem = (updatedItem: ModuleItem) => { void updateState(readModules(), (data: ModuleItem[]) => { const new_data = data.map((mi) => mi.id === updatedItem.id ? { ...mi, ...updatedItem } : mi @@ -128,28 +123,25 @@ const Modules = () => { setNumChanges(new_data.filter(hasModulesChanged).length); return new_data; }); - }, []); + }; - const onDialogSave = useCallback( - (updatedItem: ModuleItem) => { - setDialogOpen(false); - updateModuleItem(updatedItem); - }, - [updateModuleItem] - ); + const onDialogSave = (updatedItem: ModuleItem) => { + setDialogOpen(false); + updateModuleItem(updatedItem); + }; - const editModuleItem = useCallback((mi: ModuleItem) => { + const editModuleItem = (mi: ModuleItem) => { setSelectedModuleItem(mi); setDialogOpen(true); - }, []); + }; - const onCancel = useCallback(async () => { + const onCancel = async () => { await fetchModules().then(() => { setNumChanges(0); }); - }, [fetchModules]); + }; - const saveModules = useCallback(async () => { + const saveModules = async () => { try { await Promise.all( modules.map((condensed_mi: ModuleItem) => @@ -167,9 +159,9 @@ const Modules = () => { await fetchModules(); setNumChanges(0); } - }, [modules, updateModules, LL, fetchModules]); + }; - const content = useMemo(() => { + const renderContent = () => { if (!modules) { return ( @@ -262,22 +254,12 @@ const Modules = () => { ); - }, [ - modules, - fetchModules, - error, - modules_theme, - editModuleItem, - LL, - numChanges, - onCancel, - saveModules - ]); + }; return ( {blocker ? : null} - {content} + {renderContent()} {selectedModuleItem && ( (selectedItem); - const updateFormValue = useMemo( - () => - updateValue( - setEditItem as unknown as React.Dispatch< - React.SetStateAction> - > - ), - [] + const updateFormValue = updateValue( + setEditItem as unknown as React.Dispatch< + React.SetStateAction> + > ); // Sync form state when dialog opens or selected item changes @@ -54,18 +50,13 @@ const ModulesDialog = ({ } }, [open, selectedItem]); - const handleSave = useCallback(() => { + const handleSave = () => { onSave(editItem); - }, [editItem, onSave]); - - const dialogTitle = useMemo( - () => `${LL.EDIT()} ${editItem.key}`, - [LL, editItem.key] - ); + }; return ( - {dialogTitle} + {`${LL.EDIT()} ${editItem.key}`} { } ); - const hasScheduleChanged = useCallback((si: ScheduleItem) => { + const hasScheduleChanged = (si: ScheduleItem) => { return ( si.id !== si.o_id || (si.name || '') !== (si.o_name || '') || @@ -143,15 +143,13 @@ const Scheduler = () => { si.cmd !== si.o_cmd || si.value !== si.o_value ); - }, []); + }; - const intervalCallback = useCallback(() => { + useInterval(() => { if (numChanges === 0) { void fetchSchedule(); } - }, [numChanges, fetchSchedule]); - - useInterval(intervalCallback, INTERVAL_DELAY); + }, INTERVAL_DELAY); useEffect(() => { const formatter = new Intl.DateTimeFormat(locale, { @@ -169,7 +167,7 @@ const Scheduler = () => { const schedule_theme = useTheme(scheduleTheme); - const saveSchedule = useCallback(async () => { + const saveSchedule = async () => { try { await updateSchedule({ schedule: schedule @@ -192,46 +190,43 @@ const Scheduler = () => { await fetchSchedule(); setNumChanges(0); } - }, [LL, schedule, updateSchedule, fetchSchedule]); + }; - const editScheduleItem = useCallback((si: ScheduleItem) => { + const editScheduleItem = (si: ScheduleItem) => { setCreating(false); setSelectedScheduleItem(si); setDialogOpen(true); if (si.o_name === undefined) { si.o_name = si.name; } - }, []); + }; - const onDialogClose = useCallback(() => { + const onDialogClose = () => { setDialogOpen(false); - }, []); + }; - const onDialogCancel = useCallback(async () => { + const onDialogCancel = async () => { await fetchSchedule().then(() => { setNumChanges(0); }); - }, [fetchSchedule]); + }; - const onDialogSave = useCallback( - (updatedItem: ScheduleItem) => { - setDialogOpen(false); - void updateState(readSchedule(), (data: ScheduleItem[]) => { - const new_data = creating - ? [...data, updatedItem] - : data.map((si) => - si.id === updatedItem.id ? { ...si, ...updatedItem } : si - ); + const onDialogSave = (updatedItem: ScheduleItem) => { + setDialogOpen(false); + void updateState(readSchedule(), (data: ScheduleItem[]) => { + const new_data = creating + ? [...data, updatedItem] + : data.map((si) => + si.id === updatedItem.id ? { ...si, ...updatedItem } : si + ); - setNumChanges(new_data.filter((si) => hasScheduleChanged(si)).length); + setNumChanges(new_data.filter((si) => hasScheduleChanged(si)).length); - return new_data; - }); - }, - [creating, hasScheduleChanged] - ); + return new_data; + }); + }; - const addScheduleItem = useCallback(() => { + const addScheduleItem = () => { setCreating(true); const newItem: ScheduleItem = { id: Math.floor(Math.random() * (MAX_ID - MIN_ID) + MIN_ID), @@ -239,36 +234,29 @@ const Scheduler = () => { }; setSelectedScheduleItem(newItem); setDialogOpen(true); - }, []); + }; - const filteredAndSortedSchedule = useMemo( - () => - schedule - .filter((si: ScheduleItem) => !si.deleted) - .sort((a: ScheduleItem, b: ScheduleItem) => a.flags - b.flags), - [schedule] - ); + const filteredAndSortedSchedule = schedule + .filter((si: ScheduleItem) => !si.deleted) + .sort((a: ScheduleItem, b: ScheduleItem) => a.flags - b.flags); - const dayBox = useCallback( - (si: ScheduleItem, flag: number) => { - const dayIndex = Math.log(flag) / LOG_2; - const isActive = (si.flags & flag) === flag; + const dayBox = (si: ScheduleItem, flag: number) => { + const dayIndex = Math.log(flag) / LOG_2; + const isActive = (si.flags & flag) === flag; - return ( - <> - - - {dow[dayIndex]} - - - - - ); - }, - [dow] - ); + return ( + <> + + + {dow[dayIndex]} + + + + + ); + }; - const scheduleType = useCallback((si: ScheduleItem) => { + const scheduleType = (si: ScheduleItem) => { const label = scheduleTypeLabels[si.flags]; return ( @@ -278,9 +266,9 @@ const Scheduler = () => { ); - }, []); + }; - const renderSchedule = useCallback(() => { + const renderSchedule = () => { if (!schedule) { return ( @@ -343,17 +331,7 @@ const Scheduler = () => { )} ); - }, [ - schedule, - error, - fetchSchedule, - filteredAndSortedSchedule, - schedule_theme, - editScheduleItem, - LL, - dayBox, - scheduleType - ]); + }; return ( diff --git a/interface/src/app/main/SchedulerDialog.tsx b/interface/src/app/main/SchedulerDialog.tsx index 27713de86..d68d9b727 100644 --- a/interface/src/app/main/SchedulerDialog.tsx +++ b/interface/src/app/main/SchedulerDialog.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useEffect, useState } from 'react'; import AddIcon from '@mui/icons-material/Add'; import CancelIcon from '@mui/icons-material/Cancel'; @@ -60,6 +60,12 @@ const FLAG_VALUES = [ ScheduleFlag.SCHEDULE_SAT ] as const; +const getFlagDOWnumber = (flags: string[]) => + flags.reduce((acc, flag) => acc | Number(flag), 0) & FLAG_MASK_127; + +const getFlagDOWstring = (f: number) => + FLAG_VALUES.filter((flag) => (f & flag) === flag).map((flag) => String(flag)); + interface SchedulerDialogProps { open: boolean; creating: boolean; @@ -84,14 +90,10 @@ const SchedulerDialog = ({ const [fieldErrors, setFieldErrors] = useState(); const [scheduleType, setScheduleType] = useState(); - const updateFormValue = useMemo( - () => - updateValue( - setEditItem as unknown as React.Dispatch< - React.SetStateAction> - > - ), - [] + const updateFormValue = updateValue( + setEditItem as unknown as React.Dispatch< + React.SetStateAction> + > ); useEffect(() => { @@ -112,129 +114,95 @@ const SchedulerDialog = ({ } }, [open, selectedItem]); - // Helper function to handle save operations - const handleSave = useCallback( - async (itemToSave: ScheduleItem) => { - try { - setFieldErrors(undefined); - await validate(validator, itemToSave); - onSave(itemToSave); - } catch (error) { - setFieldErrors((error as ValidationError).fieldErrors); - } - }, - [validator, onSave] - ); - - const save = useCallback(async () => { - await handleSave(editItem); - }, [editItem, handleSave]); - - const saveandactivate = useCallback(async () => { - await handleSave({ ...editItem, active: true }); - }, [editItem, handleSave]); - - const remove = useCallback(() => { - onSave({ ...editItem, deleted: true }); - }, [editItem, onSave]); - - // Optimize DOW flag conversion - const getFlagDOWnumber = useCallback((flags: string[]) => { - return flags.reduce((acc, flag) => acc | Number(flag), 0) & FLAG_MASK_127; - }, []); - - const getFlagDOWstring = useCallback((f: number) => { - return FLAG_VALUES.filter((flag) => (f & flag) === flag).map((flag) => - String(flag) - ); - }, []); - - // Day of week display component - const DayOfWeekButton = useCallback( - (flag: number) => { - const dayIndex = Math.log2(flag); - const isSelected = (editItem.flags & flag) === flag; - return ( - - {dow[dayIndex]} - - ); - }, - [editItem.flags, dow] - ); - - const handleClose = useCallback( - (_event: React.SyntheticEvent, reason: 'backdropClick' | 'escapeKeyDown') => { - if (reason !== 'backdropClick') { - onClose(); - } - }, - [onClose] - ); - - const handleScheduleTypeChange = useCallback( - (_event: React.SyntheticEvent, flag: ScheduleFlag | null) => { - if (flag !== null) { - setFieldErrors(undefined); // clear any validation errors - setScheduleType(flag); - // wipe the time field when changing the schedule type - // set the flags based on type - const newFlags = flag === ScheduleFlag.SCHEDULE_DAY ? FLAG_ALL_DAYS : flag; - setEditItem((prev) => ({ ...prev, time: '', flags: newFlags })); - } - }, - [] - ); - - const handleDOWChange = useCallback( - (_event: React.SyntheticEvent, flags: string[]) => { - const newFlags = - getFlagDOWnumber(flags) === 0 ? FLAG_ALL_DAYS : getFlagDOWnumber(flags); - setEditItem((prev) => ({ ...prev, flags: newFlags })); - }, - [getFlagDOWnumber] - ); - - // Memoize derived values - const isDaySchedule = useMemo( - () => scheduleType === ScheduleFlag.SCHEDULE_DAY, - [scheduleType] - ); - const isTimerSchedule = useMemo( - () => scheduleType === ScheduleFlag.SCHEDULE_TIMER, - [scheduleType] - ); - const isImmediateSchedule = useMemo( - () => scheduleType === ScheduleFlag.SCHEDULE_IMMEDIATE, - [scheduleType] - ); - const needsTimeField = useMemo( - () => isDaySchedule || isTimerSchedule, - [isDaySchedule, isTimerSchedule] - ); - - const dowFlags = useMemo( - () => getFlagDOWstring(editItem.flags), - [editItem.flags, getFlagDOWstring] - ); - - const timeFieldValue = useMemo(() => { - if (needsTimeField) { - return editItem.time === '' ? DEFAULT_TIME : editItem.time; + const handleSave = async (itemToSave: ScheduleItem) => { + try { + setFieldErrors(undefined); + await validate(validator, itemToSave); + onSave(itemToSave); + } catch (error) { + setFieldErrors((error as ValidationError).fieldErrors); } - return editItem.time === DEFAULT_TIME ? '' : editItem.time; - }, [editItem.time, needsTimeField]); + }; - const timeFieldLabel = useMemo(() => { + const save = async () => { + await handleSave(editItem); + }; + + const saveandactivate = async () => { + await handleSave({ ...editItem, active: true }); + }; + + const remove = () => { + onSave({ ...editItem, deleted: true }); + }; + + const DayOfWeekButton = (flag: number) => { + const dayIndex = Math.log2(flag); + const isSelected = (editItem.flags & flag) === flag; + return ( + + {dow[dayIndex]} + + ); + }; + + const handleClose = ( + _event: React.SyntheticEvent, + reason: 'backdropClick' | 'escapeKeyDown' + ) => { + if (reason !== 'backdropClick') { + onClose(); + } + }; + + const handleScheduleTypeChange = ( + _event: React.SyntheticEvent, + flag: ScheduleFlag | null + ) => { + if (flag !== null) { + setFieldErrors(undefined); // clear any validation errors + setScheduleType(flag); + // wipe the time field when changing the schedule type + // set the flags based on type + const newFlags = flag === ScheduleFlag.SCHEDULE_DAY ? FLAG_ALL_DAYS : flag; + setEditItem((prev) => ({ ...prev, time: '', flags: newFlags })); + } + }; + + const handleDOWChange = ( + _event: React.SyntheticEvent, + flags: string[] + ) => { + const newFlags = + getFlagDOWnumber(flags) === 0 ? FLAG_ALL_DAYS : getFlagDOWnumber(flags); + setEditItem((prev) => ({ ...prev, flags: newFlags })); + }; + + const isDaySchedule = scheduleType === ScheduleFlag.SCHEDULE_DAY; + const isTimerSchedule = scheduleType === ScheduleFlag.SCHEDULE_TIMER; + const isImmediateSchedule = scheduleType === ScheduleFlag.SCHEDULE_IMMEDIATE; + const needsTimeField = isDaySchedule || isTimerSchedule; + + const dowFlags = getFlagDOWstring(editItem.flags); + + const timeFieldValue = needsTimeField + ? editItem.time === '' + ? DEFAULT_TIME + : editItem.time + : editItem.time === DEFAULT_TIME + ? '' + : editItem.time; + + const timeFieldLabel = (() => { if (scheduleType === ScheduleFlag.SCHEDULE_TIMER) return LL.TIMER(1); if (scheduleType === ScheduleFlag.SCHEDULE_CONDITION) return LL.CONDITION(); if (scheduleType === ScheduleFlag.SCHEDULE_ONCHANGE) return LL.ONCHANGE(); if (scheduleType === ScheduleFlag.SCHEDULE_IMMEDIATE) return LL.IMMEDIATE(); return LL.TIME(1); - }, [scheduleType, LL]); + })(); return ( diff --git a/interface/src/app/main/Sensors.tsx b/interface/src/app/main/Sensors.tsx index 028c362fc..b19a5c146 100644 --- a/interface/src/app/main/Sensors.tsx +++ b/interface/src/app/main/Sensors.tsx @@ -1,4 +1,4 @@ -import { useCallback, useContext, useMemo, useRef, useState } from 'react'; +import { useContext, useRef, useState } from 'react'; import { toast } from 'react-toastify'; import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined'; @@ -158,18 +158,16 @@ const Sensors = () => { } ); - const intervalCallback = useCallback(() => { + useInterval(() => { if (!temperatureDialogOpen && !analogDialogOpen) { void fetchSensorData(); } - }, [temperatureDialogOpen, analogDialogOpen, fetchSensorData]); - - useInterval(intervalCallback); + }); const temperature_theme = useTheme([common_theme, temperature_theme_config]); const analog_theme = useTheme([common_theme, analog_theme_config]); - const getSortIcon = useCallback((state: State, sortKey: unknown) => { + const getSortIcon = (state: State, sortKey: unknown) => { if (state.sortKey === sortKey && state.reverse) { return ; } @@ -177,7 +175,7 @@ const Sensors = () => { return ; } return ; - }, []); + }; const analog_sort = useSort( { nodes: sensorData.as }, @@ -234,119 +232,104 @@ const Sensors = () => { useLayoutTitle(LL.SENSORS()); - const formatDurationMin = useCallback( - (duration_min: number) => { - const totalMs = duration_min * MS_PER_MINUTE; - const days = Math.trunc(totalMs / MS_PER_DAY); - const hours = Math.trunc(totalMs / MS_PER_HOUR) % 24; - const minutes = Math.trunc(totalMs / MS_PER_MINUTE) % 60; + const formatDurationMin = (duration_min: number) => { + const totalMs = duration_min * MS_PER_MINUTE; + const days = Math.trunc(totalMs / MS_PER_DAY); + const hours = Math.trunc(totalMs / MS_PER_HOUR) % 24; + const minutes = Math.trunc(totalMs / MS_PER_MINUTE) % 60; - const parts: string[] = []; - if (days > 0) { - parts.push(LL.NUM_DAYS({ num: days })); - } - if (hours > 0) { - parts.push(LL.NUM_HOURS({ num: hours })); - } - if (minutes > 0) { - parts.push(LL.NUM_MINUTES({ num: minutes })); - } - return parts.join(' '); - }, - [LL] - ); + const parts: string[] = []; + if (days > 0) { + parts.push(LL.NUM_DAYS({ num: days })); + } + if (hours > 0) { + parts.push(LL.NUM_HOURS({ num: hours })); + } + if (minutes > 0) { + parts.push(LL.NUM_MINUTES({ num: minutes })); + } + return parts.join(' '); + }; - const formatValue = useCallback( - (value: unknown, uom: DeviceValueUOM) => { - if (value === undefined) { - return ''; - } - if (typeof value !== 'number') { - return value as string; - } - switch (uom) { - case DeviceValueUOM.HOURS: - return value ? formatDurationMin(value * 60) : LL.NUM_HOURS({ num: 0 }); - case DeviceValueUOM.MINUTES: - return value ? formatDurationMin(value) : LL.NUM_MINUTES({ num: 0 }); - case DeviceValueUOM.SECONDS: - return LL.NUM_SECONDS({ num: value }); - case DeviceValueUOM.NONE: - return new Intl.NumberFormat().format(value); - case DeviceValueUOM.DEGREES: - case DeviceValueUOM.DEGREES_R: - case DeviceValueUOM.FAHRENHEIT: - return ( - new Intl.NumberFormat(undefined, { - minimumFractionDigits: 1 - }).format(value) + - ' ' + - DeviceValueUOM_s[uom] - ); - default: - return new Intl.NumberFormat().format(value) + ' ' + DeviceValueUOM_s[uom]; - } - }, - [formatDurationMin, LL] - ); + const formatValue = (value: unknown, uom: DeviceValueUOM) => { + if (value === undefined) { + return ''; + } + if (typeof value !== 'number') { + return value as string; + } + switch (uom) { + case DeviceValueUOM.HOURS: + return value ? formatDurationMin(value * 60) : LL.NUM_HOURS({ num: 0 }); + case DeviceValueUOM.MINUTES: + return value ? formatDurationMin(value) : LL.NUM_MINUTES({ num: 0 }); + case DeviceValueUOM.SECONDS: + return LL.NUM_SECONDS({ num: value }); + case DeviceValueUOM.NONE: + return new Intl.NumberFormat().format(value); + case DeviceValueUOM.DEGREES: + case DeviceValueUOM.DEGREES_R: + case DeviceValueUOM.FAHRENHEIT: + return ( + new Intl.NumberFormat(undefined, { + minimumFractionDigits: 1 + }).format(value) + + ' ' + + DeviceValueUOM_s[uom] + ); + default: + return new Intl.NumberFormat().format(value) + ' ' + DeviceValueUOM_s[uom]; + } + }; - const updateTemperatureSensor = useCallback( - (ts: TemperatureSensor) => { - if (me.admin) { - ts.o_n = ts.n; - setSelectedTemperatureSensor(ts); - setTemperatureDialogOpen(true); - } - }, - [me.admin] - ); + const updateTemperatureSensor = (ts: TemperatureSensor) => { + if (me.admin) { + ts.o_n = ts.n; + setSelectedTemperatureSensor(ts); + setTemperatureDialogOpen(true); + } + }; - const onTemperatureDialogClose = useCallback(() => { + const onTemperatureDialogClose = () => { setTemperatureDialogOpen(false); void fetchSensorData(); - }, [fetchSensorData]); + }; - const onTemperatureDialogSave = useCallback( - async (ts: TemperatureSensor) => { - await sendTemperatureSensor({ - id: ts.id, - name: ts.n, - offset: ts.o, - is_system: ts.s + const onTemperatureDialogSave = async (ts: TemperatureSensor) => { + await sendTemperatureSensor({ + id: ts.id, + name: ts.n, + offset: ts.o, + is_system: ts.s + }) + .then(() => { + toast.success(LL.UPDATED_OF(LL.SENSOR(1))); }) - .then(() => { - toast.success(LL.UPDATED_OF(LL.SENSOR(1))); - }) - .catch(() => { - toast.error(LL.UPDATE_OF(LL.SENSOR(2)) + ' ' + LL.FAILED(1)); - }) - .finally(() => { - setTemperatureDialogOpen(false); - setSelectedTemperatureSensor(undefined); - void fetchSensorData(); - }); - }, - [sendTemperatureSensor, LL, fetchSensorData] - ); + .catch(() => { + toast.error(LL.UPDATE_OF(LL.SENSOR(2)) + ' ' + LL.FAILED(1)); + }) + .finally(() => { + setTemperatureDialogOpen(false); + setSelectedTemperatureSensor(undefined); + void fetchSensorData(); + }); + }; - const updateAnalogSensor = useCallback( - (as: AnalogSensor) => { - if (me.admin) { - setCreating(false); - as.o_n = as.n; - setSelectedAnalogSensor(as); - setAnalogDialogOpen(true); - } - }, - [me.admin] - ); + const updateAnalogSensor = (as: AnalogSensor) => { + if (me.admin) { + setCreating(false); + as.o_n = as.n; + setSelectedAnalogSensor(as); + setAnalogDialogOpen(true); + } + }; - const onAnalogDialogClose = useCallback(() => { + const onAnalogDialogClose = () => { setAnalogDialogOpen(false); void fetchSensorData(); - }, [fetchSensorData]); + }; - const addAnalogSensor = useCallback(() => { + const addAnalogSensor = () => { if (firstAvailableGPIO.current === undefined) { toast.error(LL.NO_GPIO()); return; @@ -366,194 +349,167 @@ const Sensors = () => { o_n: '' }); setAnalogDialogOpen(true); - }, []); + }; - const onAnalogDialogSave = useCallback( - async (as: AnalogSensor) => { - await sendAnalogSensor({ - id: as.id, - gpio: as.g, - name: as.n, - offset: as.o, - factor: as.f, - uom: as.u, - type: as.t, - deleted: as.d, - is_system: as.s + const onAnalogDialogSave = async (as: AnalogSensor) => { + await sendAnalogSensor({ + id: as.id, + gpio: as.g, + name: as.n, + offset: as.o, + factor: as.f, + uom: as.u, + type: as.t, + deleted: as.d, + is_system: as.s + }) + .then(() => { + toast.success(LL.UPDATED_OF(LL.ANALOG_SENSOR(2))); }) - .then(() => { - toast.success(LL.UPDATED_OF(LL.ANALOG_SENSOR(2))); - }) - .catch(() => { - toast.error(LL.UPDATE_OF(LL.ANALOG_SENSOR(5)) + ' ' + LL.FAILED(1)); - }) - .finally(() => { - setAnalogDialogOpen(false); - setSelectedAnalogSensor(undefined); - void fetchSensorData(); - }); - }, - [sendAnalogSensor, LL, fetchSensorData] + .catch(() => { + toast.error(LL.UPDATE_OF(LL.ANALOG_SENSOR(5)) + ' ' + LL.FAILED(1)); + }) + .finally(() => { + setAnalogDialogOpen(false); + setSelectedAnalogSensor(undefined); + void fetchSensorData(); + }); + }; + + const RenderAnalogSensors = ( + + {(tableList: AnalogSensor[]) => ( + <> +
+ + + + + + + + + + + + + + +
+ + {tableList.map((as: AnalogSensor) => ( + updateAnalogSensor(as)} + > + {as.g} + {as.n} + {AnalogTypeNames[as.t - 1]} + {(as.t === AnalogType.DIGITAL_OUT && + as.g !== GPIO_25 && + as.g !== GPIO_26) || + as.t === AnalogType.DIGITAL_IN || + as.t === AnalogType.PULSE ? ( + {as.v ? LL.ON() : LL.OFF()} + ) : ( + {formatValue(as.v, as.u)} + )} + + ))} + + + )} +
); - const RenderAnalogSensors = useMemo( - () => ( - - {(tableList: AnalogSensor[]) => ( - <> -
- - - - - - - - - - - - - - -
- - {tableList.map((as: AnalogSensor) => ( - updateAnalogSensor(as)} + const RenderTemperatureSensors = ( +
+ {(tableList: TemperatureSensor[]) => ( + <> +
+ + +
- ), - [ - analog_sort, - analog_theme, - getSortIcon, - sensorData.as, - LL, - updateAnalogSensor, - formatValue - ] - ); - - const RenderTemperatureSensors = useMemo( - () => ( - - {(tableList: TemperatureSensor[]) => ( - <> -
- - - - - - - - -
- - {tableList.map((ts: TemperatureSensor) => ( - updateTemperatureSensor(ts)} + {LL.NAME(0)} + + + +
- ), - [ - temperature_sort, - temperature_theme, - getSortIcon, - sensorData.ts, - LL, - updateTemperatureSensor, - formatValue - ] + {LL.VALUE(0)} + + + + + + {tableList.map((ts: TemperatureSensor) => ( + updateTemperatureSensor(ts)} + > + {ts.n} + {formatValue(ts.t, ts.u)} + + ))} + + + )} + ); return ( diff --git a/interface/src/app/main/SensorsAnalogDialog.tsx b/interface/src/app/main/SensorsAnalogDialog.tsx index ffc5a4485..483d337cc 100644 --- a/interface/src/app/main/SensorsAnalogDialog.tsx +++ b/interface/src/app/main/SensorsAnalogDialog.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useEffect, useState } from 'react'; import CancelIcon from '@mui/icons-material/Cancel'; import DoneIcon from '@mui/icons-material/Done'; @@ -53,84 +53,54 @@ const SensorsAnalogDialog = ({ const [fieldErrors, setFieldErrors] = useState(); const [editItem, setEditItem] = useState(selectedItem); - const updateFormValue = useMemo( - () => - updateValue((updater) => - setEditItem( - (prev) => - updater( - prev as unknown as Record - ) as unknown as AnalogSensor - ) - ), - [setEditItem] + const updateFormValue = updateValue((updater) => + setEditItem( + (prev) => + updater( + prev as unknown as Record + ) as unknown as AnalogSensor + ) ); - // Memoize helper functions to check sensor type conditions - const isCounterOrRate = useMemo( - () => - editItem.t === AnalogType.COUNTER || - editItem.t === AnalogType.RATE || - (editItem.t >= AnalogType.CNT_0 && editItem.t <= AnalogType.CNT_2), - [editItem.t] - ); - const isCounter = useMemo( - () => - editItem.t === AnalogType.COUNTER || - (editItem.t >= AnalogType.CNT_0 && editItem.t <= AnalogType.CNT_2), - [editItem.t] - ); - const isFreqType = useMemo( - () => editItem.t >= AnalogType.FREQ_0 && editItem.t <= AnalogType.FREQ_2, - [editItem.t] - ); - const isPWM = useMemo( - () => - editItem.t === AnalogType.PWM_0 || - editItem.t === AnalogType.PWM_1 || - editItem.t === AnalogType.PWM_2, - [editItem.t] - ); - const isDACOutGPIO = useMemo( - () => - editItem.t === AnalogType.DIGITAL_OUT && - (editItem.g === 25 || editItem.g === 26), - [editItem.t, editItem.g] - ); - const isDigitalOutGPIO = useMemo( - () => - editItem.t === AnalogType.DIGITAL_OUT && - editItem.g !== 25 && - editItem.g !== 26, - [editItem.t, editItem.g] - ); + const isCounterOrRate = + editItem.t === AnalogType.COUNTER || + editItem.t === AnalogType.RATE || + (editItem.t >= AnalogType.CNT_0 && editItem.t <= AnalogType.CNT_2); + const isCounter = + editItem.t === AnalogType.COUNTER || + (editItem.t >= AnalogType.CNT_0 && editItem.t <= AnalogType.CNT_2); + const isFreqType = + editItem.t >= AnalogType.FREQ_0 && editItem.t <= AnalogType.FREQ_2; + const isPWM = + editItem.t === AnalogType.PWM_0 || + editItem.t === AnalogType.PWM_1 || + editItem.t === AnalogType.PWM_2; + const isDACOutGPIO = + editItem.t === AnalogType.DIGITAL_OUT && + (editItem.g === 25 || editItem.g === 26); + const isDigitalOutGPIO = + editItem.t === AnalogType.DIGITAL_OUT && editItem.g !== 25 && editItem.g !== 26; - // Memoize menu items to avoid recreation on each render - const analogTypeMenuItems = useMemo( - () => - AnalogTypeNames.map((val, i) => ({ name: val, value: i + 1 })) - .sort((a, b) => a.name.localeCompare(b.name)) - .map(({ name, value }) => ( - - {name} - - )), - [disabledTypeList] - ); + const analogTypeMenuItems = AnalogTypeNames.map((val, i) => ({ + name: val, + value: i + 1 + })) + .sort((a, b) => a.name.localeCompare(b.name)) + .map(({ name, value }) => ( + + {name} + + )); - const uomMenuItems = useMemo( - () => - DeviceValueUOM_s.map((val, i) => ( - - {val} - - )), - [] - ); + const uomMenuItems = DeviceValueUOM_s.map((val, i) => ( + + {val} + + )); const analogGPIOMenuItems = () => // add selectedItem.g to the list @@ -157,16 +127,16 @@ const SensorsAnalogDialog = ({ } }, [open, selectedItem]); - const handleClose = useCallback( - (_event: React.SyntheticEvent, reason: 'backdropClick' | 'escapeKeyDown') => { - if (reason !== 'backdropClick') { - onClose(); - } - }, - [onClose] - ); + const handleClose = ( + _event: React.SyntheticEvent, + reason: 'backdropClick' | 'escapeKeyDown' + ) => { + if (reason !== 'backdropClick') { + onClose(); + } + }; - const save = useCallback(async () => { + const save = async () => { try { setFieldErrors(undefined); await validate(validator, editItem); @@ -174,17 +144,13 @@ const SensorsAnalogDialog = ({ } catch (error) { setFieldErrors((error as ValidationError).fieldErrors); } - }, [validator, editItem, onSave]); + }; - const remove = useCallback(() => { + const remove = () => { onSave({ ...editItem, d: true }); - }, [editItem, onSave]); + }; - const dialogTitle = useMemo( - () => - `${creating ? LL.ADD(1) + ' ' + LL.NEW(0) : LL.EDIT()} ${LL.ANALOG_SENSOR(0)}`, - [creating, LL] - ); + const dialogTitle = `${creating ? LL.ADD(1) + ' ' + LL.NEW(0) : LL.EDIT()} ${LL.ANALOG_SENSOR(0)}`; return ( diff --git a/interface/src/app/main/SensorsTemperatureDialog.tsx b/interface/src/app/main/SensorsTemperatureDialog.tsx index 670b34244..714156a85 100644 --- a/interface/src/app/main/SensorsTemperatureDialog.tsx +++ b/interface/src/app/main/SensorsTemperatureDialog.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useEffect, useState } from 'react'; import CancelIcon from '@mui/icons-material/Cancel'; import DoneIcon from '@mui/icons-material/Done'; @@ -50,16 +50,12 @@ const SensorsTemperatureDialog = ({ const [fieldErrors, setFieldErrors] = useState(); const [editItem, setEditItem] = useState(selectedItem); - const updateFormValue = useMemo( - () => - updateValue( - setEditItem as unknown as ( - updater: ( - prevState: Readonly> - ) => Record - ) => void - ), - [setEditItem] + const updateFormValue = updateValue( + setEditItem as unknown as ( + updater: ( + prevState: Readonly> + ) => Record + ) => void ); useEffect(() => { @@ -69,16 +65,13 @@ const SensorsTemperatureDialog = ({ } }, [open, selectedItem]); - const handleClose = useCallback( - (_event: React.SyntheticEvent, reason?: string) => { - if (reason !== 'backdropClick') { - onClose(); - } - }, - [onClose] - ); + const handleClose = (_event: React.SyntheticEvent, reason?: string) => { + if (reason !== 'backdropClick') { + onClose(); + } + }; - const save = useCallback(async () => { + const save = async () => { try { setFieldErrors(undefined); await validate(validator, editItem); @@ -86,29 +79,11 @@ const SensorsTemperatureDialog = ({ } catch (error) { setFieldErrors((error as ValidationError).fieldErrors); } - }, [validator, editItem, onSave]); - - const dialogTitle = useMemo(() => `${LL.EDIT()} ${LL.TEMP_SENSOR()}`, [LL]); - - const offsetValue = useMemo(() => numberValue(editItem.o), [editItem.o]); - - const slotProps = useMemo( - () => ({ - input: { - startAdornment: {TEMP_UNIT} - }, - htmlInput: { - min: OFFSET_MIN, - max: OFFSET_MAX, - step: OFFSET_STEP - } - }), - [] - ); + }; return ( - {dialogTitle} + {`${LL.EDIT()} ${LL.TEMP_SENSOR()}`} {LL.ID_OF(LL.SENSOR(0))}: {editItem.id} @@ -128,12 +103,23 @@ const SensorsTemperatureDialog = ({ {TEMP_UNIT} + ) + }, + htmlInput: { + min: OFFSET_MIN, + max: OFFSET_MAX, + step: OFFSET_STEP + } + }} />
diff --git a/interface/src/app/main/UserProfile.tsx b/interface/src/app/main/UserProfile.tsx index 46928e239..ebcae0be3 100644 --- a/interface/src/app/main/UserProfile.tsx +++ b/interface/src/app/main/UserProfile.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useContext } from 'react'; +import { memo, useContext } from 'react'; import PersonIcon from '@mui/icons-material/Person'; import { @@ -23,9 +23,9 @@ const UserProfileComponent = () => { useLayoutTitle(LL.USER_PROFILE()); - const handleSignOut = useCallback(() => { + const handleSignOut = () => { signOut(true); - }, [signOut]); + }; return ( diff --git a/interface/src/app/settings/APSettings.tsx b/interface/src/app/settings/APSettings.tsx index c4a20d42c..0f04aba3f 100644 --- a/interface/src/app/settings/APSettings.tsx +++ b/interface/src/app/settings/APSettings.tsx @@ -1,4 +1,4 @@ -import { useCallback, useMemo, useState } from 'react'; +import { useState } from 'react'; import CancelIcon from '@mui/icons-material/Cancel'; import WarningIcon from '@mui/icons-material/Warning'; @@ -62,22 +62,16 @@ const APSettings = () => { const [fieldErrors, setFieldErrors] = useState(); - const updateFormValue = useMemo( - () => - updateValueDirty( - origData as unknown as Record, - dirtyFlags, - setDirtyFlags, - updateDataValue as (value: unknown) => void - ), - [origData, dirtyFlags, setDirtyFlags, updateDataValue] + const updateFormValue = updateValueDirty( + origData as unknown as Record, + dirtyFlags, + setDirtyFlags, + updateDataValue as (value: unknown) => void ); - // Memoize AP enabled state - const apEnabled = useMemo(() => (data ? isAPEnabled(data) : false), [data]); + const apEnabled = data ? isAPEnabled(data) : false; - // Memoize validation and submit handler - const validateAndSubmit = useCallback(async () => { + const validateAndSubmit = async () => { if (!data) return; try { @@ -87,7 +81,7 @@ const APSettings = () => { } catch (error) { setFieldErrors((error as ValidationError).fieldErrors); } - }, [data, saveData]); + }; const content = () => { if (!data) { diff --git a/interface/src/app/settings/ApplicationSettings.tsx b/interface/src/app/settings/ApplicationSettings.tsx index cae0b1e1b..e401862cd 100644 --- a/interface/src/app/settings/ApplicationSettings.tsx +++ b/interface/src/app/settings/ApplicationSettings.tsx @@ -1,4 +1,4 @@ -import { useCallback, useMemo, useState } from 'react'; +import { useState } from 'react'; import { toast } from 'react-toastify'; import CancelIcon from '@mui/icons-material/Cancel'; @@ -107,49 +107,36 @@ const ApplicationSettings = () => { }); }); - // Memoized input props to prevent recreation on every render - const SecondsInputProps = useMemo( - () => ({ - endAdornment: {LL.SECONDS()} - }), - [LL] - ); + const SecondsInputProps = { + endAdornment: {LL.SECONDS()} + }; - const MinutesInputProps = useMemo( - () => ({ - endAdornment: {LL.MINUTES()} - }), - [LL] - ); + const MinutesInputProps = { + endAdornment: {LL.MINUTES()} + }; - const HoursInputProps = useMemo( - () => ({ - endAdornment: {LL.HOURS()} - }), - [LL] - ); + const HoursInputProps = { + endAdornment: {LL.HOURS()} + }; - const doRestart = useCallback(async () => { + const doRestart = async () => { setRestarting(true); await sendAPI({ device: 'system', cmd: 'restart', id: 0 }).catch( (error: Error) => { toast.error(error.message); } ); - }, [sendAPI]); + }; - const updateBoardProfile = useCallback( - async (board_profile: string) => { - await readBoardProfile(board_profile).catch((error: Error) => { - toast.error(error.message); - }); - }, - [readBoardProfile] - ); + const updateBoardProfile = async (board_profile: string) => { + await readBoardProfile(board_profile).catch((error: Error) => { + toast.error(error.message); + }); + }; useLayoutTitle(LL.APPLICATION()); - const validateAndSubmit = useCallback(async () => { + const validateAndSubmit = async () => { try { setFieldErrors(undefined); await validate(createSettingsValidator(data), data); @@ -158,31 +145,27 @@ const ApplicationSettings = () => { } finally { await saveData(); } - }, [data, saveData]); + }; - const changeBoardProfile = useCallback( - (event: React.ChangeEvent) => { - const boardProfile = event.target.value; - updateFormValue(event); - if (boardProfile === 'CUSTOM') { - updateDataValue({ - ...data, - board_profile: boardProfile - }); - } else { - void updateBoardProfile(boardProfile); - } - }, - [data, updateBoardProfile, updateFormValue, updateDataValue] - ); + const changeBoardProfile = (event: React.ChangeEvent) => { + const boardProfile = event.target.value; + updateFormValue(event); + if (boardProfile === 'CUSTOM') { + updateDataValue({ + ...data, + board_profile: boardProfile + }); + } else { + void updateBoardProfile(boardProfile); + } + }; - const restart = useCallback(async () => { + const restart = async () => { await validateAndSubmit(); await doRestart(); - }, [validateAndSubmit, doRestart]); + }; - // Memoize board profile select items to prevent recreation - const boardProfileItems = useMemo(() => boardProfileSelectItems(), []); + const boardProfileItems = boardProfileSelectItems(); const content = () => { if (!data || !hardwareData) { diff --git a/interface/src/app/settings/DownloadUpload.tsx b/interface/src/app/settings/DownloadUpload.tsx index 02a373e12..b47b7f242 100644 --- a/interface/src/app/settings/DownloadUpload.tsx +++ b/interface/src/app/settings/DownloadUpload.tsx @@ -1,4 +1,4 @@ -import { useCallback, useMemo, useState } from 'react'; +import { useState } from 'react'; import { toast } from 'react-toastify'; import CancelIcon from '@mui/icons-material/Cancel'; @@ -57,7 +57,7 @@ const DownloadUpload = () => { const { data, send: loadData, error } = useRequest(SystemApi.readSystemStatus); - const doRestart = useCallback(async () => { + const doRestart = async () => { setRestarting(true); try { await sendAPI({ device: 'system', cmd: 'restart', id: 0 }); @@ -65,16 +65,33 @@ const DownloadUpload = () => { toast.error((error as Error).message); setRestarting(false); } - }, [sendAPI]); + }; useLayoutTitle(LL.DOWNLOAD_UPLOAD()); - const handleCloseBackupDialog = useCallback(() => { + const handleCloseBackupDialog = () => { setConfirmBackup(false); - }, []); + }; - const renderBackupDialog = useMemo( - () => ( + const handleDownload = (type: string) => () => { + void sendExportData(type); + setConfirmBackup(false); + }; + + if (restarting) { + return ; + } + + if (!data) { + return ( + + + + ); + } + + return ( + { - ), - [confirmBackup, handleCloseBackupDialog, LL] - ); - - const handleDownload = useCallback( - (type: string) => () => { - void sendExportData(type); - setConfirmBackup(false); - }, - [sendExportData] - ); - - if (restarting) { - return ; - } - - if (!data) { - return ( - - - - ); - } - - return ( - - {renderBackupDialog} {LL.DOWNLOAD(0)} diff --git a/interface/src/app/settings/MqttSettings.tsx b/interface/src/app/settings/MqttSettings.tsx index 417fa8190..a1e8efe18 100644 --- a/interface/src/app/settings/MqttSettings.tsx +++ b/interface/src/app/settings/MqttSettings.tsx @@ -1,4 +1,4 @@ -import { useCallback, useMemo, useState } from 'react'; +import { useState } from 'react'; import { toast } from 'react-toastify'; import CancelIcon from '@mui/icons-material/Cancel'; @@ -57,7 +57,7 @@ const MqttSettings = () => { const [fieldErrors, setFieldErrors] = useState(); - const sendResetMQTT = useCallback(() => { + const sendResetMQTT = () => { void callAction({ action: 'resetMQTT' }) .then(() => { toast.success('MQTT ' + LL.REFRESH() + ' successful'); @@ -65,29 +65,20 @@ const MqttSettings = () => { .catch((error) => { toast.error(String(error.error?.message || 'An error occurred')); }); - }, []); + }; - const updateFormValue = useMemo( - () => - updateValueDirty( - origData as unknown as Record, - dirtyFlags, - setDirtyFlags, - updateDataValue as (value: unknown) => void - ), - [origData, dirtyFlags, setDirtyFlags, updateDataValue] + const updateFormValue = updateValueDirty( + origData as unknown as Record, + dirtyFlags, + setDirtyFlags, + updateDataValue as (value: unknown) => void ); - const SecondsInputProps = useMemo( - () => ({ - endAdornment: {LL.SECONDS()} - }), - [LL] - ); + const SecondsInputProps = { + endAdornment: {LL.SECONDS()} + }; - const emptyFieldErrors = useMemo(() => ({}), []); - - const validateAndSubmit = useCallback(async () => { + const validateAndSubmit = async () => { if (!data) return; try { setFieldErrors(undefined); @@ -96,25 +87,22 @@ const MqttSettings = () => { } catch (error) { setFieldErrors((error as ValidationError).fieldErrors); } - }, [data, saveData]); + }; - const publishIntervalFields = useMemo( - () => [ - { name: 'publish_time_heartbeat', label: 'Heartbeat', validated: true }, - { name: 'publish_time_boiler', label: LL.MQTT_INT_BOILER(), validated: false }, - { - name: 'publish_time_thermostat', - label: LL.MQTT_INT_THERMOSTATS(), - validated: false - }, - { name: 'publish_time_solar', label: LL.MQTT_INT_SOLAR(), validated: false }, - { name: 'publish_time_mixer', label: LL.MQTT_INT_MIXER(), validated: false }, - { name: 'publish_time_water', label: LL.MQTT_INT_WATER(), validated: false }, - { name: 'publish_time_sensor', label: LL.SENSORS(), validated: false }, - { name: 'publish_time_other', label: LL.DEFAULT(0), validated: false } - ], - [LL] - ); + const publishIntervalFields = [ + { name: 'publish_time_heartbeat', label: 'Heartbeat', validated: true }, + { name: 'publish_time_boiler', label: LL.MQTT_INT_BOILER(), validated: false }, + { + name: 'publish_time_thermostat', + label: LL.MQTT_INT_THERMOSTATS(), + validated: false + }, + { name: 'publish_time_solar', label: LL.MQTT_INT_SOLAR(), validated: false }, + { name: 'publish_time_mixer', label: LL.MQTT_INT_MIXER(), validated: false }, + { name: 'publish_time_water', label: LL.MQTT_INT_WATER(), validated: false }, + { name: 'publish_time_sensor', label: LL.SENSORS(), validated: false }, + { name: 'publish_time_other', label: LL.DEFAULT(0), validated: false } + ]; if (!data) { return ( @@ -154,7 +142,7 @@ const MqttSettings = () => { { { { { {field.validated ? ( { const { LL } = useI18nContext(); useLayoutTitle('NTP'); - // Memoized timezone select items for better performance const timeZoneItems = useTimeZoneSelectItems(); - // Memoized selected timezone value - const selectedTzValue = useMemo( - () => (data ? selectedTimeZone(data.tz_label, data.tz_format) : undefined), - [data?.tz_label, data?.tz_format] - ); + const selectedTzValue = data + ? selectedTimeZone(data.tz_label, data.tz_format) + : undefined; const [localTime, setLocalTime] = useState(''); const [settingTime, setSettingTime] = useState(false); @@ -82,32 +79,22 @@ const NTPSettings = () => { } ); - // Memoize updateFormValue to prevent recreation on every render - const updateFormValue = useMemo( - () => - updateValueDirty( - origData as unknown as Record, - dirtyFlags, - setDirtyFlags, - updateDataValue as (value: unknown) => void - ), - [origData, dirtyFlags, setDirtyFlags, updateDataValue] + const updateFormValue = updateValueDirty( + origData as unknown as Record, + dirtyFlags, + setDirtyFlags, + updateDataValue as (value: unknown) => void ); - // Memoize updateLocalTime handler - const updateLocalTime = useCallback( - (event: React.ChangeEvent) => setLocalTime(event.target.value), - [] - ); + const updateLocalTime = (event: React.ChangeEvent) => + setLocalTime(event.target.value); - // Memoize openSetTime handler - const openSetTime = useCallback(() => { + const openSetTime = () => { setLocalTime(formatLocalDateTime(new Date())); setSettingTime(true); - }, []); + }; - // Memoize configureTime handler - const configureTime = useCallback(async () => { + const configureTime = async () => { setProcessing(true); try { @@ -120,13 +107,11 @@ const NTPSettings = () => { } finally { setProcessing(false); } - }, [localTime, updateTime, LL, loadData]); + }; - // Memoize close dialog handler - const handleCloseSetTime = useCallback(() => setSettingTime(false), []); + const handleCloseSetTime = () => setSettingTime(false); - // Memoize validate and submit handler - const validateAndSubmit = useCallback(async () => { + const validateAndSubmit = async () => { if (!data) return; try { setFieldErrors(undefined); @@ -135,23 +120,18 @@ const NTPSettings = () => { } catch (error) { setFieldErrors((error as ValidationError).fieldErrors); } - }, [data, saveData]); + }; - // Memoize timezone change handler - const changeTimeZone = useCallback( - (event: React.ChangeEvent) => { - void updateState(readNTPSettings(), (settings: NTPSettingsType) => ({ - ...settings, - tz_label: event.target.value, - tz_format: TIME_ZONES[event.target.value] - })); - updateFormValue(event); - }, - [updateFormValue] - ); + const changeTimeZone = (event: React.ChangeEvent) => { + void updateState(readNTPSettings(), (settings: NTPSettingsType) => ({ + ...settings, + tz_label: event.target.value, + tz_format: TIME_ZONES[event.target.value] + })); + updateFormValue(event); + }; - // Memoize render content to prevent unnecessary re-renders - const renderContent = useMemo(() => { + const renderContent = () => { if (!data) { return ; } @@ -236,26 +216,12 @@ const NTPSettings = () => { )} ); - }, [ - data, - errorMessage, - loadData, - updateFormValue, - fieldErrors, - selectedTzValue, - changeTimeZone, - timeZoneItems, - dirtyFlags, - openSetTime, - saving, - validateAndSubmit, - LL - ]); + }; return ( {blocker ? : null} - {renderContent} + {renderContent()} {LL.SET_TIME(1)} diff --git a/interface/src/app/settings/Settings.tsx b/interface/src/app/settings/Settings.tsx index a8efc8c4b..7808633d4 100644 --- a/interface/src/app/settings/Settings.tsx +++ b/interface/src/app/settings/Settings.tsx @@ -1,190 +1,108 @@ -import { useCallback, useMemo, useState } from 'react'; +import { useContext } from 'react'; import AccessTimeIcon from '@mui/icons-material/AccessTime'; -import CancelIcon from '@mui/icons-material/Cancel'; +import BuildIcon from '@mui/icons-material/Build'; import DeviceHubIcon from '@mui/icons-material/DeviceHub'; import ImportExportIcon from '@mui/icons-material/ImportExport'; import LockIcon from '@mui/icons-material/Lock'; -import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore'; import SettingsEthernetIcon from '@mui/icons-material/SettingsEthernet'; import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna'; import TuneIcon from '@mui/icons-material/Tune'; import ViewModuleIcon from '@mui/icons-material/ViewModule'; -import { - Box, - Button, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - Divider, - List -} from '@mui/material'; +import { List } from '@mui/material'; -import { API } from 'api/app'; - -import { dialogStyle } from 'CustomTheme'; -import { useRequest } from 'alova/client'; -import type { APIcall } from 'app/main/types'; import { SectionContent, useLayoutTitle } from 'components'; import ListMenuItem from 'components/layout/ListMenuItem'; +import { AuthenticatedContext } from 'contexts/authentication'; import { useI18nContext } from 'i18n/i18n-react'; -import SystemMonitor from '../status/SystemMonitor'; - const Settings = () => { const { LL } = useI18nContext(); + const { versions } = useContext(AuthenticatedContext); useLayoutTitle(LL.SETTINGS(0)); - const [confirmFactoryReset, setConfirmFactoryReset] = useState(false); - const [restarting, setRestarting] = useState(); + const upgradeAvailable = versions?.current?.upgradeable ?? false; + const firmwareText = versions?.current?.version + ? `v${versions.current.version}${upgradeAvailable ? ` (${LL.UPDATE_AVAILABLE()})` : ''}` + : ''; - const { send: sendAPI } = useRequest((data: APIcall) => API(data), { - immediate: false - }); + return ( + + + - const doFormat = useCallback(async () => { - await sendAPI({ device: 'system', cmd: 'format', id: 0 }).then(() => { - setRestarting(true); - setConfirmFactoryReset(false); - }); - }, [sendAPI]); + - const handleFactoryResetClose = useCallback(() => { - setConfirmFactoryReset(false); - }, []); + - const handleFactoryResetClick = useCallback(() => { - setConfirmFactoryReset(true); - }, []); + - const content = useMemo(() => { - return ( - <> - - + - + - + - + - - - - - - - - - - - {LL.FACTORY_RESET()} - {LL.SYSTEM_FACTORY_TEXT_DIALOG()} - - - - - - - - - - - - - ); - }, [ - LL, - handleFactoryResetClick, - handleFactoryResetClose, - doFormat, - confirmFactoryReset, - restarting - ]); - - return restarting ? : {content}; + + + + ); }; export default Settings; diff --git a/interface/src/app/settings/TZ.tsx b/interface/src/app/settings/TZ.tsx index c734f1809..e0ff35294 100644 --- a/interface/src/app/settings/TZ.tsx +++ b/interface/src/app/settings/TZ.tsx @@ -1,5 +1,3 @@ -import { useMemo } from 'react'; - import { MenuItem } from '@mui/material'; export const TIME_ZONES: Record = { @@ -472,26 +470,16 @@ export function selectedTimeZone(label: string, format: string) { return TIME_ZONES[label] === format ? label : undefined; } -// Memoized version for use in components -export function useTimeZoneSelectItems() { - return useMemo( - () => - TIME_ZONE_LABELS.map((label) => ( - - {label} - - )), - [] - ); -} - -// Fallback export for backward compatibility - now memoized const precomputedTimeZoneItems = TIME_ZONE_LABELS.map((label) => ( {label} )); +export function useTimeZoneSelectItems() { + return precomputedTimeZoneItems; +} + export function timeZoneSelectItems() { return precomputedTimeZoneItems; } diff --git a/interface/src/app/settings/Version.tsx b/interface/src/app/settings/Version.tsx new file mode 100644 index 000000000..373133a0a --- /dev/null +++ b/interface/src/app/settings/Version.tsx @@ -0,0 +1,959 @@ +import { memo, useContext, useMemo, useState } from 'react'; +import { Link } from 'react-router'; +import { toast } from 'react-toastify'; + +import CancelIcon from '@mui/icons-material/Cancel'; +import CloseIcon from '@mui/icons-material/Close'; +import CheckIcon from '@mui/icons-material/Done'; +import DownloadIcon from '@mui/icons-material/GetApp'; +import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; +import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew'; +import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore'; +import WarningIcon from '@mui/icons-material/Warning'; +import { + Box, + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Divider, + Grid, + IconButton, + Table, + TableBody, + TableCell, + TableRow, + Typography +} from '@mui/material'; + +import * as SystemApi from 'api/system'; +import { API, callAction } from 'api/app'; + +import { dialogStyle } from 'CustomTheme'; +import { useRequest } from 'alova/client'; +import type { APIcall } from 'app/main/types'; +import SystemMonitor from 'app/status/SystemMonitor'; +import { + FormLoader, + SectionContent, + SingleUpload, + useLayoutTitle +} from 'components'; +import { AuthenticatedContext } from 'contexts/authentication'; +import { useI18nContext } from 'i18n/i18n-react'; +import type { TranslationFunctions } from 'i18n/i18n-types'; +import type { VersionInfo } from 'types'; +import { prettyDateTime } from 'utils/time'; + +// Constants moved outside component to avoid recreation +const STABLE_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/'; +const STABLE_RELNOTES_URL = + 'https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md'; +const DEV_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/latest/'; +const DEV_RELNOTES_URL = + 'https://github.com/emsesp/EMS-ESP32/blob/dev/CHANGELOG_LATEST.md'; + +// Types for better type safety +interface PartitionData { + partition: string; + version: string; + install_date?: string; + size: number; +} + +interface VersionData { + emsesp_version: string; + arduino_version: string; + esp_platform: string; + flash_chip_size: number; + psram: boolean; + build_flags?: string; + partition: string; + partitions: PartitionData[]; + developer_mode: boolean; +} + +// Memoized components for better performance +const VersionInfoDialog = memo( + ({ + showVersionInfo, + latestVersion, + latestDevVersion, + partitionVersion, + partition, + currentPartition, + size, + locale, + LL, + onClose + }: { + showVersionInfo: number; + latestVersion: VersionInfo | undefined; + latestDevVersion: VersionInfo | undefined; + partitionVersion: VersionInfo | undefined; + partition: string; + currentPartition: string; + size: number; + locale: string; + LL: TranslationFunctions; + onClose: () => void; + }) => { + if (showVersionInfo === 0) return null; + + const isStable = showVersionInfo === 1; + const isDev = showVersionInfo === 2; + const isPartition = showVersionInfo === 3; + + const version = isStable + ? latestVersion + : isDev + ? latestDevVersion + : partitionVersion; + const relNotesUrl = isStable + ? STABLE_RELNOTES_URL + : isDev + ? DEV_RELNOTES_URL + : ''; + + return ( + + {LL.FIRMWARE_VERSION_INFO()} + + + + + + {LL.VERSION()} + + + {isPartition + ? typeof version === 'string' + ? version + : version?.version + : version?.version} + + + + + {isPartition ? LL.TYPE(0) : LL.RELEASE_TYPE()} + + + {partition === currentPartition && LL.ACTIVE() + ' '} + {isStable + ? LL.STABLE() + : isDev + ? LL.DEVELOPMENT() + : 'Partition ' + LL.VERSION()} + + + {isPartition && ( + + + Partition + + + {partition} + + + )} + {isPartition && ( + + + Size + + + {size} KB + + + )} + {version && version.date && ( + + + {isPartition ? 'Install Date' : 'Build Date'} + + + {prettyDateTime(locale, new Date(version.date))} + + + )} + +
+
+ + {!isPartition && ( + + )} + + +
+ ); + } +); + +const InstallDialog = memo( + ({ + openInstallDialog, + fetchDevVersion, + latestVersion, + latestDevVersion, + upgradeImportantMessageType, + downloadOnly, + platform, + LL, + onClose, + onInstall + }: { + openInstallDialog: boolean; + fetchDevVersion: boolean; + latestVersion: VersionInfo | undefined; + latestDevVersion: VersionInfo | undefined; + upgradeImportantMessageType: number; + downloadOnly: boolean; + platform: string; + LL: TranslationFunctions; + onClose: () => void; + onInstall: (url: string) => void; + }) => { + const binURL = (() => { + if (!latestVersion || !latestDevVersion) return ''; + const version = fetchDevVersion ? latestDevVersion : latestVersion; + const filename = `EMS-ESP-${version.version.replaceAll('.', '_')}-${platform}.bin`; + return fetchDevVersion + ? `${DEV_URL}${filename}` + : `${STABLE_URL}v${version.version}/${filename}`; + })(); + + return ( + + + {`${LL.INSTALL()} ${fetchDevVersion ? LL.DEVELOPMENT() : LL.STABLE()} Firmware`} + + + + {LL.INSTALL_VERSION( + downloadOnly ? LL.DOWNLOAD(1) : LL.INSTALL(), + fetchDevVersion ? latestDevVersion?.version : latestVersion?.version + )} + + {upgradeImportantMessageType === 2 && LL.UPGRADE_IMPORTANT_MESSAGES_2()} + {upgradeImportantMessageType === 1 && ( + <> + {LL.UPGRADE_IMPORTANT_MESSAGES_1()} + + + {LL.DOWNLOAD_SYSTEM_BACKUP()} + + + + )} + + + {LL.ONLINE_HELP()} + + + + + + + {!downloadOnly && ( + + )} + + + ); + } +); + +const InstallPartitionDialog = memo( + ({ + openInstallPartitionDialog, + version, + partition, + LL, + onClose, + onInstall + }: { + openInstallPartitionDialog: boolean; + version: string; + partition: string; + LL: TranslationFunctions; + onClose: () => void; + onInstall: (partition: string) => void; + }) => { + return ( + + + {LL.INSTALL()} {LL.STORED_VERSIONS()} + + + + {LL.INSTALL_VERSION(LL.INSTALL(), version)} + + + + + + + + + ); + } +); + +// Helper function moved outside component +const getPlatform = (data: VersionData): string => { + return `${data.esp_platform}-${data.flash_chip_size >= 16384 ? '16MB' : '4MB'}${data.psram ? '+' : ''}`; +}; + +const Version = () => { + const { LL, locale } = useI18nContext(); + const { me, versions } = useContext(AuthenticatedContext); + + const [restarting, setRestarting] = useState(false); + const [confirmFactoryReset, setConfirmFactoryReset] = useState(false); + const [confirmRestart, setConfirmRestart] = useState(false); + const [openInstallDialog, setOpenInstallDialog] = useState(false); + + const [partitionVersion, setPartitionVersion] = useState( + undefined + ); + const [partition, setPartition] = useState(''); + const [openInstallPartitionDialog, setOpenInstallPartitionDialog] = + useState(false); + + const [fetchDevVersion, setFetchDevVersion] = useState(false); + const [downloadOnly, setDownloadOnly] = useState(false); + const [showVersionInfo, setShowVersionInfo] = useState(0); // 1 = stable, 2 = dev, 3 = partition + const [firmwareSize, setFirmwareSize] = useState(0); + + const latestVersion = useMemo( + () => + versions?.stable + ? { version: versions.stable.version, date: versions.stable.date } + : undefined, + [versions?.stable] + ); + const latestDevVersion = useMemo( + () => + versions?.dev + ? { version: versions.dev.version, date: versions.dev.date } + : undefined, + [versions?.dev] + ); + const usingDevVersion = versions?.current?.type === 'dev'; + const stableUpgradeAvailable = versions?.stable?.upgradeable ?? false; + const devUpgradeAvailable = versions?.dev?.upgradeable ?? false; + const internetLive = Boolean(versions?.stable || versions?.dev); + + const { send: sendSetPartition } = useRequest( + (partition: string) => callAction({ action: 'setPartition', param: partition }), + { immediate: false } + ).onError((error) => { + toast.error(String(error.error?.message || 'An error occurred')); + }); + + const { + data, + send: loadData, + error + } = useRequest(SystemApi.readSystemStatus).onSuccess((event) => { + const systemData = event.data as VersionData; + if (systemData.arduino_version.startsWith('Tasmota')) { + setDownloadOnly(true); + } + }); + + const { send: sendUploadURL } = useRequest( + (url: string) => callAction({ action: 'uploadURL', param: url }), + { immediate: false } + ); + + const { send: sendAPI } = useRequest((data: APIcall) => API(data), { + immediate: false + }); + + const [upgradeImportantMessageType, setUpgradeImportantMessageType] = + useState(0); + + const { send: checkUpgradeImportantMessages } = useRequest( + (version: string) => + callAction({ action: 'upgradeImportantMessages', param: version }), + { + immediate: false + } + ) + .onSuccess((event) => { + const upgradeImportantMessageType_n = ( + event.data as { upgradeImportantMessageType: number } + ).upgradeImportantMessageType; + setUpgradeImportantMessageType(upgradeImportantMessageType_n); + }) + .onError((error) => { + toast.error(String(error.error?.message || 'An error occurred')); + }); + + const platform = data ? getPlatform(data) : ''; + + const otherPartitions = + data?.partitions.filter((p) => p.partition !== data.partition) ?? []; + + const setPartitionVersionInfo = (partition: string) => { + setShowVersionInfo(3); + const partitionData = data?.partitions.find((p) => p.partition === partition); + if (partitionData) { + setPartitionVersion({ + version: partitionData.version, + date: partitionData.install_date ?? '' + }); + setPartition(partitionData.partition); + setFirmwareSize(partitionData.size); + } + }; + + const doRestart = async () => { + setConfirmRestart(false); + await sendAPI({ device: 'system', cmd: 'restart', id: 0 }).catch( + (error: Error) => { + toast.error(error.message); + } + ); + setRestarting(true); + }; + + const doFormat = async () => { + await sendAPI({ device: 'system', cmd: 'format', id: 0 }).then(() => { + setRestarting(true); + setConfirmFactoryReset(false); + }); + }; + + const handleFactoryResetClose = () => setConfirmFactoryReset(false); + const handleFactoryResetClick = () => setConfirmFactoryReset(true); + const handleRestartClose = () => setConfirmRestart(false); + const handleRestartClick = () => setConfirmRestart(true); + + const installFirmwareURL = async (url: string) => { + await sendUploadURL(url).catch((error: Error) => { + toast.error(error.message); + }); + await doRestart(); + }; + + const installPartitionFirmware = async (partition: string) => { + await sendSetPartition(partition).catch((error: Error) => { + toast.error(error.message); + }); + setRestarting(true); + }; + + const showPartitionDialog = ( + version: string, + partition: string, + install_date: string + ) => { + setOpenInstallPartitionDialog(true); + setPartitionVersion({ version: version, date: install_date }); + setPartition(partition); + }; + + const showFirmwareDialog = (useDevVersion: boolean) => { + setFetchDevVersion(useDevVersion); + const targetVersion = useDevVersion + ? latestDevVersion?.version + : latestVersion?.version; + if (targetVersion) { + void checkUpgradeImportantMessages(targetVersion); + } + setOpenInstallDialog(true); + }; + + const closeInstallDialog = () => setOpenInstallDialog(false); + const closeInstallPartitionDialog = () => setOpenInstallPartitionDialog(false); + + const handleVersionInfoClose = () => { + setShowVersionInfo(0); + setPartitionVersion(undefined); + setPartition(''); + }; + + useLayoutTitle('EMS-ESP Firmware'); + + const showButtons = (showingDev: boolean) => { + const choice = showingDev + ? !usingDevVersion + ? LL.SWITCH_RELEASE_TYPE(LL.DEVELOPMENT()) + : devUpgradeAvailable + ? LL.UPDATE_AVAILABLE() + : undefined + : usingDevVersion + ? LL.SWITCH_RELEASE_TYPE(LL.STABLE()) + : stableUpgradeAvailable + ? LL.UPDATE_AVAILABLE() + : undefined; + + if (!choice) { + return ( + <> + + + {LL.LATEST_VERSION(usingDevVersion ? LL.DEVELOPMENT() : LL.STABLE())} + + + + ); + } + + if (!me.admin) return null; + + const isUpdateAvailable = choice === LL.UPDATE_AVAILABLE(); + + return ( + + ); + }; + + if (restarting) { + return ; + } + + if (!data) { + return ( + + + + ); + } + + return ( + + + + {LL.THIS_VERSION()} + + + + + {LL.VERSION()} + + + + {data.emsesp_version} + {data.build_flags && ( + +   ({data.build_flags}) + + )} + setPartitionVersionInfo(data.partition)} + aria-label={LL.FIRMWARE_VERSION_INFO()} + > + + + + + + + {LL.PLATFORM()} + + + + {platform} + +   ( + {data.psram ? ( + + ) : ( + + )} + PSRAM) + + + + + + {internetLive ? ( + <> + + {LL.AVAILABLE_VERSION()} + + + + {otherPartitions.length > 0 && data.developer_mode && ( + <> + + {LL.STORED_VERSIONS()} + + + {otherPartitions.map((partition) => ( + + {partition.version} + + setPartitionVersionInfo(partition.partition) + } + aria-label={LL.FIRMWARE_VERSION_INFO()} + > + + + + + ))} + + + )} + + {LL.STABLE()} + + + + {latestVersion?.version} + setShowVersionInfo(1)} + aria-label={LL.FIRMWARE_VERSION_INFO()} + > + + + {showButtons(false)} + + + + + {LL.DEVELOPMENT()} + + + + {latestDevVersion?.version} + setShowVersionInfo(2)} + aria-label={LL.FIRMWARE_VERSION_INFO()} + > + + + {showButtons(true)} + + + + + ) : ( + + + {LL.INTERNET_CONNECTION_REQUIRED()} + + )} + {me.admin && ( + <> + + + + + {LL.UPLOAD()} + + + + )} + + + {me.admin && ( + <> + + {LL.FACTORY_RESET()} + {LL.SYSTEM_FACTORY_TEXT_DIALOG()} + + + + + + + + {LL.RESTART()} + {LL.RESTART_CONFIRM()} + + + + + + + + + {data.developer_mode && ( + + )} + + + )} + + ); +}; + +export default memo(Version); diff --git a/interface/src/app/settings/network/Network.tsx b/interface/src/app/settings/network/Network.tsx index 300010e3f..e90e5b835 100644 --- a/interface/src/app/settings/network/Network.tsx +++ b/interface/src/app/settings/network/Network.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useMemo, useState } from 'react'; +import { memo, useState } from 'react'; import { Navigate, Route, @@ -40,26 +40,20 @@ const Network = () => { const [selectedNetwork, setSelectedNetwork] = useState(); - const selectNetwork = useCallback( - (network: WiFiNetwork) => { - setSelectedNetwork(network); - void navigate('/settings/network/settings'); - }, - [navigate] - ); + const selectNetwork = (network: WiFiNetwork) => { + setSelectedNetwork(network); + void navigate('/settings/network/settings'); + }; - const deselectNetwork = useCallback(() => { + const deselectNetwork = () => { setSelectedNetwork(undefined); - }, []); + }; - const contextValue = useMemo( - () => ({ - ...(selectedNetwork && { selectedNetwork }), - selectNetwork, - deselectNetwork - }), - [selectedNetwork, selectNetwork, deselectNetwork] - ); + const contextValue = { + ...(selectedNetwork && { selectedNetwork }), + selectNetwork, + deselectNetwork + }; return ( diff --git a/interface/src/app/settings/network/NetworkSettings.tsx b/interface/src/app/settings/network/NetworkSettings.tsx index 5f96aa594..89789ccc2 100644 --- a/interface/src/app/settings/network/NetworkSettings.tsx +++ b/interface/src/app/settings/network/NetworkSettings.tsx @@ -121,19 +121,19 @@ const NetworkSettings = () => { deselectNetwork(); }, [data, saveData, deselectNetwork]); - const setCancel = useCallback(async () => { + const setCancel = async () => { deselectNetwork(); await loadData(); - }, [deselectNetwork, loadData]); + }; - const doRestart = useCallback(async () => { + const doRestart = async () => { setRestarting(true); await sendAPI({ device: 'system', cmd: 'restart', id: 0 }).catch( (error: Error) => { toast.error(error.message); } ); - }, [sendAPI]); + }; const content = () => { if (!data) { diff --git a/interface/src/app/settings/network/WiFiNetworkScanner.tsx b/interface/src/app/settings/network/WiFiNetworkScanner.tsx index b4517b0f1..b7d58206c 100644 --- a/interface/src/app/settings/network/WiFiNetworkScanner.tsx +++ b/interface/src/app/settings/network/WiFiNetworkScanner.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useRef, useState } from 'react'; +import { memo, useRef, useState } from 'react'; import PermScanWifiIcon from '@mui/icons-material/PermScanWifi'; import { Button } from '@mui/material'; @@ -48,12 +48,12 @@ const WiFiNetworkScanner = () => { } }); - const renderNetworkScanner = useCallback(() => { + const renderNetworkScanner = () => { if (!networkList) { return ; } return ; - }, [networkList, errorMessage]); + }; return ( diff --git a/interface/src/app/settings/network/WiFiNetworkSelector.tsx b/interface/src/app/settings/network/WiFiNetworkSelector.tsx index bfc0f9949..e7b7d327b 100644 --- a/interface/src/app/settings/network/WiFiNetworkSelector.tsx +++ b/interface/src/app/settings/network/WiFiNetworkSelector.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useContext } from 'react'; +import { memo, useContext } from 'react'; import LockIcon from '@mui/icons-material/Lock'; import LockOpenIcon from '@mui/icons-material/LockOpen'; @@ -63,34 +63,31 @@ const WiFiNetworkSelector = ({ networkList }: { networkList: WiFiNetworkList }) const wifiConnectionContext = useContext(WiFiConnectionContext); - const renderNetwork = useCallback( - (network: WiFiNetwork) => ( - wifiConnectionContext.selectNetwork(network)} - > - - {isNetworkOpen(network) ? : } - - - - - - - - - ), - [wifiConnectionContext, theme] + const renderNetwork = (network: WiFiNetwork) => ( + wifiConnectionContext.selectNetwork(network)} + > + + {isNetworkOpen(network) ? : } + + + + + + + + ); if (networkList.networks.length === 0) { diff --git a/interface/src/app/settings/security/ManageUsers.tsx b/interface/src/app/settings/security/ManageUsers.tsx index bc17261d8..5ae9de30a 100644 --- a/interface/src/app/settings/security/ManageUsers.tsx +++ b/interface/src/app/settings/security/ManageUsers.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useContext, useMemo, useState } from 'react'; +import { memo, useCallback, useContext, useState } from 'react'; import { useBlocker } from 'react-router'; import CancelIcon from '@mui/icons-material/Cancel'; @@ -55,16 +55,14 @@ const ManageUsers = () => { const blocker = useBlocker(changed !== 0); const { LL } = useI18nContext(); - const table_theme = useMemo( - () => - useTheme({ - Table: ` + const table_theme = useTheme({ + Table: ` --data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) minmax(120px, max-content) 120px; `, - BaseRow: ` + BaseRow: ` font-size: 14px; `, - HeaderRow: ` + HeaderRow: ` text-transform: uppercase; background-color: black; color: #90CAF9; @@ -74,7 +72,7 @@ const ManageUsers = () => { border-bottom: 1px solid #565656; } `, - Row: ` + Row: ` .td { padding: 8px; border-top: 1px solid #565656; @@ -87,7 +85,7 @@ const ManageUsers = () => { background-color: #1e1e1e; } `, - BaseCell: ` + BaseCell: ` &:nth-of-type(2) { text-align: center; } @@ -95,44 +93,36 @@ const ManageUsers = () => { text-align: right; } ` - }), - [] - ); + }); - const noAdminConfigured = useCallback( - () => !data?.users.find((u) => u.admin), - [data] - ); + const noAdminConfigured = () => !data?.users.find((u) => u.admin); - const removeUser = useCallback( - (toRemove: UserType) => { - if (!data) return; - const users = data.users.filter((u) => u.username !== toRemove.username); - updateDataValue({ ...data, users }); - setChanged(changed + 1); - }, - [data, updateDataValue, changed] - ); + const removeUser = (toRemove: UserType) => { + if (!data) return; + const users = data.users.filter((u) => u.username !== toRemove.username); + updateDataValue({ ...data, users }); + setChanged(changed + 1); + }; - const createUser = useCallback(() => { + const createUser = () => { setCreating(true); setUser({ username: '', password: '', admin: true }); - }, []); + }; - const editUser = useCallback((toEdit: UserType) => { + const editUser = (toEdit: UserType) => { setCreating(false); setUser({ ...toEdit }); - }, []); + }; - const cancelEditingUser = useCallback(() => { + const cancelEditingUser = () => { setUser(undefined); - }, []); + }; - const doneEditingUser = useCallback(() => { + const doneEditingUser = () => { if (user && data) { const users = [ ...data.users.filter( @@ -144,26 +134,26 @@ const ManageUsers = () => { setUser(undefined); setChanged(changed + 1); } - }, [user, data, updateDataValue, changed]); + }; const closeGenerateToken = useCallback(() => { setGeneratingToken(undefined); }, []); - const generateTokenForUser = useCallback((username: string) => { + const generateTokenForUser = (username: string) => { setGeneratingToken(username); - }, []); + }; - const onSubmit = useCallback(async () => { + const onSubmit = async () => { await saveData(); await authenticatedContext.refresh(); setChanged(0); - }, [saveData, authenticatedContext]); + }; - const onCancelSubmit = useCallback(async () => { + const onCancelSubmit = async () => { await loadData(); setChanged(0); - }, [loadData]); + }; const content = () => { if (!data) { @@ -177,15 +167,10 @@ const ManageUsers = () => { admin: boolean; } - // add id to the type, needed for the table - const user_table = useMemo( - () => - data.users.map((u) => ({ - ...u, - id: u.username - })) as UserType2[], - [data.users] - ); + const user_table = data.users.map((u) => ({ + ...u, + id: u.username + })) as UserType2[]; return ( <> diff --git a/interface/src/app/settings/security/Security.tsx b/interface/src/app/settings/security/Security.tsx index 012aac55a..5701a907c 100644 --- a/interface/src/app/settings/security/Security.tsx +++ b/interface/src/app/settings/security/Security.tsx @@ -1,4 +1,4 @@ -import { memo, useMemo } from 'react'; +import { memo } from 'react'; import { Navigate, Route, Routes, matchRoutes, useLocation } from 'react-router'; import { Tab } from '@mui/material'; @@ -15,19 +15,15 @@ const Security = () => { const location = useLocation(); - const matchedRoutes = useMemo( - () => - matchRoutes( - [ - { - path: '/settings/security/settings', - element: - }, - { path: '/settings/security/users', element: } - ], - location - ), - [location] + const matchedRoutes = matchRoutes( + [ + { + path: '/settings/security/settings', + element: + }, + { path: '/settings/security/users', element: } + ], + location ); const routerTab = matchedRoutes?.[0]?.route.path || false; diff --git a/interface/src/app/settings/security/SecuritySettings.tsx b/interface/src/app/settings/security/SecuritySettings.tsx index 117a84467..40cac3de6 100644 --- a/interface/src/app/settings/security/SecuritySettings.tsx +++ b/interface/src/app/settings/security/SecuritySettings.tsx @@ -79,7 +79,7 @@ const SecuritySettings = () => { onChange={updateFormValue} margin="normal" /> - + {dirtyFlags && dirtyFlags.length !== 0 && ( - - -
- ), - [confirmRestart, handleCloseRestartDialog, doRestart, LL] - ); - - // Memoize formatted values - const firmwareVersion = useMemo( - () => `v${data?.emsesp_version || ''}`, - [data?.emsesp_version] - ); - - const uptimeText = useMemo( - () => (data ? formatDurationSec(data.uptime, LL) : ''), - [data?.uptime, LL] - ); - - const freeMemoryText = useMemo( - () => (data ? `${formatNumber(data.free_heap)} KB ${LL.FREE_MEMORY()}` : ''), - [data?.free_heap, LL] - ); - - const networkIcon = useMemo( - () => - data?.network_status === NetworkConnectionStatus.WIFI_STATUS_CONNECTED - ? WifiIcon - : RouterIcon, - [data?.network_status] - ); - - const mqttStatusText = useMemo( - () => (data?.mqtt_status ? LL.CONNECTED(0) : LL.INACTIVE(0)), - [data?.mqtt_status, LL] - ); - - const apStatusText = useMemo( - () => (data?.ap_status ? LL.ACTIVE() : LL.INACTIVE(0)), - [data?.ap_status, LL] - ); - - const handleRestartClick = useCallback(() => { - setConfirmRestart(true); - }, []); - - const content = useMemo(() => { - if (!data || !LL) { - return ; - } + const activeHighlight = (value: boolean) => + value ? theme.palette.success.main : theme.palette.info.main; + if (!data || !LL) { return ( - <> - - - - - - - - - - - {me.admin && ( - - )} - - - - - - - - - - - - - - - - - - {renderRestartDialog} - + + + ); - }, [ - data, - LL, - firmwareVersion, - uptimeText, - freeMemoryText, - networkIcon, - mqttStatusText, - apStatusText, - busStatus, - busStatusHighlight, - networkStatusHighlight, - networkStatus, - ntpStatusHighlight, - ntpStatus, - activeHighlight, - me.admin, - handleRestartClick, - error, - loadData, - renderRestartDialog - ]); + } - return restarting ? : {content}; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + ); }; export default SystemStatus; diff --git a/interface/src/app/status/SystemLog.tsx b/interface/src/app/status/SystemLog.tsx index 628e7a2a1..76d384135 100644 --- a/interface/src/app/status/SystemLog.tsx +++ b/interface/src/app/status/SystemLog.tsx @@ -1,11 +1,4 @@ -import { - memo, - useCallback, - useEffect, - useLayoutEffect, - useRef, - useState -} from 'react'; +import { memo, useEffect, useLayoutEffect, useRef, useState } from 'react'; import { toast } from 'react-toastify'; import DownloadIcon from '@mui/icons-material/GetApp'; @@ -185,8 +178,7 @@ const SystemLog = () => { }; }, [data]); // Recalculate when data changes (in case layout shifts) - // Memoize message handler to avoid recreating on every render - const handleLogMessage = useCallback((message: { data: string }) => { + const handleLogMessage = (message: { data: string }) => { const rawData = message.data; const logentry = JSON.parse(rawData) as LogEntry; setLogEntries((log) => { @@ -200,7 +192,7 @@ const SystemLog = () => { const newLog = [...log, logentry]; return newLog; }); - }, []); + }; useSSE(fetchLogES, { immediate: true, @@ -211,7 +203,7 @@ const SystemLog = () => { toast.error('No connection to Log service'); }); - const onDownload = useCallback(() => { + const onDownload = () => { const result = logEntries .map((i) => `${i.t} ${levelLabel(i.l)} ${i.i}: [${i.n}] ${i.m}`) .join('\n'); @@ -225,11 +217,11 @@ const SystemLog = () => { document.body.appendChild(a); a.click(); document.body.removeChild(a); - }, [logEntries]); + }; - const saveSettings = useCallback(async () => { + const saveSettings = async () => { await saveData(); - }, [saveData]); + }; // handle scrolling - optimized to only scroll when needed const ref = useRef(null); @@ -246,7 +238,7 @@ const SystemLog = () => { } }, [logEntries.length, autoscroll]); - const sendReadCommand = useCallback(() => { + const sendReadCommand = () => { if (readValue === '') { setReadOpen(!readOpen); return; @@ -257,7 +249,7 @@ const SystemLog = () => { setReadOpen(false); setReadValue(''); } - }, [readValue, readOpen, send]); + }; const content = () => { if (!data) { diff --git a/interface/src/app/status/SystemMonitor.tsx b/interface/src/app/status/SystemMonitor.tsx index 4f4423be7..b6fa12d1f 100644 --- a/interface/src/app/status/SystemMonitor.tsx +++ b/interface/src/app/status/SystemMonitor.tsx @@ -1,4 +1,4 @@ -import { useCallback, useMemo, useRef, useState } from 'react'; +import { useRef, useState } from 'react'; import CancelIcon from '@mui/icons-material/Cancel'; import { Box, Button, Typography } from '@mui/material'; @@ -57,39 +57,31 @@ const SystemMonitor = () => { void send(); }, 1000); // check every 1 second - const { statusMessage, isUploading, progressValue } = useMemo(() => { - const status = data?.status; + const status = data?.status; - const message = - status && status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING - ? LL.WAIT_FIRMWARE() - : status === SystemStatusCodes.SYSTEM_STATUS_PENDING_RESTART - ? LL.APPLICATION_RESTARTING() - : status === SystemStatusCodes.SYSTEM_STATUS_NORMAL - ? LL.RESTARTING_PRE() - : status === SystemStatusCodes.SYSTEM_STATUS_ERROR_UPLOAD - ? 'Upload Failed' - : LL.RESTARTING_POST(); + const statusMessage = + status && status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING + ? LL.WAIT_FIRMWARE() + : status === SystemStatusCodes.SYSTEM_STATUS_PENDING_RESTART + ? LL.APPLICATION_RESTARTING() + : status === SystemStatusCodes.SYSTEM_STATUS_NORMAL + ? LL.RESTARTING_PRE() + : status === SystemStatusCodes.SYSTEM_STATUS_ERROR_UPLOAD + ? 'Upload Failed' + : LL.RESTARTING_POST(); - const uploading = - status !== undefined && status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING; - const progress = - uploading && status - ? Math.round(status - SystemStatusCodes.SYSTEM_STATUS_UPLOADING) - : 0; + const isUploading = + status !== undefined && status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING; + const progressValue = + isUploading && status + ? Math.round(status - SystemStatusCodes.SYSTEM_STATUS_UPLOADING) + : 0; - return { - statusMessage: message, - isUploading: uploading, - progressValue: progress - }; - }, [data?.status, LL]); - - const onCancel = useCallback(async () => { + const onCancel = async () => { setErrorMessage(undefined); await setSystemStatus(String(SystemStatusCodes.SYSTEM_STATUS_NORMAL)); document.location.href = '/'; - }, [setSystemStatus]); + }; return ( void; - }) => { - if (showVersionInfo === 0) return null; - - const isStable = showVersionInfo === 1; - const isDev = showVersionInfo === 2; - const isPartition = showVersionInfo === 3; - - const version = isStable - ? latestVersion - : isDev - ? latestDevVersion - : partitionVersion; - const relNotesUrl = isStable - ? STABLE_RELNOTES_URL - : isDev - ? DEV_RELNOTES_URL - : ''; - - return ( - - {LL.FIRMWARE_VERSION_INFO()} - - - - - - {LL.VERSION()} - - - {isPartition - ? typeof version === 'string' - ? version - : version?.name - : version?.name} - - - - - {isPartition ? LL.TYPE(0) : LL.RELEASE_TYPE()} - - - {partition === currentPartition && LL.ACTIVE() + ' '} - {isStable - ? LL.STABLE() - : isDev - ? LL.DEVELOPMENT() - : 'Partition ' + LL.VERSION()} - - - {isPartition && ( - - - Partition - - - {partition} - - - )} - {isPartition && ( - - - Size - - - {size} KB - - - )} - {version?.published_at && ( - - - {isPartition ? 'Install Date' : 'Build Date'} - - - {prettyDateTime(locale, new Date(version.published_at))} - - - )} - -
-
- - {!isPartition && ( - - )} - - -
- ); - } -); - -const InstallDialog = memo( - ({ - openInstallDialog, - fetchDevVersion, - latestVersion, - latestDevVersion, - upgradeImportantMessageType, - downloadOnly, - platform, - LL, - onClose, - onInstall - }: { - openInstallDialog: boolean; - fetchDevVersion: boolean; - latestVersion?: VersionInfo; - latestDevVersion?: VersionInfo; - upgradeImportantMessageType: number; - downloadOnly: boolean; - platform: string; - LL: TranslationFunctions; - onClose: () => void; - onInstall: (url: string) => void; - }) => { - const binURL = useMemo(() => { - if (!latestVersion || !latestDevVersion) return ''; - - const version = fetchDevVersion ? latestDevVersion : latestVersion; - const filename = `EMS-ESP-${version.name.replaceAll('.', '_')}-${platform}.bin`; - - return fetchDevVersion - ? `${DEV_URL}${filename}` - : `${STABLE_URL}v${version.name}/${filename}`; - }, [fetchDevVersion, latestVersion, latestDevVersion, platform]); - - return ( - - - {`${LL.INSTALL()} ${fetchDevVersion ? LL.DEVELOPMENT() : LL.STABLE()} Firmware`} - - - - {LL.INSTALL_VERSION( - downloadOnly ? LL.DOWNLOAD(1) : LL.INSTALL(), - fetchDevVersion ? latestDevVersion?.name : latestVersion?.name - )} - - - {upgradeImportantMessageType === 1 && LL.UPGRADE_IMPORTANT_MESSAGES_1()} - {upgradeImportantMessageType === 2 && LL.UPGRADE_IMPORTANT_MESSAGES_2()} - - - {LL.ONLINE_HELP()} - - - - - - - {!downloadOnly && ( - - )} - - - ); - } -); - -const InstallPartitionDialog = memo( - ({ - openInstallPartitionDialog, - version, - partition, - LL, - onClose, - onInstall - }: { - openInstallPartitionDialog: boolean; - version: string; - partition: string; - LL: TranslationFunctions; - onClose: () => void; - onInstall: (partition: string) => void; - }) => { - return ( - - - {LL.INSTALL()} {LL.STORED_VERSIONS()} - - - - {LL.INSTALL_VERSION(LL.INSTALL(), version)} - - - - - - - - - ); - } -); - -// Helper function moved outside component -const getPlatform = (data: VersionData): string => { - return `${data.esp_platform}-${data.flash_chip_size >= 16384 ? '16MB' : '4MB'}${data.psram ? '+' : ''}`; -}; - -const Version = () => { - const { LL, locale } = useI18nContext(); - const { me } = useContext(AuthenticatedContext); - - // State management - const [restarting, setRestarting] = useState(false); - const [openInstallDialog, setOpenInstallDialog] = useState(false); - - const [partitionVersion, setPartitionVersion] = useState( - undefined - ); - const [partition, setPartition] = useState(''); - const [openInstallPartitionDialog, setOpenInstallPartitionDialog] = - useState(false); - - const [usingDevVersion, setUsingDevVersion] = useState(false); - const [fetchDevVersion, setFetchDevVersion] = useState(false); - const [devUpgradeAvailable, setDevUpgradeAvailable] = useState(false); - const [stableUpgradeAvailable, setStableUpgradeAvailable] = - useState(false); - const [internetLive, setInternetLive] = useState(false); - const [downloadOnly, setDownloadOnly] = useState(false); - const [showVersionInfo, setShowVersionInfo] = useState(0); // 1 = stable, 2 = dev, 3 = partition - const [firmwareSize, setFirmwareSize] = useState(0); - - const { send: sendCheckUpgrade } = useRequest( - (versions: string) => callAction({ action: 'checkUpgrade', param: versions }), - { immediate: false } - ).onSuccess((event) => { - const data = event.data as UpgradeCheckData; - setDevUpgradeAvailable(data.dev_upgradeable); - setStableUpgradeAvailable(data.stable_upgradeable); - }); - - const { send: sendSetPartition } = useRequest( - (partition: string) => callAction({ action: 'setPartition', param: partition }), - { immediate: false } - ).onError((error) => { - toast.error(String(error.error?.message || 'An error occurred')); - }); - - const { - data, - send: loadData, - error - } = useRequest(SystemApi.readSystemStatus).onSuccess((event) => { - const systemData = event.data as VersionData; - if (systemData.arduino_version.startsWith('Tasmota')) { - setDownloadOnly(true); - } - setUsingDevVersion(systemData.emsesp_version.includes('dev')); - }); - - const { send: sendUploadURL } = useRequest( - (url: string) => callAction({ action: 'uploadURL', param: url }), - { immediate: false } - ); - - const { data: latestVersion } = useRequest(getStableVersion); - const { data: latestDevVersion } = useRequest(getDevVersion); - - const { send: sendAPI } = useRequest((data: APIcall) => API(data), { - immediate: false - }); - - const [upgradeImportantMessageType, setUpgradeImportantMessageType] = - useState(0); - - const { send: checkUpgradeImportantMessages } = useRequest( - (version: string) => - callAction({ action: 'upgradeImportantMessages', param: version }), - { - immediate: false - } - ) - .onSuccess((event) => { - const upgradeImportantMessageType_n = ( - event.data as { upgradeImportantMessageType: number } - ).upgradeImportantMessageType; - setUpgradeImportantMessageType(upgradeImportantMessageType_n); - }) - .onError((error) => { - toast.error(String(error.error?.message || 'An error occurred')); - }); - - // Memoized values - const platform = useMemo(() => (data ? getPlatform(data) : ''), [data]); - - // Memoize filtered partitions to avoid recomputing on every render - const otherPartitions = useMemo( - () => data?.partitions.filter((p) => p.partition !== data.partition) ?? [], - [data] - ); - - const setPartitionVersionInfo = useCallback( - (partition: string) => { - setShowVersionInfo(3); - - // search for the partition in the data.partitions array - const partitionData = data?.partitions.find((p) => p.partition === partition); - if (partitionData) { - setPartitionVersion({ - name: partitionData.version, - published_at: partitionData.install_date ?? '' - }); - setPartition(partitionData.partition); - setFirmwareSize(partitionData.size); - } - }, - [data] - ); - - const doRestart = useCallback(async () => { - await sendAPI({ device: 'system', cmd: 'restart', id: 0 }).catch( - (error: Error) => { - toast.error(error.message); - } - ); - setRestarting(true); - }, [sendAPI]); - - const installFirmwareURL = useCallback( - async (url: string) => { - await sendUploadURL(url).catch((error: Error) => { - toast.error(error.message); - }); - await doRestart(); - }, - [sendUploadURL, doRestart] - ); - - const installPartitionFirmware = useCallback( - async (partition: string) => { - await sendSetPartition(partition).catch((error: Error) => { - toast.error(error.message); - }); - setRestarting(true); - }, - [sendSetPartition] - ); - - const showPartitionDialog = useCallback( - (version: string, partition: string, install_date: string) => { - setOpenInstallPartitionDialog(true); - setPartitionVersion({ name: version, published_at: install_date }); - setPartition(partition); - }, - [] - ); - - const showFirmwareDialog = useCallback( - (useDevVersion: boolean) => { - setFetchDevVersion(useDevVersion); - void checkUpgradeImportantMessages( - useDevVersion ? latestDevVersion?.name : latestVersion?.name - ); - setOpenInstallDialog(true); - }, - [latestDevVersion, latestVersion, fetchDevVersion] - ); - - const closeInstallDialog = useCallback(() => { - setOpenInstallDialog(false); - }, []); - - const closeInstallPartitionDialog = useCallback(() => { - setOpenInstallPartitionDialog(false); - }, []); - - const handleVersionInfoClose = useCallback(() => { - setShowVersionInfo(0); - setPartitionVersion(undefined); - setPartition(''); - }, []); - - // check upgrades - only once when both versions are available - const upgradeCheckedRef = useRef(false); - useEffect(() => { - if (latestVersion && latestDevVersion && !upgradeCheckedRef.current) { - upgradeCheckedRef.current = true; - const versions = `${latestDevVersion.name},${latestVersion.name}`; - sendCheckUpgrade(versions) - .catch((error: Error) => { - toast.error(`Failed to check for upgrades: ${error.message}`); - }) - .finally(() => { - setInternetLive(true); - }); - } - }, [latestVersion, latestDevVersion, sendCheckUpgrade]); - - useLayoutTitle('EMS-ESP Firmware'); - - // Memoized button rendering logic - const showButtons = useCallback( - (showingDev: boolean) => { - const choice = showingDev - ? !usingDevVersion - ? LL.SWITCH_RELEASE_TYPE(LL.DEVELOPMENT()) - : devUpgradeAvailable - ? LL.UPDATE_AVAILABLE() - : undefined - : usingDevVersion - ? LL.SWITCH_RELEASE_TYPE(LL.STABLE()) - : stableUpgradeAvailable - ? LL.UPDATE_AVAILABLE() - : undefined; - - if (!choice) { - return ( - <> - - - {LL.LATEST_VERSION(usingDevVersion ? LL.DEVELOPMENT() : LL.STABLE())} - - - - ); - } - - if (!me.admin) return null; - - return ( - - ); - }, - [ - usingDevVersion, - devUpgradeAvailable, - stableUpgradeAvailable, - me.admin, - LL, - showFirmwareDialog - ] - ); - - const content = useMemo(() => { - if (!data) { - return ; - } - - return ( - <> - - - {LL.THIS_VERSION()} - - - - - {LL.VERSION()} - - - - {data.emsesp_version} - {data.build_flags && ( - -   ({data.build_flags}) - - )} - setPartitionVersionInfo(data.partition)} - aria-label={LL.FIRMWARE_VERSION_INFO()} - > - - - - - - - {LL.PLATFORM()} - - - - {platform} - -   ( - {data.psram ? ( - - ) : ( - - )} - PSRAM) - - - - - - {internetLive ? ( - <> - - {LL.AVAILABLE_VERSION()} - - - - {otherPartitions.length > 0 && data.developer_mode && ( - <> - - - {LL.STORED_VERSIONS()} - - - - {otherPartitions.map((partition) => ( - - {partition.version} - - setPartitionVersionInfo(partition.partition) - } - aria-label={LL.FIRMWARE_VERSION_INFO()} - > - - - - - ))} - - - )} - - {LL.STABLE()} - - - - {latestVersion?.name} - setShowVersionInfo(1)} - aria-label={LL.FIRMWARE_VERSION_INFO()} - > - - - {showButtons(false)} - - - - - {LL.DEVELOPMENT()} - - - - {latestDevVersion?.name} - setShowVersionInfo(2)} - aria-label={LL.FIRMWARE_VERSION_INFO()} - > - - - {showButtons(true)} - - - - - ) : ( - - - {LL.INTERNET_CONNECTION_REQUIRED()} - - )} - {me.admin && ( - <> - - - - - {LL.UPLOAD()} - - - - )} - - - ); - }, [ - data, - error, - loadData, - LL, - platform, - internetLive, - latestVersion, - latestDevVersion, - showVersionInfo, - locale, - openInstallDialog, - fetchDevVersion, - downloadOnly, - me.admin, - showButtons, - handleVersionInfoClose, - closeInstallDialog, - installFirmwareURL, - doRestart, - otherPartitions, - setPartitionVersionInfo, - showPartitionDialog, - partitionVersion, - partition, - firmwareSize, - closeInstallPartitionDialog, - installPartitionFirmware - ]); - - return restarting ? : {content}; -}; - -export default memo(Version); diff --git a/interface/src/components/MessageBox.tsx b/interface/src/components/MessageBox.tsx index aa17e6215..ae7d8e177 100644 --- a/interface/src/components/MessageBox.tsx +++ b/interface/src/components/MessageBox.tsx @@ -1,4 +1,4 @@ -import { type FC, type PropsWithChildren, memo, useMemo } from 'react'; +import { type FC, type PropsWithChildren, memo } from 'react'; import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; import ErrorIcon from '@mui/icons-material/Error'; @@ -38,18 +38,17 @@ const MessageBox: FC> = ({ }) => { const theme = useTheme(); - const { Icon, backgroundColor } = useMemo(() => { - const Icon = LEVEL_ICONS[level]; - const palettePath = LEVEL_PALETTE_PATHS[level]; - const [key, shade] = palettePath.split('.') as [ - keyof typeof theme.palette, - string - ]; - const paletteKey = theme.palette[key] as unknown as Record; - const backgroundColor = paletteKey[shade]; - - return { Icon, backgroundColor }; - }, [level, theme]); + const Icon = LEVEL_ICONS[level]; + const palettePath = LEVEL_PALETTE_PATHS[level]; + const [paletteKeyName, shade] = palettePath.split('.') as [ + keyof typeof theme.palette, + string + ]; + const paletteKey = theme.palette[paletteKeyName] as unknown as Record< + string, + string + >; + const backgroundColor = paletteKey[shade]; return ( { const { setLocale, locale, LL } = useContext(I18nContext); - const onLocaleSelected: ChangeEventHandler = useCallback( - async ({ target }) => { - const loc = target.value as Locales; - localStorage.setItem('lang', loc); - await loadLocaleAsync(loc); - setLocale(loc); - }, - [setLocale] - ); - - // Memoize menu items to prevent recreation on every render - const menuItems = useMemo( - () => - LANGUAGE_OPTIONS.map(({ key, flag, label }) => ( - - {label} -  {label} - - )), - [] - ); + const onLocaleSelected: ChangeEventHandler = async ({ + target + }) => { + const loc = target.value as Locales; + localStorage.setItem('lang', loc); + await loadLocaleAsync(loc); + setLocale(loc); + }; return ( { size="small" select > - {menuItems} + {LANGUAGE_OPTIONS.map(({ key, flag, label }) => ( + + {label} +  {label} + + ))} ); }; diff --git a/interface/src/components/inputs/ValidatedPasswordField.tsx b/interface/src/components/inputs/ValidatedPasswordField.tsx index 44ab69995..5529e7d72 100644 --- a/interface/src/components/inputs/ValidatedPasswordField.tsx +++ b/interface/src/components/inputs/ValidatedPasswordField.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useState } from 'react'; +import { memo, useState } from 'react'; import type { FC } from 'react'; import VisibilityIcon from '@mui/icons-material/Visibility'; @@ -13,9 +13,9 @@ type ValidatedPasswordFieldProps = Omit; const ValidatedPasswordField: FC = ({ ...props }) => { const [showPassword, setShowPassword] = useState(false); - const togglePasswordVisibility = useCallback(() => { + const togglePasswordVisibility = () => { setShowPassword((prev) => !prev); - }, []); + }; return ( = ({ children }) => { const [title, setTitle] = useState(PROJECT_NAME); const { pathname } = useLocation(); - // Memoize drawer toggle handler to prevent unnecessary re-renders const handleDrawerToggle = useCallback(() => { setMobileOpen((prev) => !prev); }, []); @@ -28,7 +27,6 @@ const LayoutComponent: FC = ({ children }) => { setMobileOpen(false); }, [pathname]); - // Memoize context value to prevent unnecessary re-renders const contextValue = useMemo(() => ({ title, setTitle }), [title]); return ( diff --git a/interface/src/components/layout/LayoutAppBar.tsx b/interface/src/components/layout/LayoutAppBar.tsx index 6bea11462..9ee84303a 100644 --- a/interface/src/components/layout/LayoutAppBar.tsx +++ b/interface/src/components/layout/LayoutAppBar.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useMemo } from 'react'; +import { memo } from 'react'; import { Link, useLocation, useNavigate } from 'react-router'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; @@ -39,14 +39,11 @@ const LayoutAppBarComponent = ({ title, onToggleDrawer }: LayoutAppBarProps) => const navigate = useNavigate(); const location = useLocation(); - const pathnames = useMemo( - () => location.pathname.split('/').filter((x) => x), - [location.pathname] - ); + const pathnames = location.pathname.split('/').filter((x) => x); - const handleBackClick = useCallback(() => { + const handleBackClick = () => { void navigate('/' + pathnames[0]); - }, [navigate, pathnames]); + }; return ( diff --git a/interface/src/components/layout/LayoutDrawer.tsx b/interface/src/components/layout/LayoutDrawer.tsx index c89fb396b..89237615f 100644 --- a/interface/src/components/layout/LayoutDrawer.tsx +++ b/interface/src/components/layout/LayoutDrawer.tsx @@ -1,4 +1,4 @@ -import { memo, useMemo } from 'react'; +import { memo } from 'react'; import { Box, Divider, Drawer, Toolbar, Typography, styled } from '@mui/material'; @@ -24,22 +24,18 @@ interface LayoutDrawerProps { } const LayoutDrawerComponent = ({ mobileOpen, onClose }: LayoutDrawerProps) => { - // Memoize drawer content to prevent unnecessary re-renders - const drawer = useMemo( - () => ( - <> - - - - {PROJECT_NAME} - - - - - - - ), - [] + const drawer = ( + <> + + + + {PROJECT_NAME} + + + + + + ); return ( diff --git a/interface/src/components/layout/LayoutMenu.tsx b/interface/src/components/layout/LayoutMenu.tsx index 1fa3830b5..5d52921a6 100644 --- a/interface/src/components/layout/LayoutMenu.tsx +++ b/interface/src/components/layout/LayoutMenu.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useContext, useState } from 'react'; +import { memo, useContext, useState } from 'react'; import AccountCircleIcon from '@mui/icons-material/AccountCircle'; import AssessmentIcon from '@mui/icons-material/Assessment'; @@ -18,13 +18,15 @@ import { AuthenticatedContext } from 'contexts/authentication'; import { useI18nContext } from 'i18n/i18n-react'; const LayoutMenuComponent = () => { - const { me } = useContext(AuthenticatedContext); + const { me, versions } = useContext(AuthenticatedContext); const { LL } = useI18nContext(); const [menuOpen, setMenuOpen] = useState(true); - const handleMenuToggle = useCallback(() => { + const upgradeAvailable = versions?.current?.upgradeable ?? false; + + const handleMenuToggle = () => { setMenuOpen((prev) => !prev); - }, []); + }; return ( <> @@ -105,6 +107,7 @@ const LayoutMenuComponent = () => { label={LL.SETTINGS(0)} disabled={!me.admin} to="/settings" + badge={upgradeAvailable} /> diff --git a/interface/src/components/layout/LayoutMenuItem.tsx b/interface/src/components/layout/LayoutMenuItem.tsx index a0dbc8354..5cdbf8c58 100644 --- a/interface/src/components/layout/LayoutMenuItem.tsx +++ b/interface/src/components/layout/LayoutMenuItem.tsx @@ -1,7 +1,7 @@ -import { memo, useMemo } from 'react'; +import { memo } from 'react'; import { Link, useLocation } from 'react-router'; -import { ListItemButton, ListItemIcon, ListItemText } from '@mui/material'; +import { Box, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'; import type { SvgIconProps, SxProps, Theme } from '@mui/material'; import { routeMatches } from 'utils'; @@ -11,60 +11,52 @@ interface LayoutMenuItemProps { label: string; to: string; disabled?: boolean; + badge?: boolean; } const LayoutMenuItemComponent = ({ icon: Icon, label, to, - disabled + disabled, + badge }: LayoutMenuItemProps) => { const { pathname } = useLocation(); - const selected = useMemo(() => routeMatches(to, pathname), [to, pathname]); + const selected = routeMatches(to, pathname); - // Memoize dynamic styles based on selected state - const buttonStyles: SxProps = useMemo( - () => ({ - transition: 'all 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)', - backgroundColor: selected ? 'rgba(144, 202, 249, 0.1)' : 'transparent', - borderRadius: '8px', - margin: '2px 8px', - '&:hover': { - backgroundColor: 'rgba(68, 82, 211, 0.39)' - }, - '&::before': { - content: '""', - position: 'absolute', - left: 0, - top: 0, - bottom: 0, - width: selected ? '3px' : '0px', - backgroundColor: '#90caf9', - transition: 'width 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)' - } - }), - [selected] - ); + const buttonStyles: SxProps = { + transition: 'all 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)', + backgroundColor: selected ? 'rgba(144, 202, 249, 0.1)' : 'transparent', + borderRadius: '8px', + margin: '2px 8px', + '&:hover': { + backgroundColor: 'rgba(68, 82, 211, 0.39)' + }, + '&::before': { + content: '""', + position: 'absolute', + left: 0, + top: 0, + bottom: 0, + width: selected ? '3px' : '0px', + backgroundColor: '#90caf9', + transition: 'width 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)' + } + }; - const iconStyles: SxProps = useMemo( - () => ({ - color: selected ? '#90caf9' : '#9e9e9e', - transition: 'color 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)', - transform: selected ? 'scale(1.1)' : 'scale(1)', - transitionProperty: 'color, transform' - }), - [selected] - ); + const iconStyles: SxProps = { + color: selected ? '#90caf9' : '#9e9e9e', + transition: 'color 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)', + transform: selected ? 'scale(1.1)' : 'scale(1)', + transitionProperty: 'color, transform' + }; - const textStyles: SxProps = useMemo( - () => ({ - color: selected ? '#90caf9' : '#f5f5f5', - transition: 'color 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)', - transitionProperty: 'color, font-weight' - }), - [selected] - ); + const textStyles: SxProps = { + color: selected ? '#90caf9' : '#f5f5f5', + transition: 'color 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)', + transitionProperty: 'color, font-weight' + }; return ( {label} + {badge && ( + + )} ); }; diff --git a/interface/src/components/layout/ListMenuItem.tsx b/interface/src/components/layout/ListMenuItem.tsx index db92093de..c78d02ac2 100644 --- a/interface/src/components/layout/ListMenuItem.tsx +++ b/interface/src/components/layout/ListMenuItem.tsx @@ -5,6 +5,7 @@ import { Link } from 'react-router'; import NavigateNextIcon from '@mui/icons-material/NavigateNext'; import { Avatar, + Box, ListItem, ListItemAvatar, ListItemButton, @@ -20,6 +21,7 @@ interface ListMenuItemProps { text: string; to?: string; disabled?: boolean; + badge?: boolean; } const iconStyles: CSSProperties = { @@ -28,15 +30,40 @@ const iconStyles: CSSProperties = { verticalAlign: 'middle' }; +const Badge = () => ( + +); + const RenderIcon = memo( - ({ icon: Icon, bgcolor, label, text }: ListMenuItemProps) => ( + ({ icon: Icon, bgcolor, label, text, badge }: ListMenuItemProps) => ( <> - + + {label} + {badge && } + + } + secondary={text} + /> ) ); @@ -47,7 +74,8 @@ const LayoutMenuItem = ({ label, text, to, - disabled + disabled, + badge }: ListMenuItemProps) => ( <> {to && !disabled ? ( @@ -65,6 +93,7 @@ const LayoutMenuItem = ({ {...(bgcolor && { bgcolor })} label={label} text={text} + {...(badge && { badge })} /> @@ -75,6 +104,7 @@ const LayoutMenuItem = ({ {...(bgcolor && { bgcolor })} label={label} text={text} + {...(badge && { badge })} /> )} diff --git a/interface/src/components/routing/BlockNavigation.tsx b/interface/src/components/routing/BlockNavigation.tsx index 74601d785..cb0cb8c35 100644 --- a/interface/src/components/routing/BlockNavigation.tsx +++ b/interface/src/components/routing/BlockNavigation.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback } from 'react'; +import { memo } from 'react'; import type { Blocker } from 'react-router'; import { @@ -15,13 +15,13 @@ import { useI18nContext } from 'i18n/i18n-react'; const BlockNavigation = ({ blocker }: { blocker: Blocker }) => { const { LL } = useI18nContext(); - const handleReset = useCallback(() => { + const handleReset = () => { blocker.reset?.(); - }, [blocker]); + }; - const handleProceed = useCallback(() => { + const handleProceed = () => { blocker.proceed?.(); - }, [blocker]); + }; return ( diff --git a/interface/src/components/routing/RouterTabs.tsx b/interface/src/components/routing/RouterTabs.tsx index 9a3d7d31e..f8c6b2a09 100644 --- a/interface/src/components/routing/RouterTabs.tsx +++ b/interface/src/components/routing/RouterTabs.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback } from 'react'; +import { memo } from 'react'; import type { FC } from 'react'; import { useNavigate } from 'react-router'; @@ -16,12 +16,9 @@ const RouterTabs: FC = ({ value, children }) => { const theme = useTheme(); const smallDown = useMediaQuery(theme.breakpoints.down('sm')); - const handleTabChange = useCallback( - (_event: unknown, path: string) => { - void navigate(path); - }, - [navigate] - ); + const handleTabChange = (_event: unknown, path: string) => { + void navigate(path); + }; return ( { ).upgradeImportantMessageType; setUpgradeImportantMessageType(upgradeImportantMessageType_n); if (upgradeImportantMessageType_n === 0) { - onFileSelected(file); + if (file) { + onFileSelected(file); + } } }) .onError((error) => { diff --git a/interface/src/contexts/authentication/Authentication.tsx b/interface/src/contexts/authentication/Authentication.tsx index dba45cad7..669f06e6a 100644 --- a/interface/src/contexts/authentication/Authentication.tsx +++ b/interface/src/contexts/authentication/Authentication.tsx @@ -3,6 +3,7 @@ import type { FC } from 'react'; import { redirect } from 'react-router'; import { toast } from 'react-toastify'; +import { callAction } from 'api/app'; import { ACCESS_TOKEN } from 'api/endpoints'; import * as AuthenticationApi from 'components/routing/authentication'; @@ -10,7 +11,7 @@ import { useRequest } from 'alova/client'; import { LoadingSpinner } from 'components'; import { verifyAuthorization } from 'components/routing/authentication'; import { useI18nContext } from 'i18n/i18n-react'; -import type { Me } from 'types'; +import type { Me, VersionsResponse } from 'types'; import type { RequiredChildrenProps } from 'utils'; import { AuthenticationContext } from './context'; @@ -20,17 +21,34 @@ const Authentication: FC = ({ children }) => { const [initialized, setInitialized] = useState(false); const [me, setMe] = useState(); + const [versions, setVersions] = useState(); const { send: sendVerifyAuthorization } = useRequest(verifyAuthorization(), { immediate: false }); + const { send: sendGetVersions } = useRequest( + () => callAction({ action: 'getVersions' }), + { immediate: false } + ) + .onSuccess((event) => { + setVersions(event.data as VersionsResponse); + }) + .onError(() => { + setVersions(undefined); + }); + + const refreshVersions = useCallback(async () => { + await sendGetVersions().catch(() => undefined); + }, []); + const signIn = (accessToken: string) => { try { AuthenticationApi.getStorage().setItem(ACCESS_TOKEN, accessToken); const decodedMe = AuthenticationApi.decodeMeJWT(accessToken); setMe(decodedMe); toast.success(LL.LOGGED_IN({ name: decodedMe.username })); + void refreshVersions(); } catch { setMe(undefined); throw new Error('Failed to parse JWT'); @@ -40,6 +58,7 @@ const Authentication: FC = ({ children }) => { const signOut = (doRedirect: boolean) => { AuthenticationApi.clearAccessToken(); setMe(undefined); + setVersions(undefined); if (doRedirect) { redirect('/'); } @@ -49,8 +68,9 @@ const Authentication: FC = ({ children }) => { const accessToken = AuthenticationApi.getStorage().getItem(ACCESS_TOKEN); if (accessToken) { await sendVerifyAuthorization() - .then(() => { + .then(async () => { setMe(AuthenticationApi.decodeMeJWT(accessToken)); + await refreshVersions(); setInitialized(true); }) .catch(() => { @@ -61,21 +81,24 @@ const Authentication: FC = ({ children }) => { setMe(undefined); setInitialized(true); } + // refreshVersions and sendVerifyAuthorization are stable + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { void refresh(); }, [refresh]); - // cache object to prevent re-renders const obj = useMemo( () => ({ signIn, signOut, refresh, - ...(me && { me }) + refreshVersions, + ...(me && { me }), + ...(versions && { versions }) }), - [signIn, signOut, me, refresh] + [signIn, signOut, me, refresh, refreshVersions, versions] ); if (initialized) { diff --git a/interface/src/contexts/authentication/context.ts b/interface/src/contexts/authentication/context.ts index d58b320ff..1717bfaef 100644 --- a/interface/src/contexts/authentication/context.ts +++ b/interface/src/contexts/authentication/context.ts @@ -1,12 +1,14 @@ import { createContext } from 'react'; -import type { Me } from 'types'; +import type { Me, VersionsResponse } from 'types'; export interface AuthenticationContextValue { refresh: () => Promise; signIn: (accessToken: string) => void; signOut: (redirect: boolean) => void; me?: Me; + versions?: VersionsResponse; + refreshVersions: () => Promise; } const AuthenticationContextDefaultValue = {} as AuthenticationContextValue; diff --git a/interface/src/types/index.ts b/interface/src/types/index.ts index 8c2f8760c..a4e8726d9 100644 --- a/interface/src/types/index.ts +++ b/interface/src/types/index.ts @@ -7,3 +7,4 @@ export * from './ntp'; export * from './security'; export * from './signin'; export * from './system'; +export * from './versions'; diff --git a/interface/src/types/versions.ts b/interface/src/types/versions.ts new file mode 100644 index 000000000..6f081c613 --- /dev/null +++ b/interface/src/types/versions.ts @@ -0,0 +1,23 @@ +// Types for the `getVersions` action response coming from the device. +// The device proxies the request to emsesp.org/versions.json. If the device +// is offline the `stable` and `dev` fields are omitted. + +export interface VersionInfo { + version: string; + date: string; +} + +export interface RemoteVersionInfo extends VersionInfo { + upgradeable: boolean; +} + +export interface CurrentVersionInfo extends VersionInfo { + type: 'stable' | 'dev'; + upgradeable: boolean; +} + +export interface VersionsResponse { + current: CurrentVersionInfo; + stable?: RemoteVersionInfo; + dev?: RemoteVersionInfo; +} diff --git a/interface/src/utils/usePersistState.ts b/interface/src/utils/usePersistState.ts index 2a627a852..43b80afc8 100644 --- a/interface/src/utils/usePersistState.ts +++ b/interface/src/utils/usePersistState.ts @@ -1,34 +1,27 @@ -import { useEffect, useMemo, useState } from 'react'; +import { useEffect, useState } from 'react'; export const usePersistState = ( initial_value: T, id: string ): [T, (new_state: T) => void] => { - // Set initial value - only computed once on mount - const _initial_value = useMemo(() => { + const [state, setState] = useState(() => { try { - const local_storage_value_str = localStorage.getItem(`state:${id}`); - // If there is a value stored in localStorage, use that - if (local_storage_value_str) { - return JSON.parse(local_storage_value_str) as T; + const stored = localStorage.getItem(`state:${id}`); + if (stored) { + return JSON.parse(stored) as T; } } catch (error) { - // If parsing fails, fall back to initial_value console.warn( `Failed to parse localStorage value for key "state:${id}"`, error ); } - // Otherwise use initial_value that was passed to the function return initial_value; - }, [id]); // initial_value intentionally omitted - only read on first mount - - const [state, setState] = useState(_initial_value); + }); useEffect(() => { try { - const state_str = JSON.stringify(state); - localStorage.setItem(`state:${id}`, state_str); + localStorage.setItem(`state:${id}`, JSON.stringify(state)); } catch (error) { console.warn( `Failed to save state to localStorage for key "state:${id}"`, diff --git a/interface/src/utils/useRest.ts b/interface/src/utils/useRest.ts index 0d57abff9..791c6e4e0 100644 --- a/interface/src/utils/useRest.ts +++ b/interface/src/utils/useRest.ts @@ -1,4 +1,4 @@ -import { useCallback, useMemo, useState } from 'react'; +import { useCallback, useState } from 'react'; import { useBlocker } from 'react-router'; import { toast } from 'react-toastify'; @@ -54,61 +54,44 @@ export const useRest = ({ read, update }: RestRequestOptions) => { } }, [readData]); - const saveData = useCallback(async () => { + const saveData = async () => { if (!data) return; - // Reset states before saving setRestartNeeded(false); setErrorMessage(undefined); try { await writeData(data as D); - // Only update origData on successful save (dirtyFlags cleared by onSuccess handler) setOrigData(data as D); } catch (error) { const message = error instanceof Error ? error.message : String(error); if (message === REBOOT_ERROR_MESSAGE) { setRestartNeeded(true); - return; // Early return - save succeeded but needs reboot + return; } - // Restore original data on validation error if (origData) { updateData({ data: origData }); } toast.error(message); setErrorMessage(message); - setDirtyFlags([]); // Clear flags so user can retry + setDirtyFlags([]); } - }, [data, writeData, origData, updateData]); + }; - return useMemo( - () => ({ - loadData, - saveData, - saving: !!saving, - updateDataValue, - data: data as D, - origData: origData as D, - dirtyFlags, - setDirtyFlags, - setOrigData, - blocker, - errorMessage, - restartNeeded - }), - [ - loadData, - saveData, - saving, - updateDataValue, - data, - origData, - dirtyFlags, - blocker, - errorMessage, - restartNeeded - ] - ); + return { + loadData, + saveData, + saving: !!saving, + updateDataValue, + data: data as D, + origData: origData as D, + dirtyFlags, + setDirtyFlags, + setOrigData, + blocker, + errorMessage, + restartNeeded + }; }; diff --git a/interface/vite.config.ts b/interface/vite.config.ts index ff34966b7..e04cdde27 100644 --- a/interface/vite.config.ts +++ b/interface/vite.config.ts @@ -6,9 +6,6 @@ import { Plugin, PluginOption, defineConfig } from 'vite'; import viteImagemin from 'vite-plugin-imagemin'; import zlib from 'zlib'; -// @ts-expect-error - mock server doesn't have type declarations -import mockServer from '../mock-api/mockServer.js'; - // Constants const KB_DIVISOR = 1024; const REPEAT_CHAR = '='; @@ -100,6 +97,10 @@ const createPreactPlugin = (devToolsEnabled: boolean) => // Patch preact/compat to export stub React 19 APIs (use, useOptimistic) so that // react-router v7 doesn't trigger IMPORT_IS_UNDEFINED warnings from Rolldown. +// Rolldown tracks the constant strings used in `React[REACT_USE]` / +// `React[USE_OPTIMISTIC]` lookups inside react-router and resolves them +// statically, so simply relying on a runtime guard is not enough — we need +// matching (stub) exports on the aliased preact/compat module. const preactCompatPatchPlugin = (): Plugin => ({ name: 'preact-compat-react19-patch', transform(code, id) { @@ -210,9 +211,11 @@ const imageOptimizationPlugin = { }; export default defineConfig( - ({ command, mode }: { command: string; mode: string }) => { + async ({ command, mode }: { command: string; mode: string }) => { if (command === 'serve') { console.log(`Preparing for standalone build with server, mode=${mode}`); + // @ts-expect-error - mock server doesn't have type declarations + const { default: mockServer } = await import('../mock-api/mockServer.js'); return { plugins: [...createBasePlugins(true, true), mockServer()], resolve: { @@ -229,8 +232,7 @@ export default defineConfig( changeOrigin: true, secure: false }, - '/rest': 'http://localhost:3080', - '/gh': 'http://localhost:3080' + '/rest': 'http://localhost:3080' } }, build: { diff --git a/mock-api/package.json b/mock-api/package.json index dea8d1846..b294dba5a 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -15,5 +15,5 @@ "itty-router": "^5.0.23", "prettier": "^3.8.3" }, - "packageManager": "pnpm@10.33.1+sha512.05ba3c1d5d1c18f68df06470d74055e62d41fc110a0c660db1b2dfb2785327f04cf0f68345d4609bc52089e7fa0343c31593b2f9594e2c5d5da426230acc9820" + "packageManager": "pnpm@10.33.2+sha512.a90faf6feeab71ad6c6e57f94e0fe1a12f5dcc22cd754db40ae9593eb6a3e0b6b12e3540218bb37ae083404b1f2ce6db2a4121e979829b4aff94b99f49da1cf8" } diff --git a/mock-api/restServer.ts b/mock-api/restServer.ts index 1e3a7afae..22e2c72b3 100644 --- a/mock-api/restServer.ts +++ b/mock-api/restServer.ts @@ -6,7 +6,6 @@ const router = AutoRouter(); const REST_ENDPOINT_ROOT = '/rest/'; const API_ENDPOINT_ROOT = '/api/'; -const GH_ENDPOINT_ROOT = '/gh/'; // for mock GitHub API for version checking // HTTP HEADERS for msgpack const headers = { @@ -128,7 +127,7 @@ let system_status = { } ], // partitions: [], - developer_mode: true, + developer_mode: settings.developer_mode, model: '', board: '', // model: 'BBQKees Electronics EMS Gateway E32 V2 (E32 V2.0 P3/2024011)', @@ -142,13 +141,13 @@ let DEV_VERSION_IS_UPGRADEABLE: boolean; let STABLE_VERSION_IS_UPGRADEABLE: boolean; let THIS_VERSION: string; let LATEST_STABLE_VERSION = '3.8.2'; -let LATEST_DEV_VERSION = '3.8.3-dev.2'; +let LATEST_DEV_VERSION = '3.9.0-dev.1'; // scenarios for testing versioning -let version_test = 0; // on latest stable, or switch to dev +// let version_test = 0; // on latest stable, or switch to dev // let version_test = 1; // on latest dev, or switch back to stable // let version_test = 2; // upgrade an older stable to latest stable or switch to latest dev -// let version_test = 3; // upgrade dev to latest, or switch to stable +let version_test = 3; // upgrade dev to latest, or switch to stable // let version_test = 4; // downgrade to an older dev, or switch back to stable switch (version_test as number) { @@ -415,36 +414,60 @@ function upgradeImportantMessages(version: string) { return { upgradeImportantMessageType: upgradeImportantMessageType_n }; } -// called by Action endpoint checkUpgrade -function check_upgrade(version: string) { - let data = {}; - if (version) { - const dev_version = version.split(',')[0]; - const stable_version = version.split(',')[1]; +// called by Action endpoint getVersions +// Set MOCK_OFFLINE = true to simulate a device with no internet (omits stable/dev). +const MOCK_OFFLINE = false; +function get_versions() { + const isDev = THIS_VERSION.includes('dev'); + const currentUpgradeable = + !MOCK_OFFLINE && + (isDev ? DEV_VERSION_IS_UPGRADEABLE : STABLE_VERSION_IS_UPGRADEABLE); - console.log( - 'Upgrade this version (' + - THIS_VERSION + - ') to dev (' + - dev_version + - ') is ' + - (DEV_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + - ' and to stable (' + - stable_version + - ') is ' + - (STABLE_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') - ); - data = { - emsesp_version: THIS_VERSION, - dev_upgradeable: DEV_VERSION_IS_UPGRADEABLE, - stable_upgradeable: STABLE_VERSION_IS_UPGRADEABLE + const data: { + current: { + version: string; + type: 'stable' | 'dev'; + date: string; + upgradeable: boolean; }; - } else { - console.log('requesting ems-esp version (' + THIS_VERSION + ')'); - data = { - emsesp_version: THIS_VERSION + stable?: { version: string; date: string; upgradeable: boolean }; + dev?: { version: string; date: string; upgradeable: boolean }; + } = { + current: { + version: THIS_VERSION, + type: isDev ? 'dev' : 'stable', + date: '2026-04-25T12:00:00', + upgradeable: currentUpgradeable + } + }; + + if (!MOCK_OFFLINE) { + data.stable = { + version: LATEST_STABLE_VERSION, + date: '2026-04-25', + upgradeable: STABLE_VERSION_IS_UPGRADEABLE + }; + data.dev = { + version: LATEST_DEV_VERSION, + date: '2026-04-25', + upgradeable: DEV_VERSION_IS_UPGRADEABLE }; } + + console.log( + 'getVersions: current=' + + THIS_VERSION + + ' stable=' + + LATEST_STABLE_VERSION + + ' (upgradeable=' + + (STABLE_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + + ') dev=' + + LATEST_DEV_VERSION + + ' (upgradeable=' + + (DEV_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + + ')' + + (MOCK_OFFLINE ? ' [offline]' : '') + ); return data; } @@ -4579,6 +4602,7 @@ router .post(EMSESP_SETTINGS_ENDPOINT, async (request: any) => { settings = await request.json(); console.log('application settings saved', settings); + system_status.developer_mode = settings.developer_mode; return status(200); // no restart needed // return status(205); // reboot required }) @@ -5172,13 +5196,9 @@ router } else if (action === 'getCustomSupport') { // send custom support return custom_support(); - } else if (action === 'checkUpgrade') { - // check upgrade - // check if content has a param - if (!content.param) { - return check_upgrade(''); - } - return check_upgrade(content.param); + } else if (action === 'getVersions') { + // get versions + return get_versions(); } else if (action === 'uploadURL') { // upload URL console.log('upload File from URL', content.param); @@ -5233,27 +5253,6 @@ router return status(404); // not found }); -// Mock GitHub API -// https://api.github.com/repos/emsesp/EMS-ESP32/releases - -router - .get(GH_ENDPOINT_ROOT + '/tags/latest', () => { - const data = { - name: 'v' + LATEST_DEV_VERSION, - published_at: new Date().toISOString() // use todays date - }; - console.log('returning latest development version (today): ', data); - return data; - }) - .get(GH_ENDPOINT_ROOT + '/latest', () => { - const data = { - name: 'v' + LATEST_STABLE_VERSION, - published_at: '2025-03-01T13:29:13.999Z' - }; - console.log('returning latest stable version: ', data); - return data; - }); - // const logger: ResponseHandler = (response, request) => { // console.log( // response.status, diff --git a/platformio.ini b/platformio.ini index acb518d9b..5abde677e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -91,7 +91,7 @@ board_build.filesystem = littlefs lib_deps = bblanchon/ArduinoJson @ 7.4.3 ESP32Async/AsyncTCP @ 3.4.10 - ESP32Async/ESPAsyncWebServer @ 3.10.3 + ESP32Async/ESPAsyncWebServer @ 3.11.0 https://github.com/mobizt/ReadyMail.git @ 0.4.0 https://github.com/mobizt/ESP_SSLClient.git @ 3.1.3 ; https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.8 diff --git a/src/core/EMSESP_Version.h b/src/core/EMSESP_Version.h deleted file mode 100644 index 0803be2b5..000000000 --- a/src/core/EMSESP_Version.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * EMS-ESP - https://github.com/emsesp/EMS-ESP - * Copyright 2020-2026 emsesp.org - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef EMSESP_Version_H -#define EMSESP_Version_H - -#include -#include -#include - -// Drop-in lightweight replacement for the subset of the semver library actually used by EMS-ESP. -// The previous semver library (lib/semver) builds a std::map + std::function-based state machine on -// every parse, which fragments the internal heap on the ESP32. This replacement does no heap -// allocation beyond the std::string member for the prerelease tag, and matches the API surface -// we consume: construction from string, major()/minor()/patch()/prerelease(), and operator>/(const EMSESP_Version & a, const EMSESP_Version & b) { - return b < a; - } - - friend bool operator==(const EMSESP_Version & a, const EMSESP_Version & b) { - return a.major_ == b.major_ && a.minor_ == b.minor_ && a.patch_ == b.patch_ && a.prerelease_ == b.prerelease_; - } - - friend bool operator!=(const EMSESP_Version & a, const EMSESP_Version & b) { - return !(a == b); - } - - friend bool operator>=(const EMSESP_Version & a, const EMSESP_Version & b) { - return !(a < b); - } - - friend bool operator<=(const EMSESP_Version & a, const EMSESP_Version & b) { - return !(b < a); - } - - private: - int major_ = 0; - int minor_ = 0; - int patch_ = 0; - std::string prerelease_; - - void parse(const char * s) { - major_ = minor_ = patch_ = 0; - prerelease_.clear(); - if (s == nullptr || *s == '\0') { - return; - } - // parse numeric major.minor.patch; accept partial ("3", "3.9", "3.9.0") - sscanf(s, "%d.%d.%d", &major_, &minor_, &patch_); - // capture prerelease tag after '-' if present (stop at '+' which is build metadata) - const char * dash = strchr(s, '-'); - if (dash != nullptr) { - const char * plus = strchr(dash, '+'); - if (plus != nullptr) { - prerelease_.assign(dash + 1, plus - dash - 1); - } else { - prerelease_.assign(dash + 1); - } - } - } -}; - -} // namespace version - -#endif diff --git a/src/core/emsesp.cpp b/src/core/emsesp.cpp index e811e7888..330210591 100644 --- a/src/core/emsesp.cpp +++ b/src/core/emsesp.cpp @@ -1817,10 +1817,10 @@ void EMSESP::start() { analogsensor_.start(factory_settings); // Analog external sensors // start web services + LOG_INFO("Starting Web Server"); webLogService.start(); // apply settings to weblog service webModulesService.begin(); // setup the external library modules webServer.begin(); // start the web server - LOG_INFO("Starting Web Server"); } void EMSESP::start_serial_console() { @@ -1874,6 +1874,7 @@ void EMSESP::loop() { } // loop through the services + webStatusService.loop(); // periodic refresh of cached versions.json rxservice_.loop(); // process any incoming Rx telegrams shower_.loop(); // check for shower on/off temperaturesensor_.loop(); // read sensor temperatures diff --git a/src/core/firmwareVersion.cpp b/src/core/firmwareVersion.cpp new file mode 100644 index 000000000..de2aed742 --- /dev/null +++ b/src/core/firmwareVersion.cpp @@ -0,0 +1,100 @@ +/* + * EMS-ESP - https://github.com/emsesp/EMS-ESP + * Copyright 2020-2026 emsesp.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "firmwareVersion.h" + +#include +#include + +namespace emsesp { + +FirmwareVersion::FirmwareVersion(const std::string & s) { + parse(s.c_str()); +} + +FirmwareVersion::FirmwareVersion(const char * s) { + parse(s ? s : ""); +} + +int FirmwareVersion::major() const { + return major_; +} + +int FirmwareVersion::minor() const { + return minor_; +} + +int FirmwareVersion::patch() const { + return patch_; +} + +const std::string & FirmwareVersion::prerelease() const { + return prerelease_; +} + +bool operator<(const FirmwareVersion & a, const FirmwareVersion & b) { + if (a.major_ != b.major_) + return a.major_ < b.major_; + if (a.minor_ != b.minor_) + return a.minor_ < b.minor_; + if (a.patch_ != b.patch_) + return a.patch_ < b.patch_; + return a.prerelease_ < b.prerelease_; +} + +bool operator>(const FirmwareVersion & a, const FirmwareVersion & b) { + return b < a; +} + +bool operator==(const FirmwareVersion & a, const FirmwareVersion & b) { + return a.major_ == b.major_ && a.minor_ == b.minor_ && a.patch_ == b.patch_ && a.prerelease_ == b.prerelease_; +} + +bool operator!=(const FirmwareVersion & a, const FirmwareVersion & b) { + return !(a == b); +} + +bool operator>=(const FirmwareVersion & a, const FirmwareVersion & b) { + return !(a < b); +} + +bool operator<=(const FirmwareVersion & a, const FirmwareVersion & b) { + return !(b < a); +} + +void FirmwareVersion::parse(const char * s) { + major_ = minor_ = patch_ = 0; + prerelease_.clear(); + if (s == nullptr || *s == '\0') { + return; + } + // parse numeric major.minor.patch; accept partial ("3", "3.9", "3.9.0") + sscanf(s, "%d.%d.%d", &major_, &minor_, &patch_); + // capture prerelease tag after '-' if present (stop at '+' which is build metadata) + const char * dash = strchr(s, '-'); + if (dash != nullptr) { + const char * plus = strchr(dash, '+'); + if (plus != nullptr) { + prerelease_.assign(dash + 1, plus - dash - 1); + } else { + prerelease_.assign(dash + 1); + } + } +} + +} // namespace emsesp diff --git a/src/core/firmwareVersion.h b/src/core/firmwareVersion.h new file mode 100644 index 000000000..8076b14c5 --- /dev/null +++ b/src/core/firmwareVersion.h @@ -0,0 +1,59 @@ +/* + * EMS-ESP - https://github.com/emsesp/EMS-ESP + * Copyright 2020-2026 emsesp.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef firmwareVersion_H +#define firmwareVersion_H + +#include + +namespace emsesp { + +class FirmwareVersion { + public: + FirmwareVersion() = default; + + // Construct from a version string like "3.9.0-dev.14" or "3.9.0". + // Anything past a '-' or '+' is kept as the prerelease string and not interpreted. + explicit FirmwareVersion(const std::string & s); + explicit FirmwareVersion(const char * s); + + int major() const; + int minor() const; + int patch() const; + const std::string & prerelease() const; + + // Numeric-only comparison (major.minor.patch). Prerelease tags are ignored on purpose. + friend bool operator<(const FirmwareVersion & a, const FirmwareVersion & b); + friend bool operator>(const FirmwareVersion & a, const FirmwareVersion & b); + friend bool operator==(const FirmwareVersion & a, const FirmwareVersion & b); + friend bool operator!=(const FirmwareVersion & a, const FirmwareVersion & b); + friend bool operator>=(const FirmwareVersion & a, const FirmwareVersion & b); + friend bool operator<=(const FirmwareVersion & a, const FirmwareVersion & b); + + private: + int major_ = 0; + int minor_ = 0; + int patch_ = 0; + std::string prerelease_; + + void parse(const char * s); +}; + +} // namespace emsesp + +#endif diff --git a/src/core/system.cpp b/src/core/system.cpp index 68f4e56e9..64700323b 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -32,7 +32,7 @@ #include #include -#include "EMSESP_Version.h" +#include "firmwareVersion.h" #if defined(EMSESP_TEST) #include "../test/test.h" @@ -991,7 +991,6 @@ void System::heartbeat_json(JsonObject output) { #if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 output["temperature"] = (int)temperature_; #endif -#endif #ifndef EMSESP_STANDALONE if (!EMSESP::network_.ethernet_connected()) { @@ -1001,6 +1000,11 @@ void System::heartbeat_json(JsonObject output) { output["wifireconnects"] = EMSESP::network_.getWifiReconnects(); } #endif + + // see if there is a newer version available + if (EMSESP::webStatusService.versions_cache_valid()) { + output["upgradeable"] = EMSESP::webStatusService.current_upgradeable(); + } } // send periodic MQTT message with system information @@ -1570,8 +1574,8 @@ bool System::check_upgrade() { settingsVersion = "3.5.0"; // this was the last stable version without version info } - version::EMSESP_Version settings_version(settingsVersion); - version::EMSESP_Version this_version(EMSESP_APP_VERSION); + FirmwareVersion settings_version(settingsVersion); + FirmwareVersion this_version(EMSESP_APP_VERSION); std::string settings_version_type = settings_version.prerelease().empty() ? "" : ("-" + settings_version.prerelease()); std::string this_version_type = this_version.prerelease().empty() ? "" : ("-" + this_version.prerelease()); diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index aa909b515..ceba2fc86 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -173,7 +173,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i for (uint8_t i = 0; i < monitor_size; i++) { register_telegram_type(monitor_typeids[i], "RC300Monitor", false, MAKE_PF_CB(process_RC300Monitor), 33); register_telegram_type(set_typeids[i], "RC300Set", false, MAKE_PF_CB(process_RC300Set), 29); - register_telegram_type(summer_typeids[i], "RC300Summer", false, MAKE_PF_CB(process_RC300Summer), 13); + register_telegram_type(summer_typeids[i], "RC300Summer", false, MAKE_PF_CB(process_RC300Summer), 14); register_telegram_type(curve_typeids[i], "RC300Curves", false, MAKE_PF_CB(process_RC300Curve), 9); register_telegram_type(summer2_typeids[i], "RC300Summer2", false, MAKE_PF_CB(process_RC300Summer2), 8); } diff --git a/src/test/test.cpp b/src/test/test.cpp index 4a7181893..1ea87e770 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -1329,16 +1329,6 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // request.url("/rest/action"); // EMSESP::webStatusService.action(&request, doc.as()); - // test version checks - // use same data as in restServer.ts - // log shows first if you can upgrade to dev, and then if you can upgrade to stable - // request.url("/rest/action"); - // std::string LATEST_STABLE_VERSION = "3.8.0"; - // std::string LATEST_DEV_VERSION = "3.8.1-dev.3"; - // std::string param = LATEST_DEV_VERSION + "," + LATEST_STABLE_VERSION; - // std::string action = "{\"action\":\"checkUpgrade\", \"param\":\"" + param + "\"}"; - // deserializeJson(doc, action); - // // case 0: on latest stable, can upgrade to dev only. So true, false // EMSESP::webStatusService.set_current_version(LATEST_STABLE_VERSION); // EMSESP::webStatusService.action(&request, doc.as()); diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 77a349839..fbcbeee4a 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -20,6 +20,7 @@ #ifndef EMSESP_STANDALONE #include +#include #endif namespace emsesp { @@ -205,11 +206,11 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) bool is_admin = AuthenticationPredicates::IS_ADMIN(authentication); // call action command - bool ok = false; + bool ok = true; std::string action = json["action"]; - if (action == "checkUpgrade") { - ok = checkUpgrade(root, param); // param could be empty, if so only send back version + if (action == "getVersions") { + getVersions(root); } else if (action == "setPartition") { ok = EMSESP::system_.set_partition(param.c_str()); } else if (action == "export") { @@ -224,10 +225,8 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) ok = setSystemStatus(param.c_str()); } else if (action == "resetMQTT" && is_admin) { EMSESP::mqtt_.reset_mqtt(); - ok = true; } else if (action == "upgradeImportantMessages") { root["upgradeImportantMessageType"] = upgradeImportantMessages(param); - ok = true; } #if defined(EMSESP_STANDALONE) && !defined(EMSESP_UNITY) @@ -262,7 +261,7 @@ uint8_t WebStatusService::upgradeImportantMessages(std::string & version) { // it's a filename with a .bin or .md extension, try and extract the version from it // e.g. EMS-ESP-3_8_2-dev_13-ESP32-16MB+.bin -> major=3 minor=8 patch=2 - version::EMSESP_Version latest_version; + FirmwareVersion latest_version; if ((version.find(".bin") != std::string::npos) || (version.find(".md") != std::string::npos)) { std::string filename = version; auto pos = filename.find("EMS-ESP-"); @@ -283,18 +282,18 @@ uint8_t WebStatusService::upgradeImportantMessages(std::string & version) { std::string major_version = filename.substr(pos, underscore1 - pos); std::string minor_version = filename.substr(underscore1 + 1, underscore2 - underscore1 - 1); std::string patch_version = filename.substr(underscore2 + 1, dash - underscore2 - 1); - latest_version = version::EMSESP_Version(major_version + "." + minor_version + "." + patch_version); + latest_version = FirmwareVersion(major_version + "." + minor_version + "." + patch_version); } else { // if it's .json file exit if (version.find(".json") != std::string::npos) { return 0; } else { // treat it like a version string like "3.9.0" - latest_version = version::EMSESP_Version(version); + latest_version = FirmwareVersion(version); } } - version::EMSESP_Version current_version(current_version_s); // get current version + FirmwareVersion current_version(current_version_s); // get current version if ((current_version.major() <= 3 && current_version.minor() <= 8) && (latest_version.major() == 3 && latest_version.minor() == 9)) { return 1; // if moving from below 3.8.x to 3.9.x return 1 @@ -311,46 +310,164 @@ uint8_t WebStatusService::upgradeImportantMessages(std::string & version) { return 0; // if it's not a valid version upgrade return 0 } -// action = checkUpgrade -// versions holds the latest development version and stable version in one string, comma separated -bool WebStatusService::checkUpgrade(JsonObject root, std::string & version) { - if (!version.empty()) { - version::EMSESP_Version current_version(current_version_s); - version::EMSESP_Version latest_dev_version(version.substr(0, version.find(','))); - version::EMSESP_Version latest_stable_version(version.substr(version.find(',') + 1)); +// action = getVersions +// returns the device's current version for dev and stable +// The remote fetch runs from the main loop task via WebStatusService::loop() so that we never block the AsyncTCP callback +void WebStatusService::getVersions(JsonObject root) { + FirmwareVersion current_version(current_version_s); + bool is_dev = current_version.prerelease().find("dev") != std::string::npos; - bool dev_upgradeable = latest_dev_version > current_version; - bool stable_upgradeable = latest_stable_version > current_version; + JsonObject current = root["current"].to(); + current["version"] = current_version_s; + current["type"] = is_dev ? "dev" : "stable"; + current["date"] = ""; + current["upgradeable"] = current_upgradeable(); // false if cache not valid yet -#if defined(EMSESP_DEBUG) - // look for dev in the name to determine if we're using a dev release - bool using_dev_version = !current_version.prerelease().find("dev"); - EMSESP::logger() - .debug("Checking version upgrade. This version=%d.%d.%d-%s (%s),latest dev=%d.%d.%d-%s (%s upgradeable),latest stable=%d.%d.%d-%s (%s upgradeable)", - current_version.major(), - current_version.minor(), - current_version.patch(), - current_version.prerelease().c_str(), - using_dev_version ? "Dev" : "Stable", - latest_dev_version.major(), - latest_dev_version.minor(), - latest_dev_version.patch(), - latest_dev_version.prerelease().c_str(), - dev_upgradeable ? "is" : "is not", - latest_stable_version.major(), - latest_stable_version.minor(), - latest_stable_version.patch(), - latest_stable_version.prerelease().c_str(), - stable_upgradeable ? "is" : "is not"); -#endif - - root["dev_upgradeable"] = dev_upgradeable; - root["stable_upgradeable"] = stable_upgradeable; +#ifndef EMSESP_STANDALONE + // pull the install_date for the running partition (if known) + const esp_partition_t * running = esp_ota_get_running_partition(); + if (running != nullptr) { + const auto & info = EMSESP::system_.partition_info_; + auto it = info.find(running->label); + if (it != info.end() && it->second.install_date > 0) { + char time_string[25]; + time_t d = it->second.install_date; + strftime(time_string, sizeof(time_string), "%FT%T", localtime(&d)); + current["date"] = time_string; + } } - root["emsesp_version"] = current_version_s; // always send back current version + if (!versions_cache_valid_) { + // no successful fetch yet (no network, fetch pending, or parse error) + return; + } + // copies a cached entry into root[key] + auto add_section = [&](const char * key, const VersionInfo & info) { + if (info.version.empty()) { + return; + } + JsonObject out = root[key].to(); + out["version"] = info.version; + out["date"] = info.date; + out["upgradeable"] = info.upgradeable; + }; + + add_section("stable", versions_stable_); + add_section("dev", versions_dev_); +#else + // standalone/test build: provide deterministic dummy data + JsonObject stable_out = root["stable"].to(); + stable_out["version"] = "3.8.2"; + stable_out["date"] = "2026-04-25"; + stable_out["upgradeable"] = FirmwareVersion("3.8.2") > current_version; + + JsonObject dev_out = root["dev"].to(); + dev_out["version"] = "3.9.0-dev.1"; + dev_out["date"] = "2026-04-25"; + dev_out["upgradeable"] = FirmwareVersion("3.9.0-dev.1") > current_version; +#endif +} + +// periodic refresh (1 hour) of the cached versions.json +// runs on the main loop task, which has a much bigger stack than AsyncTCP needed for https +void WebStatusService::loop() { +#ifndef EMSESP_STANDALONE + // need a network + if (!EMSESP::system_.ethernet_connected() && (WiFi.status() != WL_CONNECTED)) { + return; + } + + // 0 = idle, nothing scheduled + if (versions_next_fetch_ms_ == 0) { + return; + } + + // not time yet (signed difference handles uint32 wrap) + if ((int32_t)(uuid::get_uptime() - versions_next_fetch_ms_) < 0) { + return; + } + + bool ok = refresh_versions_cache(); + uint32_t next = uuid::get_uptime() + (ok ? VERSIONS_REFRESH_INTERVAL_MS : VERSIONS_RETRY_INTERVAL_MS); + if (next == 0) { + next = 1; + } + versions_next_fetch_ms_ = next; +#endif +} + +// runs on the main loop task — never call this from an AsyncWebServer handler +bool WebStatusService::refresh_versions_cache() { +#ifdef EMSESP_STANDALONE + return false; +#else + HTTPClient http; + http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + http.setTimeout(5000); + http.useHTTP10(true); + + if (!http.begin(EMSESP_VERSIONS_URL)) { +#if defined(EMSESP_DEBUG) + EMSESP::logger().debug("versions.json: failed to start HTTPS request"); +#endif + return false; + } + + int httpCode = http.GET(); + if (httpCode != HTTP_CODE_OK) { +#if defined(EMSESP_DEBUG) + EMSESP::logger().debug("versions.json: HTTP %d", httpCode); +#endif + http.end(); + return false; + } + + JsonDocument doc; + DeserializationError err = deserializeJson(doc, http.getStream()); + http.end(); + if (err) { +#if defined(EMSESP_DEBUG) + EMSESP::logger().debug("versions.json: parse error"); +#endif + return false; + } + + FirmwareVersion current_version(current_version_s); + + auto read_section = [&doc, ¤t_version](const char * key, VersionInfo & out) { + JsonObjectConst section = doc[key]; + if (section.isNull()) { + out = {}; + return; + } + out.version = section["version"] | ""; + out.date = section["date"] | ""; + out.upgradeable = !out.version.empty() && FirmwareVersion(out.version) > current_version; + }; + + read_section("stable", versions_stable_); + read_section("dev", versions_dev_); + + versions_cache_valid_ = true; +#if defined(EMSESP_DEBUG) + EMSESP::logger().debug("versions.json: refreshed (stable=%s dev=%s), current=%s", + versions_stable_.version.c_str(), + versions_dev_.version.c_str(), + current_version_s.c_str()); +#endif return true; +#endif +} + +// returns if current dev/stable is upgradeable +bool WebStatusService::current_upgradeable() const { + if (!versions_cache_valid_) { + return false; + } + FirmwareVersion current_version(current_version_s); + bool is_dev = current_version.prerelease().find("dev") != std::string::npos; + return is_dev ? versions_dev_.upgradeable : versions_stable_.upgradeable; } // action = allvalues diff --git a/src/web/WebStatusService.h b/src/web/WebStatusService.h index 6d3f59f1a..90414b6b8 100644 --- a/src/web/WebStatusService.h +++ b/src/web/WebStatusService.h @@ -4,7 +4,9 @@ #define EMSESP_SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus" #define EMSESP_ACTION_SERVICE_PATH "/rest/action" -#include "../core/EMSESP_Version.h" +#define EMSESP_VERSIONS_URL "http://emsesp.org/versions.json" + +#include "../core/firmwareVersion.h" #include "../emsesp_version.h" namespace emsesp { @@ -19,6 +21,22 @@ class WebStatusService { return current_version_s; } + // called from EMSESP::loop() to refresh the cached versions.json from emsesp.org + // so that the web request handler never has to do blocking HTTPS on the small AsyncTCP stack + void loop(); + + // true once we've had at least one successful versions.json fetch + bool versions_cache_valid() const { + return versions_cache_valid_; + } + + // refresh the versions.json cache + void schedule_versions_refresh() { + versions_next_fetch_ms_ = 1; + } + + bool current_upgradeable() const; // true if a newer version is available + // make action function public so we can test in the debug and standalone mode #ifndef EMSESP_STANDALONE protected: @@ -30,7 +48,7 @@ class WebStatusService { SecurityManager * _securityManager; // actions - bool checkUpgrade(JsonObject root, std::string & latest_version); + void getVersions(JsonObject root); bool exportData(JsonObject root, std::string & type); bool getCustomSupport(JsonObject root); bool uploadURL(const char * url); @@ -39,6 +57,22 @@ class WebStatusService { uint8_t upgradeImportantMessages(std::string & version); std::string current_version_s = EMSESP_APP_VERSION; + + // cached emsesp.org/versions.json. Refreshed from the main loop task, which has more stack. + struct VersionInfo { + std::string version; + std::string date; + bool upgradeable = false; + }; + VersionInfo versions_stable_; + VersionInfo versions_dev_; + bool versions_cache_valid_ = false; // true once we've had at least one successful fetch + uint32_t versions_next_fetch_ms_ = 0; // uuid::get_uptime() of the next attempt; 0 = idle + + bool refresh_versions_cache(); // does the actual HTTPS fetch + parse, returns true on success + + static constexpr uint32_t VERSIONS_REFRESH_INTERVAL_MS = 60UL * 60UL * 1000UL; // 1 hour on success + static constexpr uint32_t VERSIONS_RETRY_INTERVAL_MS = 5UL * 60UL * 1000UL; // 5 min after failure }; } // namespace emsesp diff --git a/test/test_api/api_test.http b/test/test_api/api_test.http index 1a37372bc..e8a1af255 100755 --- a/test/test_api/api_test.http +++ b/test/test_api/api_test.http @@ -3,9 +3,8 @@ # Open this file in VSC, modify the token, go to the API call and click on 'Send Request' (or Ctrl+Alt+R) # The response will be shown in the right panel -# @host = http://ems-esp.local -@host = http://192.168.1.223 -@host_dev = http://192.168.1.65 +@host = http://ems-esp.local +@host_dev = http://ems-espT.local @host_standalone = http://localhost:3080 @host_standalone2 = http://localhost:3082 diff --git a/test/test_api/api_test.sh b/test/test_api/api_test.sh index 8deaa3013..0de8cde3b 100755 --- a/test/test_api/api_test.sh +++ b/test/test_api/api_test.sh @@ -4,7 +4,8 @@ # Command line test for the API # -emsesp_url="http://192.168.1.223" +# emsesp_url="http://ems-esp.local" +emsesp_url="http://ems-espT.local" # get the token from the Security page. This is the token for the admin user, unless changed it'll always be the same emsesp_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiYWRtaW4iOnRydWV9.2bHpWya2C7Q12WjNUBD6_7N3RCD7CMl-EGhyQVzFdDg" @@ -40,13 +41,22 @@ curl -X POST \ echo "\n" +# Get all versions +curl -X POST \ + -H "Authorization: Bearer ${emsesp_token}" \ + -H "Content-Type: application/json" \ + -d '{"action":"getVersions"}' \ + ${emsesp_url}/rest/action + +echo "\n" + # This example is how to call a service in Home Assistant via the API # Which can be added to an EMS-EPS schedule - -ha_url="http://192.168.1.86:8123" -ha_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIwMzMyZjU1MjhlZmM0NGIyOTgyMjIxNThiODU1NDkyNSIsImlhdCI6MTcyMTMwNDg2NSwiZXhwIjoyMDM2NjY0ODY1fQ.Q-Y7E_i7clH3ff4Ma-OMmhZfbN7aMi_CahKwmoar" - -curl -X POST \ - ${ha_url}/api/services/script/test_notify \ - -H "Authorization: Bearer ${ha_token}" \ - -H "Content-Type: application/json" +# +# ha_url="http://192.168.1.86:8123" +# ha_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIwMzMyZjU1MjhlZmM0NGIyOTgyMjIxNThiODU1NDkyNSIsImlhdCI6MTcyMTMwNDg2NSwiZXhwIjoyMDM2NjY0ODY1fQ.Q-Y7E_i7clH3ff4Ma-OMmhZfbN7aMi_CahKwmoar" +# +# curl -X POST \ +# ${ha_url}/api/services/script/test_notify \ +# -H "Authorization: Bearer ${ha_token}" \ +# -H "Content-Type: application/json"