diff --git a/packages/cli/package-lock.json b/packages/cli/package-lock.json index 8b08714..21ce63c 100644 --- a/packages/cli/package-lock.json +++ b/packages/cli/package-lock.json @@ -29,9 +29,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "engines": { @@ -39,9 +39,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { @@ -49,13 +49,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", - "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.29.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -65,14 +65,14 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -89,21 +89,21 @@ } }, "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.2.1", + "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", "dev": true, "license": "MIT", "optional": true, @@ -112,9 +112,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", "dev": true, "license": "MIT", "optional": true, @@ -166,45 +166,6 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/config-array/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@eslint/config-helpers": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz", @@ -350,14 +311,14 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz", - "integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@tybys/wasm-util": "^0.10.2" + "@tybys/wasm-util": "^0.10.3" }, "funding": { "type": "github", @@ -407,9 +368,9 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.133.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", - "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "version": "0.137.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.137.0.tgz", + "integrity": "sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==", "dev": true, "license": "MIT", "funding": { @@ -417,9 +378,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", - "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.3.tgz", + "integrity": "sha512-DT6Z3PhvioeHMvxo+xHc3KtqggrI7CCTXCmC2h/5zUlp5jVitv7XEy+9q5/7v8IolhlioawpMo8Kg0EEBy7J0g==", "cpu": [ "arm64" ], @@ -434,9 +395,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz", - "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.3.tgz", + "integrity": "sha512-0NwgwsjM7LrsuVnXMK3koTpagBNOhloc/BNjKqZjv4V5zI5r13qx69uVhRx+o5Z0yy4Hzq+lpy7TAgUG/ocvrw==", "cpu": [ "arm64" ], @@ -451,9 +412,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", - "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.3.tgz", + "integrity": "sha512-YtiBp4disu6V560loT6PjMdiRaWmVvDNrUunAalbiFx2ggeJwxdAsgZMcoGP17uyAsTwAj5V1niksxlHnVQ1Sw==", "cpu": [ "x64" ], @@ -468,9 +429,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", - "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.3.tgz", + "integrity": "sha512-yD3EkEdXk2LypPxnf/kSZHirarsI8gcPzc62SukhR9VJTyvV+F9Q/GxWNuCojc7sXyuVC4DxRGhdDK4X8VSsbw==", "cpu": [ "x64" ], @@ -485,9 +446,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", - "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.3.tgz", + "integrity": "sha512-c+8vieQbsD7HNAHKIA34w0GJ9FedFFuJGD+7E6vz7Q3uqAIugL5p45fhlsj4UaAsHpcmlqugBWMhA0/j7o0sIg==", "cpu": [ "arm" ], @@ -502,16 +463,13 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", - "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.3.tgz", + "integrity": "sha512-50jD0uUwLvur7Zz9LHz17kaAdTPjn5wN93hEgjvmYFRZwiR7ZJYovTd5ipyWJDAnXKvZ+wgc+/Ika6dwSF5OcA==", "cpu": [ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -522,16 +480,13 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", - "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.3.tgz", + "integrity": "sha512-BO9+oPL8K9poZJBfYPsXNtYjPE5uM3qeehT3aFcW4LITOl+iSqhp0abzjR2nWBUNjIZeKXjAEWBZ64WjNoHd6w==", "cpu": [ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -542,16 +497,13 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", - "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.3.tgz", + "integrity": "sha512-f3VpLB1vQ0Eo6ecr/6cekLnvYMFF4YBFoVGkfkvPLq1bAkbAwHYQPZKoAmG6OJyTcxxoC+AvezGx/S1obNC0Mw==", "cpu": [ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -562,16 +514,13 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", - "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.3.tgz", + "integrity": "sha512-AmurZ26Pqx/RI9N1gzEOCklkKXl927yjfXWUUS0O7Puh8ARM/Ob8qfrD3qnWksScdw6cSrW5PSHE9DyLu7+PtA==", "cpu": [ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -582,16 +531,13 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", - "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.3.tgz", + "integrity": "sha512-JJpqs8bRGITDOdbkNKnlojzBabbOHrqjSvDr0IVsZObE1lBcPjxItUEY9eWIDbxaJ3cGrXPWGfGkIxFijg/URg==", "cpu": [ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -602,16 +548,13 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", - "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.3.tgz", + "integrity": "sha512-rSJcdjPxzA/by/6/rYs+v+bXU7UjvnbUWz8MJb6kh6+knqB1dCrtHg0uu7C/4haqJvqdkYHQ5IGn+tCH9GLW/g==", "cpu": [ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -622,9 +565,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", - "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.3.tgz", + "integrity": "sha512-hQ3/PYkDJICgevvyNcVrihVeqq7k1Pp3VZ9lY+dauAYUJKO+auqApvANhvR1An9BhmqYKvW2Mu1F9u4DXSMLxQ==", "cpu": [ "arm64" ], @@ -639,9 +582,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", - "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.3.tgz", + "integrity": "sha512-Elcv/BtML9lXrV6JuKITc/grN2kYV9gjsQpW8Jfw4ioK0TOkjBjye0nnyqQNy9STNaI20lXNaQBRrD5gSgR0Yg==", "cpu": [ "wasm32" ], @@ -649,18 +592,18 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", - "@napi-rs/wasm-runtime": "^1.1.4" + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" }, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", - "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.3.tgz", + "integrity": "sha512-2DrEfhluH9yhiaFApmsjsjwrSYbNcY1oFTzYSP1a535jDbV98zCFanA/96TBUd0iDFcxGmw9QRExwGCXz3U+/g==", "cpu": [ "arm64" ], @@ -675,9 +618,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", - "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.3.tgz", + "integrity": "sha512-OL4OMk7UPXOeVGGd3qo5zJyPIljf4AFgk5QAkPPS+OoLuOOozhuaQGC18MxVTnw/06q93gShAJzlwnSCY9YtqA==", "cpu": [ "x64" ], @@ -706,9 +649,9 @@ "license": "MIT" }, "node_modules/@tybys/wasm-util": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", - "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", "dev": true, "license": "MIT", "optional": true, @@ -809,17 +752,6 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" "node_modules/@typescript-eslint/parser": { "version": "8.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.62.0.tgz", @@ -863,12 +795,16 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.0.tgz", - "integrity": "sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.62.0.tgz", + "integrity": "sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.62.0", + "eslint-visitor-keys": "^5.0.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -877,22 +813,29 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/project-service": { "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.0.tgz", - "integrity": "sha512-+hVbNxtW64pIcZWDPGbyaKF7vp2IBTVY5ma1blwwksrjdsbdqqEKvJWMGbBofei4F6Dovx1M0RJgoFeNu2279A==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.62.0.tgz", + "integrity": "sha512-wexnCqiTg7BOGtbLDftYpRWlmLq4xfoMd7BKFR6Y75sZS3QmRKLdN3yWLhmIYgqMmP/OXWpj3H8odkb5nGURCQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.62.0", - "@typescript-eslint/tsconfig-utils": "8.62.0", - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/visitor-keys": "8.62.0", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" + "@typescript-eslint/tsconfig-utils": "^8.62.0", + "@typescript-eslint/types": "^8.62.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -905,112 +848,160 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.62.0.tgz", - "integrity": "sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.62.0", - "eslint-visitor-keys": "^5.0.0" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", "dev": true, "license": "MIT", "engines": { - "node": "18 || 20 || >=22" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.0.tgz", + "integrity": "sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^4.0.2" + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "18 || 20 || >=22" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "BSD-2-Clause", "dependencies": { - "brace-expansion": "^5.0.5" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "18 || 20 || >=22" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/parser/node_modules/ts-api-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", - "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "node_modules/@typescript-eslint/type-utils/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.62.0.tgz", - "integrity": "sha512-wexnCqiTg7BOGtbLDftYpRWlmLq4xfoMd7BKFR6Y75sZS3QmRKLdN3yWLhmIYgqMmP/OXWpj3H8odkb5nGURCQ==", + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.62.0", - "@typescript-eslint/types": "^8.62.0", - "debug": "^4.4.3" + "brace-expansion": "^2.0.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/project-service/node_modules/@typescript-eslint/types": { + "node_modules/@typescript-eslint/types": { "version": "8.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.0.tgz", "integrity": "sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==", @@ -1024,84 +1015,89 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.0.tgz", + "integrity": "sha512-+hVbNxtW64pIcZWDPGbyaKF7vp2IBTVY5ma1blwwksrjdsbdqqEKvJWMGbBofei4F6Dovx1M0RJgoFeNu2279A==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" + "@typescript-eslint/project-service": "8.62.0", + "@typescript-eslint/tsconfig-utils": "8.62.0", + "@typescript-eslint/types": "8.62.0", + "@typescript-eslint/visitor-keys": "8.62.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys": { "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.0.tgz", - "integrity": "sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.62.0.tgz", + "integrity": "sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.62.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4" - }, + "license": "MIT", "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=18.12" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "typescript": ">=4.8.4" } }, - "node_modules/@typescript-eslint/scope-manager": { + "node_modules/@typescript-eslint/utils": { "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", "dev": true, "license": "MIT", "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" + "@typescript-eslint/typescript-estree": "7.18.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1109,9 +1105,12 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" } }, - "node_modules/@typescript-eslint/types": { + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", @@ -1125,7 +1124,7 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/typescript-estree": { + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", @@ -1154,6 +1153,39 @@ } } }, + "node_modules/@typescript-eslint/utils/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/visitor-keys": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", @@ -1172,6 +1204,20 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@vitest/coverage-v8": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.9.tgz", @@ -1386,9 +1432,9 @@ } }, "node_modules/ast-v8-to-istanbul": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz", - "integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.4.tgz", + "integrity": "sha512-0bC0/4bTSrnwdhU3IsZDwEdojvuPrSg59OYZfKsLRtJZ0u8VBx9DebfqqG8bRdCC0I7vjgxmPi41P0lpkhJHtA==", "dev": true, "license": "MIT", "dependencies": { @@ -1398,20 +1444,26 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, "node_modules/brace-expansion": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", - "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { @@ -1535,9 +1587,9 @@ "license": "MIT" }, "node_modules/es-module-lexer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", - "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.2.0.tgz", + "integrity": "sha512-3lGxdTXCLfe1MYfTz1y2ksAAUM4NAOP6rPEjxGJVKO7TZ5+tvHCaQWGpC4Y3IXvW3ece0Cz1cIP4FWBxOnGCTQ==", "dev": true, "license": "MIT" }, @@ -1645,29 +1697,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", @@ -1681,22 +1710,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/espree": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", @@ -1785,9 +1798,9 @@ } }, "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1855,6 +1868,24 @@ "reusify": "^1.0.4" } }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -2295,9 +2326,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -2319,9 +2347,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -2343,9 +2368,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -2367,9 +2389,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -2503,17 +2522,30 @@ "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.2" + "brace-expansion": "^5.0.5" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2553,15 +2585,18 @@ "license": "MIT" }, "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz", + "integrity": "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } }, "node_modules/optionator": { "version": "0.9.4", @@ -2658,22 +2693,22 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", + "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", "dev": true, "funding": [ { @@ -2752,13 +2787,13 @@ } }, "node_modules/rolldown": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", - "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.3.tgz", + "integrity": "sha512-1F1eEtUBtFvcGm1HQ9TiUIUHPQG7mSAODrhIzjxoUEFuo8OcbrGLiVLkevNgj84TE4lnHvnumwFjhJO5Eu135g==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.133.0", + "@oxc-project/types": "=0.137.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -2768,21 +2803,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.3", - "@rolldown/binding-darwin-arm64": "1.0.3", - "@rolldown/binding-darwin-x64": "1.0.3", - "@rolldown/binding-freebsd-x64": "1.0.3", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", - "@rolldown/binding-linux-arm64-gnu": "1.0.3", - "@rolldown/binding-linux-arm64-musl": "1.0.3", - "@rolldown/binding-linux-ppc64-gnu": "1.0.3", - "@rolldown/binding-linux-s390x-gnu": "1.0.3", - "@rolldown/binding-linux-x64-gnu": "1.0.3", - "@rolldown/binding-linux-x64-musl": "1.0.3", - "@rolldown/binding-openharmony-arm64": "1.0.3", - "@rolldown/binding-wasm32-wasi": "1.0.3", - "@rolldown/binding-win32-arm64-msvc": "1.0.3", - "@rolldown/binding-win32-x64-msvc": "1.0.3" + "@rolldown/binding-android-arm64": "1.1.3", + "@rolldown/binding-darwin-arm64": "1.1.3", + "@rolldown/binding-darwin-x64": "1.1.3", + "@rolldown/binding-freebsd-x64": "1.1.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.1.3", + "@rolldown/binding-linux-arm64-gnu": "1.1.3", + "@rolldown/binding-linux-arm64-musl": "1.1.3", + "@rolldown/binding-linux-ppc64-gnu": "1.1.3", + "@rolldown/binding-linux-s390x-gnu": "1.1.3", + "@rolldown/binding-linux-x64-gnu": "1.1.3", + "@rolldown/binding-linux-x64-musl": "1.1.3", + "@rolldown/binding-openharmony-arm64": "1.1.3", + "@rolldown/binding-wasm32-wasi": "1.1.3", + "@rolldown/binding-win32-arm64-msvc": "1.1.3", + "@rolldown/binding-win32-x64-msvc": "1.1.3" } }, "node_modules/run-parallel": { @@ -2810,9 +2845,9 @@ } }, "node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { @@ -2933,9 +2968,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", - "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, "license": "MIT", "engines": { @@ -2959,37 +2994,6 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/tinyrainbow": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", @@ -3079,16 +3083,16 @@ } }, "node_modules/vite": { - "version": "8.0.16", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", - "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.0.tgz", + "integrity": "sha512-BuJcQK/56NQTWDGn4ABea3q4SSBdNPWwNZKTkkUpcMPnLoquSYH8llRtSUIgoL1KSCpHt5eghLShn50mH36y7Q==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.15", - "rolldown": "1.0.3", + "rolldown": "~1.1.2", "tinyglobby": "^0.2.17" }, "bin": { @@ -3105,7 +3109,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.1.18", + "@vitejs/devtools": "^0.3.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -3156,19 +3160,6 @@ } } }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/vitest": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.9.tgz", @@ -3259,19 +3250,6 @@ } } }, - "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/packages/cli/src/formatters/text.ts b/packages/cli/src/formatters/text.ts new file mode 100644 index 0000000..a157662 --- /dev/null +++ b/packages/cli/src/formatters/text.ts @@ -0,0 +1,48 @@ +/** + * Generic text formatter for arbitrary record objects. + * Used by tests/formatters/text.test.ts and any caller that needs + * a plain key=value representation of a transaction or account record. + */ + +type RecordValue = string | number | boolean | null | undefined; + +function truncate(value: string, max = 56): string { + if (value.length <= max) return value; + return `${value.slice(0, 8)}…${value.slice(-8)}`; +} + +function renderValue(value: RecordValue): string { + if (value === null || value === undefined) return "(none)"; + const str = String(value); + // Truncate long strings that look like Stellar addresses + if (typeof value === "string" && value.length > 56) { + return truncate(str); + } + return str; +} + +/** + * Render a data record as a simple multiline key: value text block. + * + * @param data - Flat record (unknown extra keys are ignored if not string/number/boolean). + * @param _kind - Hint about the record type ("transaction" | "account" | string). Reserved + * for future per-type formatting. + */ +export function formatText( + data: Record, + _kind: string, +): string { + const lines: string[] = []; + for (const [key, value] of Object.entries(data)) { + if ( + value === null || + value === undefined || + typeof value === "string" || + typeof value === "number" || + typeof value === "boolean" + ) { + lines.push(`${key}: ${renderValue(value as RecordValue)}`); + } + } + return lines.join("\n"); +} diff --git a/packages/cli/src/utils/detect.ts b/packages/cli/src/utils/detect.ts new file mode 100644 index 0000000..a79aeed --- /dev/null +++ b/packages/cli/src/utils/detect.ts @@ -0,0 +1,34 @@ +/** + * Detect the type of a raw user-provided input string. + * + * Returns one of: + * "transaction" – 64-character lowercase/uppercase hex string + * "account" – Stellar public key starting with G (56 chars, base-32) + * "federation" – federation address in the form "name*domain.tld" + * "unknown" – does not match any known pattern + */ +export type DetectedInputType = + | "transaction" + | "account" + | "federation" + | "unknown"; + +/** 64-char hex: a valid Stellar transaction hash */ +const TX_HASH_RE = /^[0-9a-fA-F]{64}$/; + +/** Stellar public key: starts with G, 56 total chars, base-32 alphabet */ +const STELLAR_ADDRESS_RE = /^G[A-Z2-7]{55}$/; + +/** Federation address: "name*domain.tld" – asterisk-separated, no spaces */ +const FEDERATION_RE = /^[^*\s]+\*[^*\s]+\.[^*\s]+$/; + +/** + * Detect the type of a raw user-provided input string. + */ +export function detectInputType(input: string): DetectedInputType { + if (!input) return "unknown"; + if (TX_HASH_RE.test(input)) return "transaction"; + if (STELLAR_ADDRESS_RE.test(input)) return "account"; + if (FEDERATION_RE.test(input)) return "federation"; + return "unknown"; +} diff --git a/packages/cli/tests/commands/batch.test.ts b/packages/cli/tests/commands/batch.test.ts new file mode 100644 index 0000000..4720bf9 --- /dev/null +++ b/packages/cli/tests/commands/batch.test.ts @@ -0,0 +1,261 @@ +/** + * Tests for the batch command (issue #578). + * + * Covers: + * - reading hashes from a file + * - dry-run mode (validates & lists without calling API) + * - invalid/missing file path + * - empty or comment-only files + * - writing results to an output file + * - human-readable stdout output + */ +import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; +import * as fs from "fs"; +import * as path from "path"; +import * as os from "os"; +import { Command } from "commander"; + +// ─── Helpers ────────────────────────────────────────────────────────────────── + +/** A valid 64-char hex transaction hash. */ +function makeHash(n: number): string { + return n.toString(16).padStart(64, "0"); +} + +// ─── Temp dir for isolation ──────────────────────────────────────────────────── +const TEMP_DIR = path.join(os.tmpdir(), `se-batch-test-${process.pid}`); + +function tmpFile(name: string): string { + return path.join(TEMP_DIR, name); +} + +// ─── Mock the API client so no real network calls are made ──────────────────── +vi.mock("../../src/lib/client.js", () => ({ + createClient: () => ({ + getTransaction: async (hash: string) => ({ + hash, + summary: `Summary for ${hash}`, + status: "success", + ledger: 50000000, + created_at: "2024-01-01T00:00:00Z", + fee_charged: "100", + memo: null, + payments: [], + skipped_operations: 0, + }), + }), +})); + +// ─── Setup/teardown ─────────────────────────────────────────────────────────── + +beforeEach(() => { + fs.mkdirSync(TEMP_DIR, { recursive: true }); +}); + +afterEach(() => { + fs.rmSync(TEMP_DIR, { recursive: true, force: true }); +}); + +// ─── Shared program builder ─────────────────────────────────────────────────── + +import { registerBatch } from "../../src/commands/batch.js"; + +function makeProgram(): Command { + const program = new Command(); + program.exitOverride(); + program + .option("--url ", "API base URL", "https://stellar-explain-core.onrender.com") + .option("--timeout ", "timeout", (v) => parseInt(v, 10), 10000) + .option("--retries ", "retries", (v) => parseInt(v, 10), 0) + .option("--verbose", "verbose", false) + .option("--json", "json output", false); + registerBatch(program); + return program; +} + +/** Run a program command and capture stdout writes. */ +async function captureStdout( + fn: () => void | Promise, +): Promise { + const chunks: string[] = []; + const spy = vi + .spyOn(process.stdout, "write") + .mockImplementation((chunk: string | Uint8Array) => { + chunks.push(typeof chunk === "string" ? chunk : chunk.toString()); + return true; + }); + const logSpy = vi.spyOn(console, "log").mockImplementation((...args: unknown[]) => { + chunks.push(args.map(String).join(" ") + "\n"); + }); + try { + await fn(); + } finally { + spy.mockRestore(); + logSpy.mockRestore(); + } + return chunks.join(""); +} + +// ─── Tests ──────────────────────────────────────────────────────────────────── + +describe("batch command", () => { + // ── File reading ─────────────────────────────────────────────────────────── + + describe("file reading", () => { + it("reads hashes from a newline-separated file (dry-run)", async () => { + const hash1 = makeHash(1); + const hash2 = makeHash(2); + const hashFile = tmpFile("hashes.txt"); + fs.writeFileSync(hashFile, `${hash1}\n${hash2}\n`, "utf8"); + + const program = makeProgram(); + const out = await captureStdout(() => + program.parseAsync(["batch", hashFile, "--dry-run"], { from: "user" }), + ); + + expect(out).toContain(hash1); + expect(out).toContain(hash2); + }); + + it("ignores comment lines starting with #", async () => { + const hash = makeHash(42); + const hashFile = tmpFile("hashes.txt"); + fs.writeFileSync( + hashFile, + `# this is a comment\n${hash}\n# another comment\n`, + "utf8", + ); + + const program = makeProgram(); + const out = await captureStdout(() => + program.parseAsync(["batch", hashFile, "--dry-run"], { from: "user" }), + ); + + expect(out).toContain(hash); + expect(out).not.toContain("# this is a comment"); + }); + + it("ignores blank lines", async () => { + const hash = makeHash(7); + const hashFile = tmpFile("hashes.txt"); + fs.writeFileSync(hashFile, `\n${hash}\n\n`, "utf8"); + + const program = makeProgram(); + const out = await captureStdout(() => + program.parseAsync(["batch", hashFile, "--dry-run"], { from: "user" }), + ); + + expect(out).toContain(hash); + }); + }); + + // ── --dry-run mode ───────────────────────────────────────────────────────── + + describe("--dry-run mode", () => { + it("reports how many hashes would be processed", async () => { + const hashFile = tmpFile("hashes.txt"); + fs.writeFileSync( + hashFile, + [makeHash(1), makeHash(2), makeHash(3)].join("\n"), + "utf8", + ); + + const program = makeProgram(); + const out = await captureStdout(() => + program.parseAsync(["batch", hashFile, "--dry-run"], { from: "user" }), + ); + + expect(out).toContain("3"); + }); + + it("lists each hash on its own line", async () => { + const hashes = [makeHash(10), makeHash(11)]; + const hashFile = tmpFile("hashes.txt"); + fs.writeFileSync(hashFile, hashes.join("\n"), "utf8"); + + const program = makeProgram(); + const out = await captureStdout(() => + program.parseAsync(["batch", hashFile, "--dry-run"], { from: "user" }), + ); + + for (const h of hashes) { + expect(out).toContain(h); + } + }); + }); + + // ── Error: missing file ──────────────────────────────────────────────────── + + describe("error handling", () => { + it("throws when the input file does not exist", async () => { + const program = makeProgram(); + await expect( + program.parseAsync(["batch", tmpFile("missing.txt")], { from: "user" }), + ).rejects.toThrow(/file not found/i); + }); + + it("throws when the file contains no valid hashes", async () => { + const emptyFile = tmpFile("empty.txt"); + fs.writeFileSync(emptyFile, "# only comments\n\n", "utf8"); + + const program = makeProgram(); + await expect( + program.parseAsync(["batch", emptyFile], { from: "user" }), + ).rejects.toThrow(/no hashes found/i); + }); + + it("throws for an invalid transaction hash", async () => { + const badFile = tmpFile("bad.txt"); + fs.writeFileSync(badFile, "not-a-valid-hash\n", "utf8"); + + const program = makeProgram(); + await expect( + program.parseAsync(["batch", badFile], { from: "user" }), + ).rejects.toThrow(); + }); + }); + + // ── --output file ────────────────────────────────────────────────────────── + + describe("--output flag", () => { + it("writes JSON results to the output file", async () => { + const hash = makeHash(99); + const hashFile = tmpFile("in.txt"); + const outFile = tmpFile("out.json"); + fs.writeFileSync(hashFile, hash, "utf8"); + + const program = makeProgram(); + await program.parseAsync( + ["batch", hashFile, "--output", outFile], + { from: "user" }, + ); + + expect(fs.existsSync(outFile)).toBe(true); + const parsed = JSON.parse(fs.readFileSync(outFile, "utf8")) as Array<{ + hash: string; + status: string; + }>; + expect(parsed).toHaveLength(1); + expect(parsed[0]!.hash).toBe(hash); + expect(parsed[0]!.status).toBe("ok"); + }); + }); + + // ── Successful execution (human-readable) ────────────────────────────────── + + describe("successful execution", () => { + it("outputs a result for each hash", async () => { + const hashes = [makeHash(101), makeHash(102)]; + const hashFile = tmpFile("two.txt"); + fs.writeFileSync(hashFile, hashes.join("\n"), "utf8"); + + const program = makeProgram(); + const out = await captureStdout(() => + program.parseAsync(["batch", hashFile], { from: "user" }), + ); + + expect(out).toContain(hashes[0]); + expect(out).toContain(hashes[1]); + }); + }); +}); diff --git a/packages/cli/tests/commands/history.test.ts b/packages/cli/tests/commands/history.test.ts new file mode 100644 index 0000000..3fec874 --- /dev/null +++ b/packages/cli/tests/commands/history.test.ts @@ -0,0 +1,297 @@ +/** + * Tests for the history command (issue #577). + * + * Covers: + * - listing entries + * - filtering by kind (--kind tx | account) + * - applying --limit + * - empty history output + * - `history clear` subcommand + */ +import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; +import * as fs from "fs"; +import * as path from "path"; +import * as os from "os"; +import { Command } from "commander"; + +// ─── Temp dir for isolation ──────────────────────────────────────────────────── +const TEMP_HOME = path.join( + os.tmpdir(), + `se-history-cmd-test-${process.pid}`, +); +const HISTORY_FILE = path.join(TEMP_HOME, "history.json"); + +// ─── Mock history lib to use temp dir ───────────────────────────────────────── +vi.mock("../../src/lib/history.js", () => { + const fs = require("fs") as typeof import("fs"); + const path = require("path") as typeof import("path"); + const os = require("os") as typeof import("os"); + + const TEMP = path.join( + os.tmpdir(), + `se-history-cmd-test-${process.pid}`, + ); + const FILE = path.join(TEMP, "history.json"); + + type LookupKind = "tx" | "account"; + interface HistoryEntry { + kind: LookupKind; + query: string; + timestamp: string; + } + + function ensureDir() { + if (!fs.existsSync(TEMP)) fs.mkdirSync(TEMP, { recursive: true }); + } + + function readHistory(): HistoryEntry[] { + ensureDir(); + if (!fs.existsSync(FILE)) return []; + try { + return JSON.parse(fs.readFileSync(FILE, "utf8")) as HistoryEntry[]; + } catch { + return []; + } + } + + function addEntry(kind: LookupKind, query: string): void { + ensureDir(); + const entries = readHistory(); + entries.push({ kind, query, timestamp: new Date().toISOString() }); + fs.writeFileSync(FILE, JSON.stringify(entries, null, 2), "utf8"); + } + + function clearHistory(): void { + if (fs.existsSync(FILE)) fs.rmSync(FILE); + } + + function historyFilePath(): string { + return FILE; + } + + return { readHistory, addEntry, clearHistory, historyFilePath }; +}); + +import { registerHistoryCommand } from "../../src/commands/history.js"; +import { + addEntry, + clearHistory, + readHistory, +} from "../../src/lib/history.js"; + +// ─── Helpers ────────────────────────────────────────────────────────────────── + +function makeProgram() { + const program = new Command(); + program.exitOverride(); // prevent process.exit in tests + registerHistoryCommand(program); + return program; +} + +/** Capture console.log output while running a callback. */ +async function captureLog(fn: () => void | Promise): Promise { + const lines: string[] = []; + const spy = vi.spyOn(console, "log").mockImplementation((...args: unknown[]) => { + lines.push(args.map(String).join(" ")); + }); + await fn(); + spy.mockRestore(); + return lines; +} + +/** Capture console.error output while running a callback. */ +async function captureError(fn: () => void | Promise): Promise { + const lines: string[] = []; + const spy = vi.spyOn(console, "error").mockImplementation((...args: unknown[]) => { + lines.push(args.map(String).join(" ")); + }); + await fn(); + spy.mockRestore(); + return lines; +} + +// ─── Setup / teardown ───────────────────────────────────────────────────────── + +beforeEach(() => { + fs.mkdirSync(TEMP_HOME, { recursive: true }); + clearHistory(); +}); + +afterEach(() => { + clearHistory(); + fs.rmSync(TEMP_HOME, { recursive: true, force: true }); +}); + +// ─── Tests ──────────────────────────────────────────────────────────────────── + +describe("history command", () => { + // ── Empty history ────────────────────────────────────────────────────────── + + describe("empty history", () => { + it('prints "No history found." when no entries exist', async () => { + const program = makeProgram(); + const lines = await captureLog(() => { + program.parse(["history"], { from: "user" }); + }); + expect(lines.join("\n")).toContain("No history found."); + }); + }); + + // ── Listing entries ──────────────────────────────────────────────────────── + + describe("listing entries", () => { + it("shows all entries by default", async () => { + const txHash = "a".repeat(64); + const acctId = "G" + "B".repeat(55); + addEntry("tx", txHash); + addEntry("account", acctId); + + const program = makeProgram(); + const lines = await captureLog(() => { + program.parse(["history"], { from: "user" }); + }); + + const output = lines.join("\n"); + expect(output).toContain(txHash); + expect(output).toContain(acctId); + }); + + it("shows a summary line at the end", async () => { + addEntry("tx", "a".repeat(64)); + + const program = makeProgram(); + const lines = await captureLog(() => { + program.parse(["history"], { from: "user" }); + }); + + const output = lines.join("\n"); + expect(output).toMatch(/1 entr(y|ies) shown/); + }); + + it("includes the history file path in summary", async () => { + addEntry("tx", "a".repeat(64)); + + const program = makeProgram(); + const lines = await captureLog(() => { + program.parse(["history"], { from: "user" }); + }); + + const output = lines.join("\n"); + expect(output).toContain(HISTORY_FILE); + }); + }); + + // ── Filtering by kind ────────────────────────────────────────────────────── + + describe("--kind filtering", () => { + beforeEach(() => { + addEntry("tx", "a".repeat(64)); + addEntry("account", "G" + "C".repeat(55)); + addEntry("tx", "b".repeat(64)); + }); + + it("--kind tx shows only tx entries", async () => { + const program = makeProgram(); + const lines = await captureLog(() => { + program.parse(["history", "--kind", "tx"], { from: "user" }); + }); + + const output = lines.join("\n"); + expect(output).toContain("tx"); + expect(output).not.toContain("G" + "C".repeat(55)); + expect(output).toMatch(/2 entr/); + }); + + it("--kind account shows only account entries", async () => { + const program = makeProgram(); + const lines = await captureLog(() => { + program.parse(["history", "--kind", "account"], { from: "user" }); + }); + + const output = lines.join("\n"); + expect(output).toContain("G" + "C".repeat(55)); + expect(output).not.toContain("a".repeat(64)); + expect(output).toMatch(/1 entry/); + }); + + it("unknown kind exits with error", async () => { + const program = makeProgram(); + const errLines = await captureError(() => { + try { + program.parse(["history", "--kind", "invalid"], { from: "user" }); + } catch { + // process.exit is thrown as an error via exitOverride + } + }); + + expect(errLines.join("\n")).toMatch(/unknown kind/i); + }); + }); + + // ── --limit option ───────────────────────────────────────────────────────── + + describe("--limit option", () => { + beforeEach(() => { + for (let i = 1; i <= 5; i++) { + addEntry("tx", i.toString(16).padStart(64, "0")); + } + }); + + it("--limit 3 shows only the 3 most recent entries", async () => { + const program = makeProgram(); + const lines = await captureLog(() => { + program.parse(["history", "--limit", "3"], { from: "user" }); + }); + + const output = lines.join("\n"); + expect(output).toMatch(/3 entr/); + }); + + it("--limit 1 shows only the most recent entry", async () => { + const program = makeProgram(); + const lines = await captureLog(() => { + program.parse(["history", "--limit", "1"], { from: "user" }); + }); + + const output = lines.join("\n"); + expect(output).toMatch(/1 entry/); + }); + }); + + // ── history clear subcommand ─────────────────────────────────────────────── + + describe("history clear", () => { + it("removes the history file", async () => { + addEntry("tx", "a".repeat(64)); + expect(readHistory()).toHaveLength(1); + + const program = makeProgram(); + await captureLog(() => { + program.parse(["history", "clear"], { from: "user" }); + }); + + expect(readHistory()).toHaveLength(0); + expect(fs.existsSync(HISTORY_FILE)).toBe(false); + }); + + it("prints a confirmation message", async () => { + addEntry("tx", "a".repeat(64)); + + const program = makeProgram(); + const lines = await captureLog(() => { + program.parse(["history", "clear"], { from: "user" }); + }); + + expect(lines.join("\n")).toMatch(/history cleared/i); + }); + + it("is safe to call with no history file", async () => { + const program = makeProgram(); + await expect( + captureLog(() => { + program.parse(["history", "clear"], { from: "user" }); + }), + ).resolves.not.toThrow(); + }); + }); +}); diff --git a/packages/cli/tests/configFile.test.ts b/packages/cli/tests/configFile.test.ts index f3bf1aa..31cca2f 100644 --- a/packages/cli/tests/configFile.test.ts +++ b/packages/cli/tests/configFile.test.ts @@ -1 +1,63 @@ -"import { mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { afterEach, describe, expect, it, vi } from \"vitest\";\nimport { readConfigFile } from \"../src/lib/configFile.js\";\n\nafterEach(() => {\n vi.restoreAllMocks();\n});\n\ndescribe(\"readConfigFile\", () => {\n it(\"reads updateCheck from the local config file\", () => {\n const dir = mkdtempSync(join(tmpdir(), \"stellar-explain-\"));\n writeFileSync(\n join(dir, \".stellar-explain.json\"),\n JSON.stringify({ url: \"https://example.com\", timeout: 4500, updateCheck: false }),\n \"utf8\",\n );\n\n const cwdSpy = vi.spyOn(process, \"cwd\").mockReturnValue(dir);\n\n expect(readConfigFile()).toEqual({\n url: \"https://example.com\",\n timeout: 4500,\n updateCheck: false,\n });\n\n cwdSpy.mockRestore();\n rmSync(dir, { recursive: true, force: true });\n });\n\n it(\"returns empty object when no config file exists\", () => {\n const dir = mkdtempSync(join(tmpdir(), \"stellar-explain-\"));\n const cwdSpy = vi.spyOn(process, \"cwd\").mockReturnValue(dir);\n\n expect(readConfigFile()).toEqual({});\n\n cwdSpy.mockRestore();\n rmSync(dir, { recursive: true, force: true });\n });\n\n it(\"returns empty object for malformed JSON config\", () => {\n const dir = mkdtempSync(join(tmpdir(), \"stellar-explain-\"));\n writeFileSync(join(dir, \".stellar-explain.json\"), \"not valid json\", \"utf8\");\n const cwdSpy = vi.spyOn(process, \"cwd\").mockReturnValue(dir);\n\n expect(readConfigFile()).toEqual({});\n\n cwdSpy.mockRestore();\n rmSync(dir, { recursive: true, force: true });\n });\n\n it(\"returns empty object for empty config file\", () => {\n const dir = mkdtempSync(join(tmpdir(), \"stellar-explain-\"));\n writeFileSync(join(dir, \".stellar-explain.json\"), \"\", \"utf8\");\n const cwdSpy = vi.spyOn(process, \"cwd\").mockReturnValue(dir);\n\n expect(readConfigFile()).toEqual({});\n\n cwdSpy.mockRestore();\n rmSync(dir, { recursive: true, force: true });\n });\n});\n" \ No newline at end of file +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { readConfigFile } from "../src/lib/configFile.js"; + +afterEach(() => { + vi.restoreAllMocks(); +}); + +describe("readConfigFile", () => { + it("reads updateCheck from the local config file", () => { + const dir = mkdtempSync(join(tmpdir(), "stellar-explain-")); + writeFileSync( + join(dir, ".stellar-explain.json"), + JSON.stringify({ url: "https://example.com", timeout: 4500, updateCheck: false }), + "utf8", + ); + + const cwdSpy = vi.spyOn(process, "cwd").mockReturnValue(dir); + + expect(readConfigFile()).toEqual({ + url: "https://example.com", + timeout: 4500, + updateCheck: false, + }); + + cwdSpy.mockRestore(); + rmSync(dir, { recursive: true, force: true }); + }); + + it("returns empty object when no config file exists", () => { + const dir = mkdtempSync(join(tmpdir(), "stellar-explain-")); + const cwdSpy = vi.spyOn(process, "cwd").mockReturnValue(dir); + + expect(readConfigFile()).toEqual({}); + + cwdSpy.mockRestore(); + rmSync(dir, { recursive: true, force: true }); + }); + + it("returns empty object for malformed JSON config", () => { + const dir = mkdtempSync(join(tmpdir(), "stellar-explain-")); + writeFileSync(join(dir, ".stellar-explain.json"), "not valid json", "utf8"); + const cwdSpy = vi.spyOn(process, "cwd").mockReturnValue(dir); + + expect(readConfigFile()).toEqual({}); + + cwdSpy.mockRestore(); + rmSync(dir, { recursive: true, force: true }); + }); + + it("returns empty object for empty config file", () => { + const dir = mkdtempSync(join(tmpdir(), "stellar-explain-")); + writeFileSync(join(dir, ".stellar-explain.json"), "", "utf8"); + const cwdSpy = vi.spyOn(process, "cwd").mockReturnValue(dir); + + expect(readConfigFile()).toEqual({}); + + cwdSpy.mockRestore(); + rmSync(dir, { recursive: true, force: true }); + }); +}); diff --git a/packages/cli/tests/formatters/health.test.ts b/packages/cli/tests/formatters/health.test.ts index 301460d..7b6a269 100644 --- a/packages/cli/tests/formatters/health.test.ts +++ b/packages/cli/tests/formatters/health.test.ts @@ -1 +1,28 @@ -"import { describe, it, expect } from \"vitest\";\nimport { formatHealth } from \"../../src/formatters/health.js\";\n\ndescribe(\"formatHealth\", () => {\n it(\"renders ok status with reachable horizon\", () => {\n const output = formatHealth({ status: \"ok\", horizon_reachable: true, version: \"1.0.0\" });\n expect(output).toContain(\"Status: ok\");\n expect(output).toContain(\"Horizon: reachable\");\n expect(output).toContain(\"Version: 1.0.0\");\n });\n\n it(\"renders degraded status\", () => {\n const output = formatHealth({ status: \"degraded\", horizon_reachable: true, version: \"1.0.0\" });\n expect(output).toContain(\"Status: degraded\");\n });\n\n it(\"renders down status with unreachable horizon\", () => {\n const output = formatHealth({ status: \"down\", horizon_reachable: false, version: \"1.0.0\" });\n expect(output).toContain(\"Status: down\");\n expect(output).toContain(\"Horizon: unreachable\");\n });\n\n it(\"handles horizon unreachable with ok status\", () => {\n const output = formatHealth({ status: \"ok\", horizon_reachable: false, version: \"2.0.0\" });\n expect(output).toContain(\"Status: ok\");\n expect(output).toContain(\"Horizon: unreachable\");\n });\n});\n" \ No newline at end of file +import { describe, it, expect } from "vitest"; +import { formatHealth } from "../../src/formatters/health.js"; + +describe("formatHealth", () => { + it("renders ok status with reachable horizon", () => { + const output = formatHealth({ status: "ok", horizon_reachable: true, version: "1.0.0" }); + expect(output).toContain("Status: ok"); + expect(output).toContain("Horizon: reachable"); + expect(output).toContain("Version: 1.0.0"); + }); + + it("renders degraded status", () => { + const output = formatHealth({ status: "degraded", horizon_reachable: true, version: "1.0.0" }); + expect(output).toContain("Status: degraded"); + }); + + it("renders down status with unreachable horizon", () => { + const output = formatHealth({ status: "down", horizon_reachable: false, version: "1.0.0" }); + expect(output).toContain("Status: down"); + expect(output).toContain("Horizon: unreachable"); + }); + + it("handles horizon unreachable with ok status", () => { + const output = formatHealth({ status: "ok", horizon_reachable: false, version: "2.0.0" }); + expect(output).toContain("Status: ok"); + expect(output).toContain("Horizon: unreachable"); + }); +}); diff --git a/packages/cli/tests/history.test.ts b/packages/cli/tests/history.test.ts index c143d91..5a5184a 100644 --- a/packages/cli/tests/history.test.ts +++ b/packages/cli/tests/history.test.ts @@ -3,184 +3,237 @@ import * as fs from "fs"; import * as path from "path"; import * as os from "os"; -const DEFAULT_HISTORY_LIMIT = 10; - -function applyLimit(entries: T[], limit: number): T[] { - return entries.slice(-Math.abs(limit)); -} +// ─── Temp dir used by the mock ──────────────────────────────────────────────── +const TEMP_HOME = path.join(os.tmpdir(), `se-history-test-${process.pid}`); +const HISTORY_FILE = path.join(TEMP_HOME, "history.json"); +// ─── Mock the history module so it writes to our temp dir ───────────────────── vi.mock("../src/lib/history.js", () => { const fs = require("fs") as typeof import("fs"); const path = require("path") as typeof import("path"); const os = require("os") as typeof import("os"); - const TEMP_HOME = path.join(os.tmpdir(), `se-history-test-${process.pid}`); - const FILE = path.join(TEMP_HOME, ".stellar-explain-history.json"); - - const LIMIT = 10; - - function applyLimitInner(entries: T[], limit: number): T[] { - return entries.slice(-Math.abs(limit)); - } + const TEMP = path.join(os.tmpdir(), `se-history-test-${process.pid}`); + const FILE = path.join(TEMP, "history.json"); + const MAX_STORED = 500; + type LookupKind = "tx" | "account"; interface HistoryEntry { - input: string; + kind: LookupKind; + query: string; timestamp: string; } - function loadEntries(): HistoryEntry[] { + function ensureDir() { + if (!fs.existsSync(TEMP)) fs.mkdirSync(TEMP, { recursive: true }); + } + + function readHistory(): HistoryEntry[] { + ensureDir(); if (!fs.existsSync(FILE)) return []; - return JSON.parse(fs.readFileSync(FILE, "utf8")) as HistoryEntry[]; + try { + return JSON.parse(fs.readFileSync(FILE, "utf8")) as HistoryEntry[]; + } catch { + return []; + } } - function addEntry(entry: HistoryEntry, limit = LIMIT): void { - const entries = loadEntries(); - entries.push(entry); - const trimmed = applyLimitInner(entries, limit); - fs.mkdirSync(path.dirname(FILE), { recursive: true }); - fs.writeFileSync(FILE, JSON.stringify(trimmed), "utf8"); + function addEntry(kind: LookupKind, query: string): void { + ensureDir(); + const entries = readHistory(); + entries.push({ kind, query, timestamp: new Date().toISOString() }); + const trimmed = entries.slice(-MAX_STORED); + fs.writeFileSync(FILE, JSON.stringify(trimmed, null, 2), "utf8"); } function clearHistory(): void { - if (fs.existsSync(FILE)) fs.unlinkSync(FILE); + if (fs.existsSync(FILE)) fs.rmSync(FILE); } - return { addEntry, loadEntries, clearHistory }; + function historyFilePath(): string { + return FILE; + } + + return { readHistory, addEntry, clearHistory, historyFilePath }; }); -import { addEntry, loadEntries, clearHistory } from "../src/lib/history.js"; +import { + readHistory, + addEntry, + clearHistory, + historyFilePath, +} from "../src/lib/history.js"; -const TEMP_HOME = path.join(os.tmpdir(), `se-history-test-${process.pid}`); -const HISTORY_FILE = path.join(TEMP_HOME, ".stellar-explain-history.json"); +// ─── Helpers ───────────────────────────────────────────────────────────────── -function entry(n: number): { input: string; timestamp: string } { - return { input: `tx-${n}`, timestamp: new Date(Date.now() + n).toISOString() }; +function txEntry(n: number) { + return { kind: "tx" as const, query: `${"a".repeat(63)}${n % 10}` }; } +function accountEntry(n: number) { + return { + kind: "account" as const, + query: `G${"A".repeat(54)}${n % 10}`, + }; +} + +// ─── Setup/teardown ─────────────────────────────────────────────────────────── + +beforeEach(() => { + fs.mkdirSync(TEMP_HOME, { recursive: true }); +}); + +afterEach(() => { + clearHistory(); + fs.rmSync(TEMP_HOME, { recursive: true, force: true }); +}); + +// ─── Tests ──────────────────────────────────────────────────────────────────── + describe("history", () => { - beforeEach(() => { - fs.mkdirSync(TEMP_HOME, { recursive: true }); - }); + // ── Reading an empty history ─────────────────────────────────────────────── - afterEach(() => { - clearHistory(); - fs.rmSync(TEMP_HOME, { recursive: true, force: true }); + describe("readHistory (empty)", () => { + it("returns an empty array when no history file exists", () => { + expect(readHistory()).toEqual([]); + }); }); - // ── Adding entries ───────────────────────────────────────────── + // ── Adding entries ───────────────────────────────────────────────────────── describe("addEntry", () => { - it("persists a single entry", () => { - addEntry(entry(1)); + it("persists a single tx entry", () => { + const { kind, query } = txEntry(1); + addEntry(kind, query); - const entries = loadEntries(); + const entries = readHistory(); expect(entries).toHaveLength(1); - expect(entries[0].input).toBe("tx-1"); + expect(entries[0]!.kind).toBe("tx"); + expect(entries[0]!.query).toBe(query); + expect(entries[0]!.timestamp).toBeTruthy(); + }); + + it("persists a single account entry", () => { + const { kind, query } = accountEntry(1); + addEntry(kind, query); + + const entries = readHistory(); + expect(entries).toHaveLength(1); + expect(entries[0]!.kind).toBe("account"); + expect(entries[0]!.query).toBe(query); }); it("appends entries in order", () => { - addEntry(entry(1)); - addEntry(entry(2)); - addEntry(entry(3)); + addEntry("tx", txEntry(1).query); + addEntry("account", accountEntry(2).query); + addEntry("tx", txEntry(3).query); - const entries = loadEntries(); + const entries = readHistory(); expect(entries).toHaveLength(3); - expect(entries[0].input).toBe("tx-1"); - expect(entries[1].input).toBe("tx-2"); - expect(entries[2].input).toBe("tx-3"); + expect(entries[0]!.kind).toBe("tx"); + expect(entries[1]!.kind).toBe("account"); + expect(entries[2]!.kind).toBe("tx"); }); it("creates the history file if it does not exist", () => { expect(fs.existsSync(HISTORY_FILE)).toBe(false); - - addEntry(entry(1)); - + addEntry("tx", txEntry(1).query); expect(fs.existsSync(HISTORY_FILE)).toBe(true); }); - }); - - // ── Reading entries ──────────────────────────────────────────── - describe("loadEntries", () => { - it("returns an empty array when no history file exists", () => { - expect(loadEntries()).toEqual([]); + it("records an ISO-8601 timestamp", () => { + addEntry("tx", txEntry(1).query); + const [entry] = readHistory(); + expect(new Date(entry!.timestamp).toISOString()).toBe(entry!.timestamp); }); + }); + + // ── Reading entries ──────────────────────────────────────────────────────── - it("reads entries from the history file", () => { - addEntry(entry(1)); - addEntry(entry(2)); + describe("readHistory", () => { + it("reads back what was written", () => { + addEntry("tx", txEntry(1).query); + addEntry("account", accountEntry(2).query); - const entries = loadEntries(); + const entries = readHistory(); expect(entries).toHaveLength(2); - expect(entries[0].input).toBe("tx-1"); - expect(entries[1].input).toBe("tx-2"); + expect(entries[0]!.kind).toBe("tx"); + expect(entries[1]!.kind).toBe("account"); }); - it("preserves all entry fields", () => { - const e = { input: "abc123", timestamp: "2025-01-01T00:00:00Z" }; - addEntry(e); - - const [result] = loadEntries(); - expect(result.input).toBe("abc123"); - expect(result.timestamp).toBe("2025-01-01T00:00:00Z"); + it("preserves all three entry fields", () => { + addEntry("account", accountEntry(1).query); + const [result] = readHistory(); + expect(result).toHaveProperty("kind"); + expect(result).toHaveProperty("query"); + expect(result).toHaveProperty("timestamp"); }); }); - // ── Limiting to max count ────────────────────────────────────── + // ── Filtering by kind ────────────────────────────────────────────────────── + + describe("filtering by kind", () => { + beforeEach(() => { + addEntry("tx", txEntry(1).query); + addEntry("account", accountEntry(2).query); + addEntry("tx", txEntry(3).query); + addEntry("account", accountEntry(4).query); + }); - describe("limiting entries", () => { - it("trims to the default limit of 10 when exceeded", () => { - for (let i = 1; i <= 15; i++) { - addEntry(entry(i)); - } + it("can filter to only tx entries", () => { + const txEntries = readHistory().filter((e) => e.kind === "tx"); + expect(txEntries).toHaveLength(2); + expect(txEntries.every((e) => e.kind === "tx")).toBe(true); + }); - const entries = loadEntries(); - expect(entries).toHaveLength(10); - // Should keep the latest 10 (entries 6-15) - expect(entries[0].input).toBe("tx-6"); - expect(entries[9].input).toBe("tx-15"); + it("can filter to only account entries", () => { + const acctEntries = readHistory().filter((e) => e.kind === "account"); + expect(acctEntries).toHaveLength(2); + expect(acctEntries.every((e) => e.kind === "account")).toBe(true); }); + }); - it("respects a custom limit", () => { - for (let i = 1; i <= 5; i++) { - addEntry(entry(i), 3); - } + // ── Applying a limit ─────────────────────────────────────────────────────── - const entries = loadEntries(); - expect(entries).toHaveLength(3); - expect(entries[0].input).toBe("tx-3"); - expect(entries[2].input).toBe("tx-5"); + describe("applying a limit (slice)", () => { + it("slicing the last N entries gives the most recent ones", () => { + for (let i = 1; i <= 5; i++) addEntry("tx", txEntry(i).query); + + const entries = readHistory(); + const shown = entries.slice(-3).reverse(); + + expect(shown).toHaveLength(3); + // Most recent should be last written (entry 5) + expect(shown[0]!.query).toBe(txEntry(5).query); }); + }); - it("does not trim when under the limit", () => { - for (let i = 1; i <= 5; i++) { - addEntry(entry(i)); - } + // ── historyFilePath ──────────────────────────────────────────────────────── - const entries = loadEntries(); - expect(entries).toHaveLength(5); + describe("historyFilePath", () => { + it("returns a non-empty string", () => { + expect(typeof historyFilePath()).toBe("string"); + expect(historyFilePath().length).toBeGreaterThan(0); }); }); - // ── Clearing history ─────────────────────────────────────────── + // ── Clearing history ─────────────────────────────────────────────────────── describe("clearHistory", () => { it("removes the history file", () => { - addEntry(entry(1)); + addEntry("tx", txEntry(1).query); expect(fs.existsSync(HISTORY_FILE)).toBe(true); clearHistory(); - expect(fs.existsSync(HISTORY_FILE)).toBe(false); }); - it("results in an empty loadEntries", () => { - addEntry(entry(1)); - addEntry(entry(2)); + it("results in an empty readHistory after clear", () => { + addEntry("tx", txEntry(1).query); + addEntry("account", accountEntry(2).query); clearHistory(); - - expect(loadEntries()).toEqual([]); + expect(readHistory()).toEqual([]); }); it("is safe to call when no history file exists", () => { diff --git a/packages/cli/tests/validate.test.ts b/packages/cli/tests/validate.test.ts index 06e11bc..8fb7b15 100644 --- a/packages/cli/tests/validate.test.ts +++ b/packages/cli/tests/validate.test.ts @@ -1 +1,120 @@ -"import {\n isValidStellarAddress,\n isValidTransactionHash,\n validateHash,\n validateAddress,\n} from '../src/lib/validate';\nimport { InvalidInputError } from '../src/lib/errors';\n\ndescribe('validate helpers', () => {\n describe('validateHash', () => {\n it('does not throw for valid hash', () => {\n const hash = 'a3f5c2b9d8e1f4a6b7c8d9e0f123456789abcdef123456789abcdef123456789';\n expect(() => validateHash(hash)).not.toThrow();\n });\n\n it('throws InvalidInputError for invalid hash', () => {\n expect(() => validateHash('short')).toThrow(InvalidInputError);\n });\n });\n\n describe('validateAddress', () => {\n it('does not throw for valid address', () => {\n const addr = 'GBRPYHIL2CI3ZJ3N6PFV6XQ5U6JYQ4KZ6Y5HZK4A6X5Q5JXJQX7P6F5S';\n expect(() => validateAddress(addr)).not.toThrow();\n });\n\n it('throws InvalidInputError for invalid address', () => {\n expect(() => validateAddress('invalid')).toThrow(InvalidInputError);\n });\n });\n\n describe('isValidTransactionHash', () => {\n it('returns true for valid transaction hash', () => {\n const hash =\n 'a3f5c2b9d8e1f4a6b7c8d9e0f123456789abcdef123456789abcdef123456789';\n\n expect(isValidTransactionHash(hash)).toBe(true);\n });\n\n it('returns false for empty hash', () => {\n expect(isValidTransactionHash('')).toBe(false);\n });\n\n it('returns false for short hash', () => {\n expect(\n isValidTransactionHash('abc123'),\n ).toBe(false);\n });\n\n it('returns false for invalid characters', () => {\n const invalidHash =\n 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz';\n\n expect(\n isValidTransactionHash(invalidHash),\n ).toBe(false);\n });\n\n it('returns false for non-string input', () => {\n expect(\n isValidTransactionHash(null as any),\n ).toBe(false);\n\n expect(\n isValidTransactionHash(undefined as any),\n ).toBe(false);\n });\n });\n\n describe('isValidStellarAddress', () => {\n it('returns true for valid Stellar address', () => {\n const address =\n 'GBRPYHIL2CI3ZJ3N6PFV6XQ5U6JYQ4KZ6Y5HZK4A6X5Q5JXJQX7P6F5S';\n\n expect(isValidStellarAddress(address)).toBe(\n true,\n );\n });\n\n it('returns false for empty address', () => {\n expect(isValidStellarAddress('')).toBe(\n false,\n );\n });\n\n it('returns false for malformed address', () => {\n expect(\n isValidStellarAddress('INVALID_ADDRESS'),\n ).toBe(false);\n });\n\n it('returns false for short address', () => {\n expect(\n isValidStellarAddress('GB123'),\n ).toBe(false);\n });\n\n it('returns false for non-string input', () => {\n expect(\n isValidStellarAddress(null as any),\n ).toBe(false);\n\n expect(\n isValidStellarAddress(undefined as any),\n ).toBe(false);\n });\n\n it('returns false for lowercase address', () => {\n expect(\n isValidStellarAddress('gbrpyhil2ci3zj3n6pfv6xq5u6jyq4kz6y5hzk4a6x5q5jxjqxp6f5s'),\n ).toBe(false);\n });\n\n it('returns false for address with wrong length', () => {\n expect(\n isValidStellarAddress('GBRPYHIL2CI3ZJ3N6PFV6XQ5U6JYQ4KZ6Y5H'),\n ).toBe(false);\n });\n });\n});\n" \ No newline at end of file +import { + isValidStellarAddress, + isValidTransactionHash, + validateHash, + validateAddress, +} from '../src/lib/validate'; +import { InvalidInputError } from '../src/lib/errors'; + +describe('validate helpers', () => { + describe('validateHash', () => { + it('does not throw for valid hash', () => { + const hash = 'a3f5c2b9d8e1f4a6b7c8d9e0f123456789abcdef123456789abcdef123456789'; + expect(() => validateHash(hash)).not.toThrow(); + }); + + it('throws InvalidInputError for invalid hash', () => { + expect(() => validateHash('short')).toThrow(InvalidInputError); + }); + }); + + describe('validateAddress', () => { + it('does not throw for valid address', () => { + const addr = 'GBRPYHIL2CI3ZJ3N6PFV6XQ5U6JYQ4KZ6Y5HZK4A6X5Q5JXJQX7P6F5S'; + expect(() => validateAddress(addr)).not.toThrow(); + }); + + it('throws InvalidInputError for invalid address', () => { + expect(() => validateAddress('invalid')).toThrow(InvalidInputError); + }); + }); + + describe('isValidTransactionHash', () => { + it('returns true for valid transaction hash', () => { + const hash = + 'a3f5c2b9d8e1f4a6b7c8d9e0f123456789abcdef123456789abcdef123456789'; + + expect(isValidTransactionHash(hash)).toBe(true); + }); + + it('returns false for empty hash', () => { + expect(isValidTransactionHash('')).toBe(false); + }); + + it('returns false for short hash', () => { + expect( + isValidTransactionHash('abc123'), + ).toBe(false); + }); + + it('returns false for invalid characters', () => { + const invalidHash = + 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'; + + expect( + isValidTransactionHash(invalidHash), + ).toBe(false); + }); + + it('returns false for non-string input', () => { + expect( + isValidTransactionHash(null as any), + ).toBe(false); + + expect( + isValidTransactionHash(undefined as any), + ).toBe(false); + }); + }); + + describe('isValidStellarAddress', () => { + it('returns true for valid Stellar address', () => { + const address = + 'GBRPYHIL2CI3ZJ3N6PFV6XQ5U6JYQ4KZ6Y5HZK4A6X5Q5JXJQX7P6F5S'; + + expect(isValidStellarAddress(address)).toBe( + true, + ); + }); + + it('returns false for empty address', () => { + expect(isValidStellarAddress('')).toBe( + false, + ); + }); + + it('returns false for malformed address', () => { + expect( + isValidStellarAddress('INVALID_ADDRESS'), + ).toBe(false); + }); + + it('returns false for short address', () => { + expect( + isValidStellarAddress('GB123'), + ).toBe(false); + }); + + it('returns false for non-string input', () => { + expect( + isValidStellarAddress(null as any), + ).toBe(false); + + expect( + isValidStellarAddress(undefined as any), + ).toBe(false); + }); + + it('returns false for lowercase address', () => { + expect( + isValidStellarAddress('gbrpyhil2ci3zj3n6pfv6xq5u6jyq4kz6y5hzk4a6x5q5jxjqxp6f5s'), + ).toBe(false); + }); + + it('returns false for address with wrong length', () => { + expect( + isValidStellarAddress('GBRPYHIL2CI3ZJ3N6PFV6XQ5U6JYQ4KZ6Y5H'), + ).toBe(false); + }); + }); +});