diff --git a/biome.json b/biome.json index db0dbff7..a8cc0ab0 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.3.3/schema.json", + "$schema": "https://biomejs.dev/schemas/2.3.6/schema.json", "vcs": { "enabled": false, "clientKind": "git", diff --git a/package.json b/package.json index cd4ae31d..326e60c6 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "react-auth-code-input": "^3.2.1", "react-click-away-listener": "^2.4.0", "react-dom": "^19.2.0", - "react-hook-form": "^7.66.0", + "react-hook-form": "^7.66.1", "react-hotkeys-hook": "^5.2.1", "react-loading-skeleton": "^3.5.0", "react-markdown": "^10.1.0", @@ -108,7 +108,7 @@ "zustand": "^5.0.8" }, "devDependencies": { - "@biomejs/biome": "^2.3.5", + "@biomejs/biome": "^2.3.6", "@hookform/devtools": "^4.4.0", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.90.10", @@ -117,7 +117,7 @@ "@types/file-saver": "^2.0.7", "@types/lodash-es": "^4.17.12", "@types/node": "^24.10.1", - "@types/react": "^19.2.5", + "@types/react": "^19.2.6", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^5.1.1", "@vitejs/plugin-react-swc": "^4.2.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 975bb0ab..a1c7b50c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: version: 0.27.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@hookform/resolvers': specifier: ^3.10.0 - version: 3.10.0(react-hook-form@7.66.0(react@19.2.0)) + version: 3.10.0(react-hook-form@7.66.1(react@19.2.0)) '@react-hook/resize-observer': specifier: ^2.0.2 version: 2.0.2(react@19.2.0) @@ -103,7 +103,7 @@ importers: version: 1.0.3 html-react-parser: specifier: ^5.2.10 - version: 5.2.10(@types/react@19.2.5)(react@19.2.0) + version: 5.2.10(@types/react@19.2.6)(react@19.2.0) itertools: specifier: ^2.5.0 version: 2.5.0 @@ -115,7 +115,7 @@ importers: version: 4.17.21 merge-refs: specifier: ^2.0.0 - version: 2.0.0(@types/react@19.2.5) + version: 2.0.0(@types/react@19.2.6) millify: specifier: ^6.1.0 version: 6.1.0 @@ -144,8 +144,8 @@ importers: specifier: ^19.2.0 version: 19.2.0(react@19.2.0) react-hook-form: - specifier: ^7.66.0 - version: 7.66.0(react@19.2.0) + specifier: ^7.66.1 + version: 7.66.1(react@19.2.0) react-hotkeys-hook: specifier: ^5.2.1 version: 5.2.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -154,7 +154,7 @@ importers: version: 3.5.0(react@19.2.0) react-markdown: specifier: ^10.1.0 - version: 10.1.0(@types/react@19.2.5)(react@19.2.0) + version: 10.1.0(@types/react@19.2.6)(react@19.2.0) react-qr-code: specifier: ^2.0.18 version: 2.0.18(react@19.2.0) @@ -169,7 +169,7 @@ importers: version: 1.0.26(react-dom@19.2.0(react@19.2.0))(react@19.2.0) recharts: specifier: ^3.4.1 - version: 3.4.1(@types/react@19.2.5)(react-dom@19.2.0(react@19.2.0))(react-is@18.3.1)(react@19.2.0)(redux@5.0.1) + version: 3.4.1(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react-is@18.3.1)(react@19.2.0)(redux@5.0.1) rehype-sanitize: specifier: ^6.0.0 version: 6.0.0 @@ -184,14 +184,14 @@ importers: version: 3.25.76 zustand: specifier: ^5.0.8 - version: 5.0.8(@types/react@19.2.5)(immer@10.2.0)(react@19.2.0)(use-sync-external-store@1.6.0(react@19.2.0)) + version: 5.0.8(@types/react@19.2.6)(immer@10.2.0)(react@19.2.0)(use-sync-external-store@1.6.0(react@19.2.0)) devDependencies: '@biomejs/biome': - specifier: ^2.3.5 - version: 2.3.5 + specifier: ^2.3.6 + version: 2.3.6 '@hookform/devtools': specifier: ^4.4.0 - version: 4.4.0(@types/react@19.2.5)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 4.4.0(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@svgr/cli': specifier: ^8.1.0 version: 8.1.0(typescript@5.9.3) @@ -214,11 +214,11 @@ importers: specifier: ^24.10.1 version: 24.10.1 '@types/react': - specifier: ^19.2.5 - version: 19.2.5 + specifier: ^19.2.6 + version: 19.2.6 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.5) + version: 19.2.3(@types/react@19.2.6) '@vitejs/plugin-react': specifier: ^5.1.1 version: 5.1.1(vite@7.2.2(@types/node@24.10.1)(sass@1.92.1)(yaml@2.8.1)) @@ -342,55 +342,55 @@ packages: resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} - '@biomejs/biome@2.3.5': - resolution: {integrity: sha512-HvLhNlIlBIbAV77VysRIBEwp55oM/QAjQEin74QQX9Xb259/XP/D5AGGnZMOyF1el4zcvlNYYR3AyTMUV3ILhg==} + '@biomejs/biome@2.3.6': + resolution: {integrity: sha512-oqUhWyU6tae0MFsr/7iLe++QWRg+6jtUhlx9/0GmCWDYFFrK366sBLamNM7D9Y+c7YSynUFKr8lpEp1r6Sk7eA==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.3.5': - resolution: {integrity: sha512-fLdTur8cJU33HxHUUsii3GLx/TR0BsfQx8FkeqIiW33cGMtUD56fAtrh+2Fx1uhiCsVZlFh6iLKUU3pniZREQw==} + '@biomejs/cli-darwin-arm64@2.3.6': + resolution: {integrity: sha512-P4JWE5d8UayBxYe197QJwyW4ZHp0B+zvRIGCusOm1WbxmlhpAQA1zEqQuunHgSIzvyEEp4TVxiKGXNFZPg7r9Q==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.3.5': - resolution: {integrity: sha512-qpT8XDqeUlzrOW8zb4k3tjhT7rmvVRumhi2657I2aGcY4B+Ft5fNwDdZGACzn8zj7/K1fdWjgwYE3i2mSZ+vOA==} + '@biomejs/cli-darwin-x64@2.3.6': + resolution: {integrity: sha512-I4rTebj+F/L9K93IU7yTFs8nQ6EhaCOivxduRha4w4WEZK80yoZ8OAdR1F33m4yJ/NfUuTUbP/Wjs+vKjlCoWA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.3.5': - resolution: {integrity: sha512-eGUG7+hcLgGnMNl1KHVZUYxahYAhC462jF/wQolqu4qso2MSk32Q+QrpN7eN4jAHAg7FUMIo897muIhK4hXhqg==} + '@biomejs/cli-linux-arm64-musl@2.3.6': + resolution: {integrity: sha512-oK1NpIXIixbJ/4Tcx40cwiieqah6rRUtMGOHDeK2ToT7yUFVEvXUGRKqH0O4hqZ9tW8TcXNZKfgRH6xrsjVtGg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@2.3.5': - resolution: {integrity: sha512-u/pybjTBPGBHB66ku4pK1gj+Dxgx7/+Z0jAriZISPX1ocTO8aHh8x8e7Kb1rB4Ms0nA/SzjtNOVJ4exVavQBCw==} + '@biomejs/cli-linux-arm64@2.3.6': + resolution: {integrity: sha512-JjYy83eVBnvuINZiqyFO7xx72v8Srh4hsgaacSBCjC22DwM6+ZvnX1/fj8/SBiLuUOfZ8YhU2pfq2Dzakeyg1A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@2.3.5': - resolution: {integrity: sha512-awVuycTPpVTH/+WDVnEEYSf6nbCBHf/4wB3lquwT7puhNg8R4XvonWNZzUsfHZrCkjkLhFH/vCZK5jHatD9FEg==} + '@biomejs/cli-linux-x64-musl@2.3.6': + resolution: {integrity: sha512-QvxB8GHQeaO4FCtwJpJjCgJkbHBbWxRHUxQlod+xeaYE6gtJdSkYkuxdKAQUZEOIsec+PeaDAhW9xjzYbwmOFA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@2.3.5': - resolution: {integrity: sha512-XrIVi9YAW6ye0CGQ+yax0gLfx+BFOtKaNX74n+xHWla6Cl6huUmcKNO7HPx7BiKnJUzrxXY1qYlm7xMvi08X4g==} + '@biomejs/cli-linux-x64@2.3.6': + resolution: {integrity: sha512-ZjPXzy5yN9wusIoX+8Zp4p6cL8r0NzJCXg/4r1KLVveIPXd2jKVlqZ6ZyzEq385WwU3OX5KOwQYLQsOc788waQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@2.3.5': - resolution: {integrity: sha512-DlBiMlBZZ9eIq4H7RimDSGsYcOtfOIfZOaI5CqsWiSlbTfqbPVfWtCf92wNzx8GNMbu1s7/g3ZZESr6+GwM/SA==} + '@biomejs/cli-win32-arm64@2.3.6': + resolution: {integrity: sha512-YM7hLHpwjdt8R7+O2zS1Vo2cKgqEeptiXB1tWW1rgjN5LlpZovBVKtg7zfwfRrFx3i08aNZThYpTcowpTlczug==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.3.5': - resolution: {integrity: sha512-nUmR8gb6yvrKhtRgzwo/gDimPwnO5a4sCydf8ZS2kHIJhEmSmk+STsusr1LHTuM//wXppBawvSQi2xFXJCdgKQ==} + '@biomejs/cli-win32-x64@2.3.6': + resolution: {integrity: sha512-psgNEYgMAobY5h+QHRBVR9xvg2KocFuBKm6axZWB/aD12NWhQjiVFQUjV6wMXhlH4iT0Q9c3yK5JFRiDC/rzHA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -771,113 +771,113 @@ packages: '@rolldown/pluginutils@1.0.0-beta.47': resolution: {integrity: sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==} - '@rollup/rollup-android-arm-eabi@4.53.2': - resolution: {integrity: sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==} + '@rollup/rollup-android-arm-eabi@4.53.3': + resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.53.2': - resolution: {integrity: sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==} + '@rollup/rollup-android-arm64@4.53.3': + resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.53.2': - resolution: {integrity: sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==} + '@rollup/rollup-darwin-arm64@4.53.3': + resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.53.2': - resolution: {integrity: sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==} + '@rollup/rollup-darwin-x64@4.53.3': + resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.53.2': - resolution: {integrity: sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==} + '@rollup/rollup-freebsd-arm64@4.53.3': + resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.53.2': - resolution: {integrity: sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==} + '@rollup/rollup-freebsd-x64@4.53.3': + resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.53.2': - resolution: {integrity: sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==} + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.53.2': - resolution: {integrity: sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==} + '@rollup/rollup-linux-arm-musleabihf@4.53.3': + resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.53.2': - resolution: {integrity: sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==} + '@rollup/rollup-linux-arm64-gnu@4.53.3': + resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.53.2': - resolution: {integrity: sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==} + '@rollup/rollup-linux-arm64-musl@4.53.3': + resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.53.2': - resolution: {integrity: sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==} + '@rollup/rollup-linux-loong64-gnu@4.53.3': + resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.53.2': - resolution: {integrity: sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==} + '@rollup/rollup-linux-ppc64-gnu@4.53.3': + resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.53.2': - resolution: {integrity: sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==} + '@rollup/rollup-linux-riscv64-gnu@4.53.3': + resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.53.2': - resolution: {integrity: sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==} + '@rollup/rollup-linux-riscv64-musl@4.53.3': + resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.53.2': - resolution: {integrity: sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==} + '@rollup/rollup-linux-s390x-gnu@4.53.3': + resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.53.2': - resolution: {integrity: sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==} + '@rollup/rollup-linux-x64-gnu@4.53.3': + resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.53.2': - resolution: {integrity: sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==} + '@rollup/rollup-linux-x64-musl@4.53.3': + resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.53.2': - resolution: {integrity: sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==} + '@rollup/rollup-openharmony-arm64@4.53.3': + resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.53.2': - resolution: {integrity: sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==} + '@rollup/rollup-win32-arm64-msvc@4.53.3': + resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.53.2': - resolution: {integrity: sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==} + '@rollup/rollup-win32-ia32-msvc@4.53.3': + resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.53.2': - resolution: {integrity: sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==} + '@rollup/rollup-win32-x64-gnu@4.53.3': + resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.53.2': - resolution: {integrity: sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==} + '@rollup/rollup-win32-x64-msvc@4.53.3': + resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} cpu: [x64] os: [win32] @@ -1303,8 +1303,8 @@ packages: peerDependencies: '@types/react': ^19.2.0 - '@types/react@19.2.5': - resolution: {integrity: sha512-keKxkZMqnDicuvFoJbzrhbtdLSPhj/rZThDlKWCDbgXmUg0rEUFtRssDXKYmtXluZlIqiC5VqkCgRwzuyLHKHw==} + '@types/react@19.2.6': + resolution: {integrity: sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==} '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -1386,8 +1386,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - baseline-browser-mapping@2.8.28: - resolution: {integrity: sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==} + baseline-browser-mapping@2.8.29: + resolution: {integrity: sha512-sXdt2elaVnhpDNRDz+1BDx1JQoJRuNk7oVlAlbGiFkLikHCAQiccexF/9e91zVi6RCgqspl04aP+6Cnl9zRLrA==} hasBin: true boolbase@1.0.0: @@ -1437,8 +1437,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001755: - resolution: {integrity: sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==} + caniuse-lite@1.0.30001756: + resolution: {integrity: sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -1550,8 +1550,8 @@ packages: resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - csstype@3.2.2: - resolution: {integrity: sha512-D80T+tiqkd/8B0xNlbstWDG4x6aqVfO52+OlSUNIdkTvmNw0uQpJLeos2J/2XvpyidAFuTPmpad+tUxLndwj6g==} + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} d3-array@3.2.4: resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} @@ -1682,8 +1682,8 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.254: - resolution: {integrity: sha512-DcUsWpVhv9svsKRxnSCZ86SjD+sp32SGidNB37KpqXJncp1mfUgKbHvBomE89WJDbfVKw1mdv5+ikrvd43r+Bg==} + electron-to-chromium@1.5.256: + resolution: {integrity: sha512-uqYq1IQhpXXLX+HgiXdyOZml7spy4xfy42yPxcCCRjswp0fYM2X+JwCON07lqnpLEGVCj739B7Yr+FngmHBMEQ==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2465,8 +2465,8 @@ packages: peerDependencies: react: ^19.2.0 - react-hook-form@7.66.0: - resolution: {integrity: sha512-xXBqsWGKrY46ZqaHDo+ZUYiMUgi8suYu5kdrS20EG8KiL7VRQitEbNjm+UcrDYrNi1YLyfpmAeGjCZYXLT9YBw==} + react-hook-form@7.66.1: + resolution: {integrity: sha512-2KnjpgG2Rhbi+CIiIBQQ9Df6sMGH5ExNyFl4Hw9qO7pIqMBR8Bvu9RQyjl3JM4vehzCh9soiNUM/xYMswb2EiA==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -2606,8 +2606,8 @@ packages: engines: {node: '>= 0.4'} hasBin: true - rollup@4.53.2: - resolution: {integrity: sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==} + rollup@4.53.3: + resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -3127,39 +3127,39 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@biomejs/biome@2.3.5': + '@biomejs/biome@2.3.6': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.3.5 - '@biomejs/cli-darwin-x64': 2.3.5 - '@biomejs/cli-linux-arm64': 2.3.5 - '@biomejs/cli-linux-arm64-musl': 2.3.5 - '@biomejs/cli-linux-x64': 2.3.5 - '@biomejs/cli-linux-x64-musl': 2.3.5 - '@biomejs/cli-win32-arm64': 2.3.5 - '@biomejs/cli-win32-x64': 2.3.5 - - '@biomejs/cli-darwin-arm64@2.3.5': + '@biomejs/cli-darwin-arm64': 2.3.6 + '@biomejs/cli-darwin-x64': 2.3.6 + '@biomejs/cli-linux-arm64': 2.3.6 + '@biomejs/cli-linux-arm64-musl': 2.3.6 + '@biomejs/cli-linux-x64': 2.3.6 + '@biomejs/cli-linux-x64-musl': 2.3.6 + '@biomejs/cli-win32-arm64': 2.3.6 + '@biomejs/cli-win32-x64': 2.3.6 + + '@biomejs/cli-darwin-arm64@2.3.6': optional: true - '@biomejs/cli-darwin-x64@2.3.5': + '@biomejs/cli-darwin-x64@2.3.6': optional: true - '@biomejs/cli-linux-arm64-musl@2.3.5': + '@biomejs/cli-linux-arm64-musl@2.3.6': optional: true - '@biomejs/cli-linux-arm64@2.3.5': + '@biomejs/cli-linux-arm64@2.3.6': optional: true - '@biomejs/cli-linux-x64-musl@2.3.5': + '@biomejs/cli-linux-x64-musl@2.3.6': optional: true - '@biomejs/cli-linux-x64@2.3.5': + '@biomejs/cli-linux-x64@2.3.6': optional: true - '@biomejs/cli-win32-arm64@2.3.5': + '@biomejs/cli-win32-arm64@2.3.6': optional: true - '@biomejs/cli-win32-x64@2.3.5': + '@biomejs/cli-win32-x64@2.3.6': optional: true '@emotion/babel-plugin@11.13.5': @@ -3194,7 +3194,7 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0)': + '@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@emotion/babel-plugin': 11.13.5 @@ -3206,7 +3206,7 @@ snapshots: hoist-non-react-statics: 3.3.2 react: 19.2.0 optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 transitivePeerDependencies: - supports-color @@ -3216,22 +3216,22 @@ snapshots: '@emotion/memoize': 0.9.0 '@emotion/unitless': 0.10.0 '@emotion/utils': 1.4.2 - csstype: 3.2.2 + csstype: 3.2.3 '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0)': + '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@emotion/babel-plugin': 11.13.5 '@emotion/is-prop-valid': 1.4.0 - '@emotion/react': 11.14.0(@types/react@19.2.5)(react@19.2.0) + '@emotion/react': 11.14.0(@types/react@19.2.6)(react@19.2.0) '@emotion/serialize': 1.3.3 '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.0) '@emotion/utils': 1.4.2 react: 19.2.0 optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 transitivePeerDependencies: - supports-color @@ -3356,10 +3356,10 @@ snapshots: '@shikijs/types': 3.15.0 '@shikijs/vscode-textmate': 10.0.2 - '@hookform/devtools@4.4.0(@types/react@19.2.5)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@hookform/devtools@4.4.0(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@emotion/react': 11.14.0(@types/react@19.2.5)(react@19.2.0) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0) + '@emotion/react': 11.14.0(@types/react@19.2.6)(react@19.2.0) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0) '@types/lodash': 4.17.20 little-state-machine: 4.8.1(react@19.2.0) lodash: 4.17.21 @@ -3372,9 +3372,9 @@ snapshots: - '@types/react' - supports-color - '@hookform/resolvers@3.10.0(react-hook-form@7.66.0(react@19.2.0))': + '@hookform/resolvers@3.10.0(react-hook-form@7.66.1(react@19.2.0))': dependencies: - react-hook-form: 7.66.0(react@19.2.0) + react-hook-form: 7.66.1(react@19.2.0) '@jridgewell/gen-mapping@0.3.13': dependencies: @@ -3470,7 +3470,7 @@ snapshots: '@react-hook/passive-layout-effect': 1.2.1(react@19.2.0) react: 19.2.0 - '@reduxjs/toolkit@2.10.1(react-redux@9.2.0(@types/react@19.2.5)(react@19.2.0)(redux@5.0.1))(react@19.2.0)': + '@reduxjs/toolkit@2.10.1(react-redux@9.2.0(@types/react@19.2.6)(react@19.2.0)(redux@5.0.1))(react@19.2.0)': dependencies: '@standard-schema/spec': 1.0.0 '@standard-schema/utils': 0.3.0 @@ -3480,76 +3480,76 @@ snapshots: reselect: 5.1.1 optionalDependencies: react: 19.2.0 - react-redux: 9.2.0(@types/react@19.2.5)(react@19.2.0)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.6)(react@19.2.0)(redux@5.0.1) '@remix-run/router@1.23.1': {} '@rolldown/pluginutils@1.0.0-beta.47': {} - '@rollup/rollup-android-arm-eabi@4.53.2': + '@rollup/rollup-android-arm-eabi@4.53.3': optional: true - '@rollup/rollup-android-arm64@4.53.2': + '@rollup/rollup-android-arm64@4.53.3': optional: true - '@rollup/rollup-darwin-arm64@4.53.2': + '@rollup/rollup-darwin-arm64@4.53.3': optional: true - '@rollup/rollup-darwin-x64@4.53.2': + '@rollup/rollup-darwin-x64@4.53.3': optional: true - '@rollup/rollup-freebsd-arm64@4.53.2': + '@rollup/rollup-freebsd-arm64@4.53.3': optional: true - '@rollup/rollup-freebsd-x64@4.53.2': + '@rollup/rollup-freebsd-x64@4.53.3': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.53.2': + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.53.2': + '@rollup/rollup-linux-arm-musleabihf@4.53.3': optional: true - '@rollup/rollup-linux-arm64-gnu@4.53.2': + '@rollup/rollup-linux-arm64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-arm64-musl@4.53.2': + '@rollup/rollup-linux-arm64-musl@4.53.3': optional: true - '@rollup/rollup-linux-loong64-gnu@4.53.2': + '@rollup/rollup-linux-loong64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.53.2': + '@rollup/rollup-linux-ppc64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.53.2': + '@rollup/rollup-linux-riscv64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-riscv64-musl@4.53.2': + '@rollup/rollup-linux-riscv64-musl@4.53.3': optional: true - '@rollup/rollup-linux-s390x-gnu@4.53.2': + '@rollup/rollup-linux-s390x-gnu@4.53.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.53.2': + '@rollup/rollup-linux-x64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-x64-musl@4.53.2': + '@rollup/rollup-linux-x64-musl@4.53.3': optional: true - '@rollup/rollup-openharmony-arm64@4.53.2': + '@rollup/rollup-openharmony-arm64@4.53.3': optional: true - '@rollup/rollup-win32-arm64-msvc@4.53.2': + '@rollup/rollup-win32-arm64-msvc@4.53.3': optional: true - '@rollup/rollup-win32-ia32-msvc@4.53.2': + '@rollup/rollup-win32-ia32-msvc@4.53.3': optional: true - '@rollup/rollup-win32-x64-gnu@4.53.2': + '@rollup/rollup-win32-x64-gnu@4.53.3': optional: true - '@rollup/rollup-win32-x64-msvc@4.53.2': + '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true '@shikijs/engine-oniguruma@3.15.0': @@ -3955,13 +3955,13 @@ snapshots: '@types/parse-json@4.0.2': {} - '@types/react-dom@19.2.3(@types/react@19.2.5)': + '@types/react-dom@19.2.3(@types/react@19.2.6)': dependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 - '@types/react@19.2.5': + '@types/react@19.2.6': dependencies: - csstype: 3.2.2 + csstype: 3.2.3 '@types/unist@2.0.11': {} @@ -4030,7 +4030,7 @@ snapshots: autoprefixer@10.4.22(postcss@8.5.6): dependencies: browserslist: 4.28.0 - caniuse-lite: 1.0.30001755 + caniuse-lite: 1.0.30001756 fraction.js: 5.3.4 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -4051,7 +4051,7 @@ snapshots: balanced-match@1.0.2: {} - baseline-browser-mapping@2.8.28: {} + baseline-browser-mapping@2.8.29: {} boolbase@1.0.0: {} @@ -4071,9 +4071,9 @@ snapshots: browserslist@4.28.0: dependencies: - baseline-browser-mapping: 2.8.28 - caniuse-lite: 1.0.30001755 - electron-to-chromium: 1.5.254 + baseline-browser-mapping: 2.8.29 + caniuse-lite: 1.0.30001756 + electron-to-chromium: 1.5.256 node-releases: 2.0.27 update-browserslist-db: 1.1.4(browserslist@4.28.0) @@ -4100,7 +4100,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001755: {} + caniuse-lite@1.0.30001756: {} ccount@2.0.1: {} @@ -4212,7 +4212,7 @@ snapshots: dependencies: css-tree: 2.2.1 - csstype@3.2.2: {} + csstype@3.2.3: {} d3-array@3.2.4: dependencies: @@ -4340,7 +4340,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.254: {} + electron-to-chromium@1.5.256: {} emoji-regex@8.0.0: {} @@ -4636,7 +4636,7 @@ snapshots: domhandler: 5.0.3 htmlparser2: 10.0.0 - html-react-parser@5.2.10(@types/react@19.2.5)(react@19.2.0): + html-react-parser@5.2.10(@types/react@19.2.6)(react@19.2.0): dependencies: domhandler: 5.0.3 html-dom-parser: 5.1.2 @@ -4644,7 +4644,7 @@ snapshots: react-property: 2.0.2 style-to-js: 1.1.21 optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 html-url-attributes@3.0.1: {} @@ -4976,9 +4976,9 @@ snapshots: memorystream@0.3.1: {} - merge-refs@2.0.0(@types/react@19.2.5): + merge-refs@2.0.0(@types/react@19.2.6): optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 micromark-core-commonmark@2.0.3: dependencies: @@ -5307,7 +5307,7 @@ snapshots: react: 19.2.0 scheduler: 0.27.0 - react-hook-form@7.66.0(react@19.2.0): + react-hook-form@7.66.1(react@19.2.0): dependencies: react: 19.2.0 @@ -5324,11 +5324,11 @@ snapshots: dependencies: react: 19.2.0 - react-markdown@10.1.0(@types/react@19.2.5)(react@19.2.0): + react-markdown@10.1.0(@types/react@19.2.6)(react@19.2.0): dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - '@types/react': 19.2.5 + '@types/react': 19.2.6 devlop: 1.1.0 hast-util-to-jsx-runtime: 2.3.6 html-url-attributes: 3.0.1 @@ -5350,13 +5350,13 @@ snapshots: qr.js: 0.0.0 react: 19.2.0 - react-redux@9.2.0(@types/react@19.2.5)(react@19.2.0)(redux@5.0.1): + react-redux@9.2.0(@types/react@19.2.6)(react@19.2.0)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 react: 19.2.0 use-sync-external-store: 1.6.0(react@19.2.0) optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 redux: 5.0.1 react-refresh@0.18.0: {} @@ -5394,9 +5394,9 @@ snapshots: readdirp@4.1.2: {} - recharts@3.4.1(@types/react@19.2.5)(react-dom@19.2.0(react@19.2.0))(react-is@18.3.1)(react@19.2.0)(redux@5.0.1): + recharts@3.4.1(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react-is@18.3.1)(react@19.2.0)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.10.1(react-redux@9.2.0(@types/react@19.2.5)(react@19.2.0)(redux@5.0.1))(react@19.2.0) + '@reduxjs/toolkit': 2.10.1(react-redux@9.2.0(@types/react@19.2.6)(react@19.2.0)(redux@5.0.1))(react@19.2.0) clsx: 2.1.1 decimal.js-light: 2.5.1 es-toolkit: 1.42.0 @@ -5405,7 +5405,7 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) react-is: 18.3.1 - react-redux: 9.2.0(@types/react@19.2.5)(react@19.2.0)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.6)(react@19.2.0)(redux@5.0.1) reselect: 5.1.1 tiny-invariant: 1.3.3 use-sync-external-store: 1.6.0(react@19.2.0) @@ -5474,32 +5474,32 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - rollup@4.53.2: + rollup@4.53.3: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.53.2 - '@rollup/rollup-android-arm64': 4.53.2 - '@rollup/rollup-darwin-arm64': 4.53.2 - '@rollup/rollup-darwin-x64': 4.53.2 - '@rollup/rollup-freebsd-arm64': 4.53.2 - '@rollup/rollup-freebsd-x64': 4.53.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.53.2 - '@rollup/rollup-linux-arm-musleabihf': 4.53.2 - '@rollup/rollup-linux-arm64-gnu': 4.53.2 - '@rollup/rollup-linux-arm64-musl': 4.53.2 - '@rollup/rollup-linux-loong64-gnu': 4.53.2 - '@rollup/rollup-linux-ppc64-gnu': 4.53.2 - '@rollup/rollup-linux-riscv64-gnu': 4.53.2 - '@rollup/rollup-linux-riscv64-musl': 4.53.2 - '@rollup/rollup-linux-s390x-gnu': 4.53.2 - '@rollup/rollup-linux-x64-gnu': 4.53.2 - '@rollup/rollup-linux-x64-musl': 4.53.2 - '@rollup/rollup-openharmony-arm64': 4.53.2 - '@rollup/rollup-win32-arm64-msvc': 4.53.2 - '@rollup/rollup-win32-ia32-msvc': 4.53.2 - '@rollup/rollup-win32-x64-gnu': 4.53.2 - '@rollup/rollup-win32-x64-msvc': 4.53.2 + '@rollup/rollup-android-arm-eabi': 4.53.3 + '@rollup/rollup-android-arm64': 4.53.3 + '@rollup/rollup-darwin-arm64': 4.53.3 + '@rollup/rollup-darwin-x64': 4.53.3 + '@rollup/rollup-freebsd-arm64': 4.53.3 + '@rollup/rollup-freebsd-x64': 4.53.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.3 + '@rollup/rollup-linux-arm-musleabihf': 4.53.3 + '@rollup/rollup-linux-arm64-gnu': 4.53.3 + '@rollup/rollup-linux-arm64-musl': 4.53.3 + '@rollup/rollup-linux-loong64-gnu': 4.53.3 + '@rollup/rollup-linux-ppc64-gnu': 4.53.3 + '@rollup/rollup-linux-riscv64-gnu': 4.53.3 + '@rollup/rollup-linux-riscv64-musl': 4.53.3 + '@rollup/rollup-linux-s390x-gnu': 4.53.3 + '@rollup/rollup-linux-x64-gnu': 4.53.3 + '@rollup/rollup-linux-x64-musl': 4.53.3 + '@rollup/rollup-openharmony-arm64': 4.53.3 + '@rollup/rollup-win32-arm64-msvc': 4.53.3 + '@rollup/rollup-win32-ia32-msvc': 4.53.3 + '@rollup/rollup-win32-x64-gnu': 4.53.3 + '@rollup/rollup-win32-x64-msvc': 4.53.3 fsevents: 2.3.3 rxjs@7.8.2: @@ -5879,7 +5879,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.53.2 + rollup: 4.53.3 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 24.10.1 @@ -5962,9 +5962,9 @@ snapshots: zod@3.25.76: {} - zustand@5.0.8(@types/react@19.2.5)(immer@10.2.0)(react@19.2.0)(use-sync-external-store@1.6.0(react@19.2.0)): + zustand@5.0.8(@types/react@19.2.6)(immer@10.2.0)(react@19.2.0)(use-sync-external-store@1.6.0(react@19.2.0)): optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 immer: 10.2.0 react: 19.2.0 use-sync-external-store: 1.6.0(react@19.2.0) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 3b7af78b..a83f622d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -970,9 +970,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.52" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa8120877db0e5c011242f96806ce3c94e0737ab8108532a76a3300a01db2ab8" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" dependencies = [ "clap_builder", "clap_derive", @@ -980,9 +980,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.52" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02576b399397b659c26064fbc92a75fede9d18ffd5f80ca1cd74ddab167016e1" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" dependencies = [ "anstream", "anstyle", @@ -4109,9 +4109,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "open" -version = "5.3.2" +version = "5.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" +checksum = "43bb73a7fa3799b198970490a51174027ba0d4ec504b03cd08caf513d40024bc" dependencies = [ "dunce", "is-wsl", diff --git a/src-tauri/src/apple.rs b/src-tauri/src/apple.rs index 27c375a4..b9aa991b 100644 --- a/src-tauri/src/apple.rs +++ b/src-tauri/src/apple.rs @@ -5,9 +5,9 @@ use std::{ net::IpAddr, str::FromStr, sync::{ - atomic::{AtomicBool, Ordering}, + atomic::{AtomicBool, AtomicUsize, Ordering}, mpsc::channel, - Arc, + Arc, Mutex, }, }; @@ -15,11 +15,13 @@ use block2::RcBlock; use defguard_wireguard_rs::{host::Peer, key::Key, net::IpAddrMask}; use objc2::{rc::Retained, runtime::AnyObject}; use objc2_foundation::{ - ns_string, NSArray, NSDictionary, NSError, NSMutableArray, NSMutableDictionary, NSNumber, - NSString, + ns_string, NSArray, NSData, NSDictionary, NSError, NSMutableArray, NSMutableDictionary, + NSNumber, NSString, }; -use objc2_network_extension::{NETunnelProviderManager, NETunnelProviderProtocol}; -use serde::Serialize; +use objc2_network_extension::{ + NETunnelProviderManager, NETunnelProviderProtocol, NETunnelProviderSession, +}; +use serde::{Deserialize, Serialize}; use sqlx::SqliteExecutor; use crate::{ @@ -32,7 +34,9 @@ use crate::{ const PLUGIN_BUNDLE_ID: &str = "net.defguard.VPNExtension"; // Should match the declaration in Swift. +#[derive(Deserialize)] #[repr(C)] +#[serde(rename_all = "camelCase")] pub(crate) struct Stats { pub(crate) location_id: Option, pub(crate) tunnel_id: Option, @@ -75,7 +79,6 @@ fn manager_for_name(name: &str) -> Option> { } } if let Some(descr) = unsafe { manager.localizedDescription() } { - error!("Descripion {descr}"); if descr == name_string { tx.send(Some(manager)).unwrap(); return; @@ -94,21 +97,17 @@ fn manager_for_name(name: &str) -> Option> { } #[derive(Serialize)] +#[serde(rename_all = "camelCase")] pub(crate) struct TunnelConfiguration { - #[serde(rename = "locationId")] location_id: Option, - #[serde(rename = "tunnelId")] tunnel_id: Option, name: String, - #[serde(rename = "privateKey")] private_key: String, addresses: Vec, - #[serde(rename = "listenPort")] listen_port: Option, peers: Vec, mtu: Option, dns: Vec, - #[serde(rename = "dnsSearch")] dns_search: Vec, } @@ -307,9 +306,93 @@ pub(crate) fn stop_tunnel(name: &str) -> bool { } } -/// IMPORTANT: This is currently for testing. Assume the config has been saved. -pub(crate) fn all_tunnel_stats() -> Vec { - Vec::::new() +pub(crate) fn tunnel_stats() -> Vec { + let new_stats = Arc::new(Mutex::new(Vec::new())); + let plugin_bundle_id = NSString::from_str(PLUGIN_BUNDLE_ID); + let spinlock = Arc::new(AtomicUsize::new(1)); + + let new_stats_clone = Arc::clone(&new_stats); + let spinlock_for_response = Arc::clone(&spinlock); + let response_handler = RcBlock::new(move |data_ptr: *mut NSData| { + if let Some(data) = unsafe { data_ptr.as_ref() } { + if let Ok(stats) = serde_json::from_slice(data.to_vec().as_slice()) { + if let Ok(mut new_stats_locked) = new_stats_clone.lock() { + new_stats_locked.push(stats); + } + } else { + warn!("Failed to deserialize tunnel stats"); + } + } else { + warn!("No data"); + } + spinlock_for_response.fetch_sub(1, Ordering::Release); + }); + + let spinlock_for_handler = Arc::clone(&spinlock); + let handler = RcBlock::new( + move |managers_ptr: *mut NSArray, error_ptr: *mut NSError| { + if !error_ptr.is_null() { + error!("Failed to load tunnel provider managers."); + return; + } + + let Some(managers) = (unsafe { managers_ptr.as_ref() }) else { + error!("No managers"); + return; + }; + + for manager in managers { + let Some(vpn_protocol) = (unsafe { manager.protocolConfiguration() }) else { + continue; + }; + let Ok(tunnel_protocol) = vpn_protocol.downcast::() + else { + error!("Failed to downcast to NETunnelProviderProtocol"); + continue; + }; + // Sometimes all managers from all apps come through, so filter by bundle ID. + if let Some(bundle_id) = unsafe { tunnel_protocol.providerBundleIdentifier() } { + if bundle_id != plugin_bundle_id { + continue; + } + } + + let Ok(session) = + unsafe { manager.connection() }.downcast::() + else { + error!("Failed to downcast to NETunnelProviderSession"); + continue; + }; + + let message_data = NSData::new(); + if unsafe { + session.sendProviderMessage_returnError_responseHandler( + &message_data, + None, + Some(&response_handler), + ) + } { + spinlock_for_handler.fetch_add(1, Ordering::Release); + info!("Message sent to NETunnelProviderSession"); + } else { + error!("Failed to send to NETunnelProviderSession"); + } + } + // Final release + spinlock_for_handler.fetch_sub(1, Ordering::Release); + }, + ); + unsafe { + NETunnelProviderManager::loadAllFromPreferencesWithCompletionHandler(&handler); + } + + // Wait for all handlers to complete. + while spinlock.load(Ordering::Acquire) != 0 { + spin_loop(); + } + + let stats = new_stats.lock().unwrap().drain(..).collect(); + stats } impl Location { @@ -409,16 +492,12 @@ impl Location { } impl Tunnel { - pub(crate) async fn tunnel_configurarion<'e, E>( + pub(crate) fn tunnel_configurarion( &self, - executor: E, dns: Vec, dns_search: Vec, mtu: Option, - ) -> Result - where - E: SqliteExecutor<'e>, - { + ) -> Result { // prepare peer config debug!("Decoding tunnel {self} public key: {}.", self.server_pubkey); let peer_key = Key::from_str(&self.server_pubkey)?; diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 14e9f09c..2341c239 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -15,11 +15,6 @@ const UPDATE_URL: &str = "https://pkgs.defguard.net/api/update/check"; #[cfg(target_os = "macos")] use crate::apple::stop_tunnel; -#[cfg(not(target_os = "macos"))] -use crate::service::{ - proto::{DeleteServiceLocationsRequest, RemoveInterfaceRequest, SaveServiceLocationsRequest}, - utils::DAEMON_CLIENT, -}; use crate::{ active_connections::{find_connection, get_connection_id_by_type}, app_config::{AppConfig, AppConfigPatch}, @@ -46,13 +41,23 @@ use crate::{ proto::DeviceConfigResponse, tray::{configure_tray_icon, reload_tray_menu}, utils::{ - construct_platform_header, disconnect_interface, execute_command, - get_location_interface_details, get_tunnel_interface_details, get_tunnel_or_location_name, - handle_connection_for_location, handle_connection_for_tunnel, + construct_platform_header, disconnect_interface, get_location_interface_details, + get_tunnel_interface_details, get_tunnel_or_location_name, handle_connection_for_location, + handle_connection_for_tunnel, }, wg_config::parse_wireguard_config, CommonConnection, CommonConnectionInfo, CommonLocationStats, ConnectionType, }; +#[cfg(not(target_os = "macos"))] +use crate::{ + service::{ + proto::{ + DeleteServiceLocationsRequest, RemoveInterfaceRequest, SaveServiceLocationsRequest, + }, + utils::DAEMON_CLIENT, + }, + utils::execute_command, +}; /// Open new WireGuard connection. #[tauri::command(async)] diff --git a/src-tauri/src/database/models/tunnel.rs b/src-tauri/src/database/models/tunnel.rs index b53570d5..7522e7c7 100644 --- a/src-tauri/src/database/models/tunnel.rs +++ b/src-tauri/src/database/models/tunnel.rs @@ -1,3 +1,5 @@ +#[cfg(target_os = "macos")] +use std::net::IpAddr; use std::{fmt, time::SystemTime}; use chrono::{NaiveDateTime, Utc}; @@ -252,6 +254,28 @@ impl Tunnel { } } +impl Tunnel { + /// Split DNS settings into resolver IP addresses and search domains. + #[cfg(target_os = "macos")] + pub(crate) fn dns(&self) -> (Vec, Vec) { + let mut dns = Vec::new(); + let mut dns_search = Vec::new(); + + if let Some(dns_string) = &self.dns { + for entry in dns_string.split(',').map(str::trim) { + // Assume that every entry that can't be parsed as an IP address is a domain name. + if let Ok(ip) = entry.parse::() { + dns.push(ip); + } else { + dns_search.push(entry.into()); + } + } + } + + (dns, dns_search) + } +} + #[derive(Debug, Serialize, Deserialize)] pub struct TunnelStats { id: I, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 83ac4ee2..e7025f85 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -115,6 +115,7 @@ pub struct CommonLocationStats { pub persistent_keepalive_interval: Option, pub connection_type: ConnectionType, } + // Common fields for ConnectionInfo and TunnelConnectionInfo due to shared command #[derive(Debug, Serialize)] pub struct CommonConnectionInfo { diff --git a/src-tauri/src/periodic/mod.rs b/src-tauri/src/periodic/mod.rs index ebbd46ef..37daff37 100644 --- a/src-tauri/src/periodic/mod.rs +++ b/src-tauri/src/periodic/mod.rs @@ -22,7 +22,7 @@ pub async fn run_periodic_tasks(app_handle: &AppHandle) { () = poll_config(app_handle.clone()) => { error!("Config polling task has stopped unexpectedly"); } - () = verify_active_connections(app_handle.clone()), if cfg!(not(target_os = "macos")) => { + () = verify_active_connections(app_handle.clone()) => { error!("Active connection verification task has stopped unexpectedly"); } () = purge_stats() => { diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs index 800b586b..ab9e8b41 100644 --- a/src-tauri/src/utils.rs +++ b/src-tauri/src/utils.rs @@ -1,6 +1,9 @@ -#[cfg(target_os = "macos")] -use std::time::Duration; use std::{env, path::Path, process::Command, str::FromStr}; +#[cfg(target_os = "macos")] +use std::{ + sync::{Arc, Mutex}, + time::Duration, +}; use base64::{prelude::BASE64_STANDARD, Engine}; use common::{find_free_tcp_port, get_interface_name}; @@ -22,7 +25,7 @@ use windows_sys::Win32::Foundation::ERROR_SERVICE_DOES_NOT_EXIST; #[cfg(windows)] use crate::active_connections::find_connection; #[cfg(target_os = "macos")] -use crate::apple::{all_tunnel_stats, start_tunnel, stop_tunnel}; +use crate::apple::{start_tunnel, stop_tunnel, tunnel_stats}; #[cfg(not(target_os = "macos"))] use crate::service::{ proto::{CreateInterfaceRequest, ReadInterfaceDataRequest, RemoveInterfaceRequest}, @@ -128,6 +131,7 @@ pub(crate) async fn setup_interface( pool: &DbPool, ) -> Result { debug!("Setting up interface for location: {location}"); + // FIXME: not really useful nor true. let interface_name = get_interface_name(name); let (dns, dns_search) = location.dns(); @@ -148,40 +152,40 @@ pub(crate) async fn stats_handler( _interface_name: String, _connection_type: ConnectionType, ) { - const CHECK_INTERVAL: Duration = Duration::from_secs(5); + use crate::database::models::{location_stats::LocationStats, tunnel::TunnelStats}; + + const CHECK_INTERVAL: Duration = Duration::from_secs(10); let mut interval = tokio::time::interval(CHECK_INTERVAL); loop { - info!("Stats loop"); interval.tick().await; - let all_stats = all_tunnel_stats(); + let mut all_stats = tunnel_stats(); if all_stats.is_empty() { continue; } - // Let `all_stats` be `Send`. - let all_stats = all_stats.as_slice().to_owned(); - - // let mut transaction = match pool.begin().await { - // Ok(transactions) => transactions, - // Err(err) => { - // error!( - // "Failed to begin database transaction for saving location/tunnel stats: {err}", - // ); - // continue; - // } - // }; - - for stats in all_stats { - info!( - "==> Stats: {} {} {}", - stats.last_handshake, stats.tx_bytes, stats.rx_bytes - ); + let mut transaction = match pool.begin().await { + Ok(transactions) => transactions, + Err(err) => { + error!( + "Failed to begin database transaction for saving location/tunnel stats: {err}", + ); + continue; + } + }; + + for stats in all_stats.drain(..) { if let Some(location_id) = stats.location_id { - //let location_stats = LocationStats { - //}; - /*match location_stats.save(&mut *transaction).await { + let location_stats = LocationStats::new( + location_id, + stats.tx_bytes as i64, + stats.rx_bytes as i64, + stats.last_handshake as i64, + 0, + None, + ); + match location_stats.save(&mut *transaction).await { Ok(_) => { debug!("Saved network usage stats for location ID {location_id}"); } @@ -191,12 +195,19 @@ pub(crate) async fn stats_handler( {err}" ); } - }*/ + } } if let Some(tunnel_id) = stats.tunnel_id { - //let tunnel_stats = TunnelStats { - //}; - /*match tunnel_stats.save(&mut *transaction).await { + let tunnel_stats = TunnelStats::new( + tunnel_id, + stats.tx_bytes as i64, + stats.rx_bytes as i64, + stats.last_handshake as i64, + chrono::Utc::now().naive_utc(), + 0, + 0, + ); + match tunnel_stats.save(&mut *transaction).await { Ok(_) => { debug!("Saved network usage stats for tunnel ID {tunnel_id}"); } @@ -206,13 +217,13 @@ pub(crate) async fn stats_handler( {err}" ); } - }*/ + } } } - // if let Err(err) = transaction.commit().await { - // error!("Failed to commit database transaction for saving location/tunnel stats: {err}"); - // } + if let Err(err) = transaction.commit().await { + error!("Failed to commit database transaction for saving location/tunnel stats: {err}"); + } } } @@ -368,6 +379,7 @@ pub fn get_service_log_dir() -> &'static Path { } /// Setup client interface +#[cfg(not(target_os = "macos"))] pub async fn setup_interface_tunnel( tunnel: &Tunnel, name: &str, @@ -465,65 +477,82 @@ pub async fn setup_interface_tunnel( mtu, }; - #[cfg(not(target_os = "macos"))] - { - debug!("Creating interface {interface_config:?}"); - let request = CreateInterfaceRequest { - config: Some(interface_config.clone().into()), - dns: tunnel.dns.clone(), - }; - if let Some(pre_up) = &tunnel.pre_up { - debug!( - "Executing defined PreUp command before setting up the interface {} for the \ + debug!("Creating interface {interface_config:?}"); + let request = CreateInterfaceRequest { + config: Some(interface_config.clone().into()), + dns: tunnel.dns.clone(), + }; + if let Some(pre_up) = &tunnel.pre_up { + debug!( + "Executing defined PreUp command before setting up the interface {} for the \ tunnel {tunnel}: {pre_up}", - interface_config.name - ); - let _ = execute_command(pre_up); - info!( - "Executed defined PreUp command before setting up the interface {} for the \ + interface_config.name + ); + let _ = execute_command(pre_up); + info!( + "Executed defined PreUp command before setting up the interface {} for the \ tunnel {tunnel}: {pre_up}", - interface_config.name - ); - } - if let Err(error) = DAEMON_CLIENT.clone().create_interface(request).await { - error!( - "Failed to create a network interface ({}) for tunnel {tunnel}: {error}", - interface_config.name - ); - return Err(Error::InternalError(format!( + interface_config.name + ); + } + if let Err(error) = DAEMON_CLIENT.clone().create_interface(request).await { + error!( + "Failed to create a network interface ({}) for tunnel {tunnel}: {error}", + interface_config.name + ); + return Err(Error::InternalError(format!( "Failed to create a network interface ({}) for tunnel {tunnel}, error message: {}. \ Check logs for more details.", interface_config.name, error.message() ))); - } else { - info!( - "Network interface {} for tunnel {tunnel} created successfully.", + } else { + info!( + "Network interface {} for tunnel {tunnel} created successfully.", + interface_config.name + ); + if let Some(post_up) = &tunnel.post_up { + debug!( + "Executing defined PostUp command after setting up the interface {} for the \ + tunnel {tunnel}: {post_up}", interface_config.name ); - if let Some(post_up) = &tunnel.post_up { - debug!( - "Executing defined PostUp command after setting up the interface {} for the \ - tunnel {tunnel}: {post_up}", - interface_config.name - ); - let _ = execute_command(post_up); - info!( - "Executed defined PostUp command after setting up the interface {} for the \ + let _ = execute_command(post_up); + info!( + "Executed defined PostUp command after setting up the interface {} for the \ tunnel {tunnel}: {post_up}", - interface_config.name - ); - } - debug!( - "Created interface {} with config: {interface_config:?}", interface_config.name ); } + debug!( + "Created interface {} with config: {interface_config:?}", + interface_config.name + ); } Ok(interface_name) } +#[cfg(target_os = "macos")] +pub async fn setup_interface_tunnel( + tunnel: &Tunnel, + name: &str, + mtu: Option, +) -> Result { + debug!("Setting up interface for tunnel: {tunnel}"); + // FIXME: not really useful nor true. + let interface_name = get_interface_name(name); + + let (dns, dns_search) = tunnel.dns(); + let tunnel_config = tunnel.tunnel_configurarion(dns, dns_search, mtu)?; + + tunnel_config.save(); + tokio::time::sleep(TUNNEL_START_DELAY).await; + start_tunnel(&tunnel.name); + + Ok(interface_name) +} + pub async fn get_tunnel_interface_details( tunnel_id: Id, pool: &DbPool, diff --git a/swift/plugin/Sources/Defguard/TunnelConfiguration.swift b/swift/plugin/Sources/Defguard/TunnelConfiguration.swift index ded41f36..19251c79 100644 --- a/swift/plugin/Sources/Defguard/TunnelConfiguration.swift +++ b/swift/plugin/Sources/Defguard/TunnelConfiguration.swift @@ -29,6 +29,8 @@ final class TunnelConfiguration: Codable { /// Only encode these properties. enum CodingKeys: String, CodingKey { + case locationId + case tunnelId case name case privateKey case addresses